Skip to content

Commit c45d659

Browse files
authored
Merge pull request #16264 from nkcsgexi/cache-absolute-pos-c-plus
libSyntax: cache absolute positions on SyntaxData.
2 parents 6bdd24d + 7b4218c commit c45d659

File tree

6 files changed

+74
-57
lines changed

6 files changed

+74
-57
lines changed

include/swift/Syntax/RawSyntax.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ class RawSyntax final
458458
llvm::Optional<AbsolutePosition>
459459
accumulateAbsolutePosition(AbsolutePosition &Pos) const;
460460

461+
/// Advance the provided AbsolutePosition by the first trivia of this node.
462+
/// Return true if we found this trivia; otherwise false.
463+
bool accumulateLeadingTrivia(AbsolutePosition &Pos) const;
464+
461465
/// Print this piece of syntax recursively.
462466
void print(llvm::raw_ostream &OS, SyntaxPrintOptions Opts) const;
463467

include/swift/Syntax/Syntax.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,9 @@ class Syntax {
190190

191191
/// Get the absolute position of this raw syntax: its offset, line,
192192
/// and column.
193-
AbsolutePosition getAbsolutePosition() const;
193+
AbsolutePosition getAbsolutePosition() const {
194+
return Data->getAbsolutePosition();
195+
}
194196

195197
// TODO: hasSameStructureAs ?
196198
};

include/swift/Syntax/SyntaxData.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class SyntaxData final
7878
/// If there is no parent, this is 0.
7979
const CursorIndex IndexInParent;
8080

81+
/// Cache the absolute position of this node.
82+
Optional<AbsolutePosition> PositionCache;
83+
8184
size_t numTrailingObjects(OverloadToken<AtomicCache<SyntaxData>>) const {
8285
return Raw->getNumChildren();
8386
}
@@ -129,6 +132,13 @@ class SyntaxData final
129132
return {getTrailingObjects<AtomicCache<SyntaxData>>(), getNumChildren()};
130133
}
131134

135+
/// Get the node immediately before this current node. Return 0 if we cannot
136+
/// find such node.
137+
RC<SyntaxData> getPreviousNode() const;
138+
139+
/// Get the absolute position without skipping the leading trivia of this node.
140+
AbsolutePosition getAbsolutePositionWithLeadingTrivia() const;
141+
132142
public:
133143
~SyntaxData() {
134144
for (auto &I : getChildren())
@@ -235,6 +245,10 @@ class SyntaxData final
235245
});
236246
}
237247

248+
/// Calculate the absolute position of this node, use cache if the cache
249+
/// is populated.
250+
AbsolutePosition getAbsolutePosition() const;
251+
238252
/// Returns true if the data node represents type syntax.
239253
bool isType() const;
240254

lib/Syntax/RawSyntax.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,24 @@ RawSyntax::accumulateAbsolutePosition(AbsolutePosition &Pos) const {
189189
return Ret;
190190
}
191191

192+
bool RawSyntax::accumulateLeadingTrivia(AbsolutePosition &Pos) const {
193+
if (isToken()) {
194+
if (!isMissing()) {
195+
for (auto &Leader: getLeadingTrivia())
196+
Leader.accumulateAbsolutePosition(Pos);
197+
return true;
198+
}
199+
} else {
200+
for (auto &Child: getLayout()) {
201+
if (!Child)
202+
continue;
203+
if (Child->accumulateLeadingTrivia(Pos))
204+
return true;
205+
}
206+
}
207+
return false;
208+
}
209+
192210
void RawSyntax::print(llvm::raw_ostream &OS, SyntaxPrintOptions Opts) const {
193211
if (isMissing())
194212
return;

lib/Syntax/Syntax.cpp

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -96,59 +96,3 @@ llvm::Optional<Syntax> Syntax::getChild(const size_t N) const {
9696
return llvm::None;
9797
return Syntax {Root, ChildData.get()};
9898
}
99-
100-
AbsolutePosition Syntax::getAbsolutePosition() const {
101-
assert(getRoot().is<SourceFileSyntax>() &&
102-
"Absolute position can only be calculated for nodes which has "
103-
"SourceFile root");
104-
AbsolutePosition Pos;
105-
106-
/// This visitor collects all of the nodes before this node to calculate its
107-
/// offset from the begenning of the file.
108-
class Visitor: public SyntaxVisitor {
109-
AbsolutePosition &Pos;
110-
const SyntaxData *Target;
111-
bool Found = false;
112-
113-
public:
114-
Visitor(AbsolutePosition &Pos, const SyntaxData *Target)
115-
: Pos(Pos), Target(Target) {}
116-
~Visitor() { assert(Found); }
117-
void visitPre(Syntax Node) override {
118-
// Check if this node is the target;
119-
Found |= Node.getDataPointer() == Target;
120-
}
121-
void visit(TokenSyntax Node) override {
122-
// Ignore missing node and ignore the nodes after this node.
123-
if (Found || Node.isMissing())
124-
return;
125-
// Collect all the offsets.
126-
Node.getRaw()->accumulateAbsolutePosition(Pos);
127-
}
128-
} Calculator(Pos, getDataPointer());
129-
130-
/// This visitor visit the first token node of this node to accumulate its
131-
/// leading trivia. Therefore, the calculated absolute location will point
132-
/// to the actual token start.
133-
class FirstTokenFinder: public SyntaxVisitor {
134-
AbsolutePosition &Pos;
135-
bool Found = false;
136-
137-
public:
138-
FirstTokenFinder(AbsolutePosition &Pos): Pos(Pos) {}
139-
void visit(TokenSyntax Node) override {
140-
if (Found || Node.isMissing())
141-
return;
142-
Found = true;
143-
for (auto &Leader : Node.getRaw()->getLeadingTrivia())
144-
Leader.accumulateAbsolutePosition(Pos);
145-
}
146-
} FTFinder(Pos);
147-
148-
// Visit the root to get all the nodes before this node.
149-
getRoot().accept(Calculator);
150-
151-
// Visit this node to accumulate the leading trivia of its first token.
152-
const_cast<Syntax*>(this)->accept(FTFinder);
153-
return Pos;
154-
}

lib/Syntax/SyntaxData.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,38 @@ bool SyntaxData::isUnknown() const {
5050
void SyntaxData::dump(llvm::raw_ostream &OS) const {
5151
Raw->dump(OS, 0);
5252
}
53+
54+
RC<SyntaxData> SyntaxData::getPreviousNode() const {
55+
if (size_t N = getIndexInParent()) {
56+
if (hasParent()) {
57+
for (size_t I = N - 1; ; I--) {
58+
if (auto C = getParent()->getChild(I)) {
59+
return C;
60+
}
61+
if (I == 0)
62+
break;
63+
}
64+
}
65+
}
66+
return hasParent() ? Parent->getPreviousNode() : nullptr;
67+
}
68+
69+
AbsolutePosition SyntaxData::getAbsolutePositionWithLeadingTrivia() const {
70+
if (PositionCache.hasValue())
71+
return *PositionCache;
72+
if (auto P = getPreviousNode()) {
73+
auto Result = P->getAbsolutePositionWithLeadingTrivia();
74+
P->getRaw()->accumulateAbsolutePosition(Result);
75+
// FIXME: avoid using const_cast.
76+
const_cast<SyntaxData*>(this)->PositionCache = Result;
77+
} else {
78+
const_cast<SyntaxData*>(this)->PositionCache = AbsolutePosition();
79+
}
80+
return *PositionCache;
81+
}
82+
83+
AbsolutePosition SyntaxData::getAbsolutePosition() const {
84+
auto Result = getAbsolutePositionWithLeadingTrivia();
85+
getRaw()->accumulateLeadingTrivia(Result);
86+
return Result;
87+
}

0 commit comments

Comments
 (0)