Skip to content

Commit 87a5b67

Browse files
committed
Address Review Comments
1 parent be00bd2 commit 87a5b67

15 files changed

+192
-196
lines changed

Sources/LanguageServerProtocol/Requests/ShowDocumentRequest.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
/// Request from the server to the client to show a document on the client side.
14-
///
15-
/// - Parameters:
16-
/// - uri: The uri to show.
17-
/// - external: An optional boolean indicates to show the resource in an external program.
18-
/// - takeFocus: An optional boolean to indicate whether the editor showing the document should take focus or not.
19-
/// - selection: An optional selection range if the document is a text document.
13+
/// Request from the server to the client to show a document on the client
14+
/// side.
2015
public struct ShowDocumentRequest: RequestType {
2116
public static let method: String = "window/showDocument"
2217
public typealias Response = ShowDocumentResponse

Sources/SKSupport/FileSystem.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,20 @@ extension AbsolutePath {
3131
}
3232
}
3333

34-
/// The directory to write generated module interfaces
34+
/// The default directory to write generated files
35+
/// `<TEMPORARY_DIRECTORY>/sourcekit-lsp/`
36+
public var defaultDirectoryForGeneratedFiles: AbsolutePath {
37+
try! AbsolutePath(validating: NSTemporaryDirectory()).appending(component: "sourcekit-lsp")
38+
}
39+
40+
/// The default directory to write generated module interfaces
41+
/// `<TEMPORARY_DIRECTORY>/sourcekit-lsp/GeneratedInterfaces/`
3542
public var defaultDirectoryForGeneratedInterfaces: AbsolutePath {
36-
try! AbsolutePath(validating: NSTemporaryDirectory()).appending(component: "GeneratedInterfaces")
43+
defaultDirectoryForGeneratedFiles.appending(component: "GeneratedInterfaces")
3744
}
3845

39-
/// The directory to write generated macro expansions
46+
/// The default directory to write generated macro expansions
47+
/// `<TEMPORARY_DIRECTORY>/sourcekit-lsp/GeneratedMacroExpansions/`
4048
public var defaultDirectoryForGeneratedMacroExpansions: AbsolutePath {
41-
try! AbsolutePath(validating: NSTemporaryDirectory()).appending(component: "GeneratedMacroExpansions")
49+
defaultDirectoryForGeneratedFiles.appending(component: "GeneratedMacroExpansions")
4250
}

Sources/SourceKitLSP/SourceKitLSPServer+Options.swift

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,20 @@ extension SourceKitLSPServer {
3838
/// Options for code-completion.
3939
public var completionOptions: SKCompletionOptions
4040

41-
/// Override the default directory where generated interfaces will be stored
42-
public var generatedInterfacesPath: AbsolutePath
41+
/// Override the default directory where generated files will be stored
42+
public var generatedFilesPath: AbsolutePath
4343

44-
/// Override the default directory where generated macro expansions will be stored
45-
public var generatedMacroExpansionsPath: AbsolutePath
44+
/// Path to the generated interfaces
45+
/// `<generatedFilesPath>/GeneratedInterfaces/`
46+
public var generatedInterfacesPath: AbsolutePath {
47+
generatedFilesPath.appending(component: "GeneratedInterfaces")
48+
}
49+
50+
/// Path to the generated macro expansions
51+
/// `<generatedFilesPath>`/GeneratedMacroExpansions/
52+
public var generatedMacroExpansionsPath: AbsolutePath {
53+
generatedFilesPath.appending(component: "GeneratedMacroExpansions")
54+
}
4655

4756
/// The time that `SwiftLanguageService` should wait after an edit before starting to compute diagnostics and
4857
/// sending a `PublishDiagnosticsNotification`.
@@ -62,8 +71,7 @@ extension SourceKitLSPServer {
6271
compilationDatabaseSearchPaths: [RelativePath] = [],
6372
indexOptions: IndexOptions = .init(),
6473
completionOptions: SKCompletionOptions = .init(),
65-
generatedInterfacesPath: AbsolutePath = defaultDirectoryForGeneratedInterfaces,
66-
generatedMacroExpansionsPath: AbsolutePath = defaultDirectoryForGeneratedMacroExpansions,
74+
generatedFilesPath: AbsolutePath = defaultDirectoryForGeneratedFiles,
6775
swiftPublishDiagnosticsDebounceDuration: TimeInterval = 2, /* 2s */
6876
experimentalFeatures: Set<ExperimentalFeature> = [],
6977
indexTestHooks: IndexTestHooks = IndexTestHooks()
@@ -73,8 +81,7 @@ extension SourceKitLSPServer {
7381
self.compilationDatabaseSearchPaths = compilationDatabaseSearchPaths
7482
self.indexOptions = indexOptions
7583
self.completionOptions = completionOptions
76-
self.generatedInterfacesPath = generatedInterfacesPath
77-
self.generatedMacroExpansionsPath = generatedMacroExpansionsPath
84+
self.generatedFilesPath = generatedFilesPath
7885
self.swiftPublishDiagnosticsDebounceDuration = swiftPublishDiagnosticsDebounceDuration
7986
self.experimentalFeatures = experimentalFeatures
8087
self.indexTestHooks = indexTestHooks

Sources/SourceKitLSP/Swift/ExpandMacroCommand.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import LanguageServerProtocol
1414
import SourceKitD
1515

1616
public struct ExpandMacroCommand: RefactorCommand {
17+
typealias Response = MacroExpansion
18+
1719
public static let identifier: String = "expand.macro.command"
1820

1921
/// The name of this refactoring action.
@@ -55,8 +57,12 @@ public struct ExpandMacroCommand: RefactorCommand {
5557
)
5658
}
5759

58-
public init(title: String, actionString: String, positionRange: Range<Position>, textDocument: TextDocumentIdentifier)
59-
{
60+
public init(
61+
title: String,
62+
actionString: String,
63+
positionRange: Range<Position>,
64+
textDocument: TextDocumentIdentifier
65+
) {
6066
self.title = title
6167
self.actionString = actionString
6268
self.positionRange = positionRange

Sources/SourceKitLSP/Swift/MacroExpansion.swift

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import SourceKitD
1616

1717
/// Detailed information about the result of a macro expansion operation.
1818
///
19-
/// Wraps the information returned by sourcekitd's `semantic_refactoring` request, such as the necessary macro expansion edits.
20-
struct MacroExpansion: Refactoring {
21-
19+
/// Wraps the information returned by sourcekitd's `semantic_refactoring`
20+
/// request, such as the necessary macro expansion edits.
21+
struct MacroExpansion: RefactoringResponse {
2222
/// The title of the refactoring action.
2323
var title: String
2424

@@ -31,61 +31,65 @@ struct MacroExpansion: Refactoring {
3131
init(title: String, uri: DocumentURI, refactoringEdits: [RefactoringEdit]) {
3232
self.title = title
3333
self.uri = uri
34-
self.edits = refactoringEdits.map { refactoringEdit in
35-
MacroExpansionEdit(
34+
self.edits = refactoringEdits.compactMap { refactoringEdit in
35+
36+
guard let bufferName = refactoringEdit.bufferName else {
37+
logger.error("Unable to retrieve some parts of the expansion")
38+
return nil
39+
}
40+
41+
return MacroExpansionEdit(
3642
range: refactoringEdit.startPosition..<refactoringEdit.endPosition,
3743
newText: refactoringEdit.newText,
38-
bufferName: refactoringEdit.bufferName ?? "" // TODO: handle bufferName if nil
44+
bufferName: bufferName
3945
)
4046
}
4147
}
42-
4348
}
4449

4550
extension SwiftLanguageService {
4651
/// Handles the `ExpandMacroCommand`.
4752
///
48-
/// Makes request to sourcekitd and wraps the result into a `MacroExpansion` and then makes `ShowDocumentRequest` to the client side for each expansion to be displayed.
53+
/// Makes request to sourcekitd and wraps the result into a `MacroExpansion`
54+
/// and then makes `ShowDocumentRequest` to the client side for each
55+
/// expansion to be displayed.
4956
///
5057
/// - Parameters:
51-
/// - refactorCommand: The expand macro `SwiftCommand` that triggered this request.
58+
/// - expandMacroCommand: The `ExpandMacroCommand` that triggered this
59+
/// request.
5260
///
5361
/// - Returns:
54-
/// - an `[MacroExpansionEdit]` with the necessary edits and buffer name as a `LSPAny`
62+
/// - an `[MacroExpansionEdit]` with the necessary edits and buffer name as
63+
/// a `LSPAny`
5564
func expandMacro(
56-
_ refactorCommand: any SwiftCommand
65+
_ expandMacroCommand: ExpandMacroCommand
5766
) async throws -> LSPAny {
5867
guard let sourceKitLSPServer else {
59-
// `SourceKitLSPServer` has been destructed. We are tearing down the language
60-
// server. Nothing left to do.
68+
// `SourceKitLSPServer` has been destructed. We are tearing down the
69+
// language server. Nothing left to do.
6170
throw ResponseError.unknown("Connection to the editor closed")
6271
}
6372

64-
guard let refactorCommand = refactorCommand as? ExpandMacroCommand else {
65-
throw ResponseError.unknown("refactorCommand is not a ExpandMacroCommand")
66-
}
67-
68-
let expansion = try await self.refactoring(refactorCommand, MacroExpansion.self)
73+
let expansion = try await self.refactoring(expandMacroCommand)
6974

7075
for macroEdit in expansion.edits {
7176
let macroExpansionFilePath = self.generatedMacroExpansionsPath.appendingPathComponent(
7277
macroEdit.bufferName
7378
)
7479
let macroExpansionDocURI = DocumentURI(macroExpansionFilePath)
75-
if let _ = try? self.documentManager.latestSnapshot(macroExpansionDocURI) {
76-
continue
77-
}
7880

7981
do {
8082
try macroEdit.newText.write(to: macroExpansionFilePath, atomically: true, encoding: String.Encoding.utf8)
8183
} catch {
8284
throw ResponseError.unknown("Unable to write macro expansion to file path: \"\(macroExpansionFilePath.path)\"")
8385
}
8486

85-
let req = ShowDocumentRequest(uri: macroExpansionDocURI, selection: macroEdit.range)
86-
let response = try await sourceKitLSPServer.sendRequestToClient(req)
87-
if !response.success {
88-
logger.error("client refused to show document for \(expansion.title, privacy: .public)!")
87+
Task {
88+
let req = ShowDocumentRequest(uri: macroExpansionDocURI, selection: macroEdit.range)
89+
let response = try await sourceKitLSPServer.sendRequestToClient(req)
90+
if !response.success {
91+
logger.error("client refused to show document for \(expansion.title, privacy: .public)!")
92+
}
8993
}
9094
}
9195

Sources/SourceKitLSP/Swift/MacroExpansionEdit.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
import LanguageServerProtocol
1414
import SourceKitD
1515

16-
/// Represents a macro expansion as an edit. Notionally, a subclass of `TextEdit`
17-
public struct MacroExpansionEdit: ResponseType, Hashable, Sendable {
16+
/// Represents a macro expansion as an edit. Notionally, a subclass of
17+
/// `TextEdit`
18+
public struct MacroExpansionEdit: Hashable, Sendable, Codable {
1819
/// The range of text to be replaced.
1920
@CustomCodable<PositionRange>
2021
public var range: Range<Position>

Sources/SourceKitLSP/Swift/RefactorCommand.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@
1313
import LanguageServerProtocol
1414
import SourceKitD
1515

16-
/// A protocol to be utilised by all commands where underlies sourcekitd calls to perform semantic refactoring.
16+
/// A protocol to be utilised by all commands where underlies sourcekitd calls
17+
/// to perform semantic refactoring.
1718
protocol RefactorCommand: SwiftCommand {
1819

20+
/// The response type of the refactor command
21+
associatedtype Response: RefactoringResponse
22+
1923
/// The sourcekitd identifier of the refactoring action.
2024
var actionString: String { get set }
2125

Sources/SourceKitLSP/Swift/Refactoring.swift

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,31 @@
1313
import LanguageServerProtocol
1414
import SourceKitD
1515

16-
protocol Refactoring {
16+
protocol RefactoringResponse {
17+
1718
init(title: String, uri: DocumentURI, refactoringEdits: [RefactoringEdit])
1819

19-
/// Create an instance of `Refactoring` from a sourcekitd semantic refactoring response dictionary, if possible. Passes the response to `init(title: String, uri: DocumentURI, refactoringEdits: [RefactoringEdit])` in a neat manner
20+
/// Create an instance of `RefactoringResponse` from a sourcekitd semantic
21+
/// refactoring response dictionary, if possible. Passes the response to
22+
/// `init(title: String, uri: DocumentURI, refactoringEdits:
23+
/// [RefactoringEdit])` in a neat manner
2024
init?(_ title: String, _ dict: SKDResponseDictionary, _ snapshot: DocumentSnapshot, _ keys: sourcekitd_api_keys)
2125
}
2226

2327
typealias RefactoringEdit = (startPosition: Position, endPosition: Position, newText: String, bufferName: String?)
2428

25-
extension Refactoring {
26-
/// Create an instance of `Refactoring` from a sourcekitd semantic refactoring response dictionary, if possible. Passes the response to `init(title: String, uri: DocumentURI, refactoringEdits: [RefactoringEdit])` in a neat manner
29+
extension RefactoringResponse {
30+
31+
/// Create an instance of `RefactoringResponse` from a sourcekitd semantic
32+
/// refactoring response dictionary, if possible. Passes the response to
33+
/// `init(title: String, uri: DocumentURI, refactoringEdits:
34+
/// [RefactoringEdit])` in a neat manner
2735
///
2836
/// - Parameters:
2937
/// - title: The title of the refactoring action.
3038
/// - dict: Response dictionary to extract information from.
31-
/// - url: The client URL that triggered the `semantic_refactoring` request.
39+
/// - snapshot: The snapshot that triggered the `semantic_refactoring`
40+
/// request.
3241
/// - keys: The sourcekitd key set to use for looking up into `dict`.
3342
init?(_ title: String, _ dict: SKDResponseDictionary, _ snapshot: DocumentSnapshot, _ keys: sourcekitd_api_keys) {
3443
guard let categorizedEdits: SKDResponseArray = dict[keys.categorizedEdits] else {
@@ -61,7 +70,8 @@ extension Refactoring {
6170
utf8Column: endColumn - 1
6271
)
6372
// Snippets are only supported in code completion.
64-
// Remove SourceKit placeholders in refactoring actions because they can't be represented in the editor properly.
73+
// Remove SourceKit placeholders in refactoring actions because they
74+
// can't be represented in the editor properly.
6575
let textWithSnippets = rewriteSourceKitPlaceholders(in: text, clientSupportsSnippets: false)
6676
refactoringEdits.append(
6777
(
@@ -83,16 +93,20 @@ extension Refactoring {
8393
}
8494

8595
extension SwiftLanguageService {
86-
/// Provides detailed information about the result of a specific refactoring operation.
96+
/// Provides detailed information about the result of a specific refactoring
97+
/// operation.
8798
///
88-
/// Wraps the information returned by sourcekitd's `semantic_refactoring` request, such as the necessary edits and placeholder locations.
99+
/// Wraps the information returned by sourcekitd's `semantic_refactoring`
100+
/// request, such as the necessary edits and placeholder locations.
89101
///
90102
/// - Parameters:
91103
/// - command: The semantic `RefactorCommand` that triggered this request.
92104
/// - responseType: The response type `T.Type` of the particular command
93105
/// - Returns:
94-
/// - The `Refactoring` as `T`
95-
func refactoring<T: Refactoring>(_ refactorCommand: any RefactorCommand, _ responseType: T.Type) async throws -> T {
106+
/// - The `RefactoringResponse` as `T`
107+
func refactoring<T: RefactorCommand>(_ refactorCommand: T) async throws
108+
-> T.Response
109+
{
96110
let keys = self.keys
97111

98112
let uri = refactorCommand.textDocument.uri
@@ -116,7 +130,7 @@ extension SwiftLanguageService {
116130
])
117131

118132
let dict = try await self.sourcekitd.send(skreq, fileContents: snapshot.text)
119-
guard let refactor = T(refactorCommand.title, dict, snapshot, self.keys) else {
133+
guard let refactor = T.Response(refactorCommand.title, dict, snapshot, self.keys) else {
120134
throw SemanticRefactoringError.noEditsNeeded(uri)
121135
}
122136
return refactor

Sources/SourceKitLSP/Swift/SemanticRefactorCommand.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1010
//
1111
//===----------------------------------------------------------------------===//
12+
1213
import LanguageServerProtocol
1314
import SourceKitD
1415

1516
public struct SemanticRefactorCommand: RefactorCommand {
17+
typealias Response = SemanticRefactoring
1618

1719
public static let identifier: String = "semantic.refactor.command"
1820

Sources/SourceKitLSP/Swift/SemanticRefactoring.swift

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import LSPLogging
21
//===----------------------------------------------------------------------===//
32
//
43
// This source file is part of the Swift.org open source project
@@ -10,13 +9,16 @@ import LSPLogging
109
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
1110
//
1211
//===----------------------------------------------------------------------===//
12+
13+
import LSPLogging
1314
import LanguageServerProtocol
1415
import SourceKitD
1516

1617
/// Detailed information about the result of a specific refactoring operation.
1718
///
18-
/// Wraps the information returned by sourcekitd's `semantic_refactoring` request, such as the necessary edits and placeholder locations.
19-
struct SemanticRefactoring: Refactoring {
19+
/// Wraps the information returned by sourcekitd's `semantic_refactoring`
20+
/// request, such as the necessary edits and placeholder locations.
21+
struct SemanticRefactoring: RefactoringResponse {
2022

2123
/// The title of the refactoring action.
2224
var title: String
@@ -61,27 +63,26 @@ extension SwiftLanguageService {
6163

6264
/// Handles the `SemanticRefactorCommand`.
6365
///
64-
/// Makes request to sourcekitd and wraps the result into a `SemanticRefactoring` and then makes an `ApplyEditRequest` to the client side for the actual refactoring.
66+
/// Makes request to sourcekitd and wraps the result into a
67+
/// `SemanticRefactoring` and then makes an `ApplyEditRequest` to the client
68+
/// side for the actual refactoring.
6569
///
6670
/// - Parameters:
67-
/// - refactorCommand: The semantic refactor `SwiftCommand` that triggered this request.
71+
/// - semanticRefactorCommand: The `SemanticRefactorCommand` that triggered
72+
/// this request.
6873
///
6974
/// - Returns:
7075
/// - a `WorkspaceEdit` with the necessary refactors as a `LSPAny`
7176
func semanticRefactoring(
72-
_ refactorCommand: any SwiftCommand
77+
_ semanticRefactorCommand: SemanticRefactorCommand
7378
) async throws -> LSPAny {
7479
guard let sourceKitLSPServer else {
75-
// `SourceKitLSPServer` has been destructed. We are tearing down the language
76-
// server. Nothing left to do.
80+
// `SourceKitLSPServer` has been destructed. We are tearing down the
81+
// language server. Nothing left to do.
7782
throw ResponseError.unknown("Connection to the editor closed")
7883
}
7984

80-
guard let refactorCommand = refactorCommand as? SemanticRefactorCommand else {
81-
throw ResponseError.unknown("refactorCommand is not a SemanticRefactorCommand")
82-
}
83-
84-
let semanticRefactor = try await self.refactoring(refactorCommand, SemanticRefactoring.self)
85+
let semanticRefactor = try await self.refactoring(semanticRefactorCommand)
8586

8687
let edit = semanticRefactor.edit
8788
let req = ApplyEditRequest(label: semanticRefactor.title, edit: edit)

0 commit comments

Comments
 (0)