-
Notifications
You must be signed in to change notification settings - Fork 147
Validate and filter parameter and return value documentation #776
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
Validate and filter parameter and return value documentation #776
Conversation
@swift-ci please test |
bd55af0
to
fd99373
Compare
fd99373
to
bcd97ec
Compare
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work, and a great improvement for DocC!
I'm about halfway through reviewing this. I've read the code and have a number of questions for you. Most of my concerns are about understand your new algorithms... in some places it's a bit hard to follow. Some more code comments and different variable names might help a lot.
Next week I'll find some time to test this more carefully and review the test code.
// Ensure that the parameters are displayed in the order that they're declared. | ||
var sortedParameters: [Parameter] = [] | ||
sortedParameters.reserveCapacity(languageApplicableParameters.count) | ||
for parameter in signature.parameters { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like you might be able to refactor this function and avoid these separate sorting loops for each trait. Above you iterate over the signature parameter also... If you could find a way to add each language's parameter in the loop above then the result array would already be sorted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could avoid one loop of the parameters but there is a sequence to these steps; the sorted parameters for the trait needs to know the parameters that's applicable to that language which in turn needs to know the parameter names.
# Conflicts: # Package.resolved # Sources/SwiftDocC/Utility/FeatureFlags.swift # Sources/SwiftDocCUtilities/ArgumentParsing/ActionExtensions/ConvertAction+CommandInitialization.swift # Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/Convert.swift
78bb328
to
ef26467
Compare
@swift-ci please test |
@patshaughnessy I addressed all the feedback. Would you mind taking another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic. Thank you for adding all those new comments and for renaming the local variables. Helps a lot to understand the new code.
Maybe fix a typo and merge it 👍
/// ```swift | ||
/// func doSomething(with someValue: Int) {} | ||
/// // │ ╰─ name | ||
/// // ╰─ externalName (also known as "argument label") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this explanation! Love the ascii-art :)
var sortedParameters: [Parameter] = [] | ||
sortedParameters.reserveCapacity(languageApplicableParametersByName.count) | ||
for parameter in signature.parameters { | ||
if let foundParameter = languageApplicableParametersByName[parameter.name]?.first { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be sure first
will return the proper parameter? Does it matter? Is the call to (grouping: by:)
above guaranteed to retain the original order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the order is documented to be the same as the original order. It mostly doesn't matter since documenting the same parameter more than once results in a warning but it's nice that the behavior is stable across documentation builds even when there are warnings.
The arrays in the “values” position of the new dictionary each contain at least one element, with the elements in the same order as the source sequence.
/// ## Example | ||
/// | ||
/// ```swift | ||
/// /// - Paramaters: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo/spelling - and throughout this appears in various places.
/// /// - Paramaters: | ||
/// /// - someValue: Some description of this parameter | ||
/// /// - Returns: Description of what this function returns | ||
/// /// ^~~~~~~ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love these examples of the error messages and how they will appear - thank you!
private func makeMissingParameterProblem(name: String, before nextParameter: Parameter?, standalone: Bool, lastParameterEndLocation: SourceLocation?) -> Problem { | ||
let solutions: [Solution] | ||
if let insertLocation = nextParameter?.range?.lowerBound ?? lastParameterEndLocation { | ||
let extraWhitespace = "\n///" + String(repeating: " ", count: (nextParameter?.range?.lowerBound.column ?? 1 + (standalone ? 0 : 2) /* indent items in a parameter outline by 2 spaces */) - 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why include ///
here? Does that make the replacement ("Fix It" in the Xcode UI?) look better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the fix it inserts the placeholder text for the new parameter on its own line we need to include "///" after the newline so that the new line is part of the documentation comment.
For example, consider this declaration and documentation comment where the "first" parameter is undocumented and should be inserted before the "second".
/// - Paramaters:
/// - second: Some description of the first parameter
func someFunction(first: Int, second: Int) {}
Inserting only - first: placeholder
without a newline would result in
/// - Paramaters:
/// - first: placeholder- second: Some description of the first parameter
func someFunction(first: Int, second: Int) {}
Inserting only - parameterName: placeholder\n
with a newline would result in
/// - Paramaters:
/// - first: placeholder
- second: Some description of the first parameter
func someFunction(first: Int, second: Int) {}
But inserting - parameterName: placeholder\n///
with a newline, a triple slash, and the same leading whitespace as the previous parameter had would result in
/// - Paramaters:
/// - first: placeholder
/// - second: Some description of the first parameter
func someFunction(first: Int, second: Int) {}
@swift-ci please test |
Bug/issue #, if applicable: rdar://118739612
Summary
This adds validation and filtering of parameter and return value documentation based on a symbol's function signature in each language representation.
This results in 3 new behaviors:
Filtering parameters
If a symbol has different parameters and return values in different languages, then each language's version of that symbol's page will only display the parameters that's applicable to that language.
This is for example relevant for API with errors in Objective-C that bridge to API that
throws
in Swift;This method become
func doSomething(with someValue: Int) throws
in Swift which returnsVoid
and doesn't have anerror
parameter, so displaying documentation for the error parameter and the return value wouldn't be helpful for someone reading the Swift version of that method's documentation.Before this PR we displayed all documented parameters in all language variants of a symbol's page. With these changes, the Swift page won't display the "error" parameter documentation or the return value documentation.
Adding Objective-C error documentation
The above works well for functions defined in Objective-C that document parameters and return values that aren't available in Swift, but it doesn't work in the other direction;
This becomes
- (BOOL)doSomethingWith:(NSInteger)someValue error:(NSError **)error;
in Objective-C but the Swift documentation comment doesn't have any documentation for the Objective-C "error" parameter or the Objective-C specific return value.Before this PR we only displayed the developer documented parameters. With these changes, the Objective-C page will display a synthesized "error" parameter documentation with the generic description:
and a synthesized return value documentation with the generic description:
If the throwing Swift function was defined with a non-null return value that bridges to a nullable return value in Objective-C;
Then the Objective-C return value documentation is appended with a generic description of this automatic bridging behavior:
Parameter and return value diagnostics
If the symbol documents at least one parameter or its return value, then DocC will validate that symbol's parameters section and return value section. Specifically, DocC will warn in 5 cases:
Void
has documented a return valueThe Swift function below shows minimal examples of each of these cases:
Dependencies
swiftlang/swift-docc-symbolkit#64
Testing
In a multi-language project, add:
@objc
API thatthrows
with documentation for the Swift parameters.Build documentation for the project and pass
--enable-experimental-parameters-and-returns-validation
.View both the Swift and Objective-C versions of the documentation pages for both the API defined in Objective-C and the API defined in Swift.
Add parameter documentation for parameters that doesn't exist to the Swift and Objective-C definitions and build documentation again.
View both the Swift and Objective-C versions of the documentation pages for both the API defined in Objective-C and the API defined in Swift.
Checklist
Make sure you check off the following items. If they cannot be completed, provide a reason.
./bin/test
script and it succeeded