Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up internal property nesting #315

Merged
merged 1 commit into from
May 21, 2021
Merged

Clean up internal property nesting #315

merged 1 commit into from
May 21, 2021

Conversation

rauhul
Copy link
Contributor

@rauhul rauhul commented May 19, 2021

  • Removes one layer of help properties by directly including the members
    of ArgumentHelp in ArgumentDefinition.Help. This also results in the
    discussion field which previously existed in both structures, now
    having a single source of truth. Adds helper method for setting each
    of these members using an instance of ArgumentHelp and additionally
    annotates each of the String? members with a new @NonEmpty property
    wrapper that ensures the wrapped string is either nil or nonempty so
    clients no do not need to check for the empty string case.

Replace this paragraph with a description of your changes and rationale. Provide links to an existing issue or external references/discussions, if appropriate.

Checklist

  • I've added at least one test that validates that my change is working, if appropriate
  • I've followed the code style of the rest of the project
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary

@rauhul rauhul requested a review from natecook1000 May 19, 2021 21:34
@rauhul
Copy link
Contributor Author

rauhul commented May 19, 2021

@swift-ci Please test

@rauhul
Copy link
Contributor Author

rauhul commented May 20, 2021

I'm sure about the @NonEmpty property wrapper. I would personally prefer using something like swift-nonempty by point free to embed this information in the typesystem. @natecook1000 thoughts?

Copy link
Member

@natecook1000 natecook1000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, other than @NonEmpty, as you mentioned. Thanks, @rauhul!

Comment on lines 44 to 46
@NonEmpty var abstract: String?
@NonEmpty var discussion: String?
@NonEmpty var valueName: String?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a semantic difference for these between "" and nil? If not, I'd rather make these non-optional and just use empty strings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe so, just that the property is derived from help: ArgumentHelp? so the optionality is inherited from there. I am happy to make these non-optional and make the points of use test for empty string. I think the only rough point is losing the ergonomics of optional chaining and defaulting. ex: valueName ?? otherValueName ?? "default"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example:

-    return help.valueName
-      ?? preferredNameForSynopsis?.valueString
+    return help.valueName.isEmpty
+      ? help.valueName
+      : preferredNameForSynopsis?.valueString
       ?? help.keys.first?.rawValue.convertedToSnakeCase(separator: "-")
       ?? "value"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is less desirable as it makes it easier to accidentally introduce bugs, like I just did in the above code. The condition should be *!*help.valueName.isEmpty

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the ergonomics are annoying, but I'd rather not keep them optional just for that purpose. That's kind of a funny usage point, since it's then lifting help.valueName into an optional to use with the following optional chaining… You could add a String extension like func mapEmpty(_ f: () -> String) -> String that would clear that up:

help.valueName.mapEmpty {
    preferredNameForSynopsis?.valueString
       ?? help.keys.first?.rawValue.convertedToSnakeCase(separator: "-")
       ?? "value"
}

Copy link
Contributor Author

@rauhul rauhul May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with your suggestion, but as an extension on Collection instead, since this replacement behavior seems generally useful.


It almost seems like there should be a NullValue protocol, such that this extension could operate on anything with a defined null and then the ?? operator could be extended to as well.

protocol NullValue {
  static var null: Self
}

extension NullValue where Self: Equatable {
  func mapNull(_ replacement: () -> Self) -> Self {
    self == null ? replacement() : self
  }
}

func ??<T: NullValue>(lhs: T, rhs: T) -> T {
  lhs.mapNull { rhs }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it’s been proposed, I think!

- Removes one layer of help properties by directly including the members
  of ArgumentHelp in ArgumentDefinition.Help. This also results in the
  discussion field which previously existed in both structures, now
  having a single source of truth. Adds helper method for setting each
  of these members using an instance of ArgumentHelp. Makes previously
  optional Strings into plain Strings and updates points of use to check
  for the empty string case.
@rauhul
Copy link
Contributor Author

rauhul commented May 20, 2021

@swift-ci please test

@natecook1000 natecook1000 merged commit 860afda into apple:main May 21, 2021
@rauhul rauhul deleted the rauhul/internal-help-gardening branch May 21, 2021 01:09
@compnerd
Copy link
Collaborator

compnerd added a commit to compnerd/swift-argument-parser that referenced this pull request May 22, 2021
apple#315 added a new file but failed to update
the CMakeLists.txt, resulting in the inability to bootstrap the
toolchain.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants