File: CommandArgTree.swift

package info (click to toggle)
swiftlang 6.1.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 2,791,644 kB
  • sloc: cpp: 9,901,738; ansic: 2,201,433; asm: 1,091,827; python: 308,252; objc: 82,166; f90: 80,126; lisp: 38,358; pascal: 25,559; sh: 20,429; ml: 5,058; perl: 4,745; makefile: 4,484; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (59 lines) | stat: -rw-r--r-- 2,377 bytes parent folder | download | duplicates (2)
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
//===--- CommandArgTree.swift ---------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

/// A tree of compile command arguments, indexed by path such that those unique
/// to a particular file can be queried, with common arguments associated
/// with a common parent.
struct CommandArgTree {
  private var storage: [RelativePath: Set<Command.Argument>]

  init() {
    self.storage = [:]
  }

  mutating func insert(_ args: [Command.Argument], for path: RelativePath) {
    let args = Set(args)
    for component in path.stackedComponents {
      // If we haven't added any arguments, add them. If we're adding arguments
      // for the file itself, this is the only way we'll add arguments,
      // otherwise we can form an intersection with the other arguments.
      let inserted = storage.insertValue(args, for: component)
      guard !inserted && component != path else { continue }

      // We use subscript(_:default:) to mutate in-place without CoW.
      storage[component, default: []].formIntersection(args)
    }
  }

  /// Retrieve the arguments at a given path, including those in the parent.
  func getArgs(for path: RelativePath) -> Set<Command.Argument> {
    storage[path] ?? []
  }

  /// Retrieve the arguments at a given path, excluding those already covered
  /// by a given parent.
  func getUniqueArgs(
    for path: RelativePath, parent: RelativePath
  ) -> Set<Command.Argument> {
    getArgs(for: path).subtracting(getArgs(for: parent))
  }

  /// Whether the given path has any unique args not covered by `parent`.
  func hasUniqueArgs(for path: RelativePath, parent: RelativePath) -> Bool {
    let args = getArgs(for: path)
    guard !args.isEmpty else { return false }
    // Assuming `parent` is an ancestor of path, the arguments for parent is
    // guaranteed to be a subset of the arguments for `path`. As such, we
    // only have to compare sizes here.
    return args.count != getArgs(for: parent).count
  }
}