diff --git a/Sources/PackageGraph/ModulesGraph.swift b/Sources/PackageGraph/ModulesGraph.swift index 54db2aa9c59..35d59d6a4ab 100644 --- a/Sources/PackageGraph/ModulesGraph.swift +++ b/Sources/PackageGraph/ModulesGraph.swift @@ -102,6 +102,14 @@ public struct ModulesGraph { /// Returns all the targets in the graph, regardless if they are reachable from the root targets or not. public private(set) var allTargets: IdentifiableSet + /// Returns all targets within the module graph in topological order, starting with low-level targets (that have no + /// dependencies). + package var allTargetsInTopologicalOrder: [ResolvedModule] { + get throws { + try topologicalSort(Array(allTargets)) { $0.dependencies.compactMap { $0.target } }.reversed() + } + } + /// Returns all the products in the graph, regardless if they are reachable from the root targets or not. public private(set) var allProducts: IdentifiableSet diff --git a/Sources/SourceKitLSPAPI/BuildDescription.swift b/Sources/SourceKitLSPAPI/BuildDescription.swift index af012d12802..ddb2030c912 100644 --- a/Sources/SourceKitLSPAPI/BuildDescription.swift +++ b/Sources/SourceKitLSPAPI/BuildDescription.swift @@ -27,6 +27,9 @@ import struct PackageGraph.ModulesGraph public protocol BuildTarget { var sources: [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 } + /// 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 } @@ -46,6 +49,10 @@ private struct WrappedClangTargetBuildDescription: BuildTarget { return (try? description.compilePaths().map { URL(fileURLWithPath: $0.source.pathString) }) ?? [] } + public var name: String { + return description.clangTarget.name + } + public func compileArguments(for fileURL: URL) throws -> [String] { let filePath = try resolveSymlinks(try AbsolutePath(validating: fileURL.path)) let commandLine = try description.emitCommandLine(for: filePath) @@ -63,6 +70,10 @@ private struct WrappedSwiftTargetBuildDescription: BuildTarget { self.isPartOfRootPackage = isPartOfRootPackage } + public var name: String { + return description.target.name + } + var sources: [URL] { return description.sources.map { URL(fileURLWithPath: $0.pathString) } } @@ -110,4 +121,12 @@ public struct BuildDescription { return nil } } + + /// Returns all targets within the module graph in topological order, starting with low-level targets (that have no + /// dependencies). + public func allTargetsInTopologicalOrder(in modulesGraph: ModulesGraph) throws -> [BuildTarget] { + try modulesGraph.allTargetsInTopologicalOrder.compactMap { + getBuildTarget(for: $0, in: modulesGraph) + } + } } diff --git a/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift b/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift index 8e6a147cc3e..5c6ab83197b 100644 --- a/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift +++ b/Sources/SourceKitLSPAPI/PluginTargetBuildDescription.swift @@ -34,6 +34,10 @@ struct PluginTargetBuildDescription: BuildTarget { return target.sources.paths.map { URL(fileURLWithPath: $0.pathString) } } + var name: String { + return target.name + } + func compileArguments(for fileURL: URL) throws -> [String] { // FIXME: This is very odd and we should clean this up by merging `ManifestLoader` and `DefaultPluginScriptRunner` again. let loader = ManifestLoader(toolchain: try UserToolchain(swiftSDK: .hostSwiftSDK()))