@@ -164,3 +164,92 @@ SyntaxTreeCreator::lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {
164
164
size_t length = raw->getTextLength ();
165
165
return {length, static_cast <OpaqueSyntaxNode>(raw)};
166
166
}
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