Skip to content

Commit 5a8053e

Browse files
committed
libSyntax: add getAbsoluteEndPosition() method to syntax nodes.
This implementation uses sibling's absolute start position to help populate caches while getting the end position.
1 parent 574e556 commit 5a8053e

File tree

5 files changed

+73
-0
lines changed

5 files changed

+73
-0
lines changed

include/swift/Syntax/Syntax.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ class Syntax {
194194
return Data->getAbsolutePosition();
195195
}
196196

197+
/// Get the absolute end position (exclusively) of this raw syntax: its offset,
198+
/// line, and column.
199+
AbsolutePosition getAbsoluteEndPosition() const {
200+
return Data->getAbsoluteEndPosition();
201+
}
197202
// TODO: hasSameStructureAs ?
198203
};
199204

include/swift/Syntax/SyntaxData.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ class SyntaxData final
136136
/// find such node.
137137
RC<SyntaxData> getPreviousNode() const;
138138

139+
/// Get the node immediately after this current node. Return 0 if we cannot
140+
/// find such node.
141+
RC<SyntaxData> getNextNode() const;
142+
139143
/// Get the absolute position without skipping the leading trivia of this node.
140144
AbsolutePosition getAbsolutePositionWithLeadingTrivia() const;
141145

@@ -249,6 +253,10 @@ class SyntaxData final
249253
/// is populated.
250254
AbsolutePosition getAbsolutePosition() const;
251255

256+
/// Calculate the absolute end position of this node, use cache of the immediate
257+
/// next node if populated.
258+
AbsolutePosition getAbsoluteEndPosition() const;
259+
252260
/// Returns true if the data node represents type syntax.
253261
bool isType() const;
254262

lib/Syntax/SyntaxData.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ RC<SyntaxData> SyntaxData::getPreviousNode() const {
6666
return hasParent() ? Parent->getPreviousNode() : nullptr;
6767
}
6868

69+
RC<SyntaxData> SyntaxData::getNextNode() const {
70+
if (hasParent()) {
71+
for (size_t I = getIndexInParent() + 1, N = Parent->getNumChildren();
72+
I != N; I++) {
73+
if (auto C = getParent()->getChild(I))
74+
return C;
75+
}
76+
return Parent->getNextNode();
77+
}
78+
return nullptr;
79+
}
80+
6981
AbsolutePosition SyntaxData::getAbsolutePositionWithLeadingTrivia() const {
7082
if (PositionCache.hasValue())
7183
return *PositionCache;
@@ -85,3 +97,13 @@ AbsolutePosition SyntaxData::getAbsolutePosition() const {
8597
getRaw()->accumulateLeadingTrivia(Result);
8698
return Result;
8799
}
100+
101+
AbsolutePosition SyntaxData::getAbsoluteEndPosition() const {
102+
if (auto N = getNextNode()) {
103+
return N->getAbsolutePositionWithLeadingTrivia();
104+
} else {
105+
auto Result = getAbsolutePositionWithLeadingTrivia();
106+
getRaw()->accumulateAbsolutePosition(Result);
107+
return Result;
108+
}
109+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "swift/Syntax/SyntaxFactory.h"
2+
#include "swift/Syntax/SyntaxNodes.h"
3+
#include "swift/Syntax/SyntaxBuilders.h"
4+
#include "llvm/ADT/SmallString.h"
5+
#include "gtest/gtest.h"
6+
7+
using namespace swift;
8+
using namespace swift::syntax;
9+
10+
TEST(PositionTests, AbsolutePosition1) {
11+
Trivia Leading;
12+
Leading.Pieces = {TriviaPiece::newlines(2), TriviaPiece::carriageReturns(2),
13+
TriviaPiece::carriageReturnLineFeeds(2)};
14+
auto Token = SyntaxFactory::makeIdentifier("aaa", Leading, {});
15+
AbsolutePosition Pos = Token.getAbsolutePosition();
16+
ASSERT_EQ(7u, Pos.getLine());
17+
ASSERT_EQ(1u, Pos.getColumn());
18+
ASSERT_EQ(8u, Pos.getOffset());
19+
AbsolutePosition EndPos = Token.getAbsoluteEndPosition();
20+
ASSERT_EQ(7u, EndPos.getLine());
21+
ASSERT_EQ(4u, EndPos.getColumn());
22+
ASSERT_EQ(11u, EndPos.getOffset());
23+
}
24+
25+
TEST(PositionTests, AbsolutePosition2) {
26+
Trivia Leading;
27+
Leading.Pieces = { TriviaPiece::blockComment("/* \n\r\r\n */") };
28+
auto Token = SyntaxFactory::makeIdentifier("aaa", Leading, {});
29+
AbsolutePosition Pos = Token.getAbsolutePosition();
30+
ASSERT_EQ(4u, Pos.getLine());
31+
ASSERT_EQ(4u, Pos.getColumn());
32+
ASSERT_EQ(10u, Pos.getOffset());
33+
AbsolutePosition EndPos = Token.getAbsoluteEndPosition();
34+
ASSERT_EQ(4u, EndPos.getLine());
35+
ASSERT_EQ(7u, EndPos.getColumn());
36+
ASSERT_EQ(13u, EndPos.getOffset());
37+
}

unittests/Syntax/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_swift_unittest(SwiftSyntaxTests
99
TriviaTests.cpp
1010
TypeSyntaxTests.cpp
1111
UnknownSyntaxTests.cpp
12+
AbsolutePositionTests.cpp
1213
)
1314

1415
target_link_libraries(SwiftSyntaxTests

0 commit comments

Comments
 (0)