1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
extension Package {
/// The list of targets matching the given names. Throws an error if any of
/// the targets cannot be found.
public func targets(named targetNames: [String]) throws -> [Target] {
return try targetNames.map { name in
guard let target = self.targets.first(where: { $0.name == name }) else {
throw PluginContextError.targetNotFound(name: name, package: self)
}
return target
}
}
/// The list of products matching the given names. Throws an error if any of
/// the products cannot be found.
public func products(named productNames: [String]) throws -> [Product] {
return try productNames.map { name in
guard let product = self.products.first(where: { $0.name == name }) else {
throw PluginContextError.productNotFound(name: name, package: self)
}
return product
}
}
@available(_PackageDescription, introduced: 5.9)
public var sourceModules: [SourceModuleTarget] {
return targets.compactMap { $0.sourceModule }
}
}
extension Product {
@available(_PackageDescription, introduced: 5.9)
public var sourceModules: [SourceModuleTarget] {
return targets.compactMap { $0.sourceModule }
}
}
extension Target {
/// The transitive closure of all the targets on which the receiver depends,
/// ordered such that every dependency appears before any other target that
/// depends on it (i.e. in "topological sort order").
public var recursiveTargetDependencies: [Target] {
// FIXME: We can rewrite this to use a stack instead of recursion.
var visited = Set<Target.ID>()
func dependencyClosure(for target: Target) -> [Target] {
guard visited.insert(target.id).inserted else { return [] }
return target.dependencies.flatMap{ dependencyClosure(for: $0) } + [target]
}
func dependencyClosure(for dependency: TargetDependency) -> [Target] {
switch dependency {
case .target(let target):
return dependencyClosure(for: target)
case .product(let product):
return product.targets.flatMap{ dependencyClosure(for: $0) }
}
}
return self.dependencies.flatMap{ dependencyClosure(for: $0) }
}
/// Convenience accessor which casts the receiver to`SourceModuleTarget` if possible.
@available(_PackageDescription, introduced: 5.9)
public var sourceModule: SourceModuleTarget? {
return self as? SourceModuleTarget
}
}
extension Package {
/// The products in this package that conform to a specific type.
public func products<T: Product>(ofType: T.Type) -> [T] {
return self.products.compactMap { $0 as? T }
}
/// The targets in this package that conform to a specific type.
public func targets<T: Target>(ofType: T.Type) -> [T] {
return self.targets.compactMap { $0 as? T }
}
}
extension SourceModuleTarget {
/// A possibly empty list of source files in the target that have the given
/// filename suffix.
public func sourceFiles(withSuffix suffix: String) -> FileList {
return FileList(self.sourceFiles.filter{ $0.url.lastPathComponent.hasSuffix(suffix) })
}
}
|