Make CompilationDatabase use DocumentURI instead of URL

This commit is contained in:
Alex Hoppen
2024-06-01 12:20:08 -07:00
parent 80c214b008
commit f84cfecbf2
3 changed files with 40 additions and 40 deletions

View File

@@ -12,6 +12,7 @@
import Foundation
import LSPLogging
import LanguageServerProtocol
import SKSupport
import struct TSCBasic.AbsolutePath
@@ -47,15 +48,15 @@ public struct CompilationDatabaseCompileCommand: Equatable {
extension CompilationDatabase.Command {
/// The `URL` for this file. If `filename` is relative and `directory` is
/// The `DocumentURI` for this file. If `filename` is relative and `directory` is
/// absolute, returns the concatenation. However, if both paths are relative,
/// it falls back to `filename`, which is more likely to be the identifier
/// that a caller will be looking for.
public var url: URL {
public var uri: DocumentURI {
if filename.hasPrefix("/") || !directory.hasPrefix("/") {
return URL(fileURLWithPath: filename)
return DocumentURI(filePath: filename, isDirectory: false)
} else {
return URL(fileURLWithPath: directory).appendingPathComponent(filename, isDirectory: false)
return DocumentURI(URL(fileURLWithPath: directory).appendingPathComponent(filename, isDirectory: false))
}
}
}
@@ -65,7 +66,7 @@ extension CompilationDatabase.Command {
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
public protocol CompilationDatabase {
typealias Command = CompilationDatabaseCompileCommand
subscript(_ path: URL) -> [Command] { get }
subscript(_ uri: DocumentURI) -> [Command] { get }
var allCommands: AnySequence<Command> { get }
}
@@ -110,13 +111,13 @@ public func tryLoadCompilationDatabase(
///
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html under Alternatives
public struct FixedCompilationDatabase: CompilationDatabase, Equatable {
public var allCommands: AnySequence<Command> { AnySequence([]) }
public var allCommands: AnySequence<CompilationDatabaseCompileCommand> { AnySequence([]) }
private let fixedArgs: [String]
private let directory: String
public subscript(path: URL) -> [Command] {
[Command(directory: directory, filename: path.path, commandLine: fixedArgs + [path.path])]
public subscript(path: DocumentURI) -> [CompilationDatabaseCompileCommand] {
[Command(directory: directory, filename: path.pseudoPath, commandLine: fixedArgs + [path.pseudoPath])]
}
}
@@ -168,32 +169,38 @@ extension FixedCompilationDatabase {
///
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
public struct JSONCompilationDatabase: CompilationDatabase, Equatable {
var pathToCommands: [URL: [Int]] = [:]
var commands: [Command] = []
var pathToCommands: [DocumentURI: [Int]] = [:]
var commands: [CompilationDatabaseCompileCommand] = []
public init(_ commands: [Command] = []) {
commands.forEach { try! add($0) }
public init(_ commands: [CompilationDatabaseCompileCommand] = []) {
for command in commands {
add(command)
}
}
public subscript(_ url: URL) -> [Command] {
if let indices = pathToCommands[url] {
public subscript(_ uri: DocumentURI) -> [CompilationDatabaseCompileCommand] {
if let indices = pathToCommands[uri] {
return indices.map { commands[$0] }
}
if let indices = pathToCommands[url.resolvingSymlinksInPath()] {
if let fileURL = uri.fileURL, let indices = pathToCommands[DocumentURI(fileURL.resolvingSymlinksInPath())] {
return indices.map { commands[$0] }
}
return []
}
public var allCommands: AnySequence<Command> { AnySequence(commands) }
public var allCommands: AnySequence<CompilationDatabaseCompileCommand> { AnySequence(commands) }
public mutating func add(_ command: Command) throws {
let url = command.url
pathToCommands[url, default: []].append(commands.count)
public mutating func add(_ command: CompilationDatabaseCompileCommand) {
let uri = command.uri
pathToCommands[uri, default: []].append(commands.count)
let canonical = URL(fileURLWithPath: try resolveSymlinks(AbsolutePath(validating: url.path)).pathString)
if canonical != url {
pathToCommands[canonical, default: []].append(commands.count)
if let fileURL = uri.fileURL,
let symlinksResolved = try? resolveSymlinks(AbsolutePath(validating: fileURL.path))
{
let canonical = DocumentURI(filePath: symlinksResolved.pathString, isDirectory: false)
if canonical != uri {
pathToCommands[canonical, default: []].append(commands.count)
}
}
commands.append(command)
@@ -204,7 +211,7 @@ extension JSONCompilationDatabase: Codable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
while !container.isAtEnd {
try self.add(try container.decode(Command.self))
self.add(try container.decode(Command.self))
}
}

View File

@@ -106,12 +106,8 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
in buildTarget: ConfiguredTarget,
language: Language
) async -> FileBuildSettings? {
guard let url = document.fileURL else {
// We can't determine build settings for non-file URIs.
return nil
}
guard let db = database(for: url),
let cmd = db[url].first
guard let db = database(for: document),
let cmd = db[document].first
else { return nil }
return FileBuildSettings(
compilerArguments: Array(cmd.commandLine.dropFirst()),
@@ -153,8 +149,8 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
self.watchedFiles.remove(uri)
}
private func database(for url: URL) -> CompilationDatabase? {
if let path = try? AbsolutePath(validating: url.path) {
private func database(for uri: DocumentURI) -> CompilationDatabase? {
if let url = uri.fileURL, let path = try? AbsolutePath(validating: url.path) {
return database(for: path)
}
return compdb
@@ -212,10 +208,7 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
}
public func fileHandlingCapability(for uri: DocumentURI) -> FileHandlingCapability {
guard let fileUrl = uri.fileURL else {
return .unhandled
}
if database(for: fileUrl) != nil {
if database(for: uri) != nil {
return .handled
} else {
return .unhandled
@@ -227,7 +220,7 @@ extension CompilationDatabaseBuildSystem: BuildSystem {
return []
}
return compdb.allCommands.map {
SourceFileInfo(uri: DocumentURI($0.url), isPartOfRootProject: true, mayContainTests: true)
SourceFileInfo(uri: $0.uri, isPartOfRootProject: true, mayContainTests: true)
}
}

View File

@@ -157,9 +157,9 @@ final class CompilationDatabaseTests: XCTestCase {
let db = JSONCompilationDatabase([cmd1, cmd2, cmd3])
XCTAssertEqual(db[URL(fileURLWithPath: "b")], [cmd1])
XCTAssertEqual(db[URL(fileURLWithPath: "/c/b")], [cmd2])
XCTAssertEqual(db[URL(fileURLWithPath: "/b")], [cmd3])
XCTAssertEqual(db[DocumentURI(filePath: "b", isDirectory: false)], [cmd1])
XCTAssertEqual(db[DocumentURI(filePath: "/c/b", isDirectory: false)], [cmd2])
XCTAssertEqual(db[DocumentURI(filePath: "/b", isDirectory: false)], [cmd3])
}
func testJSONCompilationDatabaseFromDirectory() throws {
@@ -255,7 +255,7 @@ final class CompilationDatabaseTests: XCTestCase {
XCTAssertNotNil(db)
XCTAssertEqual(
db![URL(fileURLWithPath: "/a/b")],
db![DocumentURI(filePath: "/a/b", isDirectory: false)],
[
CompilationDatabase.Command(
directory: try AbsolutePath(validating: "/a").pathString,