Skip to content

Commit

Permalink
Cherry-picks to release/6.0 for sourcekit-lsp update (#7520)
Browse files Browse the repository at this point in the history
- **Explanation**: Cherry-pick the following to PRs which are companions
of apple/sourcekit-lsp#1213
  - #7505
  - #7492
- **Scope**: CMake build and SourceKit-LSP API
- **Risk**: Low, the SourceKit-LSP API is only used by SourceKit-LSP and
the CMake build changes will all be caught at build-time
- **Testing**: n/a
- **Issue**: n/a
- **Reviewer**: @DougGregor and @MaxDesiatov on
#7505 and
#7492

---------

Co-authored-by: Ben Barham <[email protected]>
  • Loading branch information
ahoppen and bnbarham committed May 3, 2024
1 parent eb2d5b3 commit 85cc54c
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 45 deletions.
24 changes: 13 additions & 11 deletions BuildSupport/SwiftSyntax/CMakeLists.txt
@@ -1,14 +1,16 @@
include(FetchContent)

set(BUILD_SHARED_LIBS OFF)

if(DEFINED SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE)
file(TO_CMAKE_PATH "${SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE}" swift_syntax_path)
FetchContent_Declare(SwiftSyntax
SOURCE_DIR "${swift_syntax_path}")
else()
FetchContent_Declare(SwiftSyntax
GIT_REPOSITORY https://github.com/apple/swift-syntax
GIT_TAG main)
find_package(SwiftSyntax CONFIG GLOBAL)
if(NOT SwiftSyntax_FOUND)
set(SWIFT_SYNTAX_INSTALL_TARGETS YES)
if(DEFINED SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE)
file(TO_CMAKE_PATH "${SWIFTPM_PATH_TO_SWIFT_SYNTAX_SOURCE}" swift_syntax_path)
FetchContent_Declare(SwiftSyntax
SOURCE_DIR "${swift_syntax_path}")
else()
FetchContent_Declare(SwiftSyntax
GIT_REPOSITORY https://github.com/apple/swift-syntax
GIT_TAG main)
endif()
FetchContent_MakeAvailable(SwiftSyntax)
endif()
FetchContent_MakeAvailable(SwiftSyntax)
26 changes: 6 additions & 20 deletions Sources/PackageModelSyntax/CMakeLists.txt
Expand Up @@ -24,12 +24,12 @@ target_link_libraries(PackageModelSyntax PUBLIC
PackageLoading
PackageModel

SwiftBasicFormat
SwiftDiagnostics
SwiftIDEUtils
SwiftParser
SwiftSyntax
SwiftSyntaxBuilder
SwiftSyntax::SwiftBasicFormat
SwiftSyntax::SwiftDiagnostics
SwiftSyntax::SwiftIDEUtils
SwiftSyntax::SwiftParser
SwiftSyntax::SwiftSyntax
SwiftSyntax::SwiftSyntaxBuilder
)

# NOTE(compnerd) workaround for CMake not setting up include flags yet
Expand All @@ -41,17 +41,3 @@ install(TARGETS PackageModelSyntax
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
set_property(GLOBAL APPEND PROPERTY SwiftPM_EXPORTS PackageModelSyntax)

set(SWIFT_SYNTAX_MODULES
SwiftBasicFormat
SwiftParser
SwiftParserDiagnostics
SwiftDiagnostics
SwiftSyntax
SwiftSyntaxBuilder
SwiftIDEUtils
)
export(TARGETS ${SWIFT_SYNTAX_MODULES}
NAMESPACE SPMSwiftSyntax::
FILE ${CMAKE_BINARY_DIR}/cmake/modules/SwiftSyntaxConfig.cmake
EXPORT_LINK_INTERFACE_LIBRARIES)
42 changes: 33 additions & 9 deletions Sources/SourceKitLSPAPI/BuildDescription.swift
Expand Up @@ -22,31 +22,45 @@ import class Build.BuildPlan
import class Build.ClangTargetBuildDescription
import class Build.SwiftTargetBuildDescription
import struct PackageGraph.ResolvedTarget
import struct PackageGraph.ModulesGraph

public protocol BuildTarget {
var sources: [URL] { get }

/// Whether the target is part of the root package that the user opened or if it's part of a package dependency.
var isPartOfRootPackage: Bool { get }

func compileArguments(for fileURL: URL) throws -> [String]
}
}

private struct WrappedClangTargetBuildDescription: BuildTarget {
private let description: ClangTargetBuildDescription
let isPartOfRootPackage: Bool

init(description: ClangTargetBuildDescription, isPartOfRootPackage: Bool) {
self.description = description
self.isPartOfRootPackage = isPartOfRootPackage
}

extension ClangTargetBuildDescription: BuildTarget {
public var sources: [URL] {
return (try? compilePaths().map { URL(fileURLWithPath: $0.source.pathString) }) ?? []
return (try? description.compilePaths().map { URL(fileURLWithPath: $0.source.pathString) }) ?? []
}

public func compileArguments(for fileURL: URL) throws -> [String] {
let filePath = try resolveSymlinks(try AbsolutePath(validating: fileURL.path))
let commandLine = try self.emitCommandLine(for: filePath)
let commandLine = try description.emitCommandLine(for: filePath)
// First element on the command line is the compiler itself, not an argument.
return Array(commandLine.dropFirst())
}
}

private struct WrappedSwiftTargetBuildDescription: BuildTarget {
private let description: SwiftTargetBuildDescription
let isPartOfRootPackage: Bool

init(description: SwiftTargetBuildDescription) {
init(description: SwiftTargetBuildDescription, isPartOfRootPackage: Bool) {
self.description = description
self.isPartOfRootPackage = isPartOfRootPackage
}

var sources: [URL] {
Expand All @@ -71,17 +85,27 @@ public struct BuildDescription {
}

// FIXME: should not use `ResolvedTarget` in the public interface
public func getBuildTarget(for target: ResolvedTarget) -> BuildTarget? {
public func getBuildTarget(for target: ResolvedTarget, in modulesGraph: ModulesGraph) -> BuildTarget? {
if let description = buildPlan.targetMap[target.id] {
switch description {
case .clang(let description):
return description
return WrappedClangTargetBuildDescription(
description: description,
isPartOfRootPackage: modulesGraph.rootPackages.map(\.id).contains(description.package.id)
)
case .swift(let description):
return WrappedSwiftTargetBuildDescription(description: description)
return WrappedSwiftTargetBuildDescription(
description: description,
isPartOfRootPackage: modulesGraph.rootPackages.map(\.id).contains(description.package.id)
)
}
} else {
if target.type == .plugin, let package = self.buildPlan.graph.package(for: target) {
return PluginTargetBuildDescription(target: target, toolsVersion: package.manifest.toolsVersion)
return PluginTargetBuildDescription(
target: target,
toolsVersion: package.manifest.toolsVersion,
isPartOfRootPackage: modulesGraph.rootPackages.map(\.id).contains(package.id)
)
}
return nil
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift
Expand Up @@ -21,11 +21,13 @@ private import class PackageModel.UserToolchain
struct PluginTargetBuildDescription: BuildTarget {
private let target: ResolvedTarget
private let toolsVersion: ToolsVersion
let isPartOfRootPackage: Bool

init(target: ResolvedTarget, toolsVersion: ToolsVersion) {
init(target: ResolvedTarget, toolsVersion: ToolsVersion, isPartOfRootPackage: Bool) {
assert(target.type == .plugin)
self.target = target
self.toolsVersion = toolsVersion
self.isPartOfRootPackage = isPartOfRootPackage
}

var sources: [URL] {
Expand Down
9 changes: 5 additions & 4 deletions Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift
Expand Up @@ -51,15 +51,15 @@ class SourceKitLSPAPITests: XCTestCase {
)
let description = BuildDescription(buildPlan: plan)

try description.checkArguments(for: "exe", graph: graph, partialArguments: ["-module-name", "exe", "-emit-dependencies", "-emit-module", "-emit-module-path", "/path/to/build/debug/exe.build/exe.swiftmodule"])
try description.checkArguments(for: "lib", graph: graph, partialArguments: ["-module-name", "lib", "-emit-dependencies", "-emit-module", "-emit-module-path", "/path/to/build/debug/Modules/lib.swiftmodule"])
try description.checkArguments(for: "exe", graph: graph, partialArguments: ["-module-name", "exe", "-emit-dependencies", "-emit-module", "-emit-module-path", "/path/to/build/debug/exe.build/exe.swiftmodule"], isPartOfRootPackage: true)
try description.checkArguments(for: "lib", graph: graph, partialArguments: ["-module-name", "lib", "-emit-dependencies", "-emit-module", "-emit-module-path", "/path/to/build/debug/Modules/lib.swiftmodule"], isPartOfRootPackage: true)
}
}

extension SourceKitLSPAPI.BuildDescription {
@discardableResult func checkArguments(for targetName: String, graph: ModulesGraph, partialArguments: [String]) throws -> Bool {
@discardableResult func checkArguments(for targetName: String, graph: ModulesGraph, partialArguments: [String], isPartOfRootPackage: Bool) throws -> Bool {
let target = try XCTUnwrap(graph.allTargets.first(where: { $0.name == targetName }))
let buildTarget = try XCTUnwrap(self.getBuildTarget(for: target))
let buildTarget = try XCTUnwrap(self.getBuildTarget(for: target, in: graph))

guard let file = buildTarget.sources.first else {
XCTFail("build target \(targetName) contains no files")
Expand All @@ -70,6 +70,7 @@ extension SourceKitLSPAPI.BuildDescription {
let result = arguments.contains(partialArguments)

XCTAssertTrue(result, "could not match \(partialArguments) to actual arguments \(arguments)")
XCTAssertEqual(buildTarget.isPartOfRootPackage, isPartOfRootPackage)
return result
}
}

0 comments on commit 85cc54c

Please sign in to comment.