Skip to content

Commit 950e97f

Browse files
authored
Merge pull request #609 from ahoppen/pr/presence-token-only
Make `presence` a token-only property
2 parents 4da1457 + 7b61a46 commit 950e97f

File tree

13 files changed

+74
-56
lines changed

13 files changed

+74
-56
lines changed

Sources/SwiftParser/Diagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
7878
if shouldSkip(node) {
7979
return .skipChildren
8080
}
81-
if node.isMissing {
81+
if node.presence == .missing {
8282
addDiagnostic(node, MissingTokenDiagnostic(missingToken: node))
8383
}
8484
return .skipChildren

Sources/SwiftSyntax/Raw/RawSyntax.swift

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,15 @@ extension RawSyntax {
158158
}
159159

160160
var recursiveFlags: RecursiveRawSyntaxFlags {
161-
switch rawData.payload {
162-
case .materializedToken, .parsedToken:
161+
switch view {
162+
case .token(let tokenView):
163163
var recursiveFlags: RecursiveRawSyntaxFlags = []
164-
if presence == .missing {
164+
if tokenView.presence == .missing {
165165
recursiveFlags.insert(.hasError)
166166
}
167167
return recursiveFlags
168-
case .layout(let dat):
169-
return dat.recursiveFlags
168+
case .layout(let layoutView):
169+
return layoutView.layoutData.recursiveFlags
170170
}
171171
}
172172

@@ -181,26 +181,6 @@ extension RawSyntax {
181181
}
182182
}
183183

184-
var presence: SourcePresence {
185-
if self.byteLength != 0 {
186-
// The node has source text associated with it. It's present.
187-
return .present
188-
}
189-
if self.isCollection || self.isUnknown {
190-
// We always consider collections 'present' because they can just be empty.
191-
return .present
192-
}
193-
if isToken && (self.tokenView!.rawKind == .eof || self.tokenView!.rawKind == .stringSegment) {
194-
// The end of file token never has source code associated with it but we
195-
// still consider it valid.
196-
// String segments can be empty if they occur in an empty string literal or in between two interpolation segments.
197-
return .present
198-
}
199-
200-
// If none of the above apply, the node is missing.
201-
return .missing
202-
}
203-
204184
/// The "width" of the node.
205185
///
206186
/// Sum of text byte lengths of all descendant token nodes.

Sources/SwiftSyntax/Raw/RawSyntaxLayoutView.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ struct RawSyntaxLayoutView {
3737
}
3838
}
3939

40+
var layoutData: RawSyntaxData.Layout {
41+
switch raw.rawData.payload {
42+
case .parsedToken(_),
43+
.materializedToken(_):
44+
preconditionFailure("RawSyntax must be a layout")
45+
case .layout(let dat):
46+
return dat
47+
}
48+
}
49+
4050
/// Creates a new node of the same kind but with children replaced by `elements`.
4151
func replacingLayout<C: Collection>(
4252
with elements: C,
@@ -140,13 +150,7 @@ struct RawSyntaxLayoutView {
140150

141151
/// Child nodes.
142152
var children: RawSyntaxBuffer {
143-
switch raw.rawData.payload {
144-
case .parsedToken(_),
145-
.materializedToken(_):
146-
preconditionFailure("RawSyntax must be a layout")
147-
case .layout(let dat):
148-
return dat.layout
149-
}
153+
layoutData.layout
150154
}
151155

152156
/// Returns the child at the provided cursor in the layout.

Sources/SwiftSyntax/Raw/RawSyntaxNodeProtocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public struct RawTokenSyntax: RawSyntaxNodeProtocol {
9595
}
9696

9797
public var presence: SourcePresence {
98-
raw.presence
98+
tokenView.presence
9999
}
100100

101101
public var isMissing: Bool {

Sources/SwiftSyntax/Raw/RawSyntaxTokenView.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,21 @@ struct RawSyntaxTokenView {
187187
preconditionFailure("Must be invoked on a token")
188188
}
189189
}
190+
191+
var presence: SourcePresence {
192+
if self.raw.byteLength != 0 {
193+
// The node has source text associated with it. It's present.
194+
return .present
195+
}
196+
if rawKind == .eof || rawKind == .stringSegment {
197+
// The end of file token never has source code associated with it but we
198+
// still consider it valid.
199+
// String segments can be empty if they occur in an empty string literal or in between two interpolation segments.
200+
return .present
201+
}
202+
203+
// If none of the above apply, the node is missing.
204+
return .missing
205+
}
206+
190207
}

Sources/SwiftSyntax/Syntax.swift

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,16 +146,6 @@ public extension SyntaxProtocol {
146146
return SyntaxChildrenIndex(self.data.absoluteRaw.info)
147147
}
148148

149-
/// Whether or not this node is marked as `present`.
150-
var isPresent: Bool {
151-
return raw.presence == .present
152-
}
153-
154-
/// Whether or not this node is marked as `missing`.
155-
var isMissing: Bool {
156-
return raw.presence == .missing
157-
}
158-
159149
/// Whether or not this node is a token one.
160150
var isToken: Bool {
161151
return raw.isToken
@@ -553,7 +543,7 @@ public extension SyntaxProtocol {
553543
target.write(" [\(range.start)...\(range.end)]")
554544
}
555545

556-
if isMissing {
546+
if let tokenView = raw.tokenView, tokenView.presence == .missing {
557547
target.write(" MISSING")
558548
}
559549

Sources/SwiftSyntax/SyntaxOtherNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
9898
}
9999

100100
public var presence: SourcePresence {
101-
return raw.presence
101+
return tokenView.presence
102102
}
103103

104104
/// The text of the token as written in the source code.

Sources/SwiftSyntax/SyntaxTreeViewMode.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ public enum SyntaxTreeViewMode {
3131
func shouldTraverse(node: RawSyntax) -> Bool {
3232
switch self {
3333
case .sourceAccurate:
34-
return node.presence == .present
34+
if let tokenView = node.tokenView {
35+
return tokenView.presence == .present
36+
}
37+
return true
3538
case .fixedUp:
3639
return node.kind != .unexpectedNodes
3740
case .all:

Sources/_SwiftSyntaxTestSupport/SyntaxComparison.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,11 @@ public extension SyntaxProtocol {
119119
return .nodeType
120120
}
121121

122-
if isPresent != baseline.isPresent {
123-
return .presence
124-
}
125-
126122
if isToken {
127123
if let token = Syntax(self).as(TokenSyntax.self), let baselineToken = Syntax(baseline).as(TokenSyntax.self) {
124+
if token.presence != baselineToken.presence {
125+
return .presence
126+
}
128127
if token.tokenKind != baselineToken.tokenKind {
129128
return .token
130129
}

Tests/SwiftSyntaxParserTest/SyntaxComparisonTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ public class SyntaxComparisonTests: XCTestCase {
8888
func expectations(_ diff: TreeDifference?, file: StaticString = #filePath, line: UInt = #line) throws {
8989
let diff = try XCTUnwrap(diff, file: file, line: line)
9090
XCTAssertEqual(diff.reason, .presence)
91-
XCTAssertTrue(diff.baseline.isMissing)
92-
XCTAssertFalse(diff.node.isMissing)
91+
XCTAssertEqual(diff.baseline.as(TokenSyntax.self)?.presence, .missing)
92+
XCTAssertEqual(diff.node.as(TokenSyntax.self)?.presence, .present)
9393
}
9494

9595
let actual = Syntax(makeFunc(identifier: .identifier("f")))

Tests/SwiftSyntaxTest/SyntaxChildrenTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class SyntaxChildrenTests: XCTestCase {
5656
)))
5757

5858
var sourceAccurateIt = node.children(viewMode: .sourceAccurate).makeIterator()
59-
XCTAssertNextIsNil(&sourceAccurateIt)
59+
try XCTAssertNext(&sourceAccurateIt) { $0.is(MissingDeclSyntax.self) }
6060

6161
var fixedUpIt = node.children(viewMode: .fixedUp).makeIterator()
6262
try XCTAssertNext(&fixedUpIt) { $0.is(MissingDeclSyntax.self) }

Tests/SwiftSyntaxTest/VisitorTests.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,35 @@ public class VisitorTests: XCTestCase {
2323
}
2424
}
2525

26-
XCTAssertFalse(MissingDeclChecker.check(node, viewMode: .sourceAccurate))
26+
XCTAssertTrue(MissingDeclChecker.check(node, viewMode: .sourceAccurate))
2727
XCTAssertTrue(MissingDeclChecker.check(node, viewMode: .fixedUp))
2828
}
2929

30+
public func testVisitMissingToken() throws {
31+
let node = ReturnStmtSyntax(
32+
returnKeyword: .returnKeyword(presence: .missing),
33+
expression: nil
34+
)
35+
36+
class MissingTokenChecker: SyntaxVisitor {
37+
var didSeeToken = false
38+
39+
override func visit(_ node: TokenSyntax) -> SyntaxVisitorContinueKind {
40+
didSeeToken = true
41+
return .visitChildren
42+
}
43+
44+
static func check<Tree: SyntaxProtocol>(_ tree: Tree, viewMode: SyntaxTreeViewMode) -> Bool {
45+
let visitor = MissingTokenChecker(viewMode: viewMode)
46+
visitor.walk(tree)
47+
return visitor.didSeeToken
48+
}
49+
}
50+
51+
XCTAssertFalse(MissingTokenChecker.check(node, viewMode: .sourceAccurate))
52+
XCTAssertTrue(MissingTokenChecker.check(node, viewMode: .fixedUp))
53+
}
54+
3055
public func testVisitUnexpected() throws {
3156
// This is just bunch of unexpected
3257
let unexpectedReturnStmt = ReturnStmtSyntax(

lit_tests/coloring.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func f(x: Int) -> Int {
232232
)
233233
"""
234234

235-
// CHECK: <str>"</str>\<anchor>(</anchor><int>1</int><anchor>)</anchor>\<anchor>(</anchor><int>1</int><anchor>)</anchor><str>"</str>
235+
// CHECK: <str>"</str>\<anchor>(</anchor><int>1</int><anchor>)</anchor><str></str>\<anchor>(</anchor><int>1</int><anchor>)</anchor><str>"</str>
236236
"\(1)\(1)"
237237
}
238238

0 commit comments

Comments
 (0)