Skip to content

Commit 350ac15

Browse files
committed
[libSyntax] Only keep track of range in ParsedRawSyntaxNode if verifying element ranges
This makes ParsedRawSyntaxNode a zero-cost wrapper around RecordedOrDeferredNode in the case that ranges are not verified.
1 parent 0d913e9 commit 350ac15

File tree

8 files changed

+246
-125
lines changed

8 files changed

+246
-125
lines changed

include/swift/Parse/ParsedRawSyntaxNode.h

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@
2121
#include "swift/Syntax/SyntaxKind.h"
2222
#include "llvm/Support/Debug.h"
2323

24+
#ifndef NDEBUG
25+
/// Whether \c ParsedRawSyntaxNode should keep track of its range and verify
26+
/// that the children of layout nodes have consecutive ranges.
27+
/// Because this significantly changes the way, \c ParsedRawSyntaxNode and
28+
/// \c ParsedRawSyntaxNodeRecorder are being compiled, this is a separate
29+
/// constant from \c NDEBUG, so that it can be toggled independently to \c
30+
/// NDEBUG during development.
31+
#define PARSEDRAWSYNTAXNODE_VERIFY_RANGES 1
32+
#endif
33+
2434
namespace swift {
2535

2636
typedef const void *OpaqueSyntaxNode;
@@ -48,8 +58,13 @@ class ParsedRawSyntaxNode {
4858
/// SyntaxParseActions, which created it.
4959
RecordedOrDeferredNode Data;
5060

61+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
5162
/// The range of this node, including trivia.
63+
/// Only store this as a member when it's actually needed to keep \c
64+
/// ParsedRawSyntaxNode as small as possible, which improves performance
65+
/// when it is being passed around.
5266
CharSourceRange Range;
67+
#endif
5368
uint16_t SynKind;
5469
uint16_t TokKind;
5570
/// Primary used for capturing a deferred missing token.
@@ -62,24 +77,46 @@ class ParsedRawSyntaxNode {
6277
// MARK: - Constructors
6378

6479
ParsedRawSyntaxNode()
65-
: Data(nullptr, DataKind::Null), Range(),
80+
: Data(nullptr, DataKind::Null),
6681
SynKind(uint16_t(syntax::SyntaxKind::Unknown)),
6782
TokKind(uint16_t(tok::unknown)) {}
6883

69-
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, CharSourceRange Range,
70-
syntax::SyntaxKind SynKind, tok TokKind, DataKind DK,
71-
bool IsMissing)
72-
: Data(Opaque, DK), Range(Range), SynKind(uint16_t(SynKind)),
84+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
85+
ParsedRawSyntaxNode(RecordedOrDeferredNode Data, syntax::SyntaxKind SynKind,
86+
tok TokKind, bool IsMissing, CharSourceRange Range)
87+
: Data(Data), Range(Range), SynKind(uint16_t(SynKind)),
7388
TokKind(uint16_t(TokKind)), IsMissing(IsMissing) {
7489
assert(getKind() == SynKind && "Syntax kind with too large value!");
7590
assert(getTokenKind() == TokKind && "Token kind with too large value!");
7691
}
7792

93+
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, syntax::SyntaxKind SynKind,
94+
tok TokKind, DataKind DK, bool IsMissing,
95+
CharSourceRange Range)
96+
: ParsedRawSyntaxNode(RecordedOrDeferredNode(Opaque, DK), SynKind,
97+
TokKind, IsMissing, Range) {}
98+
#else
99+
ParsedRawSyntaxNode(RecordedOrDeferredNode Data, syntax::SyntaxKind SynKind,
100+
tok TokKind, bool IsMissing)
101+
: Data(Data), SynKind(uint16_t(SynKind)), TokKind(uint16_t(TokKind)),
102+
IsMissing(IsMissing) {
103+
assert(getKind() == SynKind && "Syntax kind with too large value!");
104+
assert(getTokenKind() == TokKind && "Token kind with too large value!");
105+
}
106+
107+
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, syntax::SyntaxKind SynKind,
108+
tok TokKind, DataKind DK, bool IsMissing)
109+
: ParsedRawSyntaxNode(RecordedOrDeferredNode(Opaque, DK), SynKind,
110+
TokKind, IsMissing) {}
111+
#endif
112+
78113
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
79114
assert(ensureDataIsNotRecorded() &&
80115
"recorded data is being destroyed by assignment");
81116
Data = std::move(other.Data);
117+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
82118
Range = std::move(other.Range);
119+
#endif
83120
SynKind = std::move(other.SynKind);
84121
TokKind = std::move(other.TokKind);
85122
IsMissing = std::move(other.IsMissing);
@@ -91,9 +128,7 @@ class ParsedRawSyntaxNode {
91128
*this = std::move(other);
92129
}
93130

94-
static ParsedRawSyntaxNode null() {
95-
return ParsedRawSyntaxNode{};
96-
}
131+
static ParsedRawSyntaxNode null() { return ParsedRawSyntaxNode(); }
97132

98133
~ParsedRawSyntaxNode() {
99134
assert(ensureDataIsNotRecorded() && "recorded data is being destructed");
@@ -152,8 +187,13 @@ class ParsedRawSyntaxNode {
152187
}
153188
bool isMissing() const { return IsMissing; }
154189

190+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
155191
/// Returns the range of this node including leading and trailing trivia.
192+
///
193+
/// This method is only present if \c ParsedRawSyntaxNode is keeping track
194+
/// of its range to verify element ranges.
156195
CharSourceRange getRange() const { return Range; }
196+
#endif
157197

158198
size_t
159199
getDeferredNumChildren(const SyntaxParsingContext *SyntaxContext) const;
@@ -174,13 +214,17 @@ class ParsedRawSyntaxNode {
174214
SynKind = uint16_t(syntax::SyntaxKind::Unknown);
175215
TokKind = uint16_t(tok::unknown);
176216
IsMissing = false;
217+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
177218
Range = CharSourceRange();
219+
#endif
178220
}
179221

180222
ParsedRawSyntaxNode unsafeCopy() const {
181223
ParsedRawSyntaxNode copy;
182224
copy.Data = Data;
225+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
183226
copy.Range = Range;
227+
#endif
184228
copy.SynKind = SynKind;
185229
copy.TokKind = TokKind;
186230
copy.IsMissing = IsMissing;

include/swift/Parse/ParsedRawSyntaxRecorder.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
#define SWIFT_PARSE_PARSEDRAWSYNTAXRECORDER_H
2121

2222
#include "swift/Basic/LLVM.h"
23+
#include "swift/Parse/ParsedRawSyntaxNode.h"
2324
#include <memory>
2425

2526
namespace swift {
2627

2728
class CharSourceRange;
28-
class ParsedRawSyntaxNode;
2929
struct ParsedTrivia;
3030
class ParsedTriviaPiece;
3131
class SyntaxParseActions;
@@ -38,6 +38,18 @@ namespace syntax {
3838
enum class SyntaxKind;
3939
}
4040

41+
/// The information returned from the \c lookupNode method in \c
42+
/// SyntaxParseActions.
43+
struct ParseLookupResult {
44+
ParsedRawSyntaxNode Node;
45+
46+
/// The length of \c Node spelled out in source, including trivia.
47+
size_t Length;
48+
49+
ParseLookupResult(ParsedRawSyntaxNode &&Node, size_t Length)
50+
: Node(std::move(Node)), Length(Length) {}
51+
};
52+
4153
class ParsedRawSyntaxRecorder final {
4254
std::shared_ptr<SyntaxParseActions> SPActions;
4355

@@ -92,8 +104,8 @@ class ParsedRawSyntaxRecorder final {
92104
ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc);
93105

94106
/// Used for incremental re-parsing.
95-
ParsedRawSyntaxNode lookupNode(size_t lexerOffset, SourceLoc loc,
96-
syntax::SyntaxKind kind);
107+
ParseLookupResult lookupNode(size_t lexerOffset, SourceLoc loc,
108+
syntax::SyntaxKind kind);
97109

98110
/// For a deferred layout node \p parent, retrieve the deferred child node
99111
/// at \p ChildIndex.
@@ -103,8 +115,11 @@ class ParsedRawSyntaxRecorder final {
103115
/// For a deferred layout node \p node, retrieve the number of children.
104116
size_t getDeferredNumChildren(const ParsedRawSyntaxNode &node) const;
105117

106-
#ifndef NDEBUG
107-
static void verifyElementRanges(ArrayRef<ParsedRawSyntaxNode> elements);
118+
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
119+
/// Verify that the ranges of \p elements are all consecutive and return the
120+
/// range spanned by all \p elements.
121+
static CharSourceRange
122+
verifyElementRanges(ArrayRef<ParsedRawSyntaxNode> elements);
108123
#endif
109124
};
110125

include/swift/Parse/SyntaxParseActions.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,11 @@ struct DeferredNodeInfo {
7171
syntax::SyntaxKind SyntaxKind;
7272
tok TokenKind;
7373
bool IsMissing;
74-
CharSourceRange Range;
7574

7675
DeferredNodeInfo(RecordedOrDeferredNode Data, syntax::SyntaxKind SyntaxKind,
77-
tok TokenKind, bool IsMissing, CharSourceRange Range)
76+
tok TokenKind, bool IsMissing)
7877
: Data(Data), SyntaxKind(SyntaxKind), TokenKind(TokenKind),
79-
IsMissing(IsMissing), Range(Range) {}
78+
IsMissing(IsMissing) {}
8079
};
8180

8281
// MARK: - SyntaxParseActions
@@ -133,12 +132,24 @@ class SyntaxParseActions {
133132
/// which created it, to retrieve children.
134133
/// This method assumes that \p node represents a *deferred* layout node.
135134
/// This methods returns all information needed to construct a \c
136-
/// ParsedRawSyntaxNode of a child node. \p node is the parent node for which
137-
/// the child at position \p ChildIndex should be retrieved. Furthmore, \p
138-
/// node starts at \p StartLoc.
135+
/// ParsedRawSyntaxNode of a child node, except for the range which can be
136+
/// retrieved using \c getDeferredChildRange if element ranges should be
137+
/// verified
138+
/// \p node is the parent node for which the child at position \p ChildIndex
139+
/// should be retrieved. Furthmore, \p node starts at \p StartLoc.
139140
virtual DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
140-
size_t childIndex,
141-
SourceLoc startLoc) = 0;
141+
size_t childIndex) const = 0;
142+
143+
/// To verify \c ParsedRawSyntaxNode element ranges, the range of child nodes
144+
/// returend by \c getDeferredChild needs to be determined. That's what this
145+
/// method does.
146+
/// It assumes that \p node is a deferred layout node starting at \p startLoc
147+
/// and returns the range of the child node at \p childIndex.
148+
/// This method is not designed with performance in mind. Do not use in
149+
/// performance-critical code.
150+
virtual CharSourceRange getDeferredChildRange(OpaqueSyntaxNode node,
151+
size_t childIndex,
152+
SourceLoc startLoc) const = 0;
142153

143154
/// Return the number of children, \p node has. These can be retrieved using
144155
/// \c getDeferredChild.

include/swift/SyntaxParse/SyntaxTreeCreator.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,12 @@ class SyntaxTreeCreator final : public SyntaxParseActions {
8585
OpaqueSyntaxNode recordDeferredToken(OpaqueSyntaxNode deferred) override;
8686
OpaqueSyntaxNode recordDeferredLayout(OpaqueSyntaxNode deferred) override;
8787

88-
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node, size_t ChildIndex,
89-
SourceLoc StartLoc) override;
88+
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
89+
size_t ChildIndex) const override;
90+
91+
CharSourceRange getDeferredChildRange(OpaqueSyntaxNode node,
92+
size_t ChildIndex,
93+
SourceLoc StartLoc) const override;
9094

9195
size_t getDeferredNumChildren(OpaqueSyntaxNode node) override;
9296
};

0 commit comments

Comments
 (0)