Skip to content

Commit 6306675

Browse files
use a helper document in cursorInfo()
1 parent cf63bde commit 6306675

14 files changed

+80
-36
lines changed

Sources/BuildSystemIntegration/FileBuildSettings.swift

+10-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,15 @@ package struct FileBuildSettings: Equatable, Sendable {
5555
///
5656
/// This patches the arguments by searching for the argument corresponding to
5757
/// `originalFile` and replacing it.
58-
func patching(newFile: DocumentURI, originalFile: DocumentURI) -> FileBuildSettings {
58+
package func patching(newFile: DocumentURI, originalFile: DocumentURI) -> FileBuildSettings {
59+
return patching(newFile: newFile.pseudoPath, originalFile: originalFile)
60+
}
61+
62+
/// Return arguments suitable for use by `newFile`.
63+
///
64+
/// This patches the arguments by searching for the argument corresponding to
65+
/// `originalFile` and replacing it.
66+
package func patching(newFile: String, originalFile: DocumentURI) -> FileBuildSettings {
5967
var arguments = self.compilerArguments
6068
// URL.lastPathComponent is only set for file URLs but we want to also infer a file extension for non-file URLs like
6169
// untitled:file.cpp
@@ -66,7 +74,7 @@ package struct FileBuildSettings: Equatable, Sendable {
6674
// the file system.
6775
$0.hasSuffix(basename) && originalFile.pseudoPath.hasSuffix($0)
6876
}) {
69-
arguments[index] = newFile.pseudoPath
77+
arguments[index] = newFile
7078
// The `-x<lang>` flag needs to be before the possible `-c <header file>`
7179
// argument in order for Clang to respect it. If there is a pre-existing `-x`
7280
// flag though, Clang will honor that one instead since it comes after.

Sources/DocCDocumentation/DocCDocumentationManager.swift

-6
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,15 @@ package struct DocCDocumentationManager: Sendable {
151151
package func renderDocCDocumentation(
152152
symbolUSR: String? = nil,
153153
symbolGraph: String? = nil,
154-
overrideDocComments: [String]? = nil,
155154
markupFile: String? = nil,
156155
tutorialFile: String? = nil,
157156
moduleName: String?,
158157
catalogURL: URL?
159158
) async throws -> DoccDocumentationResponse {
160159
// Make inputs consumable by DocC
161160
var externalIDsToConvert: [String]? = nil
162-
var overridingDocumentationComments = [String: [String]]()
163161
if let symbolUSR {
164162
externalIDsToConvert = [symbolUSR]
165-
if let overrideDocComments {
166-
overridingDocumentationComments[symbolUSR] = overrideDocComments
167-
}
168163
}
169164
var symbolGraphs: [Data] = []
170165
if let symbolGraphData = symbolGraph?.data(using: .utf8) {
@@ -200,7 +195,6 @@ package struct DocCDocumentationManager: Sendable {
200195
documentationBundleDisplayName: moduleName ?? "Unknown",
201196
documentationBundleIdentifier: "unknown",
202197
symbolGraphs: symbolGraphs,
203-
overridingDocumentationComments: overridingDocumentationComments,
204198
emitSymbolSourceFileURIs: false,
205199
markupFiles: markupFiles,
206200
tutorialFiles: tutorialFiles,

Sources/SourceKitLSP/Documentation/DoccDocumentationHandler.swift

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if canImport(DocCDocumentation)
14+
import BuildSystemIntegration
1415
import DocCDocumentation
1516
import Foundation
1617
@preconcurrency import IndexStoreDB

Sources/SourceKitLSP/Rename.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ extension SwiftLanguageService {
355355
let req = sourcekitd.dictionary([
356356
keys.request: sourcekitd.requests.nameTranslation,
357357
keys.sourceFile: snapshot.uri.pseudoPath,
358-
keys.compilerArgs: await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: false)?.compilerArgs
358+
keys.compilerArgs: await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: false)?.compilerArgs
359359
as [SKDRequestValue]?,
360360
keys.offset: snapshot.utf8Offset(of: snapshot.position(of: symbolLocation)),
361361
keys.nameKind: sourcekitd.values.nameSwift,
@@ -407,7 +407,7 @@ extension SwiftLanguageService {
407407
let req = sourcekitd.dictionary([
408408
keys.request: sourcekitd.requests.nameTranslation,
409409
keys.sourceFile: snapshot.uri.pseudoPath,
410-
keys.compilerArgs: await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: false)?.compilerArgs
410+
keys.compilerArgs: await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: false)?.compilerArgs
411411
as [SKDRequestValue]?,
412412
keys.offset: snapshot.utf8Offset(of: snapshot.position(of: symbolLocation)),
413413
keys.nameKind: sourcekitd.values.nameObjc,

Sources/SourceKitLSP/Swift/CodeCompletion.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ extension SwiftLanguageService {
2323
let completionPos = await adjustPositionToStartOfIdentifier(req.position, in: snapshot)
2424
let filterText = String(snapshot.text[snapshot.index(of: completionPos)..<snapshot.index(of: req.position)])
2525

26-
let buildSettings = await buildSettings(for: snapshot.uri, fallbackAfterTimeout: false)
26+
let compileCommand = await compileCommand(for: snapshot.uri, fallbackAfterTimeout: false)
2727

2828
let inferredIndentationWidth = BasicFormat.inferIndentation(of: await syntaxTreeManager.syntaxTree(for: snapshot))
2929

@@ -34,7 +34,7 @@ extension SwiftLanguageService {
3434
indentationWidth: inferredIndentationWidth,
3535
completionPosition: completionPos,
3636
cursorPosition: req.position,
37-
compileCommand: buildSettings,
37+
compileCommand: compileCommand,
3838
clientCapabilities: capabilityRegistry.clientCapabilities,
3939
filterText: filterText
4040
)

Sources/SourceKitLSP/Swift/CursorInfo.swift

+40-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import BuildSystemIntegration
1314
import Csourcekitd
1415
import LanguageServerProtocol
1516
import SKLogging
@@ -121,6 +122,29 @@ extension CursorInfoError: CustomStringConvertible {
121122
}
122123

123124
extension SwiftLanguageService {
125+
fileprivate func openHelperDocument(_ snapshot: DocumentSnapshot) async throws -> String {
126+
let helperDocumentName = "/CursorInfo/" + snapshot.uri.pseudoPath
127+
let skreq = sourcekitd.dictionary([
128+
keys.request: self.requests.editorOpen,
129+
keys.name: helperDocumentName,
130+
keys.sourceText: snapshot.text,
131+
keys.syntacticOnly: 1,
132+
])
133+
_ = try await sendSourcekitdRequest(skreq, fileContents: snapshot.text)
134+
return helperDocumentName
135+
}
136+
137+
fileprivate func closeHelperDocument(_ helperDocumentName: String, _ snapshot: DocumentSnapshot) async {
138+
let skreq = sourcekitd.dictionary([
139+
keys.request: requests.editorClose,
140+
keys.name: helperDocumentName,
141+
keys.cancelBuilds: 0,
142+
])
143+
_ = await orLog("Close helper document for cursor info") {
144+
try await sendSourcekitdRequest(skreq, fileContents: snapshot.text)
145+
}
146+
}
147+
124148
/// Provides detailed information about a symbol under the cursor, if any.
125149
///
126150
/// Wraps the information returned by sourcekitd's `cursor_info` request, such as symbol name,
@@ -142,6 +166,20 @@ extension SwiftLanguageService {
142166
let documentManager = try self.documentManager
143167
let snapshot = try await self.latestSnapshotOrDisk(for: uri)
144168

169+
// Open a helper document so that we:
170+
// a) inform sourcekitd of the most recent contents of the file
171+
// b) don't have sourcekitd read from disk if the file isn't open in the client
172+
let helperDocument = try await openHelperDocument(snapshot)
173+
defer {
174+
Task { await closeHelperDocument(helperDocument, snapshot) }
175+
}
176+
// We also need to adjust the compile command to build the helper file
177+
var compilerArgs: [String]? = nil
178+
let buildSettings = await self.buildSettings(for: uri, fallbackAfterTimeout: fallbackSettingsAfterTimeout)
179+
if let buildSettings = buildSettings?.patching(newFile: helperDocument, originalFile: snapshot.uri) {
180+
compilerArgs = SwiftCompileCommand(buildSettings).compilerArgs
181+
}
182+
145183
let offsetRange = snapshot.utf8OffsetRange(of: range)
146184

147185
let keys = self.keys
@@ -151,11 +189,10 @@ extension SwiftLanguageService {
151189
keys.cancelOnSubsequentRequest: 0,
152190
keys.offset: offsetRange.lowerBound,
153191
keys.length: offsetRange.upperBound != offsetRange.lowerBound ? offsetRange.count : nil,
154-
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
192+
keys.sourceFile: helperDocument,
155193
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
156194
keys.retrieveSymbolGraph: includeSymbolGraph ? 1 : 0,
157-
keys.compilerArgs: await self.buildSettings(for: uri, fallbackAfterTimeout: fallbackSettingsAfterTimeout)?
158-
.compilerArgs as [SKDRequestValue]?,
195+
keys.compilerArgs: compilerArgs as [SKDRequestValue]?,
159196
])
160197

161198
appendAdditionalParameters?(skreq)

Sources/SourceKitLSP/Swift/DoccDocumentation.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if canImport(DocCDocumentation)
14+
import BuildSystemIntegration
1415
import DocCDocumentation
1516
import Foundation
1617
package import LanguageServerProtocol
@@ -75,7 +76,6 @@ extension SwiftLanguageService {
7576
return try await documentationManager.renderDocCDocumentation(
7677
symbolUSR: symbolUSR,
7778
symbolGraph: symbolGraph,
78-
overrideDocComments: nearestDocumentableSymbol.documentationComments,
7979
markupFile: markupExtensionFile,
8080
moduleName: moduleName,
8181
catalogURL: catalogURL

Sources/SourceKitLSP/Swift/GeneratedInterfaceManager.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ actor GeneratedInterfaceManager {
119119
keys.groupName: document.groupName,
120120
keys.name: document.sourcekitdDocumentName,
121121
keys.synthesizedExtension: 1,
122-
keys.compilerArgs: await swiftLanguageService.buildSettings(for: try document.uri, fallbackAfterTimeout: false)?
122+
keys.compilerArgs: await swiftLanguageService.compileCommand(for: try document.uri, fallbackAfterTimeout: false)?
123123
.compilerArgs as [SKDRequestValue]?,
124124
])
125125

Sources/SourceKitLSP/Swift/MacroExpansion.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,16 @@ actor MacroExpansionManager {
8888
}
8989

9090
let snapshot = try await swiftLanguageService.latestSnapshot(for: uri)
91-
let buildSettings = await swiftLanguageService.buildSettings(for: uri, fallbackAfterTimeout: false)
91+
let compileCommand = await swiftLanguageService.compileCommand(for: uri, fallbackAfterTimeout: false)
9292

9393
if let cacheEntry = cache.first(where: {
94-
$0.snapshotID == snapshot.id && $0.range == range && $0.buildSettings == buildSettings
94+
$0.snapshotID == snapshot.id && $0.range == range && $0.buildSettings == compileCommand
9595
}) {
9696
return cacheEntry.value
9797
}
98-
let macroExpansions = try await macroExpansionsImpl(in: snapshot, at: range, buildSettings: buildSettings)
98+
let macroExpansions = try await macroExpansionsImpl(in: snapshot, at: range, buildSettings: compileCommand)
9999
cache.insert(
100-
CacheEntry(snapshot: snapshot, range: range, buildSettings: buildSettings, value: macroExpansions),
100+
CacheEntry(snapshot: snapshot, range: range, buildSettings: compileCommand, value: macroExpansions),
101101
at: 0
102102
)
103103

Sources/SourceKitLSP/Swift/RefactoringResponse.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ extension SwiftLanguageService {
127127
keys.column: utf8Column + 1,
128128
keys.length: snapshot.utf8OffsetRange(of: refactorCommand.positionRange).count,
129129
keys.actionUID: self.sourcekitd.api.uid_get_from_cstr(refactorCommand.actionString)!,
130-
keys.compilerArgs: await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: true)?.compilerArgs
130+
keys.compilerArgs: await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: true)?.compilerArgs
131131
as [SKDRequestValue]?,
132132
])
133133

Sources/SourceKitLSP/Swift/RelatedIdentifiers.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ extension SwiftLanguageService {
7373
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
7474
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
7575
keys.includeNonEditableBaseNames: includeNonEditableBaseNames ? 1 : 0,
76-
keys.compilerArgs: await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: true)?.compilerArgs
76+
keys.compilerArgs: await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: true)?.compilerArgs
7777
as [SKDRequestValue]?,
7878
])
7979

Sources/SourceKitLSP/Swift/SemanticTokens.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import SwiftSyntax
2020
extension SwiftLanguageService {
2121
/// Requests the semantic highlighting tokens for the given snapshot from sourcekitd.
2222
private func semanticHighlightingTokens(for snapshot: DocumentSnapshot) async throws -> SyntaxHighlightingTokens? {
23-
guard let buildSettings = await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: false),
24-
!buildSettings.isFallback
23+
guard let compileCommand = await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: false),
24+
!compileCommand.isFallback
2525
else {
2626
return nil
2727
}
@@ -30,7 +30,7 @@ extension SwiftLanguageService {
3030
keys.request: requests.semanticTokens,
3131
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
3232
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
33-
keys.compilerArgs: buildSettings.compilerArgs as [SKDRequestValue],
33+
keys.compilerArgs: compileCommand.compilerArgs as [SKDRequestValue],
3434
])
3535

3636
let dict = try await sendSourcekitdRequest(skreq, fileContents: snapshot.text)

Sources/SourceKitLSP/Swift/SwiftLanguageService.swift

+13-9
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ package actor SwiftLanguageService: LanguageService, Sendable {
297297
}
298298
}
299299

300-
func buildSettings(for document: DocumentURI, fallbackAfterTimeout: Bool) async -> SwiftCompileCommand? {
300+
func buildSettings(for document: DocumentURI, fallbackAfterTimeout: Bool) async -> FileBuildSettings? {
301301
let buildSettingsFile = document.buildSettingsFile
302302

303303
guard let sourceKitLSPServer else {
@@ -307,11 +307,15 @@ package actor SwiftLanguageService: LanguageService, Sendable {
307307
guard let workspace = await sourceKitLSPServer.workspaceForDocument(uri: buildSettingsFile) else {
308308
return nil
309309
}
310-
if let settings = await workspace.buildSystemManager.buildSettingsInferredFromMainFile(
310+
return await workspace.buildSystemManager.buildSettingsInferredFromMainFile(
311311
for: buildSettingsFile,
312312
language: .swift,
313313
fallbackAfterTimeout: fallbackAfterTimeout
314-
) {
314+
)
315+
}
316+
317+
func compileCommand(for document: DocumentURI, fallbackAfterTimeout: Bool) async -> SwiftCompileCommand? {
318+
if let settings = await self.buildSettings(for: document, fallbackAfterTimeout: fallbackAfterTimeout) {
315319
return SwiftCompileCommand(settings)
316320
} else {
317321
return nil
@@ -471,7 +475,7 @@ extension SwiftLanguageService {
471475
try await self.sendSourcekitdRequest(closeReq, fileContents: nil)
472476
}
473477

474-
let buildSettings = await buildSettings(for: snapshot.uri, fallbackAfterTimeout: true)
478+
let buildSettings = await compileCommand(for: snapshot.uri, fallbackAfterTimeout: true)
475479
let openReq = openDocumentSourcekitdRequest(
476480
snapshot: snapshot,
477481
compileCommand: buildSettings
@@ -493,7 +497,7 @@ extension SwiftLanguageService {
493497
guard (try? documentManager.openDocuments.contains(uri)) ?? false else {
494498
return
495499
}
496-
let newBuildSettings = await self.buildSettings(for: uri, fallbackAfterTimeout: false)
500+
let newBuildSettings = await self.compileCommand(for: uri, fallbackAfterTimeout: false)
497501
if newBuildSettings != buildSettingsForOpenFiles[uri] {
498502
// Close and re-open the document internally to inform sourcekitd to update the compile command. At the moment
499503
// there's no better way to do this.
@@ -563,7 +567,7 @@ extension SwiftLanguageService {
563567
cancelInFlightPublishDiagnosticsTask(for: notification.textDocument.uri)
564568
await diagnosticReportManager.removeItemsFromCache(with: notification.textDocument.uri)
565569

566-
let buildSettings = await self.buildSettings(for: snapshot.uri, fallbackAfterTimeout: true)
570+
let buildSettings = await self.compileCommand(for: snapshot.uri, fallbackAfterTimeout: true)
567571
buildSettingsForOpenFiles[snapshot.uri] = buildSettings
568572

569573
let req = openDocumentSourcekitdRequest(snapshot: snapshot, compileCommand: buildSettings)
@@ -626,7 +630,7 @@ extension SwiftLanguageService {
626630
}
627631
do {
628632
let snapshot = try await self.latestSnapshot(for: document)
629-
let buildSettings = await self.buildSettings(for: document, fallbackAfterTimeout: false)
633+
let buildSettings = await self.compileCommand(for: document, fallbackAfterTimeout: false)
630634
let diagnosticReport = try await self.diagnosticReportManager.diagnosticReport(
631635
for: snapshot,
632636
buildSettings: buildSettings
@@ -976,7 +980,7 @@ extension SwiftLanguageService {
976980

977981
func retrieveQuickFixCodeActions(_ params: CodeActionRequest) async throws -> [CodeAction] {
978982
let snapshot = try await self.latestSnapshot(for: params.textDocument.uri)
979-
let buildSettings = await self.buildSettings(for: params.textDocument.uri, fallbackAfterTimeout: true)
983+
let buildSettings = await self.compileCommand(for: params.textDocument.uri, fallbackAfterTimeout: true)
980984
let diagnosticReport = try await self.diagnosticReportManager.diagnosticReport(
981985
for: snapshot,
982986
buildSettings: buildSettings
@@ -1084,7 +1088,7 @@ extension SwiftLanguageService {
10841088
req.textDocument.uri.buildSettingsFile
10851089
)
10861090
let snapshot = try await self.latestSnapshot(for: req.textDocument.uri)
1087-
let buildSettings = await self.buildSettings(for: req.textDocument.uri, fallbackAfterTimeout: false)
1091+
let buildSettings = await self.compileCommand(for: req.textDocument.uri, fallbackAfterTimeout: false)
10881092
try Task.checkCancellation()
10891093
let diagnosticReport = try await self.diagnosticReportManager.diagnosticReport(
10901094
for: snapshot,

Sources/SourceKitLSP/Swift/VariableTypeInfo.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ extension SwiftLanguageService {
8989
keys.request: requests.collectVariableType,
9090
keys.sourceFile: snapshot.uri.sourcekitdSourceFile,
9191
keys.primaryFile: snapshot.uri.primaryFile?.pseudoPath,
92-
keys.compilerArgs: await self.buildSettings(for: uri, fallbackAfterTimeout: false)?.compilerArgs
92+
keys.compilerArgs: await self.compileCommand(for: uri, fallbackAfterTimeout: false)?.compilerArgs
9393
as [SKDRequestValue]?,
9494
])
9595

0 commit comments

Comments
 (0)