Skip to content

Commit 6237f58

Browse files
committed
Implement PeekMacroRequest for VS Code and handle ShowDocumentRequest better for other editors
1 parent 1f4fc12 commit 6237f58

File tree

2 files changed

+112
-12
lines changed

2 files changed

+112
-12
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
public struct PeekMacroRequest: RequestType {
14+
public static let method: String = "sourcekit-lsp/peekMacro"
15+
public typealias Response = PeekMacroResponse
16+
17+
public var macroExpansion: MacroExpansion
18+
public var peekLocation: Position
19+
20+
public init(macroExpansion: MacroExpansion, peekLocation: Position) {
21+
self.macroExpansion = macroExpansion
22+
self.peekLocation = peekLocation
23+
}
24+
}
25+
26+
public struct MacroExpansion: Codable, Sendable {
27+
public var expansionURIs: [DocumentURI]
28+
29+
public init(expansionURIs: [DocumentURI]) {
30+
self.expansionURIs = expansionURIs
31+
}
32+
}
33+
34+
public struct PeekMacroResponse: ResponseType {
35+
public var success: Bool
36+
public var failureReason: String?
37+
}
38+

Sources/SourceKitLSP/Swift/MacroExpansion.swift

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ import SourceKitD
2121
/// request, such as the necessary macro expansion edits.
2222
struct MacroExpansion: RefactoringResponse {
2323
/// The title of the refactoring action.
24-
var title: String
24+
let title: String
2525

2626
/// The URI of the file where the macro is used
27-
var uri: DocumentURI
27+
let uri: DocumentURI
2828

2929
/// The resulting array of `RefactoringEdit` of a semantic refactoring request
30-
var edits: [RefactoringEdit]
30+
let edits: [RefactoringEdit]
31+
32+
var expansionURIs: [DocumentURI]?
3133

3234
init(title: String, uri: DocumentURI, refactoringEdits: [RefactoringEdit]) {
3335
self.title = title
@@ -40,6 +42,8 @@ struct MacroExpansion: RefactoringResponse {
4042

4143
return refactoringEdit
4244
}
45+
46+
expansionURIs = nil
4347
}
4448
}
4549

@@ -69,6 +73,9 @@ extension SwiftLanguageService {
6973

7074
let expansion = try await self.refactoring(expandMacroCommand)
7175

76+
var completeExpansionFileContent = ""
77+
var completeExpansionFilePath = self.generatedMacroExpansionsPath
78+
var macroExpansionFilePaths = [URL]()
7279
for macroEdit in expansion.edits {
7380
if let bufferName = macroEdit.bufferName {
7481
// buffer name without ".swift"
@@ -79,6 +86,9 @@ extension SwiftLanguageService {
7986

8087
let macroExpansionBufferDirectoryURL = self.generatedMacroExpansionsPath
8188
.appendingPathComponent(macroExpansionBufferDirectoryName)
89+
completeExpansionFilePath = completeExpansionFilePath
90+
.appendingPathComponent(macroExpansionBufferDirectoryName)
91+
8292
do {
8393
try FileManager.default.createDirectory(
8494
at: macroExpansionBufferDirectoryURL,
@@ -111,19 +121,71 @@ extension SwiftLanguageService {
111121
)
112122
}
113123

114-
Task {
115-
let req = ShowDocumentRequest(uri: DocumentURI(macroExpansionFilePath))
124+
macroExpansionFilePaths.append(macroExpansionFilePath)
116125

117-
let response = await orLog("Sending ShowDocumentRequest to Client") {
118-
try await sourceKitLSPServer.sendRequestToClient(req)
119-
}
126+
let editContent = "// \(sourceFileURL.lastPathComponent) @ \(macroEdit.range.lowerBound.line + 1):\(macroEdit.range.lowerBound.utf16index + 1) - \(macroEdit.range.upperBound.line + 1):\(macroEdit.range.upperBound.utf16index + 1)\n\(macroEdit.newText)\n"
127+
completeExpansionFileContent += editContent
128+
} else if !macroEdit.newText.isEmpty {
129+
logger.fault("Unable to retrieve some parts of macro expansion")
130+
}
131+
}
120132

121-
if let response, !response.success {
122-
logger.error("client refused to show document for \(expansion.title, privacy: .public)")
133+
do {
134+
try FileManager.default.createDirectory(
135+
at: completeExpansionFilePath,
136+
withIntermediateDirectories: true
137+
)
138+
} catch {
139+
throw ResponseError.unknown(
140+
"Failed to create directory for complete macro expansion at path: \(completeExpansionFilePath.path)"
141+
)
142+
}
143+
144+
completeExpansionFilePath =
145+
completeExpansionFilePath.appendingPathComponent(sourceFileURL.lastPathComponent)
146+
do {
147+
try completeExpansionFileContent.write(to: completeExpansionFilePath, atomically: true, encoding: .utf8)
148+
} catch {
149+
throw ResponseError.unknown(
150+
"Unable to write complete macro expansion to file path: \"\(completeExpansionFilePath.path)\""
151+
)
152+
}
153+
154+
let completeMacroExpansionFilePath = completeExpansionFilePath
155+
let macroExpansion = LanguageServerProtocol.MacroExpansion(
156+
expansionURIs: macroExpansionFilePaths.map {
157+
return DocumentURI($0)
158+
}
159+
)
160+
161+
let peekDocument = true
162+
if peekDocument {
163+
Task {
164+
let req = PeekMacroRequest(macroExpansion: macroExpansion, peekLocation: expandMacroCommand.positionRange.lowerBound)
165+
166+
let response = await orLog("Sending PeekMacroRequest to Client") {
167+
try await sourceKitLSPServer.sendRequestToClient(req)
168+
}
169+
170+
if let response, !response.success {
171+
if let failureReason = response.failureReason {
172+
logger.error("client refused to peek macro, reason: \(failureReason)")
173+
} else {
174+
logger.error("client refused to peek macro")
123175
}
124176
}
125-
} else if !macroEdit.newText.isEmpty {
126-
logger.fault("Unable to retrieve some parts of macro expansion")
177+
}
178+
} else {
179+
Task {
180+
let req = ShowDocumentRequest(uri: DocumentURI(completeMacroExpansionFilePath))
181+
182+
let response = await orLog("Sending ShowDocumentRequest to Client") {
183+
try await sourceKitLSPServer.sendRequestToClient(req)
184+
}
185+
186+
if let response, !response.success {
187+
logger.error("client refused to show document for macro expansion")
188+
}
127189
}
128190
}
129191

0 commit comments

Comments
 (0)