@@ -218,37 +218,144 @@ struct AbsoluteRawSyntax {
218
218
const AbsoluteSyntaxInfo Info;
219
219
220
220
public:
221
+ // / Create a null \c AbsoluteRawSyntax to which a real \c AbsoluteRawSyntax
222
+ // / can be stored later.
223
+ explicit AbsoluteRawSyntax ()
224
+ : Raw(nullptr ), Info(AbsoluteSyntaxPosition(0 , 0 ),
225
+ SyntaxIdentifier(0 , SyntaxIndexInTree::zero())) {}
226
+
227
+ // / Create a new \c AbsoluteRawData backed by \p Raw and with additional \p
228
+ // / Info. The caller of this constructor is responsible to ensure that the
229
+ // / Arena of \p Raw (and thus \p Raw itself) outlives this \c
230
+ // / AbsoluteRawSyntax.
221
231
AbsoluteRawSyntax (const RawSyntax *Raw, AbsoluteSyntaxInfo Info)
222
- : Raw(Raw), Info(Info) {}
232
+ : Raw(Raw), Info(Info) {
233
+ assert (Raw != nullptr &&
234
+ " A AbsoluteRawSyntax created through the memberwise constructor "
235
+ " should always have a RawSyntax" );
236
+ }
237
+
238
+ // / Whether this is a null \c AbsoluteRawSyntax created through the default
239
+ // / constructor.
240
+ bool isNull () const { return Raw == nullptr ; }
223
241
224
242
// / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
225
243
// / the syntax tree's root.
226
244
static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
227
245
return AbsoluteRawSyntax (Raw, AbsoluteSyntaxInfo::forRoot ());
228
246
}
229
247
230
- const RawSyntax *getRaw () const { return Raw; }
248
+ const RawSyntax *getRaw () const {
249
+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
250
+ return Raw;
251
+ }
231
252
232
- AbsoluteSyntaxInfo getInfo () const { return Info; }
253
+ AbsoluteSyntaxInfo getInfo () const {
254
+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
255
+ return Info;
256
+ }
233
257
234
258
// / Get the position at which the leading triva of this node starts.
235
- AbsoluteSyntaxPosition getPosition () const { return Info.getPosition (); };
259
+ AbsoluteSyntaxPosition getPosition () const {
260
+ return getInfo ().getPosition ();
261
+ };
236
262
237
- SyntaxIdentifier getNodeId () const { return Info .getNodeId (); };
263
+ SyntaxIdentifier getNodeId () const { return getInfo () .getNodeId (); };
238
264
239
265
AbsoluteSyntaxPosition::IndexInParentType getIndexInParent () const {
240
266
return getPosition ().getIndexInParent ();
241
267
}
242
268
269
+ size_t getNumChildren () const { return getRaw ()->getLayout ().size (); }
270
+
271
+ // / Get the child at \p Index if it exists. If the node does not have a child
272
+ // / at \p Index, return \c None. Asserts that \p Index < \c NumChildren
273
+ Optional<AbsoluteRawSyntax>
274
+ getChild (AbsoluteSyntaxPosition::IndexInParentType Index) const {
275
+ assert (Index < getNumChildren () && " Index out of bounds" );
276
+ auto RawChild = getRaw ()->getChild (Index);
277
+ if (RawChild) {
278
+ return getPresentChild (Index);
279
+ } else {
280
+ return None;
281
+ }
282
+ }
283
+
284
+ // / Get the child at \p Index, asserting that it exists. This is slightly
285
+ // / more performant than \c getChild in these cases since the \c
286
+ // / AbsoluteRawSyntax node does not have to be wrapped in an \c Optional.
287
+ AbsoluteRawSyntax
288
+ getPresentChild (AbsoluteSyntaxPosition::IndexInParentType Index) const {
289
+ assert (Index < getNumChildren () && " Index out of bounds" );
290
+ auto RawChild = getRaw ()->getChild (Index);
291
+ assert (RawChild &&
292
+ " Child retrieved using getPresentChild must always exist" );
293
+
294
+ AbsoluteSyntaxPosition Position = getPosition ().advancedToFirstChild ();
295
+ SyntaxIdentifier NodeId = getNodeId ().advancedToFirstChild ();
296
+
297
+ for (size_t I = 0 ; I < Index; ++I) {
298
+ Position = Position.advancedBy (getRaw ()->getChild (I));
299
+ NodeId = NodeId.advancedBy (getRaw ()->getChild (I));
300
+ }
301
+
302
+ AbsoluteSyntaxInfo Info (Position, NodeId);
303
+ return AbsoluteRawSyntax (RawChild, Info);
304
+ }
305
+
306
+ // / Get the first non-missing token node in this tree. Return \c None if
307
+ // / this node does not contain non-missing tokens.
308
+ Optional<AbsoluteRawSyntax> getFirstToken () const {
309
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
310
+ return *this ;
311
+ }
312
+
313
+ size_t NumChildren = getNumChildren ();
314
+ for (size_t I = 0 ; I < NumChildren; ++I) {
315
+ if (auto Child = getChild (I)) {
316
+ if (Child->getRaw ()->isMissing ()) {
317
+ continue ;
318
+ }
319
+
320
+ if (auto Token = Child->getFirstToken ()) {
321
+ return Token;
322
+ }
323
+ }
324
+ }
325
+ return None;
326
+ }
327
+
328
+ // / Get the last non-missing token node in this tree. Return \c None if
329
+ // / this node does not contain non-missing tokens.
330
+ Optional<AbsoluteRawSyntax> getLastToken () const {
331
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
332
+ return *this ;
333
+ }
334
+
335
+ for (int I = getNumChildren () - 1 ; I >= 0 ; --I) {
336
+ if (auto Child = getChild (I)) {
337
+ if (Child->getRaw ()->isMissing ()) {
338
+ continue ;
339
+ }
340
+
341
+ if (auto Token = Child->getLastToken ()) {
342
+ return Token;
343
+ }
344
+ }
345
+ }
346
+ return None;
347
+ }
348
+
243
349
// / Construct a new \c AbsoluteRawSyntax node that has the same info as the
244
350
// / current one, but
245
351
// / - the \p NewRaw as the backing storage
246
352
// / - the \p NewRootId as the RootId
247
353
AbsoluteRawSyntax
248
354
replacingSelf (const RawSyntax *NewRaw,
249
355
SyntaxIdentifier::RootIdType NewRootId) const {
250
- SyntaxIdentifier NewNodeId (NewRootId, Info.getNodeId ().getIndexInTree ());
251
- AbsoluteSyntaxInfo NewInfo (Info.getPosition (), NewNodeId);
356
+ SyntaxIdentifier NewNodeId (NewRootId,
357
+ getInfo ().getNodeId ().getIndexInTree ());
358
+ AbsoluteSyntaxInfo NewInfo (getInfo ().getPosition (), NewNodeId);
252
359
return AbsoluteRawSyntax (NewRaw, NewInfo);
253
360
}
254
361
};
0 commit comments