Skip to content

Commit 480bb0c

Browse files
authored
Merge pull request #1592 from ahoppen/6.0/no-lazy-prepartion
[6.0] Add option to allow SourceKit-LSP to prepare a target without lazy type checking
2 parents d849096 + 1780d06 commit 480bb0c

File tree

6 files changed

+88
-13
lines changed

6 files changed

+88
-13
lines changed

Documentation/Configuration File.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,7 @@ The structure of the file is currently not guaranteed to be stable. Options may
3838
- `updateIndexStoreTimeout: int`: Number of seconds to wait for an update index store task to finish before killing it.
3939
- `defaultWorkspaceType: "buildserver"|"compdb"|"swiftpm"`: Overrides workspace type selection logic.
4040
- `generatedFilesPath: string`: Directory in which generated interfaces and macro expansions should be stored.
41+
- `backgroundIndexing: bool`: Explicitly enable or disable background indexing.
42+
- `backgroundPreparationMode: "build"|"noLazy"|"enabled"`: Determines how background indexing should prepare a target. Possible values are: `build`: Build a target to prepare it, `noLazy`: Prepare a target without generating object files but do not do lazy type checking and function body skipping, `enabled`: Prepare a target without generating object files and the like
4143
- `experimentalFeatures: string[]`: Experimental features to enable
4244
- `swiftPublishDiagnosticsDebounce`: The time that `SwiftLanguageService` should wait after an edit before starting to compute diagnostics and sending a `PublishDiagnosticsNotification`.

Documentation/Enable Experimental Background Indexing.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ Background indexing in SourceKit-LSP is available as an experimental feature. Th
44

55
## Set Up
66

7-
1. Install a `main` or `release/6.0` Swift Development Snapshot from https://www.swift.org/install.
7+
1. Install a `main` or `release/6.0` Swift Development Snapshot from https://www.swift.org/install or install the [Xcode 16 beta](https://developer.apple.com/xcode/).
88
2. Point your editor to the newly installed toolchain.
9-
- In VS Code on macOS this can be done by adding the following to your `settings.json`: `"swift.path": "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin"`
9+
- In VS Code on macOS this can be done by adding the following to your `settings.json`:
10+
- For open source toolchains `"swift.path": "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin"`
11+
- When installing the Xcode 16 beta `"swift.path": "/Applications/Xcode-beta.app/Library/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin"`
1012
- In VS Code on other platforms, you need to set the `swift.path` to the `usr/bin` directory of your toolchain’s install location.
1113
- Other editors likely also have a way to pick the Swift toolchain, the exact steps vary by your setup.
1214
3. Enable the experimental `background-indexing` feature.
@@ -16,14 +18,10 @@ Background indexing in SourceKit-LSP is available as an experimental feature. Th
1618
## Known issues
1719

1820
- Background Indexing is only supported for SwiftPM projects [#1269](https://github.com/swiftlang/sourcekit-lsp/issues/1269), [#1271](https://github.com/swiftlang/sourcekit-lsp/issues/1271)
19-
- If a module or one of its dependencies has a compilation error, it cannot be properly prepared for indexing because we are running a regular `swift build` to generate its modules [#1254](https://github.com/swiftlang/sourcekit-lsp/issues/1254) rdar://128683404
20-
- Workaround 1: Ensure that your files dependencies are in a buildable state to get an up-to-date index and proper cross-module functionality
21-
- Workaround 2: Enable the `swiftpm-prepare-for-indexing` experimental feature, which continues to build Swift module even in the presence of errors.
2221
- If you change a function in a way that changes its USR but keeps it API compatible (such as adding a defaulted parameter), references to it will be lost and not re-indexed automatically [#1264](https://github.com/swiftlang/sourcekit-lsp/issues/1264)
2322
- Workaround: Make some edit to the files that had references to re-index them
2423
- The index build is currently completely separate from the command line build generated using `swift build`. Building *does not* update the index (break your habits of always building!) [#1270](https://github.com/swiftlang/sourcekit-lsp/issues/1270)
25-
- The initial indexing might take 2-3x more time than a regular build [#1254](https://github.com/swiftlang/sourcekit-lsp/issues/1254), [#1262](https://github.com/swiftlang/sourcekit-lsp/issues/1262), [#1268](https://github.com/swiftlang/sourcekit-lsp/issues/1268)
26-
- Spurious re-indexing of ~10-20 source files when `swift build` writes a header to the build directory [rdar://128573306](rdar://128573306)
24+
- The initial indexing might take 2-3x more time than a regular build [#1262](https://github.com/swiftlang/sourcekit-lsp/issues/1262), [#1268](https://github.com/swiftlang/sourcekit-lsp/issues/1268)
2725

2826
## Filing issues
2927

Sources/SKCore/ExperimentalFeatures.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,5 @@
1313
/// An experimental feature that can be enabled by passing `--experimental-feature` to `sourcekit-lsp` on the command
1414
/// line. The raw value of this feature is how it is named on the command line.
1515
public enum ExperimentalFeature: String, Codable, Sendable, CaseIterable {
16-
/// Add `--experimental-prepare-for-indexing` to the `swift build` command run to prepare a target for indexing.
17-
case swiftpmPrepareForIndexing = "swiftpm-prepare-for-indexing"
16+
case dummy
1817
}

Sources/SKCore/SourceKitLSPOptions.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,19 @@ public struct SourceKitLSPOptions: Sendable, Codable {
178178
}
179179
}
180180

181+
public enum BackgroundPreparationMode: String {
182+
/// Build a target to prepare it
183+
case build
184+
185+
/// Prepare a target without generating object files but do not do lazy type checking.
186+
///
187+
/// This uses SwiftPM's `--experimental-prepare-for-indexing-no-lazy` flag.
188+
case noLazy
189+
190+
/// Prepare a target without generating object files.
191+
case enabled
192+
}
193+
181194
public var swiftPM: SwiftPMOptions
182195
public var compilationDatabase: CompilationDatabaseOptions
183196
public var fallbackBuildSystem: FallbackBuildSystemOptions
@@ -195,6 +208,15 @@ public struct SourceKitLSPOptions: Sendable, Codable {
195208
return backgroundIndexing ?? false
196209
}
197210

211+
public var backgroundPreparationMode: String?
212+
213+
public var backgroundPreparationModeOrDefault: BackgroundPreparationMode {
214+
if let backgroundPreparationMode, let parsed = BackgroundPreparationMode(rawValue: backgroundPreparationMode) {
215+
return parsed
216+
}
217+
return .build
218+
}
219+
198220
/// Experimental features that are enabled.
199221
public var experimentalFeatures: Set<ExperimentalFeature>? = nil
200222

@@ -250,6 +272,7 @@ public struct SourceKitLSPOptions: Sendable, Codable {
250272
defaultWorkspaceType: WorkspaceType? = nil,
251273
generatedFilesPath: String? = nil,
252274
backgroundIndexing: Bool? = nil,
275+
backgroundPreparationMode: String? = nil,
253276
experimentalFeatures: Set<ExperimentalFeature>? = nil,
254277
swiftPublishDiagnosticsDebounceDuration: Double? = nil,
255278
workDoneProgressDebounceDuration: Double? = nil,
@@ -263,6 +286,7 @@ public struct SourceKitLSPOptions: Sendable, Codable {
263286
self.generatedFilesPath = generatedFilesPath
264287
self.defaultWorkspaceType = defaultWorkspaceType
265288
self.backgroundIndexing = backgroundIndexing
289+
self.backgroundPreparationMode = backgroundPreparationMode
266290
self.experimentalFeatures = experimentalFeatures
267291
self.swiftPublishDiagnosticsDebounceDuration = swiftPublishDiagnosticsDebounceDuration
268292
self.workDoneProgressDebounceDuration = workDoneProgressDebounceDuration
@@ -315,6 +339,7 @@ public struct SourceKitLSPOptions: Sendable, Codable {
315339
defaultWorkspaceType: override?.defaultWorkspaceType ?? base.defaultWorkspaceType,
316340
generatedFilesPath: override?.generatedFilesPath ?? base.generatedFilesPath,
317341
backgroundIndexing: override?.backgroundIndexing ?? base.backgroundIndexing,
342+
backgroundPreparationMode: override?.backgroundPreparationMode ?? base.backgroundPreparationMode,
318343
experimentalFeatures: override?.experimentalFeatures ?? base.experimentalFeatures,
319344
swiftPublishDiagnosticsDebounceDuration: override?.swiftPublishDiagnosticsDebounceDuration
320345
?? base.swiftPublishDiagnosticsDebounceDuration,

Sources/SKSwiftPMWorkspace/SwiftPMBuildSystem.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,10 @@ extension SwiftPMBuildSystem: SKCore.BuildSystem {
637637
arguments += options.swiftPM.cxxCompilerFlags?.flatMap { ["-Xcxx", $0] } ?? []
638638
arguments += options.swiftPM.swiftCompilerFlags?.flatMap { ["-Xswiftc", $0] } ?? []
639639
arguments += options.swiftPM.linkerFlags?.flatMap { ["-Xlinker", $0] } ?? []
640-
if options.hasExperimentalFeature(.swiftpmPrepareForIndexing) {
641-
arguments.append("--experimental-prepare-for-indexing")
640+
switch options.backgroundPreparationModeOrDefault {
641+
case .build: break
642+
case .noLazy: arguments += ["--experimental-prepare-for-indexing", "--experimental-prepare-for-indexing-no-lazy"]
643+
case .enabled: arguments.append("--experimental-prepare-for-indexing")
642644
}
643645
if Task.isCancelled {
644646
return

Tests/SourceKitLSPTests/BackgroundIndexingTests.swift

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,55 @@ final class BackgroundIndexingTests: XCTestCase {
10661066

10671067
func testCrossModuleFunctionalityEvenIfLowLevelModuleHasErrors() async throws {
10681068
try await SkipUnless.swiftPMSupportsExperimentalPrepareForIndexing()
1069-
let options = SourceKitLSPOptions.testDefault(experimentalFeatures: [.swiftpmPrepareForIndexing])
1069+
var options = SourceKitLSPOptions.testDefault()
1070+
options.backgroundPreparationMode = SourceKitLSPOptions.BackgroundPreparationMode.enabled.rawValue
1071+
let project = try await SwiftPMTestProject(
1072+
files: [
1073+
"LibA/LibA.swift": """
1074+
public func test() -> Invalid {
1075+
return ""
1076+
}
1077+
""",
1078+
"LibB/LibB.swift": """
1079+
import LibA
1080+
1081+
public func 1️⃣libBTest() -> Int {
1082+
return libATest()
1083+
}
1084+
""",
1085+
"MyExec/MyExec.swift": """
1086+
import LibB
1087+
1088+
func test() -> Int {
1089+
return 2️⃣libBTest()
1090+
}
1091+
""",
1092+
],
1093+
manifest: """
1094+
let package = Package(
1095+
name: "MyLibrary",
1096+
targets: [
1097+
.target(name: "LibA"),
1098+
.target(name: "LibB", dependencies: ["LibA"]),
1099+
.executableTarget(name: "MyExec", dependencies: ["LibB"]),
1100+
]
1101+
)
1102+
""",
1103+
options: options,
1104+
enableBackgroundIndexing: true
1105+
)
1106+
1107+
let (uri, positions) = try project.openDocument("MyExec.swift")
1108+
let response = try await project.testClient.send(
1109+
DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["2️⃣"])
1110+
)
1111+
XCTAssertEqual(response, .locations([try project.location(from: "1️⃣", to: "1️⃣", in: "LibB.swift")]))
1112+
}
1113+
1114+
func testCrossModuleFunctionalityWithPreparationNoSkipping() async throws {
1115+
try await SkipUnless.swiftPMSupportsExperimentalPrepareForIndexing()
1116+
var options = SourceKitLSPOptions.testDefault()
1117+
options.backgroundPreparationMode = SourceKitLSPOptions.BackgroundPreparationMode.noLazy.rawValue
10701118
let project = try await SwiftPMTestProject(
10711119
files: [
10721120
"LibA/LibA.swift": """
@@ -1250,7 +1298,8 @@ final class BackgroundIndexingTests: XCTestCase {
12501298
try await SkipUnless.swiftPMSupportsExperimentalPrepareForIndexing()
12511299
try SkipUnless.longTestsEnabled()
12521300

1253-
var options = SourceKitLSPOptions.testDefault(experimentalFeatures: [.swiftpmPrepareForIndexing])
1301+
var options = SourceKitLSPOptions.testDefault()
1302+
options.backgroundPreparationMode = SourceKitLSPOptions.BackgroundPreparationMode.enabled.rawValue
12541303
options.index.updateIndexStoreTimeout = 1 /* second */
12551304

12561305
let dateStarted = Date()

0 commit comments

Comments
 (0)