Skip to content

Commit 331f16d

Browse files
authored
Merge pull request #1091 from ahoppen/ahoppen/markdown-documentation
Emit raw documentation comments instead of parsing XML
2 parents e6080e0 + a6b8cbe commit 331f16d

File tree

6 files changed

+253
-222
lines changed

6 files changed

+253
-222
lines changed

Sources/SKTestSupport/SkipUnless.swift

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public enum SkipUnless {
5151
/// guaranteed to be up-to-date.
5252
private static func skipUnlessSupportedByToolchain(
5353
swiftVersion: SwiftVersion,
54-
featureName: String,
54+
featureName: String = #function,
5555
file: StaticString,
5656
line: UInt,
5757
featureCheck: () async throws -> Bool
@@ -99,12 +99,7 @@ public enum SkipUnless {
9999
file: StaticString = #file,
100100
line: UInt = #line
101101
) async throws {
102-
try await skipUnlessSupportedByToolchain(
103-
swiftVersion: SwiftVersion(5, 11),
104-
featureName: "semantic token support in sourcekitd",
105-
file: file,
106-
line: line
107-
) {
102+
try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(5, 11), file: file, line: line) {
108103
let testClient = try await TestSourceKitLSPClient()
109104
let uri = DocumentURI.for(.swift)
110105
testClient.openDocument("0.bitPattern", uri: uri)
@@ -134,12 +129,7 @@ public enum SkipUnless {
134129
file: StaticString = #file,
135130
line: UInt = #line
136131
) async throws {
137-
try await skipUnlessSupportedByToolchain(
138-
swiftVersion: SwiftVersion(5, 11),
139-
featureName: "rename support in sourcekitd",
140-
file: file,
141-
line: line
142-
) {
132+
try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(5, 11), file: file, line: line) {
143133
let testClient = try await TestSourceKitLSPClient()
144134
let uri = DocumentURI.for(.swift)
145135
let positions = testClient.openDocument("func 1️⃣test() {}", uri: uri)
@@ -159,12 +149,7 @@ public enum SkipUnless {
159149
file: StaticString = #file,
160150
line: UInt = #line
161151
) async throws {
162-
try await skipUnlessSupportedByToolchain(
163-
swiftVersion: SwiftVersion(5, 11),
164-
featureName: "rename support in clangd",
165-
file: file,
166-
line: line
167-
) {
152+
try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(5, 11), file: file, line: line) {
168153
let testClient = try await TestSourceKitLSPClient()
169154
let uri = DocumentURI.for(.c)
170155
let positions = testClient.openDocument("void 1️⃣test() {}", uri: uri)
@@ -194,12 +179,7 @@ public enum SkipUnless {
194179
file: StaticString = #file,
195180
line: UInt = #line
196181
) async throws {
197-
try await skipUnlessSupportedByToolchain(
198-
swiftVersion: SwiftVersion(5, 11),
199-
featureName: "SwiftPM stores modules in subdirectory",
200-
file: file,
201-
line: line
202-
) {
182+
try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(5, 11), file: file, line: line) {
203183
let workspace = try await SwiftPMTestWorkspace(
204184
files: ["test.swift": ""],
205185
build: true
@@ -217,16 +197,40 @@ public enum SkipUnless {
217197
file: StaticString = #file,
218198
line: UInt = #line
219199
) async throws {
220-
try await skipUnlessSupportedByToolchain(
221-
swiftVersion: SwiftVersion(5, 11),
222-
featureName: "Toolchain contains swift-format",
223-
file: file,
224-
line: line
225-
) {
200+
try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(5, 11), file: file, line: line) {
226201
return await ToolchainRegistry.forTesting.default?.swiftFormat != nil
227202
}
228203
}
229204

205+
public static func sourcekitdReturnsRawDocumentationResponse(
206+
file: StaticString = #file,
207+
line: UInt = #line
208+
) async throws {
209+
struct ExpectedMarkdownContentsError: Error {}
210+
211+
return try await skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(6, 0), file: file, line: line) {
212+
// The XML-based doc comment conversion did not preserve `Precondition`.
213+
let testClient = try await TestSourceKitLSPClient()
214+
let uri = DocumentURI.for(.swift)
215+
let positions = testClient.openDocument(
216+
"""
217+
/// - Precondition: Must have an apple
218+
func 1️⃣test() {}
219+
""",
220+
uri: uri
221+
)
222+
let response = try await testClient.send(
223+
HoverRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
224+
)
225+
let hover = try XCTUnwrap(response, file: file, line: line)
226+
XCTAssertNil(hover.range, file: file, line: line)
227+
guard case .markupContent(let content) = hover.contents else {
228+
throw ExpectedMarkdownContentsError()
229+
}
230+
return content.value.contains("Precondition")
231+
}
232+
}
233+
230234
public static func longTestsEnabled() throws {
231235
if let value = ProcessInfo.processInfo.environment["SKIP_LONG_TESTS"], value == "1" || value == "YES" {
232236
throw XCTSkip("Long tests disabled using the `SKIP_LONG_TESTS` environment variable")
@@ -295,7 +299,7 @@ private func getSwiftVersion(_ swiftcPath: AbsolutePath) async throws -> SwiftVe
295299
let result = try await process.waitUntilExit()
296300
let output = String(bytes: try result.output.get(), encoding: .utf8)
297301
let regex = Regex {
298-
"Apple Swift version "
302+
"Swift version "
299303
Capture { OneOrMore(.digit) }
300304
"."
301305
Capture { OneOrMore(.digit) }

Sources/SourceKitD/sourcekitd_uids.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public struct sourcekitd_api_keys {
5151
public let genericRequirements: sourcekitd_api_uid_t
5252
/// `key.doc.full_as_xml`
5353
public let docFullAsXML: sourcekitd_api_uid_t
54+
/// `key.doc_comment`
55+
public let docComment: sourcekitd_api_uid_t
5456
/// `key.line`
5557
public let line: sourcekitd_api_uid_t
5658
/// `key.column`
@@ -403,6 +405,16 @@ public struct sourcekitd_api_keys {
403405
public let indexStorePath: sourcekitd_api_uid_t
404406
/// `key.index_unit_output_path`
405407
public let indexUnitOutputPath: sourcekitd_api_uid_t
408+
/// `key.include_locals`
409+
public let includeLocals: sourcekitd_api_uid_t
410+
/// `key.ignore_clang_modules`
411+
public let ignoreClangModules: sourcekitd_api_uid_t
412+
/// `key.include_system_modules`
413+
public let includeSystemModules: sourcekitd_api_uid_t
414+
/// `key.ignore_stdlib`
415+
public let ignoreStdlib: sourcekitd_api_uid_t
416+
/// `key.disable_implicit_modules`
417+
public let disableImplicitModules: sourcekitd_api_uid_t
406418
/// `key.codecomplete.sort.byname`
407419
public let sortByName: sourcekitd_api_uid_t
408420
/// `key.codecomplete.sort.useimportdepth`
@@ -473,6 +485,7 @@ public struct sourcekitd_api_keys {
473485
genericParams = api.uid_get_from_cstr("key.generic_params")!
474486
genericRequirements = api.uid_get_from_cstr("key.generic_requirements")!
475487
docFullAsXML = api.uid_get_from_cstr("key.doc.full_as_xml")!
488+
docComment = api.uid_get_from_cstr("key.doc_comment")!
476489
line = api.uid_get_from_cstr("key.line")!
477490
column = api.uid_get_from_cstr("key.column")!
478491
receiverUSR = api.uid_get_from_cstr("key.receiver_usr")!
@@ -649,6 +662,11 @@ public struct sourcekitd_api_keys {
649662
expandedMacroReplacements = api.uid_get_from_cstr("key.expanded_macro_replacements")!
650663
indexStorePath = api.uid_get_from_cstr("key.index_store_path")!
651664
indexUnitOutputPath = api.uid_get_from_cstr("key.index_unit_output_path")!
665+
includeLocals = api.uid_get_from_cstr("key.include_locals")!
666+
ignoreClangModules = api.uid_get_from_cstr("key.ignore_clang_modules")!
667+
includeSystemModules = api.uid_get_from_cstr("key.include_system_modules")!
668+
ignoreStdlib = api.uid_get_from_cstr("key.ignore_stdlib")!
669+
disableImplicitModules = api.uid_get_from_cstr("key.disable_implicit_modules")!
652670
sortByName = api.uid_get_from_cstr("key.codecomplete.sort.byname")!
653671
useImportDepth = api.uid_get_from_cstr("key.codecomplete.sort.useimportdepth")!
654672
groupOverloads = api.uid_get_from_cstr("key.codecomplete.group.overloads")!

Sources/SourceKitLSP/Swift/CursorInfo.swift

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,31 @@ struct CursorInfo {
2828
/// The annotated declaration XML string.
2929
var annotatedDeclaration: String?
3030

31+
#if swift(>=6.2)
32+
#warning(
33+
"Documentation transitioned from XML to the raw string in Swift 6.0. We should be able to remove documentationXML now"
34+
)
35+
#endif
3136
/// The documentation comment XML string. The schema is at
3237
/// https://github.com/apple/swift/blob/main/bindings/xml/comment-xml-schema.rng
3338
var documentationXML: String?
3439

40+
/// The documentation as it is spelled in
41+
var documentation: String?
42+
3543
/// The refactor actions available at this position.
3644
var refactorActions: [SemanticRefactorCommand]? = nil
3745

3846
init(
3947
_ symbolInfo: SymbolDetails,
4048
annotatedDeclaration: String?,
41-
documentationXML: String?
49+
documentationXML: String?,
50+
documentation: String?
4251
) {
4352
self.symbolInfo = symbolInfo
4453
self.annotatedDeclaration = annotatedDeclaration
4554
self.documentationXML = documentationXML
55+
self.documentation = documentation
4656
}
4757

4858
init?(
@@ -79,7 +89,8 @@ struct CursorInfo {
7989
receiverUsrs: dict[keys.receivers]?.compactMap { $0[keys.usr] as String? } ?? []
8090
),
8191
annotatedDeclaration: dict[keys.annotatedDecl],
82-
documentationXML: dict[keys.docFullAsXML]
92+
documentationXML: dict[keys.docFullAsXML],
93+
documentation: dict[keys.docComment]
8394
)
8495
}
8596
}

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,16 @@ extension SwiftLanguageServer {
597597
}
598598

599599
var result = escapeNameMarkdown(name)
600-
if let doc = cursorInfo.documentationXML {
600+
if let documentation = cursorInfo.documentation {
601+
if let annotatedDeclaration = cursorInfo.annotatedDeclaration {
602+
let markdownDecl =
603+
orLog("Convert XML declaration to Markdown") {
604+
try xmlDocumentationToMarkdown(annotatedDeclaration)
605+
} ?? annotatedDeclaration
606+
result += "\n\(markdownDecl)"
607+
}
608+
result += documentation
609+
} else if let doc = cursorInfo.documentationXML {
601610
result += """
602611
603612
\(orLog("Convert XML to Markdown") { try xmlDocumentationToMarkdown(doc) } ?? doc)

0 commit comments

Comments
 (0)