Files
Rintaro Ishizaki b9e4c67793 Delete SwiftExtensions duplicates of swift-tools-protocols APIs
Delete `Collection+Only.swift`, `Duration+Seconds.swift`,
`FileManagerExtensions.swift`, `PipeAsStringHandler.swift`, and
`URLExtensions.swift` from `Sources/SwiftExtensions/`. The same
APIs now live in swift-tools-protocols as `@_spi(SourceKitLSP)
public` declarations.

Update each call site to add `@_spi(SourceKitLSP) import
ToolsProtocolsSwiftExtensions` next to the existing
`import SwiftExtensions`. Add the
`_ToolsProtocolsSwiftExtensionsForPlugin` dependency and the
`ToolsProtocolsSwiftExtensions=_ToolsProtocolsSwiftExtensionsForPlugin`
module alias to the `SwiftSourceKitClientPlugin` target in both
`Package.swift` and the corresponding `CMakeLists.txt`.
2026-06-08 21:08:24 -07:00

338 lines
11 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 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 BuildServerIntegration
@_spi(SourceKitLSP) import BuildServerProtocol
@_spi(SourceKitLSP) import LanguageServerProtocol
@_spi(Testing) @_spi(SourceKitLSP) import SKLogging
import SKTestSupport
import SwiftExtensions
@_spi(SourceKitLSP) import ToolsProtocolsSwiftExtensions
import XCTest
class CopyDestinationTests: SourceKitLSPTestCase {
actor BuildServer: CustomBuildServer {
let inProgressRequestsTracker = CustomBuildServerInProgressRequestTracker()
private let projectRoot: URL
var headerCopyDestination: URL {
projectRoot.appending(components: "header-copy", "CopiedTest.h")
}
init(projectRoot: URL, connectionToSourceKitLSP: any Connection) {
self.projectRoot = projectRoot
}
func initializeBuildRequest(_ request: InitializeBuildRequest) async throws -> InitializeBuildResponse {
return try initializationResponseSupportingBackgroundIndexing(
projectRoot: projectRoot,
outputPathsProvider: false
)
}
func buildTargetSourcesRequest(_ request: BuildTargetSourcesRequest) -> BuildTargetSourcesResponse {
return BuildTargetSourcesResponse(items: [
SourcesItem(
target: .dummy,
sources: [
SourceItem(
uri: DocumentURI(projectRoot.appending(component: "Test.c")),
kind: .file,
generated: false,
dataKind: .sourceKit,
data: SourceKitSourceItemData(
language: .c,
kind: .source,
).encodeToLSPAny()
),
SourceItem(
uri: DocumentURI(projectRoot.appending(component: "Test.h")),
kind: .file,
generated: false,
dataKind: .sourceKit,
data: SourceKitSourceItemData(
language: .c,
kind: .header,
copyDestinations: [DocumentURI(headerCopyDestination)]
).encodeToLSPAny()
),
]
)
])
}
func textDocumentSourceKitOptionsRequest(
_ request: TextDocumentSourceKitOptionsRequest
) throws -> TextDocumentSourceKitOptionsResponse? {
return TextDocumentSourceKitOptionsResponse(compilerArguments: [
request.textDocument.uri.pseudoPath,
"-I", try headerCopyDestination.deletingLastPathComponent().filePath,
"-D", "FOO",
])
}
func prepareTarget(_ request: BuildTargetPrepareRequest) async throws -> BuildTargetPrepareResponse {
try FileManager.default.createDirectory(
at: headerCopyDestination.deletingLastPathComponent(),
withIntermediateDirectories: true
)
try FileManager.default.copyItem(
at: projectRoot.appending(component: "Test.h"),
to: headerCopyDestination
)
return BuildTargetPrepareResponse()
}
}
func testJumpToCopiedHeader() async throws {
let project = try await CustomBuildServerTestProject(
files: [
"Test.h": """
void hello();
""",
"Test.c": """
#include <CopiedTest.h>
void test() {
1️⃣hello();
}
""",
],
buildServer: BuildServer.self,
enableBackgroundIndexing: true,
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
let (uri, positions) = try project.openDocument("Test.c")
let response = try await project.testClient.send(
DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
)
XCTAssertEqual(response?.locations?.map(\.uri), [try project.uri(for: "Test.h")])
}
func testFindReferencesInCopiedHeader() async throws {
let project = try await CustomBuildServerTestProject(
files: [
"Test.h": """
void 1️⃣hello();
""",
"Test.c": """
#include <CopiedTest.h>
void test() {
2️⃣hello();
}
""",
],
buildServer: BuildServer.self,
enableBackgroundIndexing: true
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
let (uri, positions) = try project.openDocument("Test.c")
let response = try await project.testClient.send(
ReferencesRequest(
textDocument: TextDocumentIdentifier(uri),
position: positions["2️⃣"],
context: ReferencesContext(includeDeclaration: true)
)
)
let expected = [
try project.location(from: "2️⃣", to: "2️⃣", in: "Test.c"),
try project.location(from: "1️⃣", to: "1️⃣", in: "Test.h"),
]
XCTAssertEqual(response, expected)
}
func testFindDeclarationInCopiedHeader() async throws {
let project = try await CustomBuildServerTestProject(
files: [
"Test.h": """
void 1️⃣hello2️⃣();
""",
"Test.c": """
#include <CopiedTest.h>
void hello() {}
void test() {
3️⃣hello();
}
""",
],
buildServer: BuildServer.self,
enableBackgroundIndexing: true
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
let (uri, positions) = try project.openDocument("Test.c")
let response = try await project.testClient.send(
DeclarationRequest(
textDocument: TextDocumentIdentifier(uri),
position: positions["3️⃣"]
)
)
XCTAssertEqual(
response?.locations,
[
try project.location(from: "1️⃣", to: "2️⃣", in: "Test.h")
]
)
}
func testWorkspaceSymbolsInCopiedHeader() async throws {
let project = try await CustomBuildServerTestProject(
files: [
"Test.h": """
void 1️⃣hello();
""",
"Test.c": """
#include <CopiedTest.h>
void test() {
hello();
}
""",
],
buildServer: BuildServer.self,
enableBackgroundIndexing: true
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
_ = try project.openDocument("Test.c")
let response = try await project.testClient.send(
WorkspaceSymbolsRequest(query: "hello")
)
let item = try XCTUnwrap(response?.only)
guard case .symbolInformation(let info) = item else {
XCTFail("Expected a symbol information")
return
}
XCTAssertEqual(info.location, try project.location(from: "1️⃣", to: "1️⃣", in: "Test.h"))
}
func testJumpToCopiedHeaderJumpsToCopyIfOriginalDoesNotExist() async throws {
actor BuildServer: CustomBuildServer {
let inProgressRequestsTracker = CustomBuildServerInProgressRequestTracker()
private let projectRoot: URL
var headerCopyDestination: URL {
projectRoot.appending(components: "header-copy", "CopiedTest.h")
}
init(projectRoot: URL, connectionToSourceKitLSP: any Connection) {
self.projectRoot = projectRoot
}
func initializeBuildRequest(_ request: InitializeBuildRequest) async throws -> InitializeBuildResponse {
return try initializationResponseSupportingBackgroundIndexing(
projectRoot: projectRoot,
outputPathsProvider: false
)
}
func buildTargetSourcesRequest(_ request: BuildTargetSourcesRequest) -> BuildTargetSourcesResponse {
return BuildTargetSourcesResponse(items: [
SourcesItem(
target: .dummy,
sources: [
SourceItem(
uri: DocumentURI(projectRoot.appending(component: "Test.c")),
kind: .file,
generated: false,
dataKind: .sourceKit,
data: SourceKitSourceItemData(language: .c).encodeToLSPAny()
),
SourceItem(
uri: DocumentURI(projectRoot.appending(component: "Test.h")),
kind: .file,
generated: false,
dataKind: .sourceKit,
data: SourceKitSourceItemData(
language: .c,
kind: .header,
copyDestinations: [DocumentURI(headerCopyDestination)]
).encodeToLSPAny()
),
]
)
])
}
func textDocumentSourceKitOptionsRequest(
_ request: TextDocumentSourceKitOptionsRequest
) throws -> TextDocumentSourceKitOptionsResponse? {
return TextDocumentSourceKitOptionsResponse(compilerArguments: [
request.textDocument.uri.pseudoPath, "-I", try headerCopyDestination.deletingLastPathComponent().filePath,
])
}
func prepareTarget(_ request: BuildTargetPrepareRequest) async throws -> BuildTargetPrepareResponse {
try FileManager.default.createDirectory(
at: headerCopyDestination.deletingLastPathComponent(),
withIntermediateDirectories: true
)
try await """
void hello();
""".writeWithRetry(to: headerCopyDestination)
return BuildTargetPrepareResponse()
}
}
let project = try await CustomBuildServerTestProject(
files: [
"Test.c": """
#include <CopiedTest.h>
void test() {
1️⃣hello();
}
"""
],
buildServer: BuildServer.self,
enableBackgroundIndexing: true,
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
let (uri, positions) = try project.openDocument("Test.c")
let response = try await project.testClient.send(
DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
)
assertEqual(response?.locations?.map(\.uri), [try await DocumentURI(project.buildServer().headerCopyDestination)])
}
func testSemanticFunctionalityInCopiedHeader() async throws {
let contents = """
#ifdef FOO
typedef void 1️⃣MY_VOID2️⃣;
#else
typedef void MY_VOID;
#endif
3️⃣MY_VOID hello();
"""
let project = try await CustomBuildServerTestProject(
files: ["Test.h": contents],
buildServer: BuildServer.self,
enableBackgroundIndexing: false,
)
try await project.testClient.send(SynchronizeRequest(copyFileMap: true))
let headerUri = try await DocumentURI(project.buildServer().headerCopyDestination)
let positions = project.testClient.openDocument(contents, uri: headerUri, language: .c)
let response = try await project.testClient.send(
DefinitionRequest(textDocument: TextDocumentIdentifier(headerUri), position: positions["3️⃣"])
)
XCTAssertEqual(response?.locations, [try project.location(from: "1️⃣", to: "2️⃣", in: "Test.h")])
}
}