Files
sourcekit-lsp/Tests/SourceKitLSPTests/WorkspaceTests.swift
Alex Hoppen be546308ca Use URL in many cases where we used AbsolutePath
We made quite a few fixes recently to make sure that path handling works correctly using `URL` on Windows. Use `URL` in most places to have a single type that represents file paths instead of sometimes using `AbsolutePath`.

While doing so, also remove usages of `TSCBasic.FileSystem` an `InMemoryFileSystem`. The pattern of using `InMemoryFileSystem` for tests was never consistently used and it was a little confusing that some types took a `FileSystem` parameter while other always assumed to work on the local file system.
2024-11-18 18:19:48 -08:00

971 lines
28 KiB
Swift
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Foundation
import LanguageServerProtocol
import SKLogging
import SKOptions
import SKTestSupport
import SourceKitLSP
import SwiftExtensions
import TSCBasic
import ToolchainRegistry
import XCTest
final class WorkspaceTests: XCTestCase {
func testMultipleSwiftPMWorkspaces() async throws {
// The package manifest is the same for both packages we open.
let packageManifest = """
// swift-tools-version: 5.7
import PackageDescription
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "MyLibrary"),
.executableTarget(name: "MyExec", dependencies: ["MyLibrary"])
]
)
"""
let project = try await MultiFileTestProject(
files: [
// PackageA
"PackageA/Sources/MyLibrary/libA.swift": """
public struct FancyLib {
public init() {}
public func sayHello() {}
}
""",
"PackageA/Sources/MyExec/execA.swift": """
import MyLibrary
FancyLib().1⃣sayHello()
""",
"PackageA/Package.swift": packageManifest,
// PackageB
"PackageB/Sources/MyLibrary/libB.swift": """
public struct Lib {
public init() {}
public func foo() {}
}
""",
"PackageB/Sources/MyExec/execB.swift": """
import MyLibrary
Lib().2⃣foo()
""",
"PackageB/Package.swift": packageManifest,
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageA"))),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageB"))),
]
},
enableBackgroundIndexing: true
)
try await project.testClient.send(PollIndexRequest())
let (bUri, bPositions) = try project.openDocument("execB.swift")
let completions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(bUri), position: bPositions["2"])
)
XCTAssertEqual(
completions.items,
[
CompletionItem(
label: "foo()",
kind: .method,
detail: "Void",
deprecated: false,
sortText: nil,
filterText: "foo()",
insertText: "foo()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(bPositions["2"]), newText: "foo()")
)
),
CompletionItem(
label: "self",
kind: .keyword,
detail: "Lib",
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(bPositions["2"]), newText: "self")
)
),
]
)
let (aUri, aPositions) = try project.openDocument("execA.swift")
let otherCompletions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(aUri), position: aPositions["1"])
)
XCTAssertEqual(
otherCompletions.items,
[
CompletionItem(
label: "sayHello()",
kind: .method,
detail: "Void",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "sayHello()",
insertText: "sayHello()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(aPositions["1"]), newText: "sayHello()")
)
),
CompletionItem(
label: "self",
kind: LanguageServerProtocol.CompletionItemKind(rawValue: 14),
detail: "FancyLib",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(aPositions["1"]), newText: "self")
)
),
]
)
}
func testOpenPackageManifestInMultiSwiftPMWorkspaceSetup() async throws {
let project = try await MultiFileTestProject(
files: [
// PackageA
"PackageA/Sources/MyLibrary/libA.swift": "",
"PackageA/Package.swift": SwiftPMTestProject.defaultPackageManifest,
// PackageB
"PackageB/Sources/MyLibrary/libB.swift": "",
"PackageB/Package.swift": SwiftPMTestProject.defaultPackageManifest,
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir)),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageA"))),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageB"))),
]
}
)
let bPackageManifestUri = DocumentURI(
project.scratchDirectory.appendingPathComponent("PackageB").appendingPathComponent("Package.swift")
)
project.testClient.openDocument(SwiftPMTestProject.defaultPackageManifest, uri: bPackageManifestUri)
// Ensure that we get proper build settings for Package.swift and no error about `No such module: PackageDescription`
let diags = try await project.testClient.send(
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(bPackageManifestUri))
)
XCTAssertEqual(diags.fullReport?.items, [])
}
func testCorrectWorkspaceForPackageSwiftInMultiSwiftPMWorkspaceSetup() async throws {
let project = try await MultiFileTestProject(
files: [
// PackageA
"PackageA/Sources/MyLibrary/libA.swift": "",
"PackageA/Package.swift": SwiftPMTestProject.defaultPackageManifest,
// PackageB
"PackageB/Sources/MyLibrary/libB.swift": "",
"PackageB/Package.swift": SwiftPMTestProject.defaultPackageManifest,
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir)),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageA"))),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageB"))),
]
}
)
let pkgA = DocumentURI(
project.scratchDirectory
.appendingPathComponent("PackageA")
.appendingPathComponent("Package.swift")
)
let pkgB = DocumentURI(
project.scratchDirectory
.appendingPathComponent("PackageB")
.appendingPathComponent("Package.swift")
)
assertEqual(
await project.testClient.server.workspaceForDocument(uri: pkgA)?.rootUri,
DocumentURI(project.scratchDirectory.appendingPathComponent("PackageA"))
)
assertEqual(
await project.testClient.server.workspaceForDocument(uri: pkgB)?.rootUri,
DocumentURI(project.scratchDirectory.appendingPathComponent("PackageB"))
)
}
func testSwiftPMPackageInSubfolder() async throws {
let packageManifest = """
// swift-tools-version: 5.7
import PackageDescription
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "MyLibrary"),
.executableTarget(name: "MyExec", dependencies: ["MyLibrary"])
]
)
"""
let project = try await MultiFileTestProject(
files: [
// PackageA
"PackageA/Sources/MyLibrary/libA.swift": """
public struct FancyLib {
public init() {}
public func sayHello() {}
}
""",
"PackageA/Sources/MyExec/execA.swift": """
import MyLibrary
FancyLib().1⃣sayHello()
""",
"PackageA/Package.swift": packageManifest,
],
enableBackgroundIndexing: true
)
let (uri, positions) = try project.openDocument("execA.swift")
try await project.testClient.send(PollIndexRequest())
let otherCompletions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1"])
)
XCTAssertEqual(
otherCompletions.items,
[
CompletionItem(
label: "sayHello()",
kind: .method,
detail: "Void",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "sayHello()",
insertText: "sayHello()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(positions["1"]), newText: "sayHello()")
)
),
CompletionItem(
label: "self",
kind: LanguageServerProtocol.CompletionItemKind(rawValue: 14),
detail: "FancyLib",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(positions["1"]), newText: "self")
)
),
]
)
}
func testNestedSwiftPMWorkspacesWithoutDedicatedWorkspaceFolder() async throws {
// The package manifest is the same for both packages we open.
let packageManifest = """
// swift-tools-version: 5.7
import PackageDescription
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "MyLibrary"),
.executableTarget(name: "MyExec", dependencies: ["MyLibrary"])
]
)
"""
let project = try await MultiFileTestProject(
files: [
// PackageA
"PackageA/Sources/MyLibrary/libA.swift": """
public struct FancyLib {
public init() {}
public func sayHello() {}
}
""",
"PackageA/Sources/MyExec/execA.swift": """
import MyLibrary
FancyLib().1⃣sayHello()
""",
"PackageA/Package.swift": packageManifest,
// PackageB
"Sources/MyLibrary/libB.swift": """
public struct Lib {
public init() {}
public func foo() {}
}
""",
"Sources/MyExec/execB.swift": """
import MyLibrary
Lib().2⃣foo()
""",
"Package.swift": packageManifest,
],
enableBackgroundIndexing: true
)
try await project.testClient.send(PollIndexRequest())
let (bUri, bPositions) = try project.openDocument("execB.swift")
let completions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(bUri), position: bPositions["2"])
)
XCTAssertEqual(
completions.items,
[
CompletionItem(
label: "foo()",
kind: .method,
detail: "Void",
deprecated: false,
sortText: nil,
filterText: "foo()",
insertText: "foo()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(bPositions["2"]), newText: "foo()")
)
),
CompletionItem(
label: "self",
kind: .keyword,
detail: "Lib",
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(bPositions["2"]), newText: "self")
)
),
]
)
let (aUri, aPositions) = try project.openDocument("execA.swift")
try await project.testClient.send(PollIndexRequest())
let otherCompletions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(aUri), position: aPositions["1"])
)
XCTAssertEqual(
otherCompletions.items,
[
CompletionItem(
label: "sayHello()",
kind: .method,
detail: "Void",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "sayHello()",
insertText: "sayHello()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(aPositions["1"]), newText: "sayHello()")
)
),
CompletionItem(
label: "self",
kind: LanguageServerProtocol.CompletionItemKind(rawValue: 14),
detail: "FancyLib",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(range: Range(aPositions["1"]), newText: "self")
)
),
]
)
}
func testMultipleClangdWorkspaces() async throws {
let project = try await MultiFileTestProject(
files: [
"WorkspaceA/main.cpp": """
#if FOO
void 1⃣foo2⃣() {}
#else
void foo() {}
#endif
int main() {
3⃣foo4⃣();
}
""",
"WorkspaceA/compile_flags.txt": """
-DFOO
""",
"WorkspaceB/test.m": "",
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("WorkspaceA"))),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("WorkspaceB"))),
]
},
usePullDiagnostics: false
)
_ = try project.openDocument("test.m")
let diags = try await project.testClient.nextDiagnosticsNotification()
XCTAssertEqual(diags.diagnostics.count, 0)
let (mainUri, positions) = try project.openDocument("main.cpp")
let highlightRequest = DocumentHighlightRequest(
textDocument: TextDocumentIdentifier(mainUri),
position: positions["3"]
)
let highlightResponse = try await project.testClient.send(highlightRequest)
XCTAssertEqual(
highlightResponse,
[
DocumentHighlight(range: positions["1"]..<positions["2"], kind: .text),
DocumentHighlight(range: positions["3"]..<positions["4"], kind: .text),
]
)
}
func testRecomputeFileWorkspaceMembershipOnPackageSwiftChange() async throws {
let project = try await MultiFileTestProject(
files: [
"PackageA/Sources/MyLibrary/libA.swift": "",
"PackageA/Package.swift": SwiftPMTestProject.defaultPackageManifest,
"PackageB/Sources/MyLibrary/libB.swift": """
public struct Lib {
public func foo() {}
public init() {}
}
""",
"PackageB/Sources/MyExec/main.swift": """
import MyLibrary
Lib().1️⃣
""",
"PackageB/Package.swift": SwiftPMTestProject.defaultPackageManifest,
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageA"))),
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("PackageB"))),
]
}
)
let (mainUri, _) = try project.openDocument("main.swift")
// We open PackageA first. Thus, MyExec/main (which is a file in PackageB that hasn't been added to Package.swift
// yet) will belong to PackageA by default (because it provides fallback build settings for it).
assertEqual(
await project.testClient.server.workspaceForDocument(uri: mainUri)?.rootUri,
DocumentURI(project.scratchDirectory.appendingPathComponent("PackageA"))
)
// Add the MyExec target to PackageB/Package.swift
let newPackageManifest = """
// swift-tools-version: 5.7
import PackageDescription
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "MyLibrary"),
.executableTarget(name: "MyExec", dependencies: ["MyLibrary"])
]
)
"""
let packageBManifestPath = project.scratchDirectory
.appendingPathComponent("PackageB")
.appendingPathComponent("Package.swift")
// Package resolving can open Package.swift in exclusive mode on Windows, which prevents us from writing the new
// package manifest. Keep retrying until we get a successful write. This matches what a user would do.
try await repeatUntilExpectedResult {
do {
try newPackageManifest.write(
to: packageBManifestPath,
atomically: true,
encoding: .utf8
)
return true
} catch {
logger.error("Writing new package manifest failed, will retry: \(error.forLogging)")
return false
}
}
project.testClient.send(
DidChangeWatchedFilesNotification(changes: [
FileEvent(uri: DocumentURI(packageBManifestPath), type: .changed)
])
)
// Ensure that the DidChangeWatchedFilesNotification is handled before we continue.
_ = try await project.testClient.send(BarrierRequest())
// After updating PackageB/Package.swift, PackageB can provide proper build settings for MyExec/main.swift and
// thus workspace membership should switch to PackageB.
// Updating the build settings takes a few seconds. Send code completion requests every second until we receive correct results.
let packageBRootUri = DocumentURI(project.scratchDirectory.appendingPathComponent("PackageB"))
try await repeatUntilExpectedResult {
await project.testClient.server.workspaceForDocument(uri: mainUri)?.rootUri == packageBRootUri
}
}
func testMixedPackage() async throws {
let project = try await SwiftPMTestProject(
files: [
"clib/include/clib.h": """
#ifndef CLIB_H
#define CLIB_H
void clib_func(void);
void clib_other(void);
#endif // CLIB_H
""",
"clib/clib.c": """
#include "clib.h"
void clib_func(void) {1⃣}
""",
"lib/lib.swift": """
public struct Lib {
public func foo() {}
public init() {}
}
2
""",
],
manifest: """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "lib", dependencies: []),
.target(name: "clib", dependencies: []),
]
)
"""
)
let (swiftUri, swiftPositions) = try project.openDocument("lib.swift")
let (cUri, cPositions) = try project.openDocument("clib.c")
let cCompletions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(cUri), position: cPositions["1"])
)
XCTAssertGreaterThanOrEqual(cCompletions.items.count, 0)
let swiftCompletions = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(swiftUri), position: swiftPositions["2"])
)
XCTAssertGreaterThanOrEqual(swiftCompletions.items.count, 0)
}
func testChangeWorkspaceFolders() async throws {
let project = try await MultiFileTestProject(
files: [
"subdir/Sources/otherPackage/otherPackage.swift": """
import package
func test() {
Package().1⃣helloWorld()
}
""",
"subdir/Sources/package/package.swift": """
public struct Package {
public init() {}
public func helloWorld() {
print("Hello world!")
}
}
""",
"subdir/Package.swift": """
// swift-tools-version: 5.5
import PackageDescription
let package = Package(
name: "package",
products: [
.library(name: "package", targets: ["package"]),
.library(name: "otherPackage", targets: ["otherPackage"]),
],
targets: [
.target(
name: "package",
dependencies: []
),
.target(
name: "otherPackage",
dependencies: ["package"]
),
]
)
""",
],
workspaces: { scratchDir in
return [
WorkspaceFolder(uri: DocumentURI(scratchDir.appendingPathComponent("fake")))
]
}
)
let packageDir = try project.uri(for: "Package.swift").fileURL!.deletingLastPathComponent()
try await TSCBasic.Process.checkNonZeroExit(arguments: [
ToolchainRegistry.forTesting.default!.swift!.filePath,
"build",
"--package-path", packageDir.filePath,
"-Xswiftc", "-index-ignore-system-modules",
"-Xcc", "-index-ignore-system-symbols",
])
let (otherPackageUri, positions) = try project.openDocument("otherPackage.swift")
let testPosition = positions["1"]
let preChangeWorkspaceResponse = try await project.testClient.send(
CompletionRequest(
textDocument: TextDocumentIdentifier(otherPackageUri),
position: testPosition
)
)
XCTAssertEqual(
preChangeWorkspaceResponse.items,
[],
"Should not receive cross-module code completion results when opening an unrelated directory as workspace root"
)
project.testClient.send(
DidChangeWorkspaceFoldersNotification(
event: WorkspaceFoldersChangeEvent(added: [
WorkspaceFolder(uri: DocumentURI(packageDir))
])
)
)
try await project.testClient.send(PollIndexRequest())
let postChangeWorkspaceResponse = try await project.testClient.send(
CompletionRequest(
textDocument: TextDocumentIdentifier(otherPackageUri),
position: testPosition
)
)
XCTAssertEqual(
postChangeWorkspaceResponse.items,
[
CompletionItem(
label: "helloWorld()",
kind: .method,
detail: "Void",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "helloWorld()",
insertText: "helloWorld()",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(
range: Range(testPosition),
newText: "helloWorld()"
)
)
),
CompletionItem(
label: "self",
kind: .keyword,
detail: "Package",
documentation: nil,
deprecated: false,
sortText: nil,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(
TextEdit(
range: Range(testPosition),
newText: "self"
)
)
),
]
)
}
func testIntegrationTest() async throws {
// This test is doing the same as `test-sourcekit-lsp` in the `swift-integration-tests` repo.
let project = try await SwiftPMTestProject(
files: [
"Sources/clib/include/clib.h": """
#ifndef CLIB_H
#define CLIB_H
void clib_func(void);
void clib_other(void);
#endif // CLIB_H
""",
"Sources/clib/clib.c": """
#include "clib.h"
void 1⃣clib_func(void) {2⃣}
""",
"Sources/exec/main.swift": """
import lib
import clib
Lib().3⃣foo()
4⃣clib_func()
""",
"Sources/lib/lib.swift": """
public struct Lib {
public func 5⃣foo() {}
public init() {}
}
""",
],
manifest: """
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "pkg",
targets: [
.target(name: "exec", dependencies: ["lib", "clib"]),
.target(name: "lib", dependencies: []),
.target(name: "clib", dependencies: []),
]
)
""",
enableBackgroundIndexing: true
)
let (mainUri, mainPositions) = try project.openDocument("main.swift")
let fooDefinitionResponse = try await project.testClient.send(
DefinitionRequest(textDocument: TextDocumentIdentifier(mainUri), position: mainPositions["3"])
)
XCTAssertEqual(
fooDefinitionResponse,
.locations([
Location(uri: try project.uri(for: "lib.swift"), range: try Range(project.position(of: "5", in: "lib.swift")))
])
)
let clibFuncDefinitionResponse = try await project.testClient.send(
DefinitionRequest(textDocument: TextDocumentIdentifier(mainUri), position: mainPositions["4"])
)
XCTAssertEqual(
clibFuncDefinitionResponse,
.locations([
Location(uri: try project.uri(for: "clib.c"), range: try Range(project.position(of: "1", in: "clib.c")))
])
)
let swiftCompletionResponse = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(mainUri), position: mainPositions["3"])
)
XCTAssertEqual(
swiftCompletionResponse.items,
[
CompletionItem(
label: "foo()",
kind: .method,
detail: "Void",
deprecated: false,
filterText: "foo()",
insertText: "foo()",
insertTextFormat: .plain,
textEdit: .textEdit(TextEdit(range: Range(mainPositions["3"]), newText: "foo()"))
),
CompletionItem(
label: "self",
kind: .keyword,
detail: "Lib",
deprecated: false,
filterText: "self",
insertText: "self",
insertTextFormat: .plain,
textEdit: .textEdit(TextEdit(range: Range(mainPositions["3"]), newText: "self"))
),
]
)
let (clibcUri, clibcPositions) = try project.openDocument("clib.c")
let cCompletionResponse = try await project.testClient.send(
CompletionRequest(textDocument: TextDocumentIdentifier(clibcUri), position: clibcPositions["2"])
)
// rdar://73762053: This should also suggest clib_other
XCTAssert(cCompletionResponse.items.contains(where: { $0.insertText == "clib_func" }))
}
func testWorkspaceOptions() async throws {
let project = try await SwiftPMTestProject(
files: [
"/.sourcekit-lsp/config.json": """
{
"swiftPM": {
"swiftCompilerFlags": ["-D", "TEST"]
}
}
""",
"Test.swift": """
func test() {
#if TEST
let x: String = 1
#endif
}
""",
]
)
let (uri, _) = try project.openDocument("Test.swift")
let diagnostics = try await project.testClient.send(
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri))
)
XCTAssertEqual(
diagnostics.fullReport?.items.map(\.message),
["Cannot convert value of type 'Int' to specified type 'String'"]
)
}
func testOptionsInInitializeRequest() async throws {
let project = try await SwiftPMTestProject(
files: [
"Test.swift": """
func test() {
#if TEST
let x: String = 1
#endif
}
"""
],
initializationOptions: SourceKitLSPOptions(
swiftPM: SourceKitLSPOptions.SwiftPMOptions(swiftCompilerFlags: ["-D", "TEST"])
).asLSPAny
)
let (uri, _) = try project.openDocument("Test.swift")
let diagnostics = try await project.testClient.send(
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri))
)
XCTAssertEqual(
diagnostics.fullReport?.items.map(\.message),
["Cannot convert value of type 'Int' to specified type 'String'"]
)
}
func testWorkspaceOptionsOverrideGlobalOptions() async throws {
let project = try await SwiftPMTestProject(
files: [
"/.sourcekit-lsp/config.json": """
{
"swiftPM": {
"swiftCompilerFlags": ["-D", "TEST"]
}
}
""",
"Test.swift": """
func test() {
#if TEST
let x: String = 1
#endif
#if OTHER
let x: String = 1.0
#endif
}
""",
],
initializationOptions: SourceKitLSPOptions(
swiftPM: SourceKitLSPOptions.SwiftPMOptions(swiftCompilerFlags: ["-D", "OTHER"])
).asLSPAny
)
let (uri, _) = try project.openDocument("Test.swift")
let diagnostics = try await project.testClient.send(
DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri))
)
XCTAssertEqual(
diagnostics.fullReport?.items.map(\.message),
["Cannot convert value of type 'Int' to specified type 'String'"]
)
}
}