mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
I feel like the implementations are actually simpler if we split them. This will also allow us to add more advanced logic to the JSON compilation database build system in the future, such as inferring the toolchain from the compile command.
114 lines
3.8 KiB
Swift
114 lines
3.8 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2024 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 SKLogging
|
|
import SwiftExtensions
|
|
import TSCExtensions
|
|
import ToolchainRegistry
|
|
|
|
import struct TSCBasic.AbsolutePath
|
|
import struct TSCBasic.RelativePath
|
|
|
|
#if compiler(>=6)
|
|
package import LanguageServerProtocol
|
|
package import SKOptions
|
|
#else
|
|
import LanguageServerProtocol
|
|
import SKOptions
|
|
#endif
|
|
|
|
private func searchForCompilationDatabaseConfig(
|
|
in workspaceFolder: URL,
|
|
options: SourceKitLSPOptions
|
|
) -> BuildSystemSpec? {
|
|
let searchPaths =
|
|
(options.compilationDatabaseOrDefault.searchPaths ?? []).compactMap {
|
|
try? RelativePath(validating: $0)
|
|
} + [
|
|
// These default search paths match the behavior of `clangd`
|
|
try! RelativePath(validating: "."),
|
|
try! RelativePath(validating: "build"),
|
|
]
|
|
|
|
return
|
|
searchPaths
|
|
.lazy
|
|
.compactMap { searchPath in
|
|
let path = workspaceFolder.appending(searchPath)
|
|
|
|
let jsonPath = path.appendingPathComponent(JSONCompilationDatabaseBuildSystem.dbName)
|
|
if FileManager.default.isFile(at: jsonPath) {
|
|
return BuildSystemSpec(kind: .jsonCompilationDatabase, projectRoot: workspaceFolder, configPath: jsonPath)
|
|
}
|
|
|
|
let fixedPath = path.appendingPathComponent(FixedCompilationDatabaseBuildSystem.dbName)
|
|
if FileManager.default.isFile(at: fixedPath) {
|
|
return BuildSystemSpec(kind: .fixedCompilationDatabase, projectRoot: workspaceFolder, configPath: fixedPath)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
.first
|
|
}
|
|
|
|
/// Determine which build system should be started to handle the given workspace folder and at which folder that build
|
|
/// system's project root is (see `BuiltInBuildSystem.projectRoot(for:options:)`). `onlyConsiderRoot` controls whether
|
|
/// paths outside the root should be considered (eg. configuration files in the user's home directory).
|
|
///
|
|
/// Returns `nil` if no build system can handle this workspace folder.
|
|
package func determineBuildSystem(
|
|
forWorkspaceFolder workspaceFolder: DocumentURI,
|
|
onlyConsiderRoot: Bool,
|
|
options: SourceKitLSPOptions,
|
|
hooks: BuildSystemHooks
|
|
) -> BuildSystemSpec? {
|
|
if let workspaceURL = workspaceFolder.fileURL, let buildSystemInjector = hooks.buildSystemInjector {
|
|
return BuildSystemSpec(kind: .injected(buildSystemInjector), projectRoot: workspaceURL, configPath: workspaceURL)
|
|
}
|
|
|
|
var buildSystemPreference: [WorkspaceType] = [
|
|
.buildServer, .swiftPM, .compilationDatabase,
|
|
]
|
|
if let defaultBuildSystem = options.defaultWorkspaceType {
|
|
buildSystemPreference.removeAll(where: { $0 == defaultBuildSystem })
|
|
buildSystemPreference.insert(defaultBuildSystem, at: 0)
|
|
}
|
|
guard let workspaceFolderUrl = workspaceFolder.fileURL else {
|
|
return nil
|
|
}
|
|
for buildSystemType in buildSystemPreference {
|
|
var spec: BuildSystemSpec? = nil
|
|
|
|
switch buildSystemType {
|
|
case .buildServer:
|
|
spec = ExternalBuildSystemAdapter.searchForConfig(
|
|
in: workspaceFolderUrl,
|
|
onlyConsiderRoot: onlyConsiderRoot,
|
|
options: options
|
|
)
|
|
case .compilationDatabase:
|
|
spec = searchForCompilationDatabaseConfig(in: workspaceFolderUrl, options: options)
|
|
case .swiftPM:
|
|
#if canImport(PackageModel)
|
|
spec = SwiftPMBuildSystem.searchForConfig(in: workspaceFolderUrl, options: options)
|
|
#endif
|
|
}
|
|
|
|
if let spec {
|
|
return spec
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|