@@ -218,37 +218,144 @@ struct AbsoluteRawSyntax {
218218 const AbsoluteSyntaxInfo Info;
219219
220220public:
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.
221231 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 ; }
223241
224242 // / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
225243 // / the syntax tree's root.
226244 static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
227245 return AbsoluteRawSyntax (Raw, AbsoluteSyntaxInfo::forRoot ());
228246 }
229247
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+ }
231252
232- AbsoluteSyntaxInfo getInfo () const { return Info; }
253+ AbsoluteSyntaxInfo getInfo () const {
254+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
255+ return Info;
256+ }
233257
234258 // / 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+ };
236262
237- SyntaxIdentifier getNodeId () const { return Info .getNodeId (); };
263+ SyntaxIdentifier getNodeId () const { return getInfo () .getNodeId (); };
238264
239265 AbsoluteSyntaxPosition::IndexInParentType getIndexInParent () const {
240266 return getPosition ().getIndexInParent ();
241267 }
242268
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+
243349 // / Construct a new \c AbsoluteRawSyntax node that has the same info as the
244350 // / current one, but
245351 // / - the \p NewRaw as the backing storage
246352 // / - the \p NewRootId as the RootId
247353 AbsoluteRawSyntax
248354 replacingSelf (const RawSyntax *NewRaw,
249355 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);
252359 return AbsoluteRawSyntax (NewRaw, NewInfo);
253360 }
254361};
0 commit comments