Skip to content

Commit 97ef5f4

Browse files
authored
Merge pull request #1460 from ahoppen/generated-interface-improvements
A couple of improvements for generated interfaces
2 parents addfb9e + 2a0f8c7 commit 97ef5f4

File tree

8 files changed

+59
-58
lines changed

8 files changed

+59
-58
lines changed

Sources/LanguageServerProtocol/Messages.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public let builtinRequests: [_RequestType.Type] = [
5858
InlineValueRequest.self,
5959
LinkedEditingRangeRequest.self,
6060
MonikersRequest.self,
61-
OpenInterfaceRequest.self,
61+
OpenGeneratedInterfaceRequest.self,
6262
PollIndexRequest.self,
6363
PrepareRenameRequest.self,
6464
ReferencesRequest.self,

Sources/LanguageServerProtocol/Requests/OpenInterfaceRequest.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
/// Request a textual interface of a module to display in the IDE.
13+
/// Request a generated interface of a module to display in the IDE.
1414
/// **(LSP Extension)**
15-
public struct OpenInterfaceRequest: TextDocumentRequest, Hashable {
15+
public struct OpenGeneratedInterfaceRequest: TextDocumentRequest, Hashable {
1616
public static let method: String = "textDocument/openInterface"
17-
public typealias Response = InterfaceDetails?
17+
public typealias Response = GeneratedInterfaceDetails?
1818

1919
/// The document whose compiler arguments should be used to generate the interface.
2020
public var textDocument: TextDocumentIdentifier
@@ -45,7 +45,7 @@ public struct OpenInterfaceRequest: TextDocumentRequest, Hashable {
4545
}
4646

4747
/// The textual output of a module interface.
48-
public struct InterfaceDetails: ResponseType, Hashable {
48+
public struct GeneratedInterfaceDetails: ResponseType, Hashable {
4949

5050
public var uri: DocumentURI
5151
public var position: Position?

Sources/SourceKitLSP/Clang/ClangLanguageService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ extension ClangLanguageService {
582582
return try await forwardRequestToClangd(req)
583583
}
584584

585-
func openInterface(_ request: OpenInterfaceRequest) async throws -> InterfaceDetails? {
585+
func openGeneratedInterface(_ request: OpenGeneratedInterfaceRequest) async throws -> GeneratedInterfaceDetails? {
586586
throw ResponseError.unknown("unsupported method")
587587
}
588588

Sources/SourceKitLSP/LanguageService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public protocol LanguageService: AnyObject, Sendable {
146146
func completion(_ req: CompletionRequest) async throws -> CompletionList
147147
func hover(_ req: HoverRequest) async throws -> HoverResponse?
148148
func symbolInfo(_ request: SymbolInfoRequest) async throws -> [SymbolDetails]
149-
func openInterface(_ request: OpenInterfaceRequest) async throws -> InterfaceDetails?
149+
func openGeneratedInterface(_ request: OpenGeneratedInterfaceRequest) async throws -> GeneratedInterfaceDetails?
150150

151151
/// - Note: Only called as a fallback if the definition could not be found in the index.
152152
func definition(_ request: DefinitionRequest) async throws -> LocationsOrLocationLinksResponse?

Sources/SourceKitLSP/SourceKitLSPServer.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,8 @@ extension SourceKitLSPServer: MessageHandler {
711711
await self.handleRequest(for: request, requestHandler: self.completion)
712712
case let request as RequestAndReply<HoverRequest>:
713713
await self.handleRequest(for: request, requestHandler: self.hover)
714-
case let request as RequestAndReply<OpenInterfaceRequest>:
715-
await self.handleRequest(for: request, requestHandler: self.openInterface)
714+
case let request as RequestAndReply<OpenGeneratedInterfaceRequest>:
715+
await self.handleRequest(for: request, requestHandler: self.openGeneratedInterface)
716716
case let request as RequestAndReply<DeclarationRequest>:
717717
await self.handleRequest(for: request, requestHandler: self.declaration)
718718
case let request as RequestAndReply<DefinitionRequest>:
@@ -1466,12 +1466,12 @@ extension SourceKitLSPServer {
14661466
return try await languageService.hover(req)
14671467
}
14681468

1469-
func openInterface(
1470-
_ req: OpenInterfaceRequest,
1469+
func openGeneratedInterface(
1470+
_ req: OpenGeneratedInterfaceRequest,
14711471
workspace: Workspace,
14721472
languageService: LanguageService
1473-
) async throws -> InterfaceDetails? {
1474-
return try await languageService.openInterface(req)
1473+
) async throws -> GeneratedInterfaceDetails? {
1474+
return try await languageService.openGeneratedInterface(req)
14751475
}
14761476

14771477
/// Find all symbols in the workspace that include a string in their name.
@@ -1872,13 +1872,13 @@ extension SourceKitLSPServer {
18721872
originatorUri: DocumentURI,
18731873
languageService: LanguageService
18741874
) async throws -> Location {
1875-
let openInterface = OpenInterfaceRequest(
1875+
let openInterface = OpenGeneratedInterfaceRequest(
18761876
textDocument: TextDocumentIdentifier(originatorUri),
18771877
name: moduleName,
18781878
groupName: groupName,
18791879
symbolUSR: symbolUSR
18801880
)
1881-
guard let interfaceDetails = try await languageService.openInterface(openInterface) else {
1881+
guard let interfaceDetails = try await languageService.openGeneratedInterface(openInterface) else {
18821882
throw ResponseError.unknown("Could not generate Swift Interface for \(moduleName)")
18831883
}
18841884
let position = interfaceDetails.position ?? Position(line: 0, utf16index: 0)

Sources/SourceKitLSP/Swift/OpenInterface.swift

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,82 +16,83 @@ import LanguageServerProtocol
1616
import SKSupport
1717
import SourceKitD
1818

19-
struct InterfaceInfo {
19+
struct GeneratedInterfaceInfo {
2020
var contents: String
2121
}
2222

2323
extension SwiftLanguageService {
24-
public func openInterface(_ request: OpenInterfaceRequest) async throws -> InterfaceDetails? {
25-
let uri = request.textDocument.uri
26-
let moduleName = request.moduleName
24+
public func openGeneratedInterface(
25+
_ request: OpenGeneratedInterfaceRequest
26+
) async throws -> GeneratedInterfaceDetails? {
2727
let name = request.name
2828
let symbol = request.symbolUSR
2929
let interfaceFilePath = self.generatedInterfacesPath.appendingPathComponent("\(name).swiftinterface")
3030
let interfaceDocURI = DocumentURI(interfaceFilePath)
3131
// has interface already been generated
3232
if let snapshot = try? self.documentManager.latestSnapshot(interfaceDocURI) {
33-
return await self.interfaceDetails(request: request, uri: interfaceDocURI, snapshot: snapshot, symbol: symbol)
33+
return await self.generatedInterfaceDetails(
34+
request: request,
35+
uri: interfaceDocURI,
36+
snapshot: snapshot,
37+
symbol: symbol
38+
)
3439
} else {
35-
// generate interface
36-
let interfaceInfo = try await self.openInterface(
40+
let interfaceInfo = try await self.generatedInterfaceInfo(request: request, interfaceURI: interfaceDocURI)
41+
try interfaceInfo.contents.write(to: interfaceFilePath, atomically: true, encoding: String.Encoding.utf8)
42+
let snapshot = DocumentSnapshot(
43+
uri: interfaceDocURI,
44+
language: .swift,
45+
version: 0,
46+
lineTable: LineTable(interfaceInfo.contents)
47+
)
48+
let result = await self.generatedInterfaceDetails(
3749
request: request,
38-
uri: uri,
39-
name: moduleName,
40-
interfaceURI: interfaceDocURI
50+
uri: interfaceDocURI,
51+
snapshot: snapshot,
52+
symbol: symbol
4153
)
42-
do {
43-
// write to file
44-
try interfaceInfo.contents.write(to: interfaceFilePath, atomically: true, encoding: String.Encoding.utf8)
45-
// store snapshot
46-
let snapshot = try self.documentManager.open(
47-
interfaceDocURI,
48-
language: .swift,
49-
version: 0,
50-
text: interfaceInfo.contents
51-
)
52-
return await self.interfaceDetails(request: request, uri: interfaceDocURI, snapshot: snapshot, symbol: symbol)
53-
} catch {
54-
throw ResponseError.unknown(error.localizedDescription)
54+
_ = await orLog("Closing generated interface") {
55+
try await self.sourcekitd.send(closeDocumentSourcekitdRequest(uri: interfaceDocURI), fileContents: nil)
5556
}
57+
return result
5658
}
5759
}
5860

5961
/// Open the Swift interface for a module.
6062
///
6163
/// - Parameters:
62-
/// - request: The OpenInterfaceRequest.
63-
/// - uri: The document whose compiler arguments should be used to generate the interface.
64-
/// - name: The name of the module whose interface should be generated.
64+
/// - request: The OpenGeneratedInterfaceRequest.
6565
/// - interfaceURI: The file where the generated interface should be written.
66-
private func openInterface(
67-
request: OpenInterfaceRequest,
68-
uri: DocumentURI,
69-
name: String,
66+
///
67+
/// - Important: This opens a document with name `interfaceURI.pseudoPath` in sourcekitd. The caller is responsible
68+
/// for ensuring that the document will eventually get closed in sourcekitd again.
69+
private func generatedInterfaceInfo(
70+
request: OpenGeneratedInterfaceRequest,
7071
interfaceURI: DocumentURI
71-
) async throws -> InterfaceInfo {
72+
) async throws -> GeneratedInterfaceInfo {
7273
let keys = self.keys
7374
let skreq = sourcekitd.dictionary([
7475
keys.request: requests.editorOpenInterface,
75-
keys.moduleName: name,
76+
keys.moduleName: request.moduleName,
7677
keys.groupName: request.groupName,
7778
keys.name: interfaceURI.pseudoPath,
7879
keys.synthesizedExtension: 1,
79-
keys.compilerArgs: await self.buildSettings(for: uri)?.compilerArgs as [SKDRequestValue]?,
80+
keys.compilerArgs: await self.buildSettings(for: request.textDocument.uri)?.compilerArgs as [SKDRequestValue]?,
8081
])
8182

8283
let dict = try await self.sourcekitd.send(skreq, fileContents: nil)
83-
return InterfaceInfo(contents: dict[keys.sourceText] ?? "")
84+
return GeneratedInterfaceInfo(contents: dict[keys.sourceText] ?? "")
8485
}
8586

86-
private func interfaceDetails(
87-
request: OpenInterfaceRequest,
87+
private func generatedInterfaceDetails(
88+
request: OpenGeneratedInterfaceRequest,
8889
uri: DocumentURI,
8990
snapshot: DocumentSnapshot,
9091
symbol: String?
91-
) async -> InterfaceDetails {
92+
) async -> GeneratedInterfaceDetails {
9293
do {
9394
guard let symbol = symbol else {
94-
return InterfaceDetails(uri: uri, position: nil)
95+
return GeneratedInterfaceDetails(uri: uri, position: nil)
9596
}
9697
let keys = self.keys
9798
let skreq = sourcekitd.dictionary([
@@ -102,12 +103,12 @@ extension SwiftLanguageService {
102103

103104
let dict = try await self.sourcekitd.send(skreq, fileContents: snapshot.text)
104105
if let offset: Int = dict[keys.offset] {
105-
return InterfaceDetails(uri: uri, position: snapshot.positionOf(utf8Offset: offset))
106+
return GeneratedInterfaceDetails(uri: uri, position: snapshot.positionOf(utf8Offset: offset))
106107
} else {
107-
return InterfaceDetails(uri: uri, position: nil)
108+
return GeneratedInterfaceDetails(uri: uri, position: nil)
108109
}
109110
} catch {
110-
return InterfaceDetails(uri: uri, position: nil)
111+
return GeneratedInterfaceDetails(uri: uri, position: nil)
111112
}
112113
}
113114
}

Sources/SourceKitLSP/Swift/SwiftLanguageService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ extension SwiftLanguageService {
406406
])
407407
}
408408

409-
private func closeDocumentSourcekitdRequest(uri: DocumentURI) -> SKDRequestDictionary {
409+
func closeDocumentSourcekitdRequest(uri: DocumentURI) -> SKDRequestDictionary {
410410
return sourcekitd.dictionary([
411411
keys.request: requests.editorClose,
412412
keys.name: uri.pseudoPath,

Tests/SourceKitLSPTests/SwiftInterfaceTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ final class SwiftInterfaceTests: XCTestCase {
7373
)
7474

7575
let (mainUri, _) = try project.openDocument("main.swift")
76-
let openInterface = OpenInterfaceRequest(
76+
let openInterface = OpenGeneratedInterfaceRequest(
7777
textDocument: TextDocumentIdentifier(mainUri),
7878
name: "MyLibrary",
7979
groupName: nil,

0 commit comments

Comments
 (0)