Skip to content

Commit ed2e52c

Browse files
committed
Fix a bug where allTokens would not include the last token if it is missing
1 parent 6b06cf6 commit ed2e52c

File tree

3 files changed

+30
-13
lines changed

3 files changed

+30
-13
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -660,21 +660,22 @@ public protocol SyntaxChildChoices: SyntaxProtocol {}
660660
public struct TokenSequence: Sequence {
661661
public struct Iterator: IteratorProtocol {
662662
var nextToken: TokenSyntax?
663-
let endPosition: AbsolutePosition
663+
/// The last token to iterate (inclusive).
664+
let endToken: TokenSyntax?
664665
let viewMode: SyntaxTreeViewMode
665666

666-
init(_ token: TokenSyntax?, endPosition: AbsolutePosition, viewMode: SyntaxTreeViewMode) {
667+
init(_ token: TokenSyntax?, endToken: TokenSyntax?, viewMode: SyntaxTreeViewMode) {
667668
self.nextToken = token
668-
self.endPosition = endPosition
669+
self.endToken = endToken
669670
self.viewMode = viewMode
670671
}
671672

672673
public mutating func next() -> TokenSyntax? {
673674
guard let token = self.nextToken else { return nil }
674-
self.nextToken = token.nextToken(viewMode: viewMode)
675-
// Make sure we stop once we reach the end of the containing node.
676-
if let nextTok = self.nextToken, nextTok.position >= self.endPosition {
675+
if nextToken == endToken {
677676
self.nextToken = nil
677+
} else {
678+
self.nextToken = token.nextToken(viewMode: viewMode)
678679
}
679680
return token
680681
}
@@ -689,7 +690,7 @@ public struct TokenSequence: Sequence {
689690
}
690691

691692
public func makeIterator() -> Iterator {
692-
return Iterator(node.firstToken(viewMode: viewMode), endPosition: node.endPosition, viewMode: viewMode)
693+
return Iterator(node.firstToken(viewMode: viewMode), endToken: node.lastToken(viewMode: viewMode), viewMode: viewMode)
693694
}
694695

695696
public func reversed() -> ReversedTokenSequence {

Tests/SwiftIDEUtilsTest/ClassificationTests.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ public class ClassificationTests: XCTestCase {
117117
let tree = Parser.parse(source: source)
118118
do {
119119
let tokens = Array(tree.tokens(viewMode: .sourceAccurate))
120-
XCTAssertEqual(tokens.count, 4)
121-
guard tokens.count == 4 else {
120+
XCTAssertEqual(tokens.count, 5)
121+
guard tokens.count == 5 else {
122122
return
123123
}
124124
let classif = tokens.map { $0.tokenClassification }
@@ -130,6 +130,8 @@ public class ClassificationTests: XCTestCase {
130130
XCTAssertEqual(classif[2].range, ByteSourceRange(offset: 5, length: 1))
131131
XCTAssertEqual(classif[3].kind, .typeIdentifier)
132132
XCTAssertEqual(classif[3].range, ByteSourceRange(offset: 7, length: 3))
133+
XCTAssertEqual(classif[4].kind, .none)
134+
XCTAssertEqual(classif[4].range, ByteSourceRange(offset: 10, length: 0))
133135
}
134136
do {
135137
let tok = tree.lastToken(viewMode: .sourceAccurate)!.previousToken(viewMode: .sourceAccurate)!
@@ -145,8 +147,8 @@ public class ClassificationTests: XCTestCase {
145147
let tree = Parser.parse(source: source)
146148

147149
let tokens = Array(tree.tokens(viewMode: .sourceAccurate))
148-
XCTAssertEqual(tokens.count, 10)
149-
guard tokens.count == 10 else {
150+
XCTAssertEqual(tokens.count, 11)
151+
guard tokens.count == 11 else {
150152
return
151153
}
152154
let classif = tokens.map { $0.tokenClassification }
@@ -170,15 +172,17 @@ public class ClassificationTests: XCTestCase {
170172
XCTAssertEqual(classif[8].range, ByteSourceRange(offset: 19, length: 1))
171173
XCTAssertEqual(classif[9].kind, .integerLiteral)
172174
XCTAssertEqual(classif[9].range, ByteSourceRange(offset: 21, length: 1))
175+
XCTAssertEqual(classif[10].kind, .none)
176+
XCTAssertEqual(classif[10].range, ByteSourceRange(offset: 22, length: 0))
173177
}
174178

175179
do {
176180
let source = "infix operator *--*"
177181
let tree = Parser.parse(source: source)
178182

179183
let tokens = Array(tree.tokens(viewMode: .sourceAccurate))
180-
XCTAssertEqual(tokens.count, 3)
181-
guard tokens.count == 3 else {
184+
XCTAssertEqual(tokens.count, 4)
185+
guard tokens.count == 4 else {
182186
return
183187
}
184188
let classif = tokens.map { $0.tokenClassification }
@@ -188,6 +192,8 @@ public class ClassificationTests: XCTestCase {
188192
XCTAssertEqual(classif[1].range, ByteSourceRange(offset: 6, length: 8))
189193
XCTAssertEqual(classif[2].kind, .operatorIdentifier)
190194
XCTAssertEqual(classif[2].range, ByteSourceRange(offset: 15, length: 4))
195+
XCTAssertEqual(classif[3].kind, .none)
196+
XCTAssertEqual(classif[3].range, ByteSourceRange(offset: 19, length: 0))
191197
}
192198
}
193199
}

Tests/SwiftSyntaxTest/SyntaxChildrenTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,14 @@ public class SyntaxChildrenTests: XCTestCase {
7171
try XCTAssertNext(&fixedUpIt) { $0.is(TokenSyntax.self) }
7272
try XCTAssertNext(&fixedUpIt) { $0.is(MissingExprSyntax.self) }
7373
}
74+
75+
public func testTokenSequencesWithMissingChild() {
76+
let codeBlock = CodeBlockSyntax(
77+
leftBrace: .leftBraceToken(presence: .missing),
78+
statements: [],
79+
rightBrace: .rightBraceToken(presence: .missing)
80+
)
81+
82+
XCTAssertEqual(Array(codeBlock.tokens(viewMode: .all)).count, 2)
83+
}
7484
}

0 commit comments

Comments
 (0)