[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.
This commit is contained in:
Alex Hoppen
2021-03-10 18:08:45 +01:00
parent 0d913e9531
commit 350ac1514c
8 changed files with 247 additions and 126 deletions

View File

@@ -21,6 +21,16 @@
#include "swift/Syntax/SyntaxKind.h"
#include "llvm/Support/Debug.h"
#ifndef NDEBUG
/// Whether \c ParsedRawSyntaxNode should keep track of its range and verify
/// that the children of layout nodes have consecutive ranges.
/// Because this significantly changes the way, \c ParsedRawSyntaxNode and
/// \c ParsedRawSyntaxNodeRecorder are being compiled, this is a separate
/// constant from \c NDEBUG, so that it can be toggled independently to \c
/// NDEBUG during development.
#define PARSEDRAWSYNTAXNODE_VERIFY_RANGES 1
#endif
namespace swift {
typedef const void *OpaqueSyntaxNode;
@@ -48,8 +58,13 @@ class ParsedRawSyntaxNode {
/// SyntaxParseActions, which created it.
RecordedOrDeferredNode Data;
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
/// The range of this node, including trivia.
/// Only store this as a member when it's actually needed to keep \c
/// ParsedRawSyntaxNode as small as possible, which improves performance
/// when it is being passed around.
CharSourceRange Range;
#endif
uint16_t SynKind;
uint16_t TokKind;
/// Primary used for capturing a deferred missing token.
@@ -62,24 +77,46 @@ public:
// MARK: - Constructors
ParsedRawSyntaxNode()
: Data(nullptr, DataKind::Null), Range(),
: Data(nullptr, DataKind::Null),
SynKind(uint16_t(syntax::SyntaxKind::Unknown)),
TokKind(uint16_t(tok::unknown)) {}
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, CharSourceRange Range,
syntax::SyntaxKind SynKind, tok TokKind, DataKind DK,
bool IsMissing)
: Data(Opaque, DK), Range(Range), SynKind(uint16_t(SynKind)),
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
ParsedRawSyntaxNode(RecordedOrDeferredNode Data, syntax::SyntaxKind SynKind,
tok TokKind, bool IsMissing, CharSourceRange Range)
: Data(Data), Range(Range), SynKind(uint16_t(SynKind)),
TokKind(uint16_t(TokKind)), IsMissing(IsMissing) {
assert(getKind() == SynKind && "Syntax kind with too large value!");
assert(getTokenKind() == TokKind && "Token kind with too large value!");
}
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, syntax::SyntaxKind SynKind,
tok TokKind, DataKind DK, bool IsMissing,
CharSourceRange Range)
: ParsedRawSyntaxNode(RecordedOrDeferredNode(Opaque, DK), SynKind,
TokKind, IsMissing, Range) {}
#else
ParsedRawSyntaxNode(RecordedOrDeferredNode Data, syntax::SyntaxKind SynKind,
tok TokKind, bool IsMissing)
: Data(Data), SynKind(uint16_t(SynKind)), TokKind(uint16_t(TokKind)),
IsMissing(IsMissing) {
assert(getKind() == SynKind && "Syntax kind with too large value!");
assert(getTokenKind() == TokKind && "Token kind with too large value!");
}
ParsedRawSyntaxNode(OpaqueSyntaxNode Opaque, syntax::SyntaxKind SynKind,
tok TokKind, DataKind DK, bool IsMissing)
: ParsedRawSyntaxNode(RecordedOrDeferredNode(Opaque, DK), SynKind,
TokKind, IsMissing) {}
#endif
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
assert(ensureDataIsNotRecorded() &&
"recorded data is being destroyed by assignment");
Data = std::move(other.Data);
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
Range = std::move(other.Range);
#endif
SynKind = std::move(other.SynKind);
TokKind = std::move(other.TokKind);
IsMissing = std::move(other.IsMissing);
@@ -91,9 +128,7 @@ public:
*this = std::move(other);
}
static ParsedRawSyntaxNode null() {
return ParsedRawSyntaxNode{};
}
static ParsedRawSyntaxNode null() { return ParsedRawSyntaxNode(); }
~ParsedRawSyntaxNode() {
assert(ensureDataIsNotRecorded() && "recorded data is being destructed");
@@ -152,8 +187,13 @@ public:
}
bool isMissing() const { return IsMissing; }
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
/// Returns the range of this node including leading and trailing trivia.
///
/// This method is only present if \c ParsedRawSyntaxNode is keeping track
/// of its range to verify element ranges.
CharSourceRange getRange() const { return Range; }
#endif
size_t
getDeferredNumChildren(const SyntaxParsingContext *SyntaxContext) const;
@@ -174,13 +214,17 @@ public:
SynKind = uint16_t(syntax::SyntaxKind::Unknown);
TokKind = uint16_t(tok::unknown);
IsMissing = false;
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
Range = CharSourceRange();
#endif
}
ParsedRawSyntaxNode unsafeCopy() const {
ParsedRawSyntaxNode copy;
copy.Data = Data;
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
copy.Range = Range;
#endif
copy.SynKind = SynKind;
copy.TokKind = TokKind;
copy.IsMissing = IsMissing;

View File

@@ -20,12 +20,12 @@
#define SWIFT_PARSE_PARSEDRAWSYNTAXRECORDER_H
#include "swift/Basic/LLVM.h"
#include "swift/Parse/ParsedRawSyntaxNode.h"
#include <memory>
namespace swift {
class CharSourceRange;
class ParsedRawSyntaxNode;
struct ParsedTrivia;
class ParsedTriviaPiece;
class SyntaxParseActions;
@@ -38,6 +38,18 @@ namespace syntax {
enum class SyntaxKind;
}
/// The information returned from the \c lookupNode method in \c
/// SyntaxParseActions.
struct ParseLookupResult {
ParsedRawSyntaxNode Node;
/// The length of \c Node spelled out in source, including trivia.
size_t Length;
ParseLookupResult(ParsedRawSyntaxNode &&Node, size_t Length)
: Node(std::move(Node)), Length(Length) {}
};
class ParsedRawSyntaxRecorder final {
std::shared_ptr<SyntaxParseActions> SPActions;
@@ -92,8 +104,8 @@ public:
ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc);
/// Used for incremental re-parsing.
ParsedRawSyntaxNode lookupNode(size_t lexerOffset, SourceLoc loc,
syntax::SyntaxKind kind);
ParseLookupResult lookupNode(size_t lexerOffset, SourceLoc loc,
syntax::SyntaxKind kind);
/// For a deferred layout node \p parent, retrieve the deferred child node
/// at \p ChildIndex.
@@ -103,8 +115,11 @@ public:
/// For a deferred layout node \p node, retrieve the number of children.
size_t getDeferredNumChildren(const ParsedRawSyntaxNode &node) const;
#ifndef NDEBUG
static void verifyElementRanges(ArrayRef<ParsedRawSyntaxNode> elements);
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
/// Verify that the ranges of \p elements are all consecutive and return the
/// range spanned by all \p elements.
static CharSourceRange
verifyElementRanges(ArrayRef<ParsedRawSyntaxNode> elements);
#endif
};

View File

@@ -71,12 +71,11 @@ struct DeferredNodeInfo {
syntax::SyntaxKind SyntaxKind;
tok TokenKind;
bool IsMissing;
CharSourceRange Range;
DeferredNodeInfo(RecordedOrDeferredNode Data, syntax::SyntaxKind SyntaxKind,
tok TokenKind, bool IsMissing, CharSourceRange Range)
tok TokenKind, bool IsMissing)
: Data(Data), SyntaxKind(SyntaxKind), TokenKind(TokenKind),
IsMissing(IsMissing), Range(Range) {}
IsMissing(IsMissing) {}
};
// MARK: - SyntaxParseActions
@@ -133,12 +132,24 @@ public:
/// which created it, to retrieve children.
/// This method assumes that \p node represents a *deferred* layout node.
/// This methods returns all information needed to construct a \c
/// ParsedRawSyntaxNode of a child node. \p node is the parent node for which
/// the child at position \p ChildIndex should be retrieved. Furthmore, \p
/// node starts at \p StartLoc.
/// ParsedRawSyntaxNode of a child node, except for the range which can be
/// retrieved using \c getDeferredChildRange if element ranges should be
/// verified
/// \p node is the parent node for which the child at position \p ChildIndex
/// should be retrieved. Furthmore, \p node starts at \p StartLoc.
virtual DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
size_t childIndex,
SourceLoc startLoc) = 0;
size_t childIndex) const = 0;
/// To verify \c ParsedRawSyntaxNode element ranges, the range of child nodes
/// returend by \c getDeferredChild needs to be determined. That's what this
/// method does.
/// It assumes that \p node is a deferred layout node starting at \p startLoc
/// and returns the range of the child node at \p childIndex.
/// This method is not designed with performance in mind. Do not use in
/// performance-critical code.
virtual CharSourceRange getDeferredChildRange(OpaqueSyntaxNode node,
size_t childIndex,
SourceLoc startLoc) const = 0;
/// Return the number of children, \p node has. These can be retrieved using
/// \c getDeferredChild.

View File

@@ -85,8 +85,12 @@ private:
OpaqueSyntaxNode recordDeferredToken(OpaqueSyntaxNode deferred) override;
OpaqueSyntaxNode recordDeferredLayout(OpaqueSyntaxNode deferred) override;
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node, size_t ChildIndex,
SourceLoc StartLoc) override;
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
size_t ChildIndex) const override;
CharSourceRange getDeferredChildRange(OpaqueSyntaxNode node,
size_t ChildIndex,
SourceLoc StartLoc) const override;
size_t getDeferredNumChildren(OpaqueSyntaxNode node) override;
};

View File

@@ -27,6 +27,20 @@
using namespace swift;
using namespace swift::syntax;
/// Define a macro that creates a \c ParsedRawSyntaxNode. If \c
/// PARSEDRAWSYNTAXNODE_VERIFY_RANGES is defined, it passes the \c Range
/// parameter, otherwise it ignores it at the pre-processor level, which means
/// that \c Range can be an invalid expression.
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
#define makeParsedRawSyntaxNode(Opaque, SynKind, TokKind, DataKind, IsMissing, \
Range) \
ParsedRawSyntaxNode(Opaque, SynKind, TokKind, DataKind, IsMissing, Range)
#else
#define makeParsedRawSyntaxNode(Opaque, SynKind, TokKind, DataKind, IsMissing, \
Range) \
ParsedRawSyntaxNode(Opaque, SynKind, TokKind, DataKind, IsMissing)
#endif
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::recordDeferredNode(ParsedRawSyntaxNode &node) {
switch (node.getDataKind()) {
@@ -35,15 +49,15 @@ ParsedRawSyntaxRecorder::recordDeferredNode(ParsedRawSyntaxNode &node) {
llvm_unreachable("Not deferred");
case RecordedOrDeferredNode::Kind::DeferredLayout: {
OpaqueSyntaxNode Data = SPActions->recordDeferredLayout(node.takeData());
return ParsedRawSyntaxNode(
Data, node.getRange(), node.getKind(), node.getTokenKind(),
ParsedRawSyntaxNode::DataKind::Recorded, node.isMissing());
return makeParsedRawSyntaxNode(Data, node.getKind(), node.getTokenKind(),
ParsedRawSyntaxNode::DataKind::Recorded,
node.isMissing(), node.getRange());
}
case RecordedOrDeferredNode::Kind::DeferredToken: {
OpaqueSyntaxNode Data = SPActions->recordDeferredToken(node.takeData());
return ParsedRawSyntaxNode(
Data, node.getRange(), node.getKind(), node.getTokenKind(),
ParsedRawSyntaxNode::DataKind::Recorded, node.isMissing());
return makeParsedRawSyntaxNode(Data, node.getKind(), node.getTokenKind(),
ParsedRawSyntaxNode::DataKind::Recorded,
node.isMissing(), node.getRange());
}
}
}
@@ -65,39 +79,30 @@ ParsedRawSyntaxRecorder::recordToken(tok tokKind, CharSourceRange tokRange,
CharSourceRange range(offset, length);
OpaqueSyntaxNode n =
SPActions->recordToken(tokKind, leadingTrivia, trailingTrivia, range);
return ParsedRawSyntaxNode(n, range, SyntaxKind::Token, tokKind,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false);
return makeParsedRawSyntaxNode(n, SyntaxKind::Token, tokKind,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false, range);
}
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::recordMissingToken(tok tokenKind, SourceLoc loc) {
CharSourceRange range{loc, 0};
OpaqueSyntaxNode n = SPActions->recordMissingToken(tokenKind, loc);
return ParsedRawSyntaxNode(n, range, SyntaxKind::Token, tokenKind,
ParsedRawSyntaxNode::DataKind::Recorded,
/*isMissing=*/true);
return makeParsedRawSyntaxNode(n, SyntaxKind::Token, tokenKind,
ParsedRawSyntaxNode::DataKind::Recorded,
/*isMissing=*/true, CharSourceRange(loc, 0));
}
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::recordRawSyntax(SyntaxKind kind,
MutableArrayRef<ParsedRawSyntaxNode> elements) {
assert(kind != SyntaxKind::Token && "Use recordToken to record a token");
#ifndef NDEBUG
ParsedRawSyntaxRecorder::verifyElementRanges(elements);
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
auto range = ParsedRawSyntaxRecorder::verifyElementRanges(elements);
#endif
SmallVector<OpaqueSyntaxNode, 16> subnodes;
SourceLoc startLoc;
unsigned length = 0;
if (!elements.empty()) {
for (auto &subnode : elements) {
if (!subnode.isNull() && subnode.getRange().isValid()) {
if (startLoc.isInvalid()) {
startLoc = subnode.getRange().getStart();
}
length += subnode.getRange().getByteLength();
}
switch (subnode.getDataKind()) {
case RecordedOrDeferredNode::Kind::Null:
subnodes.push_back(nullptr);
@@ -115,30 +120,28 @@ ParsedRawSyntaxRecorder::recordRawSyntax(SyntaxKind kind,
}
}
OpaqueSyntaxNode n = SPActions->recordRawSyntax(kind, subnodes);
return ParsedRawSyntaxNode(
n, CharSourceRange(startLoc, length), kind, tok::NUM_TOKENS,
ParsedRawSyntaxNode::DataKind::Recorded, /*IsMissing=*/false);
return makeParsedRawSyntaxNode(n, kind, tok::NUM_TOKENS,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false, range);
}
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::recordEmptyRawSyntaxCollection(SyntaxKind kind,
SourceLoc loc) {
CharSourceRange range{loc, 0};
OpaqueSyntaxNode n = SPActions->recordRawSyntax(kind, {});
return ParsedRawSyntaxNode(n, range, kind, tok::unknown,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false);
return makeParsedRawSyntaxNode(n, kind, tok::unknown,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false, CharSourceRange(loc, 0));
}
/// Create a deferred layout node.
ParsedRawSyntaxNode ParsedRawSyntaxRecorder::makeDeferred(
syntax::SyntaxKind k, MutableArrayRef<ParsedRawSyntaxNode> deferredNodes,
SyntaxParsingContext &ctx) {
#ifndef NDEBUG
ParsedRawSyntaxRecorder::verifyElementRanges(deferredNodes);
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
auto range = ParsedRawSyntaxRecorder::verifyElementRanges(deferredNodes);
#endif
CharSourceRange range;
RecordedOrDeferredNode *newPtr =
ctx.getScratchAlloc().Allocate<RecordedOrDeferredNode>(
deferredNodes.size());
@@ -147,23 +150,13 @@ ParsedRawSyntaxNode ParsedRawSyntaxRecorder::makeDeferred(
auto &node = deferredNodes[i];
assert(!node.isRecorded() &&
"Cannot create a deferred layout node that has recorded children");
// Cached range.
if (!node.isNull() && !node.isMissing()) {
auto nodeRange = node.getRange();
if (nodeRange.isValid()) {
if (range.isInvalid())
range = nodeRange;
else
range.widen(nodeRange);
}
}
children[i] = node.takeRecordedOrDeferredNode();
}
auto data = SPActions->makeDeferredLayout(k, /*IsMissing=*/false, children);
return ParsedRawSyntaxNode(data, range, k, tok::NUM_TOKENS,
ParsedRawSyntaxNode::DataKind::DeferredLayout,
/*IsMissing=*/false);
return makeParsedRawSyntaxNode(data, k, tok::NUM_TOKENS,
ParsedRawSyntaxNode::DataKind::DeferredLayout,
/*IsMissing=*/false, range);
}
/// Create a deferred token node.
@@ -178,9 +171,9 @@ ParsedRawSyntaxRecorder::makeDeferred(Token tok, StringRef leadingTrivia,
auto Data =
SPActions->makeDeferredToken(tok.getKind(), leadingTrivia, trailingTrivia,
RangeWithTrivia, /*IsMissing=*/false);
return ParsedRawSyntaxNode(
Data, RangeWithTrivia, SyntaxKind::Token, tok.getKind(),
ParsedRawSyntaxNode::DataKind::DeferredToken, /*IsMissing=*/false);
return makeParsedRawSyntaxNode(Data, SyntaxKind::Token, tok.getKind(),
ParsedRawSyntaxNode::DataKind::DeferredToken,
/*IsMissing=*/false, RangeWithTrivia);
}
ParsedRawSyntaxNode
@@ -189,24 +182,26 @@ ParsedRawSyntaxRecorder::makeDeferredMissing(tok tokKind, SourceLoc loc) {
tokKind, /*leadingTrivia=*/StringRef(),
/*trailingTrivia=*/StringRef(), CharSourceRange(loc, /*Length=*/0),
/*IsMissing=*/true);
return ParsedRawSyntaxNode(
Data, CharSourceRange(loc, /*Length=*/0), SyntaxKind::Token, tokKind,
ParsedRawSyntaxNode::DataKind::DeferredToken, /*IsMissing=*/true);
return makeParsedRawSyntaxNode(Data, SyntaxKind::Token, tokKind,
ParsedRawSyntaxNode::DataKind::DeferredToken,
/*IsMissing=*/true,
CharSourceRange(loc, /*Length=*/0));
}
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::lookupNode(size_t lexerOffset, SourceLoc loc,
SyntaxKind kind) {
ParseLookupResult ParsedRawSyntaxRecorder::lookupNode(size_t lexerOffset,
SourceLoc loc,
SyntaxKind kind) {
size_t length;
OpaqueSyntaxNode n;
std::tie(length, n) = SPActions->lookupNode(lexerOffset, kind);
if (length == 0) {
return ParsedRawSyntaxNode::null();
return ParseLookupResult(ParsedRawSyntaxNode::null(), length);
}
CharSourceRange range{loc, unsigned(length)};
return ParsedRawSyntaxNode(n, range, kind, tok::unknown,
ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false);
return ParseLookupResult(
makeParsedRawSyntaxNode(
n, kind, tok::unknown, ParsedRawSyntaxNode::DataKind::Recorded,
/*IsMissing=*/false, CharSourceRange(loc, unsigned(length))),
length);
}
ParsedRawSyntaxNode
@@ -214,11 +209,18 @@ ParsedRawSyntaxRecorder::getDeferredChild(const ParsedRawSyntaxNode &parent,
size_t childIndex) const {
assert(parent.isDeferredLayout());
auto childInfo = SPActions->getDeferredChild(
parent.getUnsafeDeferredOpaqueData(), childIndex);
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
auto range = SPActions->getDeferredChildRange(
parent.getUnsafeDeferredOpaqueData(), childIndex,
parent.getRange().getStart());
return ParsedRawSyntaxNode(childInfo.Data.getOpaque(), childInfo.Range,
childInfo.SyntaxKind, childInfo.TokenKind,
childInfo.Data.getKind(), childInfo.IsMissing);
return ParsedRawSyntaxNode(childInfo.Data, childInfo.SyntaxKind,
childInfo.TokenKind, childInfo.IsMissing, range);
#else
return ParsedRawSyntaxNode(childInfo.Data, childInfo.SyntaxKind,
childInfo.TokenKind, childInfo.IsMissing);
#endif
}
size_t ParsedRawSyntaxRecorder::getDeferredNumChildren(
@@ -227,18 +229,29 @@ size_t ParsedRawSyntaxRecorder::getDeferredNumChildren(
return SPActions->getDeferredNumChildren(node.getUnsafeDeferredOpaqueData());
}
#ifndef NDEBUG
void ParsedRawSyntaxRecorder::verifyElementRanges(ArrayRef<ParsedRawSyntaxNode> elements) {
#ifdef PARSEDRAWSYNTAXNODE_VERIFY_RANGES
CharSourceRange ParsedRawSyntaxRecorder::verifyElementRanges(
ArrayRef<ParsedRawSyntaxNode> elements) {
SourceLoc startLoc;
unsigned length = 0;
SourceLoc prevEndLoc;
for (const auto &elem: elements) {
if (elem.isNull() || elem.isMissing())
continue;
CharSourceRange range = elem.getRange();
if (range.isValid()) {
if (startLoc.isInvalid()) {
startLoc = range.getStart();
}
length += range.getByteLength();
assert((prevEndLoc.isInvalid() || range.getStart() == prevEndLoc)
&& "Non-contiguous child ranges?");
prevEndLoc = range.getEnd();
}
}
return CharSourceRange(startLoc, length);
}
#endif

View File

@@ -84,13 +84,12 @@ size_t SyntaxParsingContext::lookupNode(size_t LexerOffset, SourceLoc Loc) {
assert(Mode == AccumulationMode::CreateSyntax &&
"Loading from cache is only supported for mode CreateSyntax");
auto foundNode = getRecorder().lookupNode(LexerOffset, Loc, SynKind);
if (foundNode.isNull()) {
if (foundNode.Node.isNull()) {
return 0;
}
Mode = AccumulationMode::SkippedForIncrementalUpdate;
auto length = foundNode.getRange().getByteLength();
getStorage().push_back(std::move(foundNode));
return length;
getStorage().push_back(std::move(foundNode.Node));
return foundNode.Length;
}
ParsedRawSyntaxNode

View File

@@ -215,8 +215,30 @@ SyntaxTreeCreator::recordDeferredLayout(OpaqueSyntaxNode deferred) {
}
DeferredNodeInfo SyntaxTreeCreator::getDeferredChild(OpaqueSyntaxNode node,
size_t ChildIndex,
SourceLoc StartLoc) {
size_t ChildIndex) const {
const RawSyntax *raw = static_cast<const RawSyntax *>(node);
const RawSyntax *Child = raw->getChild(ChildIndex);
if (Child == nullptr) {
return DeferredNodeInfo(
RecordedOrDeferredNode(nullptr, RecordedOrDeferredNode::Kind::Null),
syntax::SyntaxKind::Unknown, tok::NUM_TOKENS, /*IsMissing=*/false);
} else if (Child->isToken()) {
return DeferredNodeInfo(
RecordedOrDeferredNode(Child,
RecordedOrDeferredNode::Kind::DeferredToken),
syntax::SyntaxKind::Token, Child->getTokenKind(), Child->isMissing());
} else {
return DeferredNodeInfo(
RecordedOrDeferredNode(Child,
RecordedOrDeferredNode::Kind::DeferredLayout),
Child->getKind(), tok::NUM_TOKENS,
/*IsMissing=*/false);
}
}
CharSourceRange SyntaxTreeCreator::getDeferredChildRange(
OpaqueSyntaxNode node, size_t ChildIndex, SourceLoc StartLoc) const {
const RawSyntax *raw = static_cast<const RawSyntax *>(node);
// Compute the start offset of the child node by advancing StartLoc by the
@@ -230,22 +252,9 @@ DeferredNodeInfo SyntaxTreeCreator::getDeferredChild(OpaqueSyntaxNode node,
const RawSyntax *Child = raw->getChild(ChildIndex);
if (Child == nullptr) {
return DeferredNodeInfo(
RecordedOrDeferredNode(nullptr, RecordedOrDeferredNode::Kind::Null),
syntax::SyntaxKind::Unknown, tok::NUM_TOKENS, /*IsMissing=*/false,
CharSourceRange(StartLoc, /*Length=*/0));
} else if (Child->isToken()) {
return DeferredNodeInfo(
RecordedOrDeferredNode(Child,
RecordedOrDeferredNode::Kind::DeferredToken),
syntax::SyntaxKind::Token, Child->getTokenKind(), Child->isMissing(),
CharSourceRange(StartLoc, Child->getTextLength()));
return CharSourceRange(StartLoc, /*Length=*/0);
} else {
return DeferredNodeInfo(
RecordedOrDeferredNode(Child,
RecordedOrDeferredNode::Kind::DeferredLayout),
Child->getKind(), tok::NUM_TOKENS,
/*IsMissing=*/false, CharSourceRange(StartLoc, Child->getTextLength()));
return CharSourceRange(StartLoc, Child->getTextLength());
}
}

View File

@@ -123,7 +123,7 @@ struct DeferredLayoutNode {
: Kind(Kind), Children(Children), Length(Length) {}
};
class CLibParseActions : public SyntaxParseActions {
class CLibParseActions final : public SyntaxParseActions {
SynParser &SynParse;
SourceManager &SM;
unsigned BufferID;
@@ -309,8 +309,43 @@ private:
return recordRawSyntax(Data->Kind, children);
}
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node, size_t ChildIndex,
SourceLoc StartLoc) override {
DeferredNodeInfo getDeferredChild(OpaqueSyntaxNode node,
size_t ChildIndex) const override {
auto Data = static_cast<const DeferredLayoutNode *>(node);
auto Child = Data->Children[ChildIndex];
switch (Child.getKind()) {
case RecordedOrDeferredNode::Kind::Null:
return DeferredNodeInfo(
RecordedOrDeferredNode(nullptr, RecordedOrDeferredNode::Kind::Null),
syntax::SyntaxKind::Unknown, tok::NUM_TOKENS,
/*IsMissing=*/false);
case RecordedOrDeferredNode::Kind::Recorded:
llvm_unreachable("Children of deferred nodes must also be deferred");
break;
case RecordedOrDeferredNode::Kind::DeferredLayout: {
auto ChildData =
static_cast<const DeferredLayoutNode *>(Child.getOpaque());
return DeferredNodeInfo(
RecordedOrDeferredNode(ChildData,
RecordedOrDeferredNode::Kind::DeferredLayout),
ChildData->Kind, tok::NUM_TOKENS,
/*IsMissing=*/false);
}
case RecordedOrDeferredNode::Kind::DeferredToken: {
auto ChildData =
static_cast<const DeferredTokenNode *>(Child.getOpaque());
return DeferredNodeInfo(
RecordedOrDeferredNode(ChildData,
RecordedOrDeferredNode::Kind::DeferredToken),
syntax::SyntaxKind::Token, ChildData->TokenKind,
ChildData->IsMissing);
}
}
}
CharSourceRange getDeferredChildRange(OpaqueSyntaxNode node,
size_t ChildIndex,
SourceLoc StartLoc) const override {
auto Data = static_cast<const DeferredLayoutNode *>(node);
// Compute the start offset of the child node by advancing StartLoc by the
@@ -337,28 +372,19 @@ private:
auto Child = Data->Children[ChildIndex];
switch (Child.getKind()) {
case RecordedOrDeferredNode::Kind::Null:
return DeferredNodeInfo(
RecordedOrDeferredNode(nullptr, RecordedOrDeferredNode::Kind::Null),
syntax::SyntaxKind::Unknown, tok::NUM_TOKENS,
/*IsMissing=*/false, CharSourceRange(StartLoc, /*Length=*/0));
return CharSourceRange(StartLoc, /*Length=*/0);
case RecordedOrDeferredNode::Kind::Recorded:
llvm_unreachable("Children of deferred nodes must also be deferred");
break;
case RecordedOrDeferredNode::Kind::DeferredLayout: {
auto ChildData = static_cast<const DeferredLayoutNode *>(Child.getOpaque());
return DeferredNodeInfo(
RecordedOrDeferredNode(ChildData,
RecordedOrDeferredNode::Kind::DeferredLayout),
ChildData->Kind, tok::NUM_TOKENS,
/*IsMissing=*/false, CharSourceRange(StartLoc, ChildData->Length));
return CharSourceRange(StartLoc, ChildData->Length);
}
case RecordedOrDeferredNode::Kind::DeferredToken: {
auto ChildData = static_cast<const DeferredTokenNode *>(Child.getOpaque());
return DeferredNodeInfo(
RecordedOrDeferredNode(ChildData,
RecordedOrDeferredNode::Kind::DeferredToken),
syntax::SyntaxKind::Token, ChildData->TokenKind, ChildData->IsMissing,
ChildData->Range);
assert(ChildData->Range.getStart() == StartLoc &&
"Something broken in our StartLoc computation?");
return ChildData->Range;
}
}
}