-
Notifications
You must be signed in to change notification settings - Fork 441
/
Copy pathTokenSyntax.swift
173 lines (155 loc) · 5.33 KB
/
TokenSyntax.swift
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// MARK: TokenSyntax
/// A Syntax node representing a single token.
///
/// All source code of a syntax tree is represented by tokens – layout nodes
/// never contain any source code by themselves.
///
/// A token consists of leading ``Trivia``, i.e. whitespaces before the actual
/// token contents, the token’s `text` and trailing ``Trivia`` after the token’s
/// content.
public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
/// The ``Syntax`` node that provides the underlying data.
///
/// Don’t access this. Use `Syntax(token)` instead.
public let _syntaxNode: Syntax
/// The ``RawSyntaxTokenView`` of this token that allows accessing raw
/// properties of the token.
@_spi(RawSyntax)
public var tokenView: RawSyntaxTokenView {
return raw.tokenView!
}
/// If `node` is a token, return the ``TokenSyntax`` that represents it.
/// Otherwise, return `nil`.
public init?<S: SyntaxProtocol>(_ node: S) {
guard node.raw.kind == .token else { return nil }
self._syntaxNode = node._syntaxNode
}
/// Creates a Syntax node from the given `SyntaxData`. This assumes
/// that the `SyntaxData` is of the correct kind. If it is not, the behaviour
/// is undefined.
internal init(_ data: SyntaxData) {
precondition(data.raw.kind == .token)
self._syntaxNode = Syntax(data)
}
/// Construct a new token with the given `kind`, `leadingTrivia`,
/// `trailingTrivia` and `presence`.
public init(
_ kind: TokenKind,
leadingTrivia: Trivia = [],
trailingTrivia: Trivia = [],
presence: SourcePresence
) {
let arena = SyntaxArena()
let raw = RawSyntax.makeMaterializedToken(
kind: kind,
leadingTrivia: leadingTrivia,
trailingTrivia: trailingTrivia,
presence: presence,
tokenDiagnostic: nil,
arena: arena
)
self.init(SyntaxData.forRoot(raw, rawNodeArena: arena))
}
/// Whether the token is present or missing.
public var presence: SourcePresence {
get {
return tokenView.presence
}
set {
self = TokenSyntax(data.withPresence(newValue, arena: SyntaxArena()))
}
}
/// The text of the token as written in the source code, without any trivia.
public var text: String {
return tokenKind.text
}
/// The leading trivia (spaces, newlines, etc.) associated with this token.
public var leadingTrivia: Trivia {
get {
return tokenView.formLeadingTrivia()
}
set {
self = TokenSyntax(data.withLeadingTrivia(newValue, arena: SyntaxArena()))
}
}
/// The trailing trivia (spaces, newlines, etc.) associated with this token.
public var trailingTrivia: Trivia {
get {
return tokenView.formTrailingTrivia()
}
set {
self = TokenSyntax(data.withTrailingTrivia(newValue, arena: SyntaxArena()))
}
}
/// The kind of token this node represents.
public var tokenKind: TokenKind {
get {
return tokenView.formKind()
}
set {
guard raw.kind == .token else {
fatalError("TokenSyntax must have token as its raw")
}
let arena = SyntaxArena()
let newRaw = tokenView.withKind(newValue, arena: arena)
let newData = data.replacingSelf(newRaw, rawNodeArena: arena, allocationArena: arena)
self = TokenSyntax(newData)
}
}
/// The length this node takes up spelled out in the source, excluding its
/// leading or trailing trivia.
public var trimmedLength: SourceLength {
return tokenView.trimmedLength
}
/// The length this node's leading trivia takes up spelled out in source.
public var leadingTriviaLength: SourceLength {
return tokenView.leadingTriviaLength
}
/// The length this node's trailing trivia takes up spelled out in source.
public var trailingTriviaLength: SourceLength {
return tokenView.trailingTriviaLength
}
/// The length of this node including all of its trivia.
public var totalLength: SourceLength {
return raw.totalLength
}
/// A token by itself has no structure, so we represent its structure by an
/// empty layout node.
///
/// Every syntax node that contains a token will have a
/// ``SyntaxNodeStructure/SyntaxChoice/token(_:)`` case for the token and those
/// choices represent the token kinds the token might have.
public static var structure: SyntaxNodeStructure {
return .layout([])
}
/// If the token has a lexical error, the type of the error.
public var tokenDiagnostic: TokenDiagnostic? {
return tokenView.tokenDiagnostic
}
}
extension TokenSyntax: CustomReflectable {
/// A custom mirror that shows the token properties in a simpler form, making
/// the debug output of the token easier to read.
public var customMirror: Mirror {
return Mirror(
self,
children: [
"text": text,
"leadingTrivia": leadingTrivia,
"trailingTrivia": trailingTrivia,
"tokenKind": tokenKind,
]
)
}
}