Skip to content

Commit

Permalink
Expose all target files to SourceKit-LSP (#8107)
Browse files Browse the repository at this point in the history
Add `resources`, `ignored`, and `other` files to `BuildTarget` for use
by SourceKit-LSP.

This is tracked by rdar://139431738 as part of
swiftlang/vscode-swift#562

### Motivation:

SourceKit-LSP needs to be able to determine which target contains a
given DocC catalog in order to fulfill documentation related requests.
However, the catalog is not listed as one of the `sources` or `headers`.
Rather, it is part of `other` files in most cases. Expose all file types
to SourceKit-LSP so that it can properly determine which target a given
file belongs to.

### Modifications:

Added three new properties to `BuildTarget`: `resources`, `ignored`, and
`other` which are arrays of `URL` pointing to the given file types in
the target.

### Result:

SourceKit-LSP will be able to see all files contained within a given
target.
  • Loading branch information
matthewbastien authored Nov 8, 2024
1 parent f34907c commit 42aaad6
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 6 deletions.
10 changes: 10 additions & 0 deletions Sources/Build/BuildDescription/ClangModuleBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ public final class ClangModuleBuildDescription {
self.target.underlying.resources + self.pluginDerivedResources
}

/// The list of files in the target that were marked as ignored.
public var ignored: [AbsolutePath] {
self.target.underlying.ignored
}

/// The list of other kinds of files in the target.
public var others: [AbsolutePath] {
self.target.underlying.others
}

/// Path to the bundle generated for this module (if any).
var bundlePath: AbsolutePath? {
guard !self.resources.isEmpty else {
Expand Down
10 changes: 10 additions & 0 deletions Sources/Build/BuildDescription/SwiftModuleBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ public final class SwiftModuleBuildDescription {
self.target.underlying.resources + self.pluginDerivedResources
}

/// The list of files in the target that were marked as ignored.
public var ignored: [AbsolutePath] {
self.target.underlying.ignored
}

/// The list of other kinds of files in the target.
public var others: [AbsolutePath] {
self.target.underlying.others
}

/// The objects in this target, containing either machine code or bitcode
/// depending on the build parameters used.
public var objects: [AbsolutePath] {
Expand Down
33 changes: 33 additions & 0 deletions Sources/SourceKitLSPAPI/BuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public protocol BuildTarget {
/// Header files in the target
var headers: [URL] { get }

/// The resource files in the target.
var resources: [URL] { get }

/// Files in the target that were marked as ignored.
var ignored: [URL] { get }

/// Other kinds of files in the target.
var others: [URL] { get }

/// The name of the target. It should be possible to build a target by passing this name to `swift build --target`
var name: String { get }

Expand Down Expand Up @@ -72,6 +81,18 @@ private struct WrappedClangTargetBuildDescription: BuildTarget {
return description.clangTarget.headers.map(\.asURL)
}

var resources: [URL] {
return description.resources.map { URL(fileURLWithPath: $0.path.pathString) }
}

var ignored: [URL] {
return description.ignored.map { URL(fileURLWithPath: $0.pathString) }
}

var others: [URL] {
return description.others.map { URL(fileURLWithPath: $0.pathString) }
}

public var name: String {
return description.clangTarget.name
}
Expand Down Expand Up @@ -113,6 +134,18 @@ private struct WrappedSwiftTargetBuildDescription: BuildTarget {

var headers: [URL] { [] }

var resources: [URL] {
return description.resources.map { URL(fileURLWithPath: $0.path.pathString) }
}

var ignored: [URL] {
return description.ignored.map { URL(fileURLWithPath: $0.pathString) }
}

var others: [URL] {
return description.others.map { URL(fileURLWithPath: $0.pathString) }
}

func compileArguments(for fileURL: URL) throws -> [String] {
// Note: we ignore the `fileURL` here as the expectation is that we get a command line for the entire target
// in case of Swift.
Expand Down
12 changes: 12 additions & 0 deletions Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ struct PluginTargetBuildDescription: BuildTarget {

var headers: [URL] { [] }

var resources: [URL] {
return target.underlying.resources.map { URL(fileURLWithPath: $0.path.pathString) }
}

var ignored: [URL] {
return target.underlying.ignored.map { URL(fileURLWithPath: $0.pathString) }
}

var others: [URL] {
return target.underlying.others.map { URL(fileURLWithPath: $0.pathString) }
}

var name: String {
return target.name
}
Expand Down
43 changes: 37 additions & 6 deletions Tests/SourceKitLSPAPITests/SourceKitLSPAPITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ final class SourceKitLSPAPITests: XCTestCase {
func testBasicSwiftPackage() async throws {
let fs = InMemoryFileSystem(emptyFiles:
"/Pkg/Sources/exe/main.swift",
"/Pkg/Sources/exe/README.md",
"/Pkg/Sources/exe/exe.docc/GettingStarted.md",
"/Pkg/Sources/exe/Resources/some_file.txt",
"/Pkg/Sources/lib/lib.swift",
"/Pkg/Sources/lib/README.md",
"/Pkg/Sources/lib/lib.docc/GettingStarted.md",
"/Pkg/Sources/lib/Resources/some_file.txt",
"/Pkg/Plugins/plugin/plugin.swift"
)

Expand All @@ -37,9 +43,19 @@ final class SourceKitLSPAPITests: XCTestCase {
Manifest.createRootManifest(
displayName: "Pkg",
path: "/Pkg",
toolsVersion: .v5_10,
targets: [
TargetDescription(name: "exe", dependencies: ["lib"]),
TargetDescription(name: "lib", dependencies: []),
TargetDescription(
name: "exe",
dependencies: ["lib"],
resources: [.init(rule: .copy, path: "Resources/some_file.txt")],
type: .executable
),
TargetDescription(
name: "lib",
dependencies: [],
resources: [.init(rule: .copy, path: "Resources/some_file.txt")]
),
TargetDescription(name: "plugin", type: .plugin, pluginCapability: .buildTool)
]),
],
Expand Down Expand Up @@ -67,21 +83,29 @@ final class SourceKitLSPAPITests: XCTestCase {
graph: graph,
partialArguments: [
"-module-name", "exe",
"-package-name", "pkg",
"-emit-dependencies",
"-emit-module",
"-emit-module-path", "/path/to/build/\(plan.destinationBuildParameters.triple)/debug/exe.build/exe.swiftmodule"
"-emit-module-path", "/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/exe.swiftmodule"
],
resources: [.init(filePath: "/Pkg/Sources/exe/Resources/some_file.txt")],
ignoredFiles: [.init(filePath: "/Pkg/Sources/exe/exe.docc")],
otherFiles: [.init(filePath: "/Pkg/Sources/exe/README.md")],
isPartOfRootPackage: true
)
try description.checkArguments(
for: "lib",
graph: graph,
partialArguments: [
"-module-name", "lib",
"-package-name", "pkg",
"-emit-dependencies",
"-emit-module",
"-emit-module-path", "/path/to/build/\(plan.destinationBuildParameters.triple)/debug/Modules/lib.swiftmodule"
],
resources: [.init(filePath: "/Pkg/Sources/lib/Resources/some_file.txt")],
ignoredFiles: [.init(filePath: "/Pkg/Sources/lib/lib.docc")],
otherFiles: [.init(filePath: "/Pkg/Sources/lib/README.md")],
isPartOfRootPackage: true
)
try description.checkArguments(
Expand Down Expand Up @@ -238,18 +262,25 @@ extension SourceKitLSPAPI.BuildDescription {
for targetName: String,
graph: ModulesGraph,
partialArguments: [String],
resources: [URL] = [],
ignoredFiles: [URL] = [],
otherFiles: [URL] = [],
isPartOfRootPackage: Bool,
destination: BuildParameters.Destination = .target
) throws -> Bool {
let target = try XCTUnwrap(graph.module(for: targetName))
let buildTarget = try XCTUnwrap(self.getBuildTarget(for: target, destination: destination))

guard let file = buildTarget.sources.first else {
XCTFail("build target \(targetName) contains no files")
XCTAssertEqual(buildTarget.resources, resources, "build target \(targetName) contains unexpected resource files")
XCTAssertEqual(buildTarget.ignored, ignoredFiles, "build target \(targetName) contains unexpected ignored files")
XCTAssertEqual(buildTarget.others, otherFiles, "build target \(targetName) contains unexpected other files")

guard let source = buildTarget.sources.first else {
XCTFail("build target \(targetName) contains no source files")
return false
}

let arguments = try buildTarget.compileArguments(for: file)
let arguments = try buildTarget.compileArguments(for: source)
let result = arguments.contains(partialArguments)

XCTAssertTrue(result, "could not match \(partialArguments) to actual arguments \(arguments)")
Expand Down

0 comments on commit 42aaad6

Please sign in to comment.