File: Trivia%2BFormatExtensions.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 (132 lines) | stat: -rw-r--r-- 4,398 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 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
//
//===----------------------------------------------------------------------===//

#if swift(>=6)
public import SwiftSyntax
#else
import SwiftSyntax
#endif

extension Trivia {
  /// Removes all whitespaces that is trailing before a newline trivia,
  /// effectively making sure that lines don't end with a whitespace
  func trimmingTrailingWhitespaceBeforeNewline(isBeforeNewline: Bool) -> Trivia {
    // Iterate through the trivia in reverse. Every time we see a newline drop
    // all whitespaces until we see a non-whitespace trivia piece.
    var isBeforeNewline = isBeforeNewline
    var trimmedReversedPieces: [TriviaPiece] = []
    for piece in pieces.reversed() {
      if piece.isNewline {
        isBeforeNewline = true
        trimmedReversedPieces.append(piece)
        continue
      }
      if isBeforeNewline && piece.isWhitespace {
        continue
      }
      trimmedReversedPieces.append(piece)
      isBeforeNewline = false
    }
    return Trivia(pieces: trimmedReversedPieces.reversed())
  }

  /// Returns `true` if this trivia contains indentation.
  func containsIndentation(isOnNewline: Bool) -> Bool {
    guard let indentation = indentation(isOnNewline: isOnNewline) else {
      return false
    }
    return !indentation.isEmpty
  }

  /// Returns the indentation of the last trivia piece in this trivia that is
  /// not a whitespace.
  /// - Parameter isOnNewline: Specifies if the character before this trivia is a newline character, i.e. if this trivia already starts on a new line.
  /// - Returns: An optional ``Trivia`` with indentation of the last trivia piece.
  public func indentation(isOnNewline: Bool) -> Trivia? {
    let lastNonWhitespaceTriviaPieceIndex = self.pieces.lastIndex(where: { !$0.isWhitespace }) ?? self.pieces.endIndex
    let piecesBeforeLastNonWhitespace = self.pieces[..<lastNonWhitespaceTriviaPieceIndex]
    let indentation: ArraySlice<TriviaPiece>
    if let lastNewlineIndex = piecesBeforeLastNonWhitespace.lastIndex(where: { $0.isNewline }) {
      indentation = piecesBeforeLastNonWhitespace[(lastNewlineIndex + 1)...]
    } else if isOnNewline {
      indentation = piecesBeforeLastNonWhitespace
    } else {
      return nil
    }
    return Trivia(pieces: indentation)
  }

  /// Adds `indentation` after every newline in this trivia.
  ///
  /// - Parameters:
  ///   - indentation: The amount of indentation to add.
  ///   - isOnNewline: Whether this token starts on a new line.
  ///     This causes the indentation to get added at the start of the trivia.
  ///   - addIndentationAfterLastNewline: Whether to add indentation after newline
  ///     if the newline is the last piece of trivia. Not doing this makes sense
  ///     if the indentation will get added to the next token's leading trivia
  ///     via `isOnNewline`.
  func indented(
    indentation: Trivia,
    isOnNewline: Bool,
    addIndentationAfterLastNewline: Bool = true
  ) -> Trivia {
    guard !isEmpty else {
      if isOnNewline {
        return indentation
      }
      return self
    }

    var indentedPieces: [TriviaPiece] = []
    if isOnNewline {
      indentedPieces += indentation
    }

    for (index, piece) in pieces.enumerated() {
      indentedPieces.append(piece)
      if piece.isNewline && !(index == pieces.count - 1 && !addIndentationAfterLastNewline) {
        indentedPieces += indentation
      }
    }

    return Trivia(pieces: indentedPieces)
  }

  var startsWithNewline: Bool {
    guard let first = self.first else {
      return false
    }
    return first.isNewline
  }

  var startsWithWhitespace: Bool {
    guard let first = self.first else {
      return false
    }
    return first.isWhitespace
  }

  var endsWithNewline: Bool {
    guard let last = self.pieces.last else {
      return false
    }
    return last.isNewline
  }

  var endsWithWhitespace: Bool {
    guard let last = self.pieces.last else {
      return false
    }
    return last.isWhitespace
  }
}