Skip to content

Commit dc958d6

Browse files
authored
Merge pull request swiftlang#18078 from ahoppen/01#2-record-reused-node-ids
[libSyntax] Record reused node IDs
2 parents 85a1371 + c8226d1 commit dc958d6

File tree

10 files changed

+122
-100
lines changed

10 files changed

+122
-100
lines changed

include/swift/Parse/SyntaxParsingCache.h

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/Syntax/SyntaxNodes.h"
1717
#include "llvm/Support/FileSystem.h"
1818
#include "llvm/Support/raw_ostream.h"
19+
#include <unordered_set>
1920

2021
namespace {
2122

@@ -48,10 +49,8 @@ namespace swift {
4849
using namespace swift::syntax;
4950

5051
struct SyntaxReuseRegion {
51-
/// The byte offset at which the range begins
52-
uintptr_t Start;
53-
/// The byte offset at which the end ends
54-
uintptr_t End;
52+
AbsolutePosition Start;
53+
AbsolutePosition End;
5554
};
5655

5756
class SyntaxParsingCache {
@@ -62,13 +61,8 @@ class SyntaxParsingCache {
6261
/// the source file that is now parsed incrementally
6362
llvm::SmallVector<SourceEdit, 4> Edits;
6463

65-
/// Whether or not information about reused nodes shall be recored in
66-
/// \c ReusedRanges
67-
bool RecordReuseInformation = false;
68-
69-
/// If \c RecordReuseInformation buffer offsets of ranges that have been
70-
/// successfully looked up in this cache are stored.
71-
std::vector<SyntaxReuseRegion> ReusedRanges;
64+
/// The IDs of all syntax nodes that got reused are collected in this vector.
65+
std::unordered_set<SyntaxNodeId> ReusedNodeIds;
7266

7367
public:
7468
SyntaxParsingCache(SourceFileSyntax OldSyntaxTree)
@@ -86,16 +80,15 @@ class SyntaxParsingCache {
8680
/// reused for a new syntax tree.
8781
llvm::Optional<Syntax> lookUp(size_t NewPosition, SyntaxKind Kind);
8882

89-
/// Turn recording of reused ranges on
90-
void setRecordReuseInformation() { RecordReuseInformation = true; }
91-
92-
/// Return the ranges of the new source file that have been successfully
93-
/// looked up in this cache as a (start, end) pair of byte offsets in the
94-
/// post-edit file.
95-
std::vector<SyntaxReuseRegion> getReusedRanges() const {
96-
return ReusedRanges;
83+
const std::unordered_set<SyntaxNodeId> &getReusedNodeIds() const {
84+
return ReusedNodeIds;
9785
}
9886

87+
/// Get the source regions of the new source file, represented by
88+
/// \p SyntaxTree that have been reused as part of the incremental parse.
89+
std::vector<SyntaxReuseRegion>
90+
getReusedRegions(const SourceFileSyntax &SyntaxTree) const;
91+
9992
private:
10093
llvm::Optional<Syntax> lookUpFrom(const Syntax &Node, size_t Position,
10194
SyntaxKind Kind);

include/swift/Syntax/RawSyntax.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ struct SyntaxPrintOptions {
212212
bool PrintTrivialNodeKind = false;
213213
};
214214

215+
typedef unsigned SyntaxNodeId;
216+
215217
/// RawSyntax - the strictly immutable, shared backing nodes for all syntax.
216218
///
217219
/// This is implementation detail - do not expose it in public API.
@@ -223,10 +225,10 @@ class RawSyntax final
223225

224226
/// The ID that shall be used for the next node that is created and does not
225227
/// have a manually specified id
226-
static unsigned NextFreeNodeId;
228+
static SyntaxNodeId NextFreeNodeId;
227229

228230
/// An ID of this node that is stable across incremental parses
229-
unsigned NodeId;
231+
SyntaxNodeId NodeId;
230232

231233
union {
232234
uint64_t OpaqueBits;
@@ -283,13 +285,13 @@ class RawSyntax final
283285
/// the caller needs to assure that the node ID has not been used yet.
284286
RawSyntax(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
285287
SourcePresence Presence, bool ManualMemory,
286-
llvm::Optional<unsigned> NodeId);
288+
llvm::Optional<SyntaxNodeId> NodeId);
287289
/// Constructor for creating token nodes
288290
/// If \p NodeId is \c None, the next free NodeId is used, if it is passed,
289291
/// the caller needs to assure that the NodeId has not been used yet.
290292
RawSyntax(tok TokKind, OwnedString Text, ArrayRef<TriviaPiece> LeadingTrivia,
291293
ArrayRef<TriviaPiece> TrailingTrivia, SourcePresence Presence,
292-
bool ManualMemory, llvm::Optional<unsigned> NodeId);
294+
bool ManualMemory, llvm::Optional<SyntaxNodeId> NodeId);
293295

294296
public:
295297
~RawSyntax();
@@ -312,15 +314,15 @@ class RawSyntax final
312314
static RC<RawSyntax> make(SyntaxKind Kind, ArrayRef<RC<RawSyntax>> Layout,
313315
SourcePresence Presence,
314316
SyntaxArena *Arena = nullptr,
315-
llvm::Optional<unsigned> NodeId = llvm::None);
317+
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
316318

317319
/// Make a raw "token" syntax node.
318320
static RC<RawSyntax> make(tok TokKind, OwnedString Text,
319321
ArrayRef<TriviaPiece> LeadingTrivia,
320322
ArrayRef<TriviaPiece> TrailingTrivia,
321323
SourcePresence Presence,
322324
SyntaxArena *Arena = nullptr,
323-
llvm::Optional<unsigned> NodeId = llvm::None);
325+
llvm::Optional<SyntaxNodeId> NodeId = llvm::None);
324326

325327
/// Make a missing raw "layout" syntax node.
326328
static RC<RawSyntax> missing(SyntaxKind Kind, SyntaxArena *Arena = nullptr) {
@@ -349,7 +351,7 @@ class RawSyntax final
349351
}
350352

351353
/// Get an ID for this node that is stable across incremental parses
352-
unsigned getId() const { return NodeId; }
354+
SyntaxNodeId getId() const { return NodeId; }
353355

354356
/// Returns true if the node is "missing" in the source (i.e. it was
355357
/// expected (or optional) but not written.
@@ -523,4 +525,8 @@ class RawSyntax final
523525
} // end namespace syntax
524526
} // end namespace swift
525527

528+
namespace llvm {
529+
raw_ostream &operator<<(raw_ostream &OS, swift::syntax::AbsolutePosition Pos);
530+
} // end namespace llvm
531+
526532
#endif // SWIFT_SYNTAX_RAWSYNTAX_H

include/swift/Syntax/Syntax.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class Syntax {
8585
RC<RawSyntax> getRaw() const;
8686

8787
/// Get an ID for this node that is stable across incremental parses
88-
unsigned getId() const { return getRaw()->getId(); }
88+
SyntaxNodeId getId() const { return getRaw()->getId(); }
8989

9090
/// Get the number of child nodes in this piece of syntax, not including
9191
/// tokens.

include/swift/Syntax/SyntaxClassifier.h.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class SyntaxClassifier: public SyntaxVisitor {
6969
ForceClassification(ForceClassification) {}
7070
};
7171

72-
std::map<unsigned, SyntaxClassification> ClassifiedTokens;
72+
std::map<SyntaxNodeId, SyntaxClassification> ClassifiedTokens;
7373
/// The top classification of this stack determines the color of identifiers
7474
std::stack<ContextStackEntry, llvm::SmallVector<ContextStackEntry, 16>> ContextStack;
7575

@@ -101,7 +101,7 @@ class SyntaxClassifier: public SyntaxVisitor {
101101
% end
102102

103103
public:
104-
std::map<unsigned, SyntaxClassification> classify(Syntax Node) {
104+
std::map<SyntaxNodeId, SyntaxClassification> classify(Syntax Node) {
105105
// Clean up the environment
106106
ContextStack = std::stack<ContextStackEntry, llvm::SmallVector<ContextStackEntry, 16>>();
107107
ContextStack.push({SyntaxClassification::None, false});

lib/Parse/SyntaxParsingCache.cpp

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Parse/SyntaxParsingCache.h"
14+
#include "swift/Syntax/SyntaxVisitor.h"
1415

1516
using namespace swift;
1617
using namespace swift::syntax;
@@ -84,10 +85,54 @@ llvm::Optional<Syntax> SyntaxParsingCache::lookUp(size_t NewPosition,
8485

8586
auto Node = lookUpFrom(OldSyntaxTree, OldPosition, Kind);
8687
if (Node.hasValue()) {
87-
if (RecordReuseInformation) {
88-
ReusedRanges.push_back(
89-
{NewPosition, NewPosition + Node->getTextLength()});
90-
}
88+
ReusedNodeIds.insert(Node->getId());
9189
}
9290
return Node;
9391
}
92+
93+
std::vector<SyntaxReuseRegion>
94+
SyntaxParsingCache::getReusedRegions(const SourceFileSyntax &SyntaxTree) const {
95+
/// Determines the reused source regions from reused syntax node IDs
96+
class ReusedRegionsCollector : public SyntaxVisitor {
97+
std::unordered_set<SyntaxNodeId> ReusedNodeIds;
98+
std::vector<SyntaxReuseRegion> ReusedRegions;
99+
100+
bool didReuseNode(SyntaxNodeId NodeId) {
101+
return ReusedNodeIds.count(NodeId) > 0;
102+
}
103+
104+
public:
105+
ReusedRegionsCollector(std::unordered_set<SyntaxNodeId> ReusedNodeIds)
106+
: ReusedNodeIds(ReusedNodeIds) {}
107+
108+
const std::vector<SyntaxReuseRegion> &getReusedRegions() {
109+
std::sort(ReusedRegions.begin(), ReusedRegions.end(),
110+
[](const SyntaxReuseRegion &Lhs,
111+
const SyntaxReuseRegion &Rhs) -> bool {
112+
return Lhs.Start.getOffset() < Rhs.Start.getOffset();
113+
});
114+
return ReusedRegions;
115+
}
116+
117+
void visit(Syntax Node) override {
118+
if (didReuseNode(Node.getId())) {
119+
// Node has been reused, add it to the list
120+
auto Start = Node.getAbsolutePositionBeforeLeadingTrivia();
121+
auto End = Node.getAbsoluteEndPositionAfterTrailingTrivia();
122+
ReusedRegions.push_back({Start, End});
123+
} else {
124+
SyntaxVisitor::visit(Node);
125+
}
126+
}
127+
128+
void collectReusedRegions(SourceFileSyntax Node) {
129+
assert(ReusedRegions.empty() &&
130+
"ReusedRegionsCollector cannot be reused");
131+
Node.accept(*this);
132+
}
133+
};
134+
135+
ReusedRegionsCollector ReuseRegionsCollector(getReusedNodeIds());
136+
ReuseRegionsCollector.collectReusedRegions(SyntaxTree);
137+
return ReuseRegionsCollector.getReusedRegions();
138+
}

lib/Syntax/RawSyntax.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,8 @@ void RawSyntax::Profile(llvm::FoldingSetNodeID &ID, tok TokKind,
343343
for (auto &Piece : TrailingTrivia)
344344
Piece.Profile(ID);
345345
}
346+
347+
llvm::raw_ostream &llvm::operator<<(raw_ostream &OS, AbsolutePosition Pos) {
348+
Pos.printLineAndColumn(OS);
349+
return OS;
350+
}

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -562,12 +562,12 @@ struct SwiftSyntaxMap {
562562
class SyntaxToSyntaxMapConverter : public SyntaxVisitor {
563563
SwiftSyntaxMap &SyntaxMap;
564564

565-
std::map<unsigned, SyntaxClassification> TokenClassifications;
565+
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications;
566566

567567
public:
568568
SyntaxToSyntaxMapConverter(
569569
SwiftSyntaxMap &SyntaxMap,
570-
std::map<unsigned, SyntaxClassification> TokenClassifications)
570+
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications)
571571
: SyntaxMap(SyntaxMap), TokenClassifications(TokenClassifications) {}
572572

573573
private:
@@ -2013,18 +2013,6 @@ SwiftEditorDocument::getSyntaxTree() const {
20132013
return Impl.SyntaxTree;
20142014
}
20152015

2016-
const SourceManager &SwiftEditorDocument::getSourceManager() const {
2017-
return Impl.SyntaxInfo->getSourceManager();
2018-
}
2019-
2020-
SourceManager &SwiftEditorDocument::getSourceManager() {
2021-
return Impl.SyntaxInfo->getSourceManager();
2022-
}
2023-
2024-
unsigned SwiftEditorDocument::getBufferID() const {
2025-
return Impl.SyntaxInfo->getBufferID();
2026-
}
2027-
20282016
std::string SwiftEditorDocument::getFilePath() const { return Impl.FilePath; }
20292017

20302018
bool SwiftEditorDocument::hasUpToDateAST() const {
@@ -2371,7 +2359,6 @@ void SwiftLangSupport::editorReplaceText(StringRef Name,
23712359
if (EditorDoc->getSyntaxTree().hasValue()) {
23722360
SyntaxCache.emplace(EditorDoc->getSyntaxTree().getValue());
23732361
SyntaxCache->addEdit(Offset, Offset + Length, Buf->getBufferSize());
2374-
SyntaxCache->setRecordReuseInformation();
23752362
}
23762363

23772364
SyntaxParsingCache *SyntaxCachePtr = nullptr;
@@ -2386,37 +2373,35 @@ void SwiftLangSupport::editorReplaceText(StringRef Name,
23862373
// Avoid computing the reused ranges if the consumer doesn't care about
23872374
// them
23882375
if (Consumer.syntaxReuseInfoEnabled()) {
2389-
auto ReuseRegions = SyntaxCache->getReusedRanges();
2376+
auto &SyntaxTree = EditorDoc->getSyntaxTree();
2377+
auto ReuseRegions = SyntaxCache->getReusedRegions(*SyntaxTree);
2378+
2379+
// Abstract away from SyntaxReuseRegions to std::pair<unsigned, unsigned>
2380+
// so that SourceKit doesn't have to import swiftParse
23902381
std::vector<SourceFileRange> ReuseRegionOffsets;
23912382
ReuseRegionOffsets.reserve(ReuseRegions.size());
23922383
for (auto ReuseRegion : ReuseRegions) {
2393-
auto Start = ReuseRegion.Start;
2394-
auto End = ReuseRegion.End;
2384+
auto Start = ReuseRegion.Start.getOffset();
2385+
auto End = ReuseRegion.End.getOffset();
23952386
ReuseRegionOffsets.push_back({Start, End});
23962387
}
23972388
Consumer.handleSyntaxReuseRegions(ReuseRegionOffsets);
23982389
}
23992390
if (LogReuseRegions) {
2391+
auto &SyntaxTree = EditorDoc->getSyntaxTree();
2392+
auto ReuseRegions = SyntaxCache->getReusedRegions(*SyntaxTree);
24002393
LOG_SECTION("SyntaxCache", InfoHighPrio) {
24012394
Log->getOS() << "Reused ";
24022395

24032396
bool FirstIteration = true;
2404-
unsigned LastPrintedBufferID;
2405-
for (auto ReuseRegion : SyntaxCache->getReusedRanges()) {
2397+
for (auto ReuseRegion : ReuseRegions) {
24062398
if (!FirstIteration) {
24072399
Log->getOS() << ", ";
24082400
} else {
24092401
FirstIteration = false;
24102402
}
24112403

2412-
const SourceManager &SM = EditorDoc->getSourceManager();
2413-
unsigned BufferID = EditorDoc->getBufferID();
2414-
auto Start = SM.getLocForOffset(BufferID, ReuseRegion.Start);
2415-
auto End = SM.getLocForOffset(BufferID, ReuseRegion.End);
2416-
2417-
Start.print(Log->getOS(), SM, LastPrintedBufferID);
2418-
Log->getOS() << " - ";
2419-
End.print(Log->getOS(), SM, LastPrintedBufferID);
2404+
Log->getOS() << ReuseRegion.Start << " - " << ReuseRegion.End;
24202405
}
24212406
}
24222407
}

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,6 @@ class SwiftEditorDocument :
110110

111111
const llvm::Optional<swift::SourceFileSyntax> &getSyntaxTree() const;
112112

113-
const swift::SourceManager &getSourceManager() const;
114-
swift::SourceManager &getSourceManager();
115-
116-
/// Get the buffer ID of this file in its source manager
117-
unsigned getBufferID() const;
118-
119113
std::string getFilePath() const;
120114

121115
/// Whether or not the AST stored for this document is up-to-date or just an

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ class PrintSyntaxColorWalker : public ide::SyntaxModelWalker {
960960
class ColoredSyntaxTreePrinter : public SyntaxVisitor {
961961
llvm::raw_ostream &OS;
962962

963-
std::map<unsigned, SyntaxClassification> TokenClassifications;
963+
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications;
964964

965965
/// The name of the tag that is currently open
966966
StringRef CurrentTag;
@@ -972,7 +972,7 @@ class ColoredSyntaxTreePrinter : public SyntaxVisitor {
972972
public:
973973
ColoredSyntaxTreePrinter(
974974
llvm::raw_ostream &OS,
975-
std::map<unsigned, SyntaxClassification> TokenClassifications)
975+
std::map<SyntaxNodeId, SyntaxClassification> TokenClassifications)
976976
: OS(OS), TokenClassifications(TokenClassifications) {}
977977

978978
private:

0 commit comments

Comments
 (0)