Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #ifndef RUST_AST_COLLECTOR_H
20 : #define RUST_AST_COLLECTOR_H
21 :
22 : #include "rust-token.h"
23 : #include "rust-ast-visitor.h"
24 : #include "rust-ast.h"
25 : #include "rust-ast-full.h"
26 : #include "rust-system.h"
27 :
28 : namespace Rust {
29 : namespace AST {
30 :
31 : class CollectItem
32 : {
33 : public:
34 : enum class Kind
35 : {
36 : Comment,
37 : InternalComment,
38 : BeginNodeDescription,
39 : EndNodeDescription,
40 : Newline,
41 : Indentation,
42 : Token,
43 : };
44 :
45 72891 : CollectItem (TokenPtr token) : token (token), kind (Kind::Token) {}
46 16399 : CollectItem (Kind kind) : kind (kind) { rust_assert (kind != Kind::Token); }
47 10894 : CollectItem (size_t level) : indent_level (level), kind (Kind::Indentation) {}
48 :
49 : static CollectItem make_internal_comment (const std::string &internal_comment)
50 : {
51 : return CollectItem (internal_comment, Kind::InternalComment);
52 : }
53 :
54 0 : static CollectItem make_comment (const std::string &comment)
55 : {
56 0 : return CollectItem (comment, Kind::Comment);
57 : }
58 :
59 : static CollectItem
60 52039 : make_begin_node_description (const std::string &node_description)
61 : {
62 104078 : return CollectItem (node_description, Kind::BeginNodeDescription);
63 : }
64 :
65 : static CollectItem
66 52039 : make_end_node_description (const std::string &node_description)
67 : {
68 104078 : return CollectItem (node_description, Kind::EndNodeDescription);
69 : }
70 :
71 204262 : Kind get_kind () { return kind; }
72 :
73 72891 : TokenPtr get_token ()
74 : {
75 72891 : rust_assert (kind == Kind::Token);
76 72891 : return token;
77 : }
78 :
79 0 : std::string get_comment ()
80 : {
81 0 : rust_assert (kind == Kind::Comment);
82 0 : return comment;
83 : }
84 :
85 25687 : size_t get_indent_level ()
86 : {
87 25687 : rust_assert (kind == Kind::Indentation);
88 25687 : return indent_level;
89 : }
90 :
91 0 : std::string get_internal_comment ()
92 : {
93 0 : rust_assert (kind == Kind::InternalComment);
94 0 : return comment;
95 : }
96 :
97 0 : std::string get_node_description ()
98 : {
99 0 : rust_assert (kind == Kind::BeginNodeDescription
100 : || kind == Kind::EndNodeDescription);
101 0 : return comment;
102 : }
103 :
104 : bool is_debug () { return debug; }
105 :
106 : private:
107 104078 : CollectItem (std::string comment, Kind kind) : comment (comment), kind (kind)
108 104078 : {}
109 :
110 : TokenPtr token;
111 : std::string comment;
112 : size_t indent_level;
113 : Kind kind;
114 : bool debug = false;
115 : };
116 :
117 2624 : class TokenCollector : public ASTVisitor
118 : {
119 : public:
120 2624 : TokenCollector () : indent_level (0) {}
121 :
122 : bool output_trailing_commas = false;
123 :
124 : void visit (AST::Crate &crate);
125 : void visit (AST::Item &item);
126 :
127 : std::vector<TokenPtr> collect_tokens () const;
128 : std::vector<CollectItem> collect () const;
129 :
130 : private:
131 : std::vector<CollectItem> tokens;
132 : size_t indent_level;
133 :
134 145782 : void push (TokenPtr token) { tokens.push_back ({token}); }
135 :
136 : /**
137 : * Visit all items in given @collection, placing the separator in between but
138 : * not at the end.
139 : */
140 : template <typename T>
141 13317 : void visit_items_joined_by_separator (T &collection,
142 : TokenId separator = COMMA,
143 : size_t start_offset = 0,
144 : size_t end_offset = 0)
145 : {
146 13317 : if (collection.size () > start_offset)
147 : {
148 9641 : visit (collection.at (start_offset));
149 9641 : auto size = collection.size () - end_offset;
150 11548 : for (size_t i = start_offset + 1; i < size; i++)
151 : {
152 3814 : push (Rust::Token::make (separator, UNDEF_LOCATION));
153 1907 : visit (collection.at (i));
154 : }
155 : }
156 13317 : }
157 :
158 : /**
159 : * Visit item placing end of line after.
160 : */
161 : template <typename T>
162 4695 : void visit_as_line (T &item, std::vector<TokenPtr> trailing = {})
163 : {
164 4695 : indentation ();
165 4695 : visit (item);
166 4716 : for (auto &token : trailing)
167 42 : push (token);
168 4695 : newline ();
169 4695 : }
170 :
171 : /**
172 : * Visit each item in @collection "as line".
173 : *
174 : * @see visit_as_line
175 : */
176 : template <typename T>
177 10218 : void visit_items_as_lines (T &collection, std::vector<TokenPtr> trailing = {})
178 : {
179 14913 : for (auto &item : collection)
180 4695 : visit_as_line (item, trailing);
181 10218 : }
182 :
183 : /**
184 : * Visit each item in @collection as lines inside a block delimited by braces
185 : * with increased indentation. Also includes special handling for empty
186 : * collection to print only the delimiters with no new line inside.
187 : */
188 : template <typename T>
189 2556 : void visit_items_as_block (T &collection, std::vector<TokenPtr> trailing = {},
190 : TokenId left_brace = LEFT_CURLY,
191 : TokenId right_brace = RIGHT_CURLY)
192 : {
193 5112 : push (Rust::Token::make (left_brace, UNDEF_LOCATION));
194 2556 : if (collection.empty ())
195 : {
196 1297 : push (Rust::Token::make (right_brace, UNDEF_LOCATION));
197 1297 : newline ();
198 : }
199 : else
200 : {
201 1259 : newline ();
202 1259 : increment_indentation ();
203 1259 : visit_items_as_lines (collection, trailing);
204 1259 : decrement_indentation ();
205 1259 : indentation ();
206 1259 : push (Rust::Token::make (right_brace, UNDEF_LOCATION));
207 1259 : newline ();
208 : }
209 2556 : }
210 :
211 : void describe_node (const std::string &node_name,
212 : std::function<void ()> visitor);
213 :
214 : void trailing_comma ();
215 : void newline ();
216 : void indentation ();
217 : void increment_indentation ();
218 : void decrement_indentation ();
219 : void comment (std::string comment);
220 : /**
221 : * Visit common items of functions: Parameters, return type, block
222 : */
223 : void visit_function_common (std::unique_ptr<Type> &return_type,
224 : std::unique_ptr<BlockExpr> &block);
225 :
226 : void visit_closure_common (ClosureExpr &expr);
227 :
228 : void visit_loop_common (BaseLoopExpr &expr);
229 :
230 : public:
231 : /**
232 : * Compatibility layer for using the visitor pattern on polymorphic classes
233 : * with a unified overload syntax. This allows us to call `visit` both on
234 : * types implementing `accept_vis` method and for classes for which the
235 : * `visit` method is directly implemented.
236 : */
237 13734 : template <typename T> void visit (std::unique_ptr<T> &node)
238 : {
239 13734 : node->accept_vis (*this);
240 822 : }
241 :
242 : /**
243 : * @see visit<std::unique_ptr<T>>
244 : */
245 13700 : template <typename T> void visit (T &node) { node.accept_vis (*this); }
246 :
247 : void visit (Visitable &v);
248 : void visit (LoopLabel &label);
249 :
250 : void visit (Literal &lit, location_t locus = UNDEF_LOCATION);
251 :
252 : void visit (FunctionParam ¶m);
253 : void visit (VariadicParam ¶m);
254 : void visit (Attribute &attrib);
255 : void visit (Visibility &vis);
256 : void visit (std::vector<std::unique_ptr<GenericParam>> ¶ms);
257 : void visit (TupleField &field);
258 : void visit (StructField &field);
259 : void visit (SimplePathSegment &segment);
260 : void visit (MacroRule &rule);
261 : void visit (WhereClause &rule);
262 : void visit (std::vector<LifetimeParam> &for_lifetimes);
263 : void visit (FunctionQualifiers &qualifiers);
264 : void visit (MaybeNamedParam ¶m);
265 : void visit (TypePathFunction &type_path_fn);
266 : void visit (GenericArgsBinding &binding);
267 : void visit (GenericArg &arg);
268 :
269 : // rust-ast.h
270 : void visit (Token &tok);
271 : void visit (DelimTokenTree &delim_tok_tree);
272 : void visit (AttrInputMetaItemContainer &input);
273 : void visit (IdentifierExpr &ident_expr);
274 : void visit (Lifetime &lifetime);
275 : void visit (LifetimeParam &lifetime_param);
276 : void visit (ConstGenericParam &const_param);
277 :
278 : // rust-path.h
279 : void visit (SimplePath &path);
280 : void visit (PathExprSegment &segment);
281 : void visit (PathIdentSegment &segment);
282 : void visit (PathInExpression &path);
283 : void visit (TypePathSegment &segment);
284 : void visit (TypePathSegmentGeneric &segment);
285 : void visit (TypePathSegmentFunction &segment);
286 : void visit (TypePath &path);
287 : void visit (QualifiedPathType &path);
288 : void visit (QualifiedPathInExpression &path);
289 : void visit (QualifiedPathInType &path);
290 :
291 : // rust-expr.h
292 : void visit (LiteralExpr &expr);
293 : void visit (AttrInputLiteral &attr_input);
294 : void visit (AttrInputMacro &attr_input);
295 : void visit (MetaItemLitExpr &meta_item);
296 : void visit (MetaItemPathExpr &meta_item);
297 : void visit (BorrowExpr &expr);
298 : void visit (DereferenceExpr &expr);
299 : void visit (ErrorPropagationExpr &expr);
300 : void visit (NegationExpr &expr);
301 : void visit (ArithmeticOrLogicalExpr &expr);
302 : void visit (ComparisonExpr &expr);
303 : void visit (LazyBooleanExpr &expr);
304 : void visit (TypeCastExpr &expr);
305 : void visit (AssignmentExpr &expr);
306 : void visit (CompoundAssignmentExpr &expr);
307 : void visit (GroupedExpr &expr);
308 : void visit (ArrayElemsValues &elems);
309 : void visit (ArrayElemsCopied &elems);
310 : void visit (ArrayExpr &expr);
311 : void visit (ArrayIndexExpr &expr);
312 : void visit (TupleExpr &expr);
313 : void visit (TupleIndexExpr &expr);
314 : void visit (StructExprStruct &expr);
315 : void visit (StructExprFieldIdentifier &field);
316 : void visit (StructExprFieldIdentifierValue &field);
317 : void visit (StructExprFieldIndexValue &field);
318 : void visit (StructBase &base);
319 : void visit (StructExprStructFields &expr);
320 : void visit (StructExprStructBase &expr);
321 : void visit (CallExpr &expr);
322 : void visit (MethodCallExpr &expr);
323 : void visit (FieldAccessExpr &expr);
324 : void visit (ClosureParam ¶m);
325 : void visit (ClosureExprInner &expr);
326 : void visit (BlockExpr &expr);
327 : void visit (AnonConst &expr);
328 : void visit (ConstBlock &expr);
329 : void visit (ClosureExprInnerTyped &expr);
330 : void visit (ContinueExpr &expr);
331 : void visit (BreakExpr &expr);
332 : void visit (RangeFromToExpr &expr);
333 : void visit (RangeFromExpr &expr);
334 : void visit (RangeToExpr &expr);
335 : void visit (RangeFullExpr &expr);
336 : void visit (RangeFromToInclExpr &expr);
337 : void visit (RangeToInclExpr &expr);
338 : void visit (ReturnExpr &expr);
339 : void visit (TryExpr &expr);
340 : void visit (BoxExpr &expr);
341 : void visit (UnsafeBlockExpr &expr);
342 : void visit (LoopExpr &expr);
343 : void visit (WhileLoopExpr &expr);
344 : void visit (WhileLetLoopExpr &expr);
345 : void visit (ForLoopExpr &expr);
346 : void visit (IfExpr &expr);
347 : void visit (IfExprConseqElse &expr);
348 : void visit (IfLetExpr &expr);
349 : void visit (IfLetExprConseqElse &expr);
350 : void visit (MatchArm &arm);
351 : void visit (MatchCase &arm);
352 : void visit (MatchExpr &expr);
353 : void visit (AwaitExpr &expr);
354 : void visit (AsyncBlockExpr &expr);
355 : void visit (InlineAsm &expr);
356 : void visit (LlvmInlineAsm &expr);
357 : // rust-item.h
358 : void visit (TypeParam ¶m);
359 : void visit (LifetimeWhereClauseItem &item);
360 : void visit (TypeBoundWhereClauseItem &item);
361 : void visit (Module &module);
362 : void visit (ExternCrate &crate);
363 : void visit (UseTreeGlob &use_tree);
364 : void visit (UseTreeList &use_tree);
365 : void visit (UseTreeRebind &use_tree);
366 : void visit (UseDeclaration &use_decl);
367 : void visit (Function &function);
368 : void visit (TypeAlias &type_alias);
369 : void visit (StructStruct &struct_item);
370 : void visit (TupleStruct &tuple_struct);
371 : void visit (EnumItem &item);
372 : void visit (EnumItemTuple &item);
373 : void visit (EnumItemStruct &item);
374 : void visit (EnumItemDiscriminant &item);
375 : void visit (Enum &enumeration);
376 : void visit (Union &union_item);
377 : void visit (ConstantItem &const_item);
378 : void visit (StaticItem &static_item);
379 : void visit (SelfParam ¶m);
380 : void visit (TraitItemType &item);
381 : void visit (Trait &trait);
382 : void visit (InherentImpl &impl);
383 : void visit (TraitImpl &impl);
384 : void visit (ExternalTypeItem &item);
385 : void visit (ExternalStaticItem &item);
386 : void visit (ExternBlock &block);
387 :
388 : // rust-macro.h
389 : void visit (MacroMatchFragment &match);
390 : void visit (MacroMatchRepetition &match);
391 : void visit (MacroMatcher &matcher);
392 : void visit (MacroRulesDefinition &rules_def);
393 : void visit (MacroInvocData &invoc_data);
394 : void visit (MacroInvocation ¯o_invoc);
395 : void visit (MetaItemPath &meta_item);
396 : void visit (MetaItemSeq &meta_item);
397 : void visit (MetaWord &meta_item);
398 : void visit (MetaNameValueStr &meta_item);
399 : void visit (MetaListPaths &meta_item);
400 : void visit (MetaListNameValueStr &meta_item);
401 :
402 : // rust-pattern.h
403 : void visit (LiteralPattern &pattern);
404 : void visit (IdentifierPattern &pattern);
405 : void visit (WildcardPattern &pattern);
406 : void visit (RestPattern &pattern);
407 : // void visit(RangePatternBound& bound);
408 : void visit (RangePatternBoundLiteral &bound);
409 : void visit (RangePatternBoundPath &bound);
410 : void visit (RangePatternBoundQualPath &bound);
411 : void visit (RangePattern &pattern);
412 : void visit (ReferencePattern &pattern);
413 : // void visit(StructPatternField& field);
414 : void visit (StructPatternFieldTuplePat &field);
415 : void visit (StructPatternFieldIdentPat &field);
416 : void visit (StructPatternFieldIdent &field);
417 : void visit (StructPattern &pattern);
418 : // void visit(TupleStructItems& tuple_items);
419 : void visit (TupleStructItemsNoRest &tuple_items);
420 : void visit (TupleStructItemsHasRest &tuple_items);
421 : void visit (TupleStructPattern &pattern);
422 : // void visit(TuplePatternItems& tuple_items);
423 : void visit (TuplePatternItemsNoRest &tuple_items);
424 : void visit (TuplePatternItemsHasRest &tuple_items);
425 : void visit (TuplePattern &pattern);
426 : void visit (GroupedPattern &pattern);
427 : void visit (SlicePatternItemsNoRest &items);
428 : void visit (SlicePatternItemsHasRest &items);
429 : void visit (SlicePattern &pattern);
430 : void visit (AltPattern &pattern);
431 :
432 : // rust-stmt.h
433 : void visit (EmptyStmt &stmt);
434 : void visit (LetStmt &stmt);
435 : void visit (ExprStmt &stmt);
436 :
437 : // rust-type.h
438 : void visit (TraitBound &bound);
439 : void visit (ImplTraitType &type);
440 : void visit (TraitObjectType &type);
441 : void visit (ParenthesisedType &type);
442 : void visit (ImplTraitTypeOneBound &type);
443 : void visit (TraitObjectTypeOneBound &type);
444 : void visit (TupleType &type);
445 : void visit (NeverType &type);
446 : void visit (RawPointerType &type);
447 : void visit (ReferenceType &type);
448 : void visit (ArrayType &type);
449 : void visit (SliceType &type);
450 : void visit (InferredType &type);
451 : void visit (BareFunctionType &type);
452 :
453 : void visit (FormatArgs &fmt);
454 : void visit (OffsetOf &offset_of);
455 : };
456 : } // namespace AST
457 :
458 : } // namespace Rust
459 :
460 : #endif // !RUST_AST_COLLECTOR_H
|