mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Previously, header files would have their compiler flags inferred from source files which include them. However, code completion didn't work properly since the file path in the arguments was incorrect, pointing to the source file instead of the header file. This also includes support for source files which include other source files, although that's not a common use case.
80 lines
3.1 KiB
Swift
80 lines
3.1 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2020 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
|
|
|
|
/// Build settings for a single file.
|
|
///
|
|
/// Encapsulates all the settings needed to compile a single file, including the compiler arguments
|
|
/// and working directory. FileBuildSettings are typically the result of a BuildSystem query.
|
|
public struct FileBuildSettings: Equatable {
|
|
|
|
/// The compiler arguments to use for this file.
|
|
public var compilerArguments: [String]
|
|
|
|
/// The working directory to resolve any relative paths in `compilerArguments`.
|
|
public var workingDirectory: String? = nil
|
|
|
|
public init(compilerArguments: [String], workingDirectory: String? = nil) {
|
|
self.compilerArguments = compilerArguments
|
|
self.workingDirectory = workingDirectory
|
|
}
|
|
}
|
|
|
|
fileprivate let cExtensions = ["c"]
|
|
fileprivate let cppExtensions = ["cpp", "cc"]
|
|
fileprivate let objcExtensions = ["m"]
|
|
fileprivate let objcppExtensions = ["mm"]
|
|
|
|
private extension String {
|
|
var pathExtension: String {
|
|
return (self as NSString).pathExtension
|
|
}
|
|
var pathBasename: String {
|
|
return (self as NSString).lastPathComponent
|
|
}
|
|
}
|
|
|
|
public extension FileBuildSettings {
|
|
/// Return arguments suitable for use by `newFile`.
|
|
///
|
|
/// This patches the arguments by searching for the argument corresponding to
|
|
/// `originalFile` and replacing it.
|
|
func patching(newFile: String, originalFile: String) -> FileBuildSettings {
|
|
var arguments = self.compilerArguments
|
|
let basename = originalFile.pathBasename
|
|
let fileExtension = originalFile.pathExtension
|
|
if let index = arguments.lastIndex(where: {
|
|
// It's possible the arguments use relative paths while the `originalFile` given
|
|
// is an absolute/real path value. We guess based on suffixes instead of hitting
|
|
// the file system.
|
|
$0.hasSuffix(basename) && originalFile.hasSuffix($0)
|
|
}) {
|
|
arguments[index] = newFile
|
|
// The `-x<lang>` flag needs to be before the possible `-c <header file>`
|
|
// argument in order for Clang to respect it. If there is a pre-existing `-x`
|
|
// flag though, Clang will honor that one instead since it comes after.
|
|
if cExtensions.contains(fileExtension) {
|
|
arguments.insert("-xc", at: 0)
|
|
} else if cppExtensions.contains(fileExtension) {
|
|
arguments.insert("-xc++", at: 0)
|
|
} else if objcExtensions.contains(fileExtension) {
|
|
arguments.insert("-xobjective-c", at: 0)
|
|
} else if (objcppExtensions.contains(fileExtension)) {
|
|
arguments.insert("-xobjective-c++", at: 0)
|
|
}
|
|
}
|
|
return FileBuildSettings(compilerArguments: arguments, workingDirectory: self.workingDirectory)
|
|
}
|
|
}
|