@@ -164,3 +164,92 @@ SyntaxTreeCreator::lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {
164164 size_t length = raw->getTextLength ();
165165 return {length, static_cast <OpaqueSyntaxNode>(raw)};
166166}
167+
168+ OpaqueSyntaxNode SyntaxTreeCreator::makeDeferredToken (tok tokenKind,
169+ StringRef leadingTrivia,
170+ StringRef trailingTrivia,
171+ CharSourceRange range,
172+ bool isMissing) {
173+ // Instead of creating dedicated deferred nodes that will be recorded only if
174+ // needed, the SyntaxTreeCreator always records all nodes and forms RawSyntax
175+ // nodes for them. This eliminates a bunch of copies that would otherwise
176+ // be required to record the deferred nodes.
177+ // Should a deferred node not be recorded, its data stays alive in the
178+ // SyntaxArena. This causes a small memory leak but since most nodes are
179+ // being recorded, it is acceptable.
180+ if (isMissing) {
181+ auto Node = recordMissingToken (tokenKind, range.getStart ());
182+ return Node;
183+ } else {
184+ auto Node = recordToken (tokenKind, leadingTrivia, trailingTrivia, range);
185+ return Node;
186+ }
187+ }
188+
189+ OpaqueSyntaxNode SyntaxTreeCreator::makeDeferredLayout (
190+ syntax::SyntaxKind k, bool IsMissing,
191+ const ArrayRef<RecordedOrDeferredNode> &children) {
192+ SmallVector<OpaqueSyntaxNode, 16 > opaqueChildren;
193+ opaqueChildren.reserve (children.size ());
194+
195+ for (size_t i = 0 ; i < children.size (); ++i) {
196+ opaqueChildren.push_back (children[i].getOpaque ());
197+ }
198+
199+ // Also see comment in makeDeferredToken
200+ return recordRawSyntax (k, opaqueChildren);
201+ }
202+
203+ OpaqueSyntaxNode
204+ SyntaxTreeCreator::recordDeferredToken (OpaqueSyntaxNode deferred) {
205+ // We don't diffirentiate between deferred and recorded nodes. See comment in
206+ // makeDeferredToken.
207+ return deferred;
208+ }
209+
210+ OpaqueSyntaxNode
211+ SyntaxTreeCreator::recordDeferredLayout (OpaqueSyntaxNode deferred) {
212+ // We don't diffirentiate between deferred and recorded nodes. See comment in
213+ // makeDeferredToken.
214+ return deferred;
215+ }
216+
217+ DeferredNodeInfo SyntaxTreeCreator::getDeferredChild (OpaqueSyntaxNode node,
218+ size_t ChildIndex,
219+ SourceLoc StartLoc) {
220+ const RawSyntax *raw = static_cast <const RawSyntax *>(node);
221+
222+ // Compute the start offset of the child node by advancing StartLoc by the
223+ // length of all previous child nodes.
224+ for (unsigned i = 0 ; i < ChildIndex; ++i) {
225+ const RawSyntax *child = raw->getChild (i);
226+ if (child) {
227+ StartLoc = StartLoc.getAdvancedLoc (child->getTextLength ());
228+ }
229+ }
230+
231+ const RawSyntax *Child = raw->getChild (ChildIndex);
232+ if (Child == nullptr ) {
233+ return DeferredNodeInfo (
234+ RecordedOrDeferredNode (nullptr , RecordedOrDeferredNode::Kind::Null),
235+ syntax::SyntaxKind::Unknown, tok::NUM_TOKENS, /* IsMissing=*/ false ,
236+ CharSourceRange (StartLoc, /* Length=*/ 0 ));
237+ } else if (Child->isToken ()) {
238+ return DeferredNodeInfo (
239+ RecordedOrDeferredNode (Child,
240+ RecordedOrDeferredNode::Kind::DeferredToken),
241+ syntax::SyntaxKind::Token, Child->getTokenKind (), Child->isMissing (),
242+ CharSourceRange (StartLoc, Child->getTextLength ()));
243+ } else {
244+ return DeferredNodeInfo (
245+ RecordedOrDeferredNode (Child,
246+ RecordedOrDeferredNode::Kind::DeferredLayout),
247+ Child->getKind (), tok::NUM_TOKENS,
248+ /* IsMissing=*/ false , CharSourceRange (StartLoc, Child->getTextLength ()));
249+ }
250+ }
251+
252+ size_t SyntaxTreeCreator::getDeferredNumChildren (OpaqueSyntaxNode node) {
253+ const syntax::RawSyntax *raw = static_cast <const syntax::RawSyntax *>(node);
254+ return raw->getNumChildren ();
255+ }
0 commit comments