Skip to content

Commit 49c9fed

Browse files
authored
Return compiler arguments for invalid package manifests (#8138)
Currently, when there‘s a syntax error in a package manifest, we don’t get any build settings from it in SourceKit-LSP and thus loose almost all semantic functionality. If we can’t parse the package manifest, fall back to providing build settings by assuming it has the current Swift tools version. Fixes swiftlang/sourcekit-lsp#1704 rdar://136423767
1 parent 0b1fc39 commit 49c9fed

File tree

2 files changed

+31
-28
lines changed

2 files changed

+31
-28
lines changed

Sources/Workspace/Workspace+Manifests.swift

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -384,33 +384,23 @@ extension Workspace {
384384
}
385385

386386
/// Returns manifest interpreter flags for a package.
387-
// TODO: should this be throwing instead?
388-
public func interpreterFlags(for packagePath: AbsolutePath) -> [String] {
389-
do {
390-
guard let manifestLoader = self.manifestLoader as? ManifestLoader else {
391-
throw StringError("unexpected manifest loader kind")
392-
}
387+
public func interpreterFlags(for manifestPath: AbsolutePath) throws -> [String] {
388+
guard let manifestLoader = self.manifestLoader as? ManifestLoader else {
389+
throw StringError("unexpected manifest loader kind")
390+
}
393391

394-
let manifestPath = try ManifestLoader.findManifest(
395-
packagePath: packagePath,
396-
fileSystem: self.fileSystem,
397-
currentToolsVersion: self.currentToolsVersion
398-
)
399-
let manifestToolsVersion = try ToolsVersionParser.parse(
400-
manifestPath: manifestPath,
401-
fileSystem: self.fileSystem
402-
)
392+
let manifestToolsVersion = (try? ToolsVersionParser.parse(
393+
manifestPath: manifestPath,
394+
fileSystem: self.fileSystem
395+
)) ?? self.currentToolsVersion
403396

404-
guard self.currentToolsVersion >= manifestToolsVersion || SwiftVersion.current.isDevelopment,
405-
manifestToolsVersion >= ToolsVersion.minimumRequired
406-
else {
407-
throw StringError("invalid tools version")
408-
}
409-
return manifestLoader.interpreterFlags(for: manifestToolsVersion)
410-
} catch {
411-
// We ignore all failures here and return empty array.
412-
return []
397+
398+
guard self.currentToolsVersion >= manifestToolsVersion || SwiftVersion.current.isDevelopment,
399+
manifestToolsVersion >= ToolsVersion.minimumRequired
400+
else {
401+
throw StringError("invalid tools version")
413402
}
403+
return manifestLoader.interpreterFlags(for: manifestToolsVersion)
414404
}
415405

416406
/// Load the manifests for the current dependency tree.

Tests/WorkspaceTests/WorkspaceTests.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@ final class WorkspaceTests: XCTestCase {
159159

160160
try testWithTemporaryDirectory { path in
161161
let foo = path.appending("foo")
162+
let packageManifest = foo.appending("Package.swift")
162163

163164
func createWorkspace(_ content: String) throws -> Workspace {
164-
try fs.writeFileContents(foo.appending("Package.swift"), string: content)
165+
try fs.writeFileContents(packageManifest, string: content)
165166

166167
let manifestLoader = ManifestLoader(toolchain: try UserToolchain.default)
167168

@@ -185,7 +186,7 @@ final class WorkspaceTests: XCTestCase {
185186
"""
186187
)
187188

188-
XCTAssertMatch(ws.interpreterFlags(for: foo), [.equal("-swift-version"), .equal("4")])
189+
XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-swift-version"), .equal("4")])
189190
}
190191

191192
do {
@@ -199,7 +200,7 @@ final class WorkspaceTests: XCTestCase {
199200
"""
200201
)
201202

202-
XCTAssertEqual(ws.interpreterFlags(for: foo), [])
203+
XCTAssertThrowsError(try ws.interpreterFlags(for: packageManifest))
203204
}
204205

205206
do {
@@ -213,7 +214,19 @@ final class WorkspaceTests: XCTestCase {
213214
"""
214215
)
215216

216-
XCTAssertMatch(ws.interpreterFlags(for: foo), [.equal("-swift-version"), .equal("6")])
217+
XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-swift-version"), .equal("6")])
218+
}
219+
220+
do {
221+
// Invalid package manifest should still produce build settings.
222+
let ws = try createWorkspace(
223+
"""
224+
// swift-tools-version:999.0
225+
import PackageDescription
226+
"""
227+
)
228+
229+
XCTAssertMatch(try ws.interpreterFlags(for: packageManifest), [.equal("-package-description-version")])
217230
}
218231
}
219232
}

0 commit comments

Comments
 (0)