File: Utilities.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (96 lines) | stat: -rw-r--r-- 3,837 bytes parent folder | download
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) })
    }
}