Skip to content

Commit e003e54

Browse files
authored
Merge pull request swiftlang#155 from rmaz/settingsreq
Add SourceKitOptions build server request
2 parents 6b1a81b + f2b5f2c commit e003e54

File tree

7 files changed

+145
-2
lines changed

7 files changed

+145
-2
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 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+
import LanguageServerProtocol
13+
14+
/// The SourceKitOptions request is sent from the client to the server
15+
/// to query for the list of compiler options necessary to compile this file.
16+
public struct SourceKitOptions: RequestType, Hashable {
17+
public static let method: String = "textDocument/sourceKitOptions"
18+
public typealias Response = SourceKitOptionsResult
19+
20+
/// The URL of the document to get options for
21+
public var uri: URL
22+
23+
public init(uri: URL) {
24+
self.uri = uri
25+
}
26+
}
27+
28+
public struct SourceKitOptionsResult: ResponseType, Hashable {
29+
/// The compiler options required for the requested file.
30+
public var options: [String]
31+
32+
/// The working directory for the compile command.
33+
public var workingDirectory: String?
34+
}

Sources/BuildServerProtocol/Messages.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ import LanguageServerProtocol
1414
fileprivate let requestTypes: [_RequestType.Type] = [
1515
InitializeBuild.self,
1616
ShutdownBuild.self,
17+
SourceKitOptions.self,
1718
]
1819

1920
fileprivate let notificationTypes: [NotificationType.Type] = [
20-
InitializedBuildNotification.self,
2121
ExitBuildNotification.self,
22+
InitializedBuildNotification.self,
2223
]
2324

2425
public let bspRegistry = MessageRegistry(requests: requestTypes, notifications: notificationTypes)

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ extension BuildServerBuildSystem: BuildSystem {
137137
}
138138

139139
public func settings(for url: URL, _ language: Language) -> FileBuildSettings? {
140-
// TODO: add `textDocument/sourceKitOptions` request and response
140+
if let response = try? self.buildServer?.sendSync(SourceKitOptions(uri: url)) {
141+
return FileBuildSettings(compilerArguments: response.options, workingDirectory: response.workingDirectory)
142+
}
141143
return nil
142144
}
143145

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "client name",
3+
"version": "10",
4+
"bspVersion": "2.0",
5+
"languages": ["a", "b"],
6+
"argv": ["server.py"]
7+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python
2+
3+
import json
4+
import os
5+
import sys
6+
7+
8+
while True:
9+
line = sys.stdin.readline()
10+
if len(line) == 0:
11+
break
12+
13+
assert line.startswith('Content-Length:')
14+
length = int(line[len('Content-Length:'):])
15+
sys.stdin.readline()
16+
message = json.loads(sys.stdin.read(length))
17+
18+
response = None
19+
if message["method"] == "build/initialize":
20+
response = {
21+
"jsonrpc": "2.0",
22+
"id": message["id"],
23+
"result": {
24+
"displayName": "test server",
25+
"version": "0.1",
26+
"bspVersion": "2.0",
27+
"rootUri": "blah",
28+
"capabilities": {"languageIds": ["a", "b"]},
29+
"data": {
30+
"indexStorePath": "some/index/store/path"
31+
}
32+
}
33+
}
34+
elif message["method"] == "build/initialized":
35+
continue
36+
elif message["method"] == "build/shutdown":
37+
response = {
38+
"jsonrpc": "2.0",
39+
"id": message["id"],
40+
"result": None
41+
}
42+
elif message["method"] == "build/exit":
43+
break
44+
elif message["method"] == "textDocument/sourceKitOptions":
45+
file_path = message["params"]["uri"][len("file://"):]
46+
if file_path.endswith(".missing"):
47+
# simulate error response for unhandled file
48+
response = {
49+
"jsonrpc": "2.0",
50+
"id": message["id"],
51+
"error": {
52+
"code": -32600,
53+
"message": "unknown file {}".format(file_path),
54+
}
55+
}
56+
else:
57+
response = {
58+
"jsonrpc": "2.0",
59+
"id": message["id"],
60+
"result": {
61+
"options": ["-a", "-b"],
62+
"workingDirectory": os.path.dirname(file_path),
63+
}
64+
}
65+
# ignore other notifications
66+
elif "id" in message:
67+
response = {
68+
"jsonrpc": "2.0",
69+
"id": message["id"],
70+
"error": {
71+
"code": -32600,
72+
"message": "unhandled method {}".format(message["method"]),
73+
}
74+
}
75+
76+
if response:
77+
responseStr = json.dumps(response)
78+
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
79+
sys.stdout.flush()

Tests/SKCoreTests/BuildServerBuildSystemTests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import XCTest
1313
import SKCore
1414
import TSCBasic
1515
import LanguageServerProtocol
16+
import Foundation
1617

1718
final class BuildServerBuildSystemTests: XCTestCase {
1819

@@ -27,4 +28,22 @@ final class BuildServerBuildSystemTests: XCTestCase {
2728
XCTAssertEqual(buildSystem!.indexStorePath, AbsolutePath("some/index/store/path", relativeTo: root))
2829
}
2930

31+
func testSettings() {
32+
let root = AbsolutePath(
33+
inputsDirectory().appendingPathComponent(testDirectoryName, isDirectory: true).path)
34+
let buildFolder = AbsolutePath(NSTemporaryDirectory())
35+
let buildSystem = try? BuildServerBuildSystem(projectRoot: root, buildFolder: buildFolder)
36+
XCTAssertNotNil(buildSystem)
37+
38+
// test settings with a response
39+
let fileURL = URL(fileURLWithPath: "/path/to/some/file.swift")
40+
let settings = buildSystem?.settings(for: fileURL, Language.swift)
41+
XCTAssertEqual(settings?.compilerArguments, ["-a", "-b"])
42+
XCTAssertEqual(settings?.workingDirectory, fileURL.deletingLastPathComponent().path)
43+
44+
// test error
45+
let missingFileURL = URL(fileURLWithPath: "/path/to/some/missingfile.missing")
46+
XCTAssertNil(buildSystem?.settings(for: missingFileURL, Language.swift))
47+
}
48+
3049
}

Tests/SKCoreTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ extension BuildServerBuildSystemTests {
77
// to regenerate.
88
static let __allTests__BuildServerBuildSystemTests = [
99
("testServerInitialize", testServerInitialize),
10+
("testSettings", testSettings),
1011
]
1112
}
1213

0 commit comments

Comments
 (0)