File: RenderRanges.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 (67 lines) | stat: -rw-r--r-- 2,065 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
//===----------------------------------------------------------------------===//
//
// 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)
  }
}