Skip to content

Commit 63e9704

Browse files
committed
Test parameter extraction edge cases and match swift-docc
1 parent 7a1d592 commit 63e9704

File tree

4 files changed

+153
-2
lines changed

4 files changed

+153
-2
lines changed

Sources/SwiftLanguageService/ParametersDocumentationExtractor.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ private struct ParametersDocumentationExtractor {
5757
}
5858

5959
for param in params {
60-
parameters[param.name] = param.documentation
60+
// If duplicate parameter documentation is found, keep the first one following swift-docc's behavior
61+
parameters[param.name] = parameters[param.name] ?? param.documentation
6162
}
6263

6364
case let doxygenParameter as DoxygenParameter:
6465
let param = extract(from: doxygenParameter)
65-
parameters[param.name] = param.documentation
66+
// If duplicate parameter documentation is found, keep the first one following swift-docc's behavior
67+
parameters[param.name] = parameters[param.name] ?? param.documentation
6668

6769
default:
6870
remainingBlocks.append(block)

Sources/SwiftLanguageService/SignatureHelp.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fileprivate extension String {
3636
}
3737

3838
fileprivate extension ParameterInformation {
39+
/// - Parameter parameterDocumentation: A dictionary with the parameter name as the key and its documentation as the value.
3940
init?(
4041
_ parameter: SKDResponseDictionary,
4142
_ signatureLabel: String,

Tests/SourceKitLSPTests/ParametersDocumentationExtractorTests.swift

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,79 @@ final class ParametersDocumentationExtractorTests: XCTestCase {
249249
"""
250250
)
251251
}
252+
253+
/// Tests that we drop non-parameter items in the parameter outline. Aligns with swift-docc.
254+
func testDropsNonParameterItemsInParameterOutline() {
255+
let comment = """
256+
- Parameters:
257+
- number: The number to do stuff with
258+
- TODO Improve this documentation
259+
"""
260+
261+
let (parameters, remaining) = extractParametersDocumentation(from: comment)
262+
263+
XCTAssertEqual(parameters, ["number": "The number to do stuff with"])
264+
XCTAssertTrue(remaining.isEmpty)
265+
}
266+
267+
/// Tests that we drop duplicate parameter documentation and keep thefirst one. Aligns with swift-docc.
268+
func testDropsDuplicateParameterDocumentation() {
269+
let comment = """
270+
- Parameters:
271+
- number: The number to do stuff with
272+
- number: The number to do amazing stuff with
273+
"""
274+
275+
let (parameters, remaining) = extractParametersDocumentation(from: comment)
276+
277+
XCTAssertEqual(parameters, ["number": "The number to do stuff with"])
278+
XCTAssertTrue(remaining.isEmpty)
279+
}
280+
281+
/// Tests that we drop text after the colon in the parameter outline. Aligns with swift-docc.
282+
func testDropsTextAfterColonInParameterOutline() {
283+
let comment = """
284+
- Parameters: listing parameter documentation below
285+
- number: The number to do stuff
286+
"""
287+
288+
let (parameters, remaining) = extractParametersDocumentation(from: comment)
289+
290+
XCTAssertEqual(parameters, ["number": "The number to do stuff"])
291+
XCTAssertTrue(remaining.isEmpty)
292+
}
293+
294+
/// Tests that we support mixed parameter documentation styles in a single comment. Aligns with swift-docc.
295+
func testMixedParameterDocumentationStyles() {
296+
let comment = #"""
297+
Function documentation.
298+
299+
- Parameters:
300+
- first: First parameter from Parameters section
301+
- Parameter second: Second parameter from separate Parameter
302+
\param third Third parameter from Doxygen style
303+
304+
Additional documentation.
305+
"""#
306+
307+
let (parameters, remaining) = extractParametersDocumentation(from: comment)
308+
309+
XCTAssertEqual(
310+
parameters,
311+
[
312+
"first": "First parameter from Parameters section",
313+
"second": "Second parameter from separate Parameter",
314+
"third": "Third parameter from Doxygen style",
315+
]
316+
)
317+
318+
XCTAssertEqual(
319+
remaining,
320+
"""
321+
Function documentation.
322+
323+
Additional documentation.
324+
"""
325+
)
326+
}
252327
}

Tests/SourceKitLSPTests/SwiftSignatureHelpTests.swift

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,4 +668,77 @@ final class SwiftSignatureHelpTests: XCTestCase {
668668
]
669669
)
670670
}
671+
672+
func testSignatureHelpMatchesParametersWithInternalNames() async throws {
673+
try await SkipUnless.sourcekitdSupportsSignatureHelp()
674+
675+
let testClient = try await TestSourceKitLSPClient()
676+
let uri = DocumentURI(for: .swift)
677+
678+
let positions = testClient.openDocument(
679+
"""
680+
/// - Parameter number: The number to add 1 to
681+
func addOne(to number: Int) -> Int { number + 1 }
682+
683+
func main() {
684+
addOne(1️⃣)
685+
}
686+
""",
687+
uri: uri
688+
)
689+
690+
let result = try await testClient.send(
691+
SignatureHelpRequest(
692+
textDocument: TextDocumentIdentifier(uri),
693+
position: positions["1️⃣"]
694+
)
695+
)
696+
697+
let signatureHelp = try XCTUnwrap(result)
698+
let signature = try XCTUnwrap(signatureHelp.signatures.only)
699+
let signatureDocumentation = try XCTUnwrap(signature.documentation)
700+
let parameter = try XCTUnwrap(signature.parameters?.only)
701+
702+
XCTAssertEqual(signatureDocumentation, .markupContent(MarkupContent(kind: .markdown, value: "")))
703+
XCTAssertEqual(
704+
parameter.documentation,
705+
.markupContent(MarkupContent(kind: .markdown, value: "The number to add 1 to"))
706+
)
707+
}
708+
709+
/// Tests that we drop parameter documentation for parameters that don't exist aligning with swift-docc.
710+
func testSignatureHelpDropsNonExistentParameterDocumentation() async throws {
711+
try await SkipUnless.sourcekitdSupportsSignatureHelp()
712+
713+
let testClient = try await TestSourceKitLSPClient()
714+
let uri = DocumentURI(for: .swift)
715+
716+
let positions = testClient.openDocument(
717+
"""
718+
/// - Parameters:
719+
/// - numberWithTypo: The number to do stuff with
720+
func compute(number: Int) {}
721+
722+
func main() {
723+
compute(1️⃣)
724+
}
725+
""",
726+
uri: uri
727+
)
728+
729+
let result = try await testClient.send(
730+
SignatureHelpRequest(
731+
textDocument: TextDocumentIdentifier(uri),
732+
position: positions["1️⃣"]
733+
)
734+
)
735+
736+
let signatureHelp = try XCTUnwrap(result)
737+
let signature = try XCTUnwrap(signatureHelp.signatures.only)
738+
let parameter = try XCTUnwrap(signature.parameters?.only)
739+
let signatureDocumentation = try XCTUnwrap(signature.documentation)
740+
741+
XCTAssertEqual(signatureDocumentation, .markupContent(MarkupContent(kind: .markdown, value: "")))
742+
XCTAssertNil(parameter.documentation)
743+
}
671744
}

0 commit comments

Comments
 (0)