Skip to content

Commit 9e771aa

Browse files
committed
Merge branch 'main' into 6.0/merge-main-2024-05-23
2 parents 25a53c1 + 3300c77 commit 9e771aa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1230
-277
lines changed

.devcontainer/Readme.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Using VSCode devcontainers
2+
3+
Official tutorial: https://code.visualstudio.com/docs/devcontainers/tutorial
4+
5+
### Recommended Settings for macOS
6+
7+
Some of these are defaults:
8+
- Recommended settings for macOS (some of these are defaults):
9+
- General:
10+
- "Choose file sharing implementation for your containers": VirtioFS (better IO performance)
11+
- Resources:
12+
- CPUs: Allow docker to use most or all of your CPUs
13+
- Memory: Allow docker to use most or all of your memory

.devcontainer/default/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM swiftlang/swift:nightly-main-jammy
2+
3+
RUN \
4+
# Disable apt interactive prompts for this RUN command
5+
export DEBIAN_FRONTEND="noninteractive" && \
6+
# Update apt package list
7+
apt-get update && \
8+
# Install sourcekit-lsp dependencies
9+
apt-get install -y libsqlite3-dev libncurses5-dev python3
10+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Reference: https://containers.dev/implementors/json_reference/
2+
{
3+
"name": "SourceKit-LSP",
4+
"dockerFile": "Dockerfile",
5+
6+
// Allow the processes in the container to attach a debugger
7+
"capAdd": [ "SYS_PTRACE" ],
8+
"securityOpt": [ "seccomp=unconfined" ],
9+
10+
"mounts": [
11+
// Use a named volume for the build products for optimal performance (https://code.visualstudio.com/remote/advancedcontainers/improve-performance#_use-a-targeted-named-volume)
12+
"source=${localWorkspaceFolderBasename}-build,target=${containerWorkspaceFolder}/.build,type=volume",
13+
// Do the same for experimental background indexing
14+
"source=${localWorkspaceFolderBasename}-index-build,target=${containerWorkspaceFolder}/.index-build,type=volume"
15+
],
16+
"customizations": {
17+
"vscode": {
18+
"extensions": [
19+
"sswg.swift-lang"
20+
],
21+
"settings": {
22+
"lldb.library": "/usr/lib/liblldb.so",
23+
"swift.buildArguments": [
24+
"-Xcxx",
25+
"-I/usr/lib/swift",
26+
"-Xcxx",
27+
"-I/usr/lib/swift/Block"
28+
]
29+
}
30+
}
31+
}
32+
}

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
default.profraw
33
Package.resolved
44
/.build
5-
/.index-build
6-
/.linux-build
5+
/.*-build
76
/Packages
87
/*.xcodeproj
98
/*.sublime-project

Package.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,12 @@ let package = Package(
7474
.target(
7575
name: "Diagnose",
7676
dependencies: [
77+
"InProcessClient",
7778
"LSPLogging",
78-
"SourceKitD",
7979
"SKCore",
80+
"SKSupport",
81+
"SourceKitD",
82+
"SourceKitLSP",
8083
.product(name: "ArgumentParser", package: "swift-argument-parser"),
8184
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
8285
.product(name: "SwiftSyntax", package: "swift-syntax"),
@@ -99,6 +102,20 @@ let package = Package(
99102
]
100103
),
101104

105+
// MARK: InProcessClient
106+
107+
.target(
108+
name: "InProcessClient",
109+
dependencies: [
110+
"CAtomics",
111+
"LanguageServerProtocol",
112+
"LSPLogging",
113+
"SKCore",
114+
"SourceKitLSP",
115+
],
116+
exclude: ["CMakeLists.txt"]
117+
),
118+
102119
// MARK: LanguageServerProtocol
103120
// The core LSP types, suitable for any LSP implementation.
104121
.target(
@@ -162,6 +179,7 @@ let package = Package(
162179
.target(
163180
name: "LSPTestSupport",
164181
dependencies: [
182+
"InProcessClient",
165183
"LanguageServerProtocol",
166184
"LanguageServerProtocolJSONRPC",
167185
"SKSupport",
@@ -278,6 +296,7 @@ let package = Package(
278296
name: "SKTestSupport",
279297
dependencies: [
280298
"CSKTestSupport",
299+
"InProcessClient",
281300
"LanguageServerProtocol",
282301
"LSPTestSupport",
283302
"LSPLogging",

Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_subdirectory(BuildServerProtocol)
22
add_subdirectory(CAtomics)
33
add_subdirectory(Csourcekitd)
44
add_subdirectory(Diagnose)
5+
add_subdirectory(InProcessClient)
56
add_subdirectory(LanguageServerProtocol)
67
add_subdirectory(LanguageServerProtocolJSONRPC)
78
add_subdirectory(LSPLogging)

Sources/Diagnose/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_library(Diagnose STATIC
22
CommandConfiguration+Sendable.swift
33
CommandLineArgumentsReducer.swift
44
DiagnoseCommand.swift
5+
IndexCommand.swift
56
MergeSwiftFiles.swift
67
OSLogScraper.swift
78
ReduceCommand.swift
@@ -23,6 +24,8 @@ set_target_properties(Diagnose PROPERTIES
2324
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
2425

2526
target_link_libraries(Diagnose PUBLIC
27+
InProcessClient
28+
LSPLogging
2629
SKCore
2730
SourceKitD
2831
ArgumentParser

Sources/Diagnose/IndexCommand.swift

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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+
import ArgumentParser
14+
import Foundation
15+
import InProcessClient
16+
import LanguageServerProtocol
17+
import SKCore
18+
import SKSupport
19+
import SourceKitLSP
20+
21+
import struct TSCBasic.AbsolutePath
22+
import class TSCBasic.Process
23+
import var TSCBasic.stderrStream
24+
import class TSCUtility.PercentProgressAnimation
25+
26+
private actor IndexLogMessageHandler: MessageHandler {
27+
var hasSeenError: Bool = false
28+
29+
/// Queue to ensure that we don't have two interleaving `print` calls.
30+
let queue = AsyncQueue<Serial>()
31+
32+
nonisolated func handle(_ notification: some NotificationType) {
33+
if let notification = notification as? LogMessageNotification {
34+
queue.async {
35+
await self.handle(notification)
36+
}
37+
}
38+
}
39+
40+
func handle(_ notification: LogMessageNotification) {
41+
self.hasSeenError = notification.type == .warning
42+
print(notification.message)
43+
}
44+
45+
nonisolated func handle<Request: RequestType>(
46+
_ request: Request,
47+
id: RequestID,
48+
reply: @escaping @Sendable (LSPResult<Request.Response>) -> Void
49+
) {
50+
reply(.failure(.methodNotFound(Request.method)))
51+
}
52+
53+
}
54+
55+
public struct IndexCommand: AsyncParsableCommand {
56+
public static let configuration: CommandConfiguration = CommandConfiguration(
57+
commandName: "index",
58+
abstract: "Index a project and print all the processes executed for it as well as their outputs",
59+
shouldDisplay: false
60+
)
61+
62+
@Option(
63+
name: .customLong("toolchain"),
64+
help: """
65+
The toolchain used to reduce the sourcekitd issue. \
66+
If not specified, the toolchain is found in the same way that sourcekit-lsp finds it
67+
"""
68+
)
69+
var toolchainOverride: String?
70+
71+
@Option(help: "The path to the project that should be indexed")
72+
var project: String
73+
74+
public init() {}
75+
76+
public func run() async throws {
77+
var serverOptions = SourceKitLSPServer.Options()
78+
serverOptions.indexOptions.enableBackgroundIndexing = true
79+
80+
let installPath =
81+
if let toolchainOverride, let toolchain = Toolchain(try AbsolutePath(validating: toolchainOverride)) {
82+
toolchain.path
83+
} else {
84+
try AbsolutePath(validating: Bundle.main.bundlePath)
85+
}
86+
87+
let messageHandler = IndexLogMessageHandler()
88+
let inProcessClient = try await InProcessSourceKitLSPClient(
89+
toolchainRegistry: ToolchainRegistry(installPath: installPath),
90+
serverOptions: serverOptions,
91+
workspaceFolders: [WorkspaceFolder(uri: DocumentURI(URL(fileURLWithPath: project)))],
92+
messageHandler: messageHandler
93+
)
94+
let start = ContinuousClock.now
95+
_ = try await inProcessClient.send(PollIndexRequest())
96+
print("Indexing finished in \(start.duration(to: .now))")
97+
if await messageHandler.hasSeenError {
98+
throw ExitCode(1)
99+
}
100+
}
101+
}
102+
103+
fileprivate extension SourceKitLSPServer {
104+
func handle<R: RequestType>(_ request: R, requestID: RequestID) async throws -> R.Response {
105+
return try await withCheckedThrowingContinuation { continuation in
106+
self.handle(request, id: requestID) { result in
107+
continuation.resume(with: result)
108+
}
109+
}
110+
}
111+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_library(InProcessClient STATIC
2+
InProcessSourceKitLSPClient.swift
3+
LocalConnection.swift)
4+
5+
set_target_properties(InProcessClient PROPERTIES
6+
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
7+
8+
target_link_libraries(InProcessClient PUBLIC
9+
CAtomics
10+
LanguageServerProtocol
11+
LSPLogging
12+
SKCore
13+
SourceKitLSP
14+
)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
import CAtomics
14+
import LanguageServerProtocol
15+
import SKCore
16+
import SourceKitLSP
17+
18+
/// Launches a `SourceKitLSPServer` in-process and allows sending messages to it.
19+
public final class InProcessSourceKitLSPClient: Sendable {
20+
private let server: SourceKitLSPServer
21+
22+
/// `nonisolated(unsafe)` if fine because `nextRequestID` is atomic.
23+
private nonisolated(unsafe) var nextRequestID = AtomicUInt32(initialValue: 0)
24+
25+
/// Create a new `SourceKitLSPServer`. An `InitializeRequest` is automatically sent to the server.
26+
///
27+
/// `messageHandler` handles notifications and requests sent from the SourceKit-LSP server to the client.
28+
public init(
29+
toolchainRegistry: ToolchainRegistry,
30+
serverOptions: SourceKitLSPServer.Options = SourceKitLSPServer.Options(),
31+
capabilities: ClientCapabilities = ClientCapabilities(),
32+
workspaceFolders: [WorkspaceFolder],
33+
messageHandler: any MessageHandler
34+
) async throws {
35+
let serverToClientConnection = LocalConnection(name: "client")
36+
self.server = SourceKitLSPServer(
37+
client: serverToClientConnection,
38+
toolchainRegistry: toolchainRegistry,
39+
options: serverOptions,
40+
onExit: {
41+
serverToClientConnection.close()
42+
}
43+
)
44+
serverToClientConnection.start(handler: messageHandler)
45+
_ = try await self.send(
46+
InitializeRequest(
47+
processId: nil,
48+
rootPath: nil,
49+
rootURI: nil,
50+
initializationOptions: nil,
51+
capabilities: capabilities,
52+
trace: .off,
53+
workspaceFolders: workspaceFolders
54+
)
55+
)
56+
}
57+
58+
/// Send the request to `server` and return the request result.
59+
///
60+
/// - Important: Because this is an async function, Swift concurrency makes no guarantees about the execution ordering
61+
/// of this request with regard to other requests to the server. If execution of requests in a particular order is
62+
/// necessary and the response of the request is not awaited, use the version of the function that takes a
63+
/// completion handler
64+
public func send<R: RequestType>(_ request: R) async throws -> R.Response {
65+
return try await withCheckedThrowingContinuation { continuation in
66+
self.send(request) {
67+
continuation.resume(with: $0)
68+
}
69+
}
70+
}
71+
72+
/// Send the request to `server` and return the request result via a completion handler.
73+
public func send<R: RequestType>(_ request: R, reply: @Sendable @escaping (LSPResult<R.Response>) -> Void) {
74+
server.handle(request, id: .number(Int(nextRequestID.fetchAndIncrement())), reply: reply)
75+
}
76+
77+
/// Send the notification to `server`.
78+
public func send(_ notification: some NotificationType) {
79+
server.handle(notification)
80+
}
81+
}

Sources/LSPLogging/NonDarwinLogging.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,5 +394,6 @@ public struct NonDarwinSignposter: Sendable {
394394

395395
public func emitEvent(_ name: StaticString, id: NonDarwinSignpostID, _ message: NonDarwinLogMessage = "") {}
396396

397-
public func endInterval(_ name: StaticString, _ state: NonDarwinSignpostIntervalState, _ message: StaticString) {}
397+
public func endInterval(_ name: StaticString, _ state: NonDarwinSignpostIntervalState, _ message: StaticString = "") {
398+
}
398399
}

Sources/LSPTestSupport/TestJSONRPCConnection.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import InProcessClient
1314
import LanguageServerProtocol
1415
import LanguageServerProtocolJSONRPC
1516
import SKSupport

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,10 @@ extension BuildServerBuildSystem: BuildSystem {
289289
return nil
290290
}
291291

292-
public func prepare(targets: [ConfiguredTarget]) async throws {
292+
public func prepare(
293+
targets: [ConfiguredTarget],
294+
indexProcessDidProduceResult: @Sendable (IndexProcessResult) -> Void
295+
) async throws {
293296
throw PrepareNotSupportedError()
294297
}
295298

Sources/SKCore/BuildSystem.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ public protocol BuildSystem: AnyObject, Sendable {
158158

159159
/// Prepare the given targets for indexing and semantic functionality. This should build all swift modules of target
160160
/// dependencies.
161-
func prepare(targets: [ConfiguredTarget]) async throws
161+
func prepare(
162+
targets: [ConfiguredTarget],
163+
indexProcessDidProduceResult: @Sendable (IndexProcessResult) -> Void
164+
) async throws
162165

163166
/// If the build system has knowledge about the language that this document should be compiled in, return it.
164167
///

0 commit comments

Comments
 (0)