File: RenderRanges.swift

package info (click to toggle)
swiftlang 6.1.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • 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 (67 lines) | stat: -rw-r--r-- 2,065 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
60
61
62
63
64
65
66
67
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021-2022 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
//
//===----------------------------------------------------------------------===//

// Useful for testing, debugging, etc.
extension AST.Node {
  func _postOrder() -> Array<AST.Node> {
    var nodes = Array<AST.Node>()
    _postOrder(into: &nodes)
    return nodes
  }
  func _postOrder(into array: inout Array<AST.Node>) {
    children?.forEach { $0._postOrder(into: &array) }
    array.append(self)
  }

  // Produce a textually "rendered" range
  //
  // NOTE: `input` must be the string from which a
  // source range was derived.
  func _renderRange(
    count: Int, into output: inout String
  ) {
    guard count > 0 else { return }
    let repl = String(repeating: "-", count: count-1) + "^"
    output.replaceSubrange(location.range, with: repl)
  }

  // We render from top-to-bottom, coalescing siblings
  public func _render(in input: String) -> [String] {
    let base = String(repeating: " ", count: input.count)
    var lines = [base]

    // TODO: drop the filtering when fake-ness is taken out of
    // this module
    let nodes = _postOrder().filter(\.location.isReal)

    nodes.forEach { node in
      let loc = node.location
      let count = input[loc.range].count
      for idx in lines.indices {
        if lines[idx][loc.range].all(\.isWhitespace) {
          node._renderRange(count: count, into: &lines[idx])
          return
        }
      }
      var nextLine = base
      node._renderRange(count: count, into: &nextLine)
      lines.append(nextLine)
    }

    return lines.first!.all(\.isWhitespace) ? [] : lines
  }
}
extension AST {
  // We render from top-to-bottom, coalescing siblings
  public func _render(in input: String) -> [String] {
    root._render(in: input)
  }
}