Files
sourcekit-lsp/Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift
Alex Hoppen 161171668c Rename test projects for consistency
Rename all the classes that write files to disk to create a test project that we can open in sourcekit-lsp to end with `TestProject`. This is better than the old `Workspace` suffix because it avoids ambiguities with the `Workspace` type inside sourcekit-lsp.

- IndexedSingleSwiftFileWorkspace -> IndexedSingleSwiftFileTestProject
- MultiFileTestWorkspace -> MultiFileTestProject
- SwiftPMTestWorkspace -> SwiftPMTestProject
2024-03-20 22:50:34 +01:00

123 lines
4.2 KiB
Swift

//===----------------------------------------------------------------------===//
//
// 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 ISDBTibs
import LanguageServerProtocol
@_spi(Testing) import SKCore
import SourceKitLSP
import TSCBasic
public struct IndexedSingleSwiftFileTestProject {
enum Error: Swift.Error {
case swiftcNotFound
}
public let testClient: TestSourceKitLSPClient
public let fileURI: DocumentURI
public let positions: DocumentPositions
public let indexDBURL: URL
/// Writes a single file to a temporary directory on disk and compiles it to index it.
///
/// - Parameters:
/// - markedText: The contents of the source file including location markers.
/// - allowBuildFailure: Whether to fail if the input source file fails to build or whether to continue the test
/// even if the input source is invalid.
/// - workspaceDirectory: If specified, the temporary files will be put in this directory. If `nil` a temporary
/// scratch directory will be created based on `testName`.
/// - cleanUp: Whether to remove the temporary directory when the SourceKit-LSP server shuts down.
public init(
_ markedText: String,
indexSystemModules: Bool = false,
allowBuildFailure: Bool = false,
workspaceDirectory: URL? = nil,
cleanUp: Bool = cleanScratchDirectories,
testName: String = #function
) async throws {
let testWorkspaceDirectory = try workspaceDirectory ?? testScratchDir(testName: testName)
let testFileURL = testWorkspaceDirectory.appendingPathComponent("test.swift")
let indexURL = testWorkspaceDirectory.appendingPathComponent("index")
self.indexDBURL = testWorkspaceDirectory.appendingPathComponent("index-db")
guard let swiftc = await ToolchainRegistry.forTesting.default?.swiftc?.asURL else {
throw Error.swiftcNotFound
}
// Create workspace with source file and compile_commands.json
try extractMarkers(markedText).textWithoutMarkers.write(to: testFileURL, atomically: false, encoding: .utf8)
var compilerArguments: [String] = [
testFileURL.path,
"-index-store-path", indexURL.path,
"-typecheck",
]
if !indexSystemModules {
compilerArguments.append("-index-ignore-system-modules")
}
if let sdk = TibsBuilder.defaultSDKPath {
compilerArguments += ["-sdk", sdk]
}
let compilationDatabase = JSONCompilationDatabase(
[
JSONCompilationDatabase.Command(
directory: testWorkspaceDirectory.path,
filename: testFileURL.path,
commandLine: [swiftc.path] + compilerArguments
)
]
)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
try encoder.encode(compilationDatabase).write(
to: testWorkspaceDirectory.appendingPathComponent("compile_commands.json")
)
// Run swiftc to build the index store
do {
try await Process.checkNonZeroExit(arguments: [swiftc.path] + compilerArguments)
} catch {
if !allowBuildFailure {
throw error
}
}
// Create the test client
var options = SourceKitLSPServer.Options.testDefault
options.indexOptions = IndexOptions(
indexStorePath: try AbsolutePath(validating: indexURL.path),
indexDatabasePath: try AbsolutePath(validating: indexDBURL.path)
)
self.testClient = try await TestSourceKitLSPClient(
serverOptions: options,
workspaceFolders: [
WorkspaceFolder(uri: DocumentURI(testWorkspaceDirectory))
],
cleanUp: {
if cleanUp {
try? FileManager.default.removeItem(at: testWorkspaceDirectory)
}
}
)
// Wait for the indexstore-db to finish indexing
_ = try await testClient.send(PollIndexRequest())
// Open the document
self.fileURI = DocumentURI(testFileURL)
self.positions = testClient.openDocument(markedText, uri: fileURI)
}
}