Skip to content

Commit 734f534

Browse files
authored
Merge pull request #1031 from DougGregor/token-at-position
2 parents f4f791e + 5d35d58 commit 734f534

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

Sources/SwiftSyntax/Syntax.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,25 @@ public extension SyntaxProtocol {
320320
return nil
321321
}
322322

323+
/// Find the syntax token at the given absolute position within this
324+
/// syntax node or any of its children.
325+
func token(at position: AbsolutePosition) -> TokenSyntax? {
326+
// If the position isn't within this node at all, return early.
327+
guard position >= self.position && position < self.endPosition else {
328+
return nil
329+
}
330+
331+
// If we are a token syntax, that's it!
332+
if let token = Syntax(self).as(TokenSyntax.self) {
333+
return token
334+
}
335+
336+
// Otherwise, it must be one of our children.
337+
return children(viewMode: .sourceAccurate).lazy.compactMap { child in
338+
child.token(at: position)
339+
}.first
340+
}
341+
323342
/// The absolute position of the starting point of this node. If the first token
324343
/// is with leading trivia, the position points to the start of the leading
325344
/// trivia.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// This source file is part of the Swift.org open source project
5+
//
6+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
7+
// Licensed under Apache License v2.0 with Runtime Library Exception
8+
//
9+
// See https://swift.org/LICENSE.txt for license information
10+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
import XCTest
15+
import SwiftSyntax
16+
import SwiftParser
17+
import _SwiftSyntaxTestSupport
18+
19+
public class AbsolutePositionTests: XCTestCase {
20+
public func testTokenAt() {
21+
let source =
22+
"""
23+
func f(a: Int) { }
24+
"""
25+
26+
let parsed = Parser.parse(source: source)
27+
for expectedToken in parsed.tokens(viewMode: .sourceAccurate) {
28+
let tokenStart = expectedToken.position.utf8Offset
29+
let tokenEnd = expectedToken.endPosition.utf8Offset
30+
for offset in tokenStart..<tokenEnd {
31+
let token = parsed.token(at: AbsolutePosition(utf8Offset: offset))
32+
XCTAssertEqual(token, expectedToken)
33+
}
34+
}
35+
}
36+
}
37+

0 commit comments

Comments
 (0)