diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/Cargo.toml | 10 | ||||
-rw-r--r-- | xtask/src/ast_src.rs | 2102 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 353 | ||||
-rw-r--r-- | xtask/src/codegen/gen_unstable_future_descriptor.rs | 2 | ||||
-rw-r--r-- | xtask/src/codegen/rust.ungram | 587 | ||||
-rw-r--r-- | xtask/src/metrics.rs | 132 | ||||
-rw-r--r-- | xtask/tests/tidy.rs | 1 |
7 files changed, 977 insertions, 2210 deletions
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index d1cfb5909..1a1140b04 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -10,9 +10,11 @@ license = "MIT OR Apache-2.0" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | walkdir = "2.3.1" | ||
14 | pico-args = "0.3.1" | ||
15 | quote = "1.0.2" | ||
16 | proc-macro2 = "1.0.8" | ||
17 | anyhow = "1.0.26" | 13 | anyhow = "1.0.26" |
18 | flate2 = "1.0" | 14 | flate2 = "1.0" |
15 | pico-args = "0.3.1" | ||
16 | proc-macro2 = "1.0.8" | ||
17 | quote = "1.0.2" | ||
18 | ungrammar = "1.1.1" | ||
19 | walkdir = "2.3.1" | ||
20 | write-json = "0.1.0" | ||
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index 392648d71..adc191254 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -93,19 +93,19 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
93 | ], | 93 | ], |
94 | nodes: &[ | 94 | nodes: &[ |
95 | "SOURCE_FILE", | 95 | "SOURCE_FILE", |
96 | "STRUCT_DEF", | 96 | "STRUCT", |
97 | "UNION_DEF", | 97 | "UNION", |
98 | "ENUM_DEF", | 98 | "ENUM", |
99 | "FN_DEF", | 99 | "FN", |
100 | "RET_TYPE", | 100 | "RET_TYPE", |
101 | "EXTERN_CRATE_ITEM", | 101 | "EXTERN_CRATE", |
102 | "MODULE", | 102 | "MODULE", |
103 | "USE_ITEM", | 103 | "USE", |
104 | "STATIC_DEF", | 104 | "STATIC", |
105 | "CONST_DEF", | 105 | "CONST", |
106 | "TRAIT_DEF", | 106 | "TRAIT", |
107 | "IMPL_DEF", | 107 | "IMPL", |
108 | "TYPE_ALIAS_DEF", | 108 | "TYPE_ALIAS", |
109 | "MACRO_CALL", | 109 | "MACRO_CALL", |
110 | "TOKEN_TREE", | 110 | "TOKEN_TREE", |
111 | "MACRO_DEF", | 111 | "MACRO_DEF", |
@@ -113,12 +113,12 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
113 | "TUPLE_TYPE", | 113 | "TUPLE_TYPE", |
114 | "NEVER_TYPE", | 114 | "NEVER_TYPE", |
115 | "PATH_TYPE", | 115 | "PATH_TYPE", |
116 | "POINTER_TYPE", | 116 | "PTR_TYPE", |
117 | "ARRAY_TYPE", | 117 | "ARRAY_TYPE", |
118 | "SLICE_TYPE", | 118 | "SLICE_TYPE", |
119 | "REFERENCE_TYPE", | 119 | "REF_TYPE", |
120 | "PLACEHOLDER_TYPE", | 120 | "INFER_TYPE", |
121 | "FN_POINTER_TYPE", | 121 | "FN_PTR_TYPE", |
122 | "FOR_TYPE", | 122 | "FOR_TYPE", |
123 | "IMPL_TRAIT_TYPE", | 123 | "IMPL_TRAIT_TYPE", |
124 | "DYN_TRAIT_TYPE", | 124 | "DYN_TRAIT_TYPE", |
@@ -126,13 +126,13 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
126 | "PAREN_PAT", | 126 | "PAREN_PAT", |
127 | "REF_PAT", | 127 | "REF_PAT", |
128 | "BOX_PAT", | 128 | "BOX_PAT", |
129 | "BIND_PAT", | 129 | "IDENT_PAT", |
130 | "PLACEHOLDER_PAT", | 130 | "WILDCARD_PAT", |
131 | "DOT_DOT_PAT", | 131 | "REST_PAT", |
132 | "PATH_PAT", | 132 | "PATH_PAT", |
133 | "RECORD_PAT", | 133 | "RECORD_PAT", |
134 | "RECORD_FIELD_PAT_LIST", | 134 | "RECORD_PAT_FIELD_LIST", |
135 | "RECORD_FIELD_PAT", | 135 | "RECORD_PAT_FIELD", |
136 | "TUPLE_STRUCT_PAT", | 136 | "TUPLE_STRUCT_PAT", |
137 | "TUPLE_PAT", | 137 | "TUPLE_PAT", |
138 | "SLICE_PAT", | 138 | "SLICE_PAT", |
@@ -144,7 +144,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
144 | "ARRAY_EXPR", | 144 | "ARRAY_EXPR", |
145 | "PAREN_EXPR", | 145 | "PAREN_EXPR", |
146 | "PATH_EXPR", | 146 | "PATH_EXPR", |
147 | "LAMBDA_EXPR", | 147 | "CLOSURE_EXPR", |
148 | "IF_EXPR", | 148 | "IF_EXPR", |
149 | "WHILE_EXPR", | 149 | "WHILE_EXPR", |
150 | "CONDITION", | 150 | "CONDITION", |
@@ -159,9 +159,9 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
159 | "MATCH_ARM_LIST", | 159 | "MATCH_ARM_LIST", |
160 | "MATCH_ARM", | 160 | "MATCH_ARM", |
161 | "MATCH_GUARD", | 161 | "MATCH_GUARD", |
162 | "RECORD_LIT", | 162 | "RECORD_EXPR", |
163 | "RECORD_FIELD_LIST", | 163 | "RECORD_EXPR_FIELD_LIST", |
164 | "RECORD_FIELD", | 164 | "RECORD_EXPR_FIELD", |
165 | "EFFECT_EXPR", | 165 | "EFFECT_EXPR", |
166 | "BOX_EXPR", | 166 | "BOX_EXPR", |
167 | // postfix | 167 | // postfix |
@@ -179,13 +179,14 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
179 | "BIN_EXPR", | 179 | "BIN_EXPR", |
180 | "EXTERN_BLOCK", | 180 | "EXTERN_BLOCK", |
181 | "EXTERN_ITEM_LIST", | 181 | "EXTERN_ITEM_LIST", |
182 | "ENUM_VARIANT", | 182 | "VARIANT", |
183 | "RECORD_FIELD_DEF_LIST", | 183 | "RECORD_FIELD_LIST", |
184 | "RECORD_FIELD_DEF", | 184 | "RECORD_FIELD", |
185 | "TUPLE_FIELD_DEF_LIST", | 185 | "TUPLE_FIELD_LIST", |
186 | "TUPLE_FIELD_DEF", | 186 | "TUPLE_FIELD", |
187 | "ENUM_VARIANT_LIST", | 187 | "VARIANT_LIST", |
188 | "ITEM_LIST", | 188 | "ITEM_LIST", |
189 | "ASSOC_ITEM_LIST", | ||
189 | "ATTR", | 190 | "ATTR", |
190 | "META_ITEM", // not an item actually | 191 | "META_ITEM", // not an item actually |
191 | "USE_TREE", | 192 | "USE_TREE", |
@@ -193,7 +194,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
193 | "PATH", | 194 | "PATH", |
194 | "PATH_SEGMENT", | 195 | "PATH_SEGMENT", |
195 | "LITERAL", | 196 | "LITERAL", |
196 | "ALIAS", | 197 | "RENAME", |
197 | "VISIBILITY", | 198 | "VISIBILITY", |
198 | "WHERE_CLAUSE", | 199 | "WHERE_CLAUSE", |
199 | "WHERE_PRED", | 200 | "WHERE_PRED", |
@@ -202,11 +203,12 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
202 | "NAME_REF", | 203 | "NAME_REF", |
203 | "LET_STMT", | 204 | "LET_STMT", |
204 | "EXPR_STMT", | 205 | "EXPR_STMT", |
205 | "TYPE_PARAM_LIST", | 206 | "GENERIC_PARAM_LIST", |
207 | "GENERIC_PARAM", | ||
206 | "LIFETIME_PARAM", | 208 | "LIFETIME_PARAM", |
207 | "TYPE_PARAM", | 209 | "TYPE_PARAM", |
208 | "CONST_PARAM", | 210 | "CONST_PARAM", |
209 | "TYPE_ARG_LIST", | 211 | "GENERIC_ARG_LIST", |
210 | "LIFETIME_ARG", | 212 | "LIFETIME_ARG", |
211 | "TYPE_ARG", | 213 | "TYPE_ARG", |
212 | "ASSOC_TYPE_ARG", | 214 | "ASSOC_TYPE_ARG", |
@@ -223,2021 +225,37 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
223 | ], | 225 | ], |
224 | }; | 226 | }; |
225 | 227 | ||
226 | pub(crate) struct AstSrc<'a> { | 228 | #[derive(Default, Debug)] |
227 | pub(crate) tokens: &'a [&'a str], | 229 | pub(crate) struct AstSrc { |
228 | pub(crate) nodes: &'a [AstNodeSrc<'a>], | 230 | pub(crate) tokens: Vec<String>, |
229 | pub(crate) enums: &'a [AstEnumSrc<'a>], | 231 | pub(crate) nodes: Vec<AstNodeSrc>, |
230 | } | 232 | pub(crate) enums: Vec<AstEnumSrc>, |
231 | |||
232 | pub(crate) struct AstNodeSrc<'a> { | ||
233 | pub(crate) doc: &'a [&'a str], | ||
234 | pub(crate) name: &'a str, | ||
235 | pub(crate) traits: &'a [&'a str], | ||
236 | pub(crate) fields: &'a [Field<'a>], | ||
237 | } | ||
238 | |||
239 | pub(crate) enum Field<'a> { | ||
240 | Token(&'a str), | ||
241 | Node { name: &'a str, src: FieldSrc<'a> }, | ||
242 | } | ||
243 | |||
244 | pub(crate) enum FieldSrc<'a> { | ||
245 | Shorthand, | ||
246 | Optional(&'a str), | ||
247 | Many(&'a str), | ||
248 | } | 233 | } |
249 | 234 | ||
250 | pub(crate) struct AstEnumSrc<'a> { | 235 | #[derive(Debug)] |
251 | pub(crate) doc: &'a [&'a str], | 236 | pub(crate) struct AstNodeSrc { |
252 | pub(crate) name: &'a str, | 237 | pub(crate) doc: Vec<String>, |
253 | pub(crate) traits: &'a [&'a str], | 238 | pub(crate) name: String, |
254 | pub(crate) variants: &'a [&'a str], | 239 | pub(crate) traits: Vec<String>, |
240 | pub(crate) fields: Vec<Field>, | ||
255 | } | 241 | } |
256 | 242 | ||
257 | macro_rules! ast_nodes { | 243 | #[derive(Debug, Eq, PartialEq)] |
258 | ($( | 244 | pub(crate) enum Field { |
259 | $(#[doc = $doc:expr])+ | 245 | Token(String), |
260 | struct $name:ident$(: $($trait:ident),*)? { | 246 | Node { name: String, ty: String, cardinality: Cardinality }, |
261 | $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)? | ||
262 | } | ||
263 | )*) => { | ||
264 | [$( | ||
265 | AstNodeSrc { | ||
266 | doc: &[$($doc),*], | ||
267 | name: stringify!($name), | ||
268 | traits: &[$($(stringify!($trait)),*)?], | ||
269 | fields: &[ | ||
270 | $(field!($(T![$token])? $field_name $($ty)?)),* | ||
271 | ], | ||
272 | |||
273 | } | ||
274 | ),*] | ||
275 | }; | ||
276 | } | 247 | } |
277 | 248 | ||
278 | macro_rules! field { | 249 | #[derive(Debug, Eq, PartialEq)] |
279 | (T![$token:tt] T) => { | 250 | pub(crate) enum Cardinality { |
280 | Field::Token(stringify!($token)) | 251 | Optional, |
281 | }; | 252 | Many, |
282 | ($field_name:ident) => { | ||
283 | Field::Node { name: stringify!($field_name), src: FieldSrc::Shorthand } | ||
284 | }; | ||
285 | ($field_name:ident [$ty:ident]) => { | ||
286 | Field::Node { name: stringify!($field_name), src: FieldSrc::Many(stringify!($ty)) } | ||
287 | }; | ||
288 | ($field_name:ident $ty:ident) => { | ||
289 | Field::Node { name: stringify!($field_name), src: FieldSrc::Optional(stringify!($ty)) } | ||
290 | }; | ||
291 | } | 253 | } |
292 | 254 | ||
293 | macro_rules! ast_enums { | 255 | #[derive(Debug)] |
294 | ($( | 256 | pub(crate) struct AstEnumSrc { |
295 | $(#[doc = $doc:expr])+ | 257 | pub(crate) doc: Vec<String>, |
296 | enum $name:ident $(: $($trait:ident),*)? { | 258 | pub(crate) name: String, |
297 | $($variant:ident),*$(,)? | 259 | pub(crate) traits: Vec<String>, |
298 | } | 260 | pub(crate) variants: Vec<String>, |
299 | )*) => { | ||
300 | [$( | ||
301 | AstEnumSrc { | ||
302 | doc: &[$($doc),*], | ||
303 | name: stringify!($name), | ||
304 | traits: &[$($(stringify!($trait)),*)?], | ||
305 | variants: &[$(stringify!($variant)),*], | ||
306 | } | ||
307 | ),*] | ||
308 | }; | ||
309 | } | 261 | } |
310 | |||
311 | pub(crate) const AST_SRC: AstSrc = AstSrc { | ||
312 | tokens: &["Whitespace", "Comment", "String", "RawString"], | ||
313 | nodes: &ast_nodes! { | ||
314 | /// The entire Rust source file. Includes all top-level inner attributes and module items. | ||
315 | /// | ||
316 | /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html) | ||
317 | struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner { | ||
318 | modules: [Module], | ||
319 | } | ||
320 | |||
321 | /// Function definition either with body or not. | ||
322 | /// Includes all of its attributes and doc comments. | ||
323 | /// | ||
324 | /// ``` | ||
325 | /// ❰ | ||
326 | /// /// Docs | ||
327 | /// #[attr] | ||
328 | /// pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32 | ||
329 | /// where | ||
330 | /// T: Debug | ||
331 | /// { | ||
332 | /// 42 | ||
333 | /// } | ||
334 | /// ❱ | ||
335 | /// | ||
336 | /// extern "C" { | ||
337 | /// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱ | ||
338 | /// } | ||
339 | /// ``` | ||
340 | /// | ||
341 | /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html) | ||
342 | /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions) | ||
343 | struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { | ||
344 | Abi, | ||
345 | T![const], | ||
346 | T![default], | ||
347 | T![async], | ||
348 | T![unsafe], | ||
349 | T![fn], | ||
350 | ParamList, | ||
351 | RetType, | ||
352 | body: BlockExpr, | ||
353 | T![;] | ||
354 | } | ||
355 | |||
356 | /// Return type annotation. | ||
357 | /// | ||
358 | /// ``` | ||
359 | /// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) } | ||
360 | /// ``` | ||
361 | /// | ||
362 | /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) | ||
363 | struct RetType { T![->], TypeRef } | ||
364 | |||
365 | /// Struct definition. | ||
366 | /// Includes all of its attributes and doc comments. | ||
367 | /// | ||
368 | /// ``` | ||
369 | /// ❰ | ||
370 | /// /// Docs | ||
371 | /// #[attr] | ||
372 | /// struct Foo<T> where T: Debug { | ||
373 | /// /// Docs | ||
374 | /// #[attr] | ||
375 | /// pub a: u32, | ||
376 | /// b: T, | ||
377 | /// } | ||
378 | /// ❱ | ||
379 | /// | ||
380 | /// ❰ struct Foo; ❱ | ||
381 | /// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱ | ||
382 | /// ``` | ||
383 | /// | ||
384 | /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) | ||
385 | struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | ||
386 | T![struct], | ||
387 | FieldDefList, | ||
388 | T![;] | ||
389 | } | ||
390 | |||
391 | /// Union definition. | ||
392 | /// Includes all of its attributes and doc comments. | ||
393 | /// | ||
394 | /// ``` | ||
395 | /// ❰ | ||
396 | /// /// Docs | ||
397 | /// #[attr] | ||
398 | /// pub union Foo<T> where T: Debug { | ||
399 | /// /// Docs | ||
400 | /// #[attr] | ||
401 | /// a: T, | ||
402 | /// b: u32, | ||
403 | /// } | ||
404 | /// ❱ | ||
405 | /// ``` | ||
406 | /// | ||
407 | /// [Reference](https://doc.rust-lang.org/reference/items/unions.html) | ||
408 | struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | ||
409 | T![union], | ||
410 | RecordFieldDefList, | ||
411 | } | ||
412 | |||
413 | /// Record field definition list including enclosing curly braces. | ||
414 | /// | ||
415 | /// ``` | ||
416 | /// struct Foo // same for union | ||
417 | /// ❰ | ||
418 | /// { | ||
419 | /// a: u32, | ||
420 | /// b: bool, | ||
421 | /// } | ||
422 | /// ❱ | ||
423 | /// ``` | ||
424 | /// | ||
425 | /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) | ||
426 | struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] } | ||
427 | |||
428 | /// Record field definition including its attributes and doc comments. | ||
429 | /// | ||
430 | /// ` `` | ||
431 | /// same for union | ||
432 | /// struct Foo { | ||
433 | /// ❰ | ||
434 | /// /// Docs | ||
435 | /// #[attr] | ||
436 | /// pub a: u32 | ||
437 | /// ❱ | ||
438 | /// | ||
439 | /// ❰ b: bool ❱ | ||
440 | /// } | ||
441 | /// ``` | ||
442 | /// | ||
443 | /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) | ||
444 | struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } | ||
445 | |||
446 | /// Tuple field definition list including enclosing parens. | ||
447 | /// | ||
448 | /// ``` | ||
449 | /// struct Foo ❰ (u32, String, Vec<u32>) ❱; | ||
450 | /// ``` | ||
451 | /// | ||
452 | /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) | ||
453 | struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] } | ||
454 | |||
455 | /// Tuple field definition including its attributes. | ||
456 | /// | ||
457 | /// ``` | ||
458 | /// struct Foo(❰ #[attr] u32 ❱); | ||
459 | /// ``` | ||
460 | /// | ||
461 | /// [Reference](https://doc.rust-lang.org/reference/items/structs.html) | ||
462 | struct TupleFieldDef: VisibilityOwner, AttrsOwner { | ||
463 | TypeRef, | ||
464 | } | ||
465 | |||
466 | /// Enum definition. | ||
467 | /// Includes all of its attributes and doc comments. | ||
468 | /// | ||
469 | /// ``` | ||
470 | /// ❰ | ||
471 | /// /// Docs | ||
472 | /// #[attr] | ||
473 | /// pub enum Foo<T> where T: Debug { | ||
474 | /// /// Docs | ||
475 | /// #[attr] | ||
476 | /// Bar, | ||
477 | /// Baz(#[attr] u32), | ||
478 | /// Bruh { | ||
479 | /// a: u32, | ||
480 | /// /// Docs | ||
481 | /// #[attr] | ||
482 | /// b: T, | ||
483 | /// } | ||
484 | /// } | ||
485 | /// ❱ | ||
486 | /// ``` | ||
487 | /// | ||
488 | /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) | ||
489 | struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | ||
490 | T![enum], | ||
491 | variant_list: EnumVariantList, | ||
492 | } | ||
493 | |||
494 | /// Enum variant definition list including enclosing curly braces. | ||
495 | /// | ||
496 | /// ``` | ||
497 | /// enum Foo | ||
498 | /// ❰ | ||
499 | /// { | ||
500 | /// Bar, | ||
501 | /// Baz(u32), | ||
502 | /// Bruh { | ||
503 | /// a: u32 | ||
504 | /// } | ||
505 | /// } | ||
506 | /// ❱ | ||
507 | /// ``` | ||
508 | /// | ||
509 | /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) | ||
510 | struct EnumVariantList { | ||
511 | T!['{'], | ||
512 | variants: [EnumVariant], | ||
513 | T!['}'] | ||
514 | } | ||
515 | |||
516 | /// Enum variant definition including its attributes and discriminant value definition. | ||
517 | /// | ||
518 | /// ``` | ||
519 | /// enum Foo { | ||
520 | /// ❰ | ||
521 | /// /// Docs | ||
522 | /// #[attr] | ||
523 | /// Bar | ||
524 | /// ❱ | ||
525 | /// | ||
526 | /// // same for tuple and record variants | ||
527 | /// } | ||
528 | /// ``` | ||
529 | /// | ||
530 | /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html) | ||
531 | struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { | ||
532 | FieldDefList, | ||
533 | T![=], | ||
534 | Expr | ||
535 | } | ||
536 | |||
537 | /// Trait definition. | ||
538 | /// Includes all of its attributes and doc comments. | ||
539 | /// | ||
540 | /// ``` | ||
541 | /// ❰ | ||
542 | /// /// Docs | ||
543 | /// #[attr] | ||
544 | /// pub unsafe trait Foo<T>: Debug where T: Debug { | ||
545 | /// // ... | ||
546 | /// } | ||
547 | /// ❱ | ||
548 | /// ``` | ||
549 | /// | ||
550 | /// [Reference](https://doc.rust-lang.org/reference/items/traits.html) | ||
551 | struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { | ||
552 | T![unsafe], | ||
553 | T![auto], | ||
554 | T![trait], | ||
555 | ItemList, | ||
556 | } | ||
557 | |||
558 | /// Module definition either with body or not. | ||
559 | /// Includes all of its inner and outer attributes, module items, doc comments. | ||
560 | /// | ||
561 | /// ``` | ||
562 | /// ❰ | ||
563 | /// /// Docs | ||
564 | /// #[attr] | ||
565 | /// pub mod foo; | ||
566 | /// ❱ | ||
567 | /// | ||
568 | /// ❰ | ||
569 | /// /// Docs | ||
570 | /// #[attr] | ||
571 | /// pub mod bar { | ||
572 | /// //! Inner docs | ||
573 | /// #![inner_attr] | ||
574 | /// } | ||
575 | /// ❱ | ||
576 | /// ``` | ||
577 | /// | ||
578 | /// [Reference](https://doc.rust-lang.org/reference/items/modules.html) | ||
579 | struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { | ||
580 | T![mod], | ||
581 | ItemList, | ||
582 | T![;] | ||
583 | } | ||
584 | |||
585 | /// Item defintion list. | ||
586 | /// This is used for both top-level items and impl block items. | ||
587 | /// | ||
588 | /// ``` | ||
589 | /// ❰ | ||
590 | /// fn foo {} | ||
591 | /// struct Bar; | ||
592 | /// enum Baz; | ||
593 | /// trait Bruh; | ||
594 | /// const BRUUH: u32 = 42; | ||
595 | /// ❱ | ||
596 | /// | ||
597 | /// impl Foo | ||
598 | /// ❰ | ||
599 | /// { | ||
600 | /// fn bar() {} | ||
601 | /// const BAZ: u32 = 42; | ||
602 | /// } | ||
603 | /// ❱ | ||
604 | /// ``` | ||
605 | /// | ||
606 | /// [Reference](https://doc.rust-lang.org/reference/items.html) | ||
607 | struct ItemList: ModuleItemOwner { | ||
608 | T!['{'], | ||
609 | assoc_items: [AssocItem], | ||
610 | T!['}'] | ||
611 | } | ||
612 | |||
613 | /// Constant variable definition. | ||
614 | /// Includes all of its attributes and doc comments. | ||
615 | /// | ||
616 | /// ``` | ||
617 | /// ❰ | ||
618 | /// /// Docs | ||
619 | /// #[attr] | ||
620 | /// pub const FOO: u32 = 42; | ||
621 | /// ❱ | ||
622 | /// ``` | ||
623 | /// | ||
624 | /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html) | ||
625 | struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | ||
626 | T![default], | ||
627 | T![const], | ||
628 | T![=], | ||
629 | body: Expr, | ||
630 | T![;] | ||
631 | } | ||
632 | |||
633 | |||
634 | /// Static variable definition. | ||
635 | /// Includes all of its attributes and doc comments. | ||
636 | /// | ||
637 | /// ``` | ||
638 | /// ❰ | ||
639 | /// /// Docs | ||
640 | /// #[attr] | ||
641 | /// pub static mut FOO: u32 = 42; | ||
642 | /// ❱ | ||
643 | /// ``` | ||
644 | /// | ||
645 | /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html) | ||
646 | struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | ||
647 | T![static], | ||
648 | T![mut], | ||
649 | T![=], | ||
650 | body: Expr, | ||
651 | T![;] | ||
652 | } | ||
653 | |||
654 | /// Type alias definition. | ||
655 | /// Includes associated type clauses with type bounds. | ||
656 | /// | ||
657 | /// ``` | ||
658 | /// ❰ | ||
659 | /// /// Docs | ||
660 | /// #[attr] | ||
661 | /// pub type Foo<T> where T: Debug = T; | ||
662 | /// ❱ | ||
663 | /// | ||
664 | /// trait Bar { | ||
665 | /// ❰ type Baz: Debug; ❱ | ||
666 | /// ❰ type Bruh = String; ❱ | ||
667 | /// ❰ type Bruuh: Debug = u32; ❱ | ||
668 | /// } | ||
669 | /// ``` | ||
670 | /// | ||
671 | /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html) | ||
672 | struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { | ||
673 | T![default], | ||
674 | T![type], | ||
675 | T![=], | ||
676 | TypeRef, | ||
677 | T![;] | ||
678 | } | ||
679 | |||
680 | /// Inherent and trait impl definition. | ||
681 | /// Includes all of its inner and outer attributes. | ||
682 | /// | ||
683 | /// ``` | ||
684 | /// ❰ | ||
685 | /// #[attr] | ||
686 | /// unsafe impl<T> const !Foo for Bar where T: Debug { | ||
687 | /// #![inner_attr] | ||
688 | /// // ... | ||
689 | /// } | ||
690 | /// ❱ | ||
691 | /// ``` | ||
692 | /// | ||
693 | /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html) | ||
694 | struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner { | ||
695 | T![default], | ||
696 | T![const], | ||
697 | T![unsafe], | ||
698 | T![impl], | ||
699 | T![!], | ||
700 | T![for], | ||
701 | ItemList, | ||
702 | } | ||
703 | |||
704 | |||
705 | /// Parenthesized type reference. | ||
706 | /// Note: parens are only used for grouping, this is not a tuple type. | ||
707 | /// | ||
708 | /// ``` | ||
709 | /// // This is effectively just `u32`. | ||
710 | /// // Single-item tuple must be defined with a trailing comma: `(u32,)` | ||
711 | /// type Foo = ❰ (u32) ❱; | ||
712 | /// | ||
713 | /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh"; | ||
714 | /// ``` | ||
715 | struct ParenType { T!['('], TypeRef, T![')'] } | ||
716 | |||
717 | /// Unnamed tuple type. | ||
718 | /// | ||
719 | /// ``` | ||
720 | /// let foo: ❰ (u32, bool) ❱ = (42, true); | ||
721 | /// ``` | ||
722 | /// | ||
723 | /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html) | ||
724 | struct TupleType { T!['('], fields: [TypeRef], T![')'] } | ||
725 | |||
726 | /// The never type (i.e. the exclamation point). | ||
727 | /// | ||
728 | /// ``` | ||
729 | /// type T = ❰ ! ❱; | ||
730 | /// | ||
731 | /// fn no_return() -> ❰ ! ❱ { | ||
732 | /// loop {} | ||
733 | /// } | ||
734 | /// ``` | ||
735 | /// | ||
736 | /// [Reference](https://doc.rust-lang.org/reference/types/never.html) | ||
737 | struct NeverType { T![!] } | ||
738 | |||
739 | /// Path to a type. | ||
740 | /// Includes single identifier type names and elaborate paths with | ||
741 | /// generic parameters. | ||
742 | /// | ||
743 | /// ``` | ||
744 | /// type Foo = ❰ String ❱; | ||
745 | /// type Bar = ❰ std::vec::Vec<T> ❱; | ||
746 | /// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱; | ||
747 | /// ``` | ||
748 | /// | ||
749 | /// [Reference](https://doc.rust-lang.org/reference/paths.html) | ||
750 | struct PathType { Path } | ||
751 | |||
752 | /// Raw pointer type. | ||
753 | /// | ||
754 | /// ``` | ||
755 | /// type Foo = ❰ *const u32 ❱; | ||
756 | /// type Bar = ❰ *mut u32 ❱; | ||
757 | /// ``` | ||
758 | /// | ||
759 | /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut) | ||
760 | struct PointerType { T![*], T![const], T![mut], TypeRef } | ||
761 | |||
762 | /// Array type. | ||
763 | /// | ||
764 | /// ``` | ||
765 | /// type Foo = ❰ [u32; 24 - 3] ❱; | ||
766 | /// ``` | ||
767 | /// | ||
768 | /// [Reference](https://doc.rust-lang.org/reference/types/array.html) | ||
769 | struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] } | ||
770 | |||
771 | /// Slice type. | ||
772 | /// | ||
773 | /// ``` | ||
774 | /// type Foo = ❰ [u8] ❱; | ||
775 | /// ``` | ||
776 | /// | ||
777 | /// [Reference](https://doc.rust-lang.org/reference/types/slice.html) | ||
778 | struct SliceType { T!['['], TypeRef, T![']'] } | ||
779 | |||
780 | /// Reference type. | ||
781 | /// | ||
782 | /// ``` | ||
783 | /// type Foo = ❰ &'static str ❱; | ||
784 | /// ``` | ||
785 | /// | ||
786 | /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html) | ||
787 | struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef } | ||
788 | |||
789 | /// Placeholder type (i.e. the underscore). | ||
790 | /// | ||
791 | /// ``` | ||
792 | /// let foo: ❰ _ ❱ = 42_u32; | ||
793 | /// ``` | ||
794 | /// | ||
795 | /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html) | ||
796 | struct PlaceholderType { T![_] } | ||
797 | |||
798 | /// Function pointer type (not to be confused with `Fn*` family of traits). | ||
799 | /// | ||
800 | /// ``` | ||
801 | /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱; | ||
802 | /// | ||
803 | /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱; | ||
804 | /// ``` | ||
805 | /// | ||
806 | /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) | ||
807 | struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType } | ||
808 | |||
809 | /// Higher order type. | ||
810 | /// | ||
811 | /// ``` | ||
812 | /// type Foo = ❰ for<'a> fn(&'a str) ❱; | ||
813 | /// ``` | ||
814 | /// | ||
815 | /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html) | ||
816 | struct ForType { T![for], TypeParamList, TypeRef } | ||
817 | |||
818 | /// Opaque `impl Trait` type. | ||
819 | /// | ||
820 | /// ``` | ||
821 | /// fn foo(bar: ❰ impl Debug + Eq ❱) {} | ||
822 | /// ``` | ||
823 | /// | ||
824 | /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html) | ||
825 | struct ImplTraitType: TypeBoundsOwner { T![impl] } | ||
826 | |||
827 | /// Trait object type. | ||
828 | /// | ||
829 | /// ``` | ||
830 | /// type Foo = ❰ dyn Debug ❱; | ||
831 | /// ``` | ||
832 | /// | ||
833 | /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html) | ||
834 | struct DynTraitType: TypeBoundsOwner { T![dyn] } | ||
835 | |||
836 | /// Tuple literal. | ||
837 | /// | ||
838 | /// ``` | ||
839 | /// ❰ (42, true) ❱; | ||
840 | /// ``` | ||
841 | /// | ||
842 | /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html) | ||
843 | struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] } | ||
844 | |||
845 | /// Array literal. | ||
846 | /// | ||
847 | /// ``` | ||
848 | /// ❰ [#![inner_attr] true, false, true] ❱; | ||
849 | /// | ||
850 | /// ❰ ["baz"; 24] ❱; | ||
851 | /// ``` | ||
852 | /// | ||
853 | /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) | ||
854 | struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] } | ||
855 | |||
856 | /// Parenthesized expression. | ||
857 | /// Note: parens are only used for grouping, this is not a tuple literal. | ||
858 | /// | ||
859 | /// ``` | ||
860 | /// ❰ (#![inner_attr] 2 + 2) ❱ * 2; | ||
861 | /// ``` | ||
862 | /// | ||
863 | /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html) | ||
864 | struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] } | ||
865 | |||
866 | /// Path to a symbol in expression context. | ||
867 | /// Includes single identifier variable names and elaborate paths with | ||
868 | /// generic parameters. | ||
869 | /// | ||
870 | /// ``` | ||
871 | /// ❰ Some::<i32> ❱; | ||
872 | /// ❰ foo ❱ + 42; | ||
873 | /// ❰ Vec::<i32>::push ❱; | ||
874 | /// ❰ <[i32]>::reverse ❱; | ||
875 | /// ❰ <String as std::borrow::Borrow<str>>::borrow ❱; | ||
876 | /// ``` | ||
877 | /// | ||
878 | /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html) | ||
879 | struct PathExpr { Path } | ||
880 | |||
881 | /// Anonymous callable object literal a.k.a. closure, lambda or functor. | ||
882 | /// | ||
883 | /// ``` | ||
884 | /// ❰ || 42 ❱; | ||
885 | /// ❰ |a: u32| val + 1 ❱; | ||
886 | /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱; | ||
887 | /// ❰ move || baz ❱; | ||
888 | /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱ | ||
889 | /// ``` | ||
890 | /// | ||
891 | /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html) | ||
892 | struct LambdaExpr: AttrsOwner { | ||
893 | T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators | ||
894 | T![async], | ||
895 | T![move], | ||
896 | ParamList, | ||
897 | RetType, | ||
898 | body: Expr, | ||
899 | } | ||
900 | |||
901 | /// If expression. Includes both regular `if` and `if let` forms. | ||
902 | /// Beware that `else if` is a special case syntax sugar, because in general | ||
903 | /// there has to be block expression after `else`. | ||
904 | /// | ||
905 | /// ``` | ||
906 | /// ❰ if bool_cond { 42 } ❱ | ||
907 | /// ❰ if bool_cond { 42 } else { 24 } ❱ | ||
908 | /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱ | ||
909 | /// | ||
910 | /// ❰ | ||
911 | /// if let Pattern(foo) = bar { | ||
912 | /// foo | ||
913 | /// } else { | ||
914 | /// panic!(); | ||
915 | /// } | ||
916 | /// ❱ | ||
917 | /// ``` | ||
918 | /// | ||
919 | /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) | ||
920 | struct IfExpr: AttrsOwner { T![if], Condition } | ||
921 | |||
922 | /// Unconditional loop expression. | ||
923 | /// | ||
924 | /// ``` | ||
925 | /// ❰ | ||
926 | /// loop { | ||
927 | /// // yeah, it's that simple... | ||
928 | /// } | ||
929 | /// ❱ | ||
930 | /// ``` | ||
931 | /// | ||
932 | /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html) | ||
933 | struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } | ||
934 | |||
935 | /// Block expression with an optional prefix (label, try ketword, | ||
936 | /// unsafe keyword, async keyword...). | ||
937 | /// | ||
938 | /// ``` | ||
939 | /// ❰ | ||
940 | /// 'label: try { | ||
941 | /// None? | ||
942 | /// } | ||
943 | /// ❱ | ||
944 | /// ``` | ||
945 | /// | ||
946 | /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html) | ||
947 | /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks) | ||
948 | /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks) | ||
949 | struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr } | ||
950 | |||
951 | |||
952 | /// For loop expression. | ||
953 | /// Note: record struct literals are not valid as iterable expression | ||
954 | /// due to ambiguity. | ||
955 | /// | ||
956 | /// ``` | ||
957 | /// ❰ | ||
958 | /// for i in (0..4) { | ||
959 | /// dbg!(i); | ||
960 | /// } | ||
961 | /// ❱ | ||
962 | /// ``` | ||
963 | /// | ||
964 | /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops) | ||
965 | struct ForExpr: AttrsOwner, LoopBodyOwner { | ||
966 | T![for], | ||
967 | Pat, | ||
968 | T![in], | ||
969 | iterable: Expr, | ||
970 | } | ||
971 | |||
972 | /// While loop expression. Includes both regular `while` and `while let` forms. | ||
973 | /// | ||
974 | /// ``` | ||
975 | /// ❰ | ||
976 | /// while bool_cond { | ||
977 | /// 42; | ||
978 | /// } | ||
979 | /// ❱ | ||
980 | /// ❰ | ||
981 | /// while let Pattern(foo) = bar { | ||
982 | /// bar += 1; | ||
983 | /// } | ||
984 | /// ❱ | ||
985 | /// ``` | ||
986 | /// | ||
987 | /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) | ||
988 | struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition } | ||
989 | |||
990 | /// Continue expression. | ||
991 | /// | ||
992 | /// ``` | ||
993 | /// while bool_cond { | ||
994 | /// ❰ continue ❱; | ||
995 | /// } | ||
996 | /// | ||
997 | /// 'outer: loop { | ||
998 | /// loop { | ||
999 | /// ❰ continue 'outer ❱; | ||
1000 | /// } | ||
1001 | /// } | ||
1002 | /// | ||
1003 | /// ``` | ||
1004 | /// | ||
1005 | /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions) | ||
1006 | struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } | ||
1007 | |||
1008 | /// Break expression. | ||
1009 | /// | ||
1010 | /// ``` | ||
1011 | /// while bool_cond { | ||
1012 | /// ❰ break ❱; | ||
1013 | /// } | ||
1014 | /// 'outer: loop { | ||
1015 | /// for foo in bar { | ||
1016 | /// ❰ break 'outer ❱; | ||
1017 | /// } | ||
1018 | /// } | ||
1019 | /// 'outer: loop { | ||
1020 | /// loop { | ||
1021 | /// ❰ break 'outer 42 ❱; | ||
1022 | /// } | ||
1023 | /// } | ||
1024 | /// ``` | ||
1025 | /// | ||
1026 | /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions) | ||
1027 | struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } | ||
1028 | |||
1029 | /// Label. | ||
1030 | /// | ||
1031 | /// ``` | ||
1032 | /// ❰ 'outer: ❱ loop {} | ||
1033 | /// | ||
1034 | /// let foo = ❰ 'bar: ❱ loop {} | ||
1035 | /// | ||
1036 | /// ❰ 'baz: ❱ { | ||
1037 | /// break 'baz; | ||
1038 | /// } | ||
1039 | /// ``` | ||
1040 | /// | ||
1041 | /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels) | ||
1042 | /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) | ||
1043 | struct Label { T![lifetime] } | ||
1044 | |||
1045 | /// Block expression. Includes unsafe blocks and block labels. | ||
1046 | /// | ||
1047 | /// ``` | ||
1048 | /// let foo = ❰ | ||
1049 | /// { | ||
1050 | /// #![inner_attr] | ||
1051 | /// ❰ { } ❱ | ||
1052 | /// | ||
1053 | /// ❰ 'label: { break 'label } ❱ | ||
1054 | /// } | ||
1055 | /// ❱; | ||
1056 | /// ``` | ||
1057 | /// | ||
1058 | /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html) | ||
1059 | /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md) | ||
1060 | struct BlockExpr: AttrsOwner, ModuleItemOwner { | ||
1061 | Label, T!['{'], statements: [Stmt], Expr, T!['}'], | ||
1062 | } | ||
1063 | |||
1064 | /// Return expression. | ||
1065 | /// | ||
1066 | /// ``` | ||
1067 | /// || ❰ return 42 ❱; | ||
1068 | /// | ||
1069 | /// fn bar() { | ||
1070 | /// ❰ return ❱; | ||
1071 | /// } | ||
1072 | /// ``` | ||
1073 | /// | ||
1074 | /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html) | ||
1075 | struct ReturnExpr: AttrsOwner { Expr } | ||
1076 | |||
1077 | /// Call expression (not to be confused with method call expression, it is | ||
1078 | /// a separate ast node). | ||
1079 | /// | ||
1080 | /// ``` | ||
1081 | /// ❰ foo() ❱; | ||
1082 | /// ❰ &str::len("bar") ❱; | ||
1083 | /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱; | ||
1084 | /// ``` | ||
1085 | /// | ||
1086 | /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) | ||
1087 | struct CallExpr: ArgListOwner { Expr } | ||
1088 | |||
1089 | /// Method call expression. | ||
1090 | /// | ||
1091 | /// ``` | ||
1092 | /// ❰ receiver_expr.method() ❱; | ||
1093 | /// ❰ receiver_expr.method::<T>(42, true) ❱; | ||
1094 | /// | ||
1095 | /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱; | ||
1096 | /// ``` | ||
1097 | /// | ||
1098 | /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html) | ||
1099 | struct MethodCallExpr: AttrsOwner, ArgListOwner { | ||
1100 | Expr, T![.], NameRef, TypeArgList, | ||
1101 | } | ||
1102 | |||
1103 | /// Index expression a.k.a. subscript operator call. | ||
1104 | /// | ||
1105 | /// ``` | ||
1106 | /// ❰ foo[42] ❱; | ||
1107 | /// ``` | ||
1108 | /// | ||
1109 | /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html) | ||
1110 | struct IndexExpr: AttrsOwner { T!['['], T![']'] } | ||
1111 | |||
1112 | /// Field access expression. | ||
1113 | /// | ||
1114 | /// ``` | ||
1115 | /// ❰ expr.bar ❱; | ||
1116 | /// | ||
1117 | /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱; | ||
1118 | /// ``` | ||
1119 | /// | ||
1120 | /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html) | ||
1121 | struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } | ||
1122 | |||
1123 | /// Await operator call expression. | ||
1124 | /// | ||
1125 | /// ``` | ||
1126 | /// ❰ expr.await ❱; | ||
1127 | /// ``` | ||
1128 | /// | ||
1129 | /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html) | ||
1130 | struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } | ||
1131 | |||
1132 | /// The question mark operator call. | ||
1133 | /// | ||
1134 | /// ``` | ||
1135 | /// ❰ expr? ❱; | ||
1136 | /// ``` | ||
1137 | /// | ||
1138 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator) | ||
1139 | struct TryExpr: AttrsOwner { Expr, T![?] } | ||
1140 | |||
1141 | /// Type cast expression. | ||
1142 | /// | ||
1143 | /// ``` | ||
1144 | /// ❰ expr as T ❱; | ||
1145 | /// ``` | ||
1146 | /// | ||
1147 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions) | ||
1148 | struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } | ||
1149 | |||
1150 | |||
1151 | /// Borrow operator call. | ||
1152 | /// | ||
1153 | /// ``` | ||
1154 | /// ❰ &foo ❱; | ||
1155 | /// ❰ &mut bar ❱; | ||
1156 | /// ❰ &raw const bar ❱; | ||
1157 | /// ❰ &raw mut bar ❱; | ||
1158 | /// ``` | ||
1159 | /// | ||
1160 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators) | ||
1161 | struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], T![const], Expr } | ||
1162 | |||
1163 | /// Prefix operator call. This is either `!` or `*` or `-`. | ||
1164 | /// | ||
1165 | /// ``` | ||
1166 | /// ❰ !foo ❱; | ||
1167 | /// ❰ *bar ❱; | ||
1168 | /// ❰ -42 ❱; | ||
1169 | /// ``` | ||
1170 | /// | ||
1171 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html) | ||
1172 | struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } | ||
1173 | |||
1174 | /// Box operator call. | ||
1175 | /// | ||
1176 | /// ``` | ||
1177 | /// ❰ box 42 ❱; | ||
1178 | /// ``` | ||
1179 | /// | ||
1180 | /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md) | ||
1181 | struct BoxExpr: AttrsOwner { T![box], Expr } | ||
1182 | |||
1183 | /// Range operator call. | ||
1184 | /// | ||
1185 | /// ``` | ||
1186 | /// ❰ 0..42 ❱; | ||
1187 | /// ❰ ..42 ❱; | ||
1188 | /// ❰ 0.. ❱; | ||
1189 | /// ❰ .. ❱; | ||
1190 | /// ❰ 0..=42 ❱; | ||
1191 | /// ❰ ..=42 ❱; | ||
1192 | /// ``` | ||
1193 | /// | ||
1194 | /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html) | ||
1195 | struct RangeExpr: AttrsOwner { /*RangeOp*/ } | ||
1196 | |||
1197 | |||
1198 | /// Binary operator call. | ||
1199 | /// Includes all arithmetic, logic, bitwise and assignment operators. | ||
1200 | /// | ||
1201 | /// ``` | ||
1202 | /// ❰ 2 + ❰ 2 * 2 ❱ ❱; | ||
1203 | /// ❰ ❰ true && false ❱ || true ❱; | ||
1204 | /// ``` | ||
1205 | /// | ||
1206 | /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators) | ||
1207 | struct BinExpr: AttrsOwner { /*BinOp*/ } | ||
1208 | |||
1209 | |||
1210 | /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal. | ||
1211 | /// | ||
1212 | /// ``` | ||
1213 | /// ❰ "str" ❱; | ||
1214 | /// ❰ br##"raw byte str"## ❱; | ||
1215 | /// ❰ 'c' ❱; | ||
1216 | /// ❰ b'c' ❱; | ||
1217 | /// ❰ 42 ❱; | ||
1218 | /// ❰ 1e9 ❱; | ||
1219 | /// ❰ true ❱; | ||
1220 | /// ``` | ||
1221 | /// | ||
1222 | /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html) | ||
1223 | struct Literal { /*LiteralToken*/ } | ||
1224 | |||
1225 | /// Match expression. | ||
1226 | /// | ||
1227 | /// ``` | ||
1228 | /// ❰ | ||
1229 | /// match expr { | ||
1230 | /// Pat1 => {} | ||
1231 | /// Pat2(_) => 42, | ||
1232 | /// } | ||
1233 | /// ❱ | ||
1234 | /// ``` | ||
1235 | /// | ||
1236 | /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) | ||
1237 | struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList } | ||
1238 | |||
1239 | /// Match arm list part of match expression. Includes its inner attributes. | ||
1240 | /// | ||
1241 | /// ``` | ||
1242 | /// match expr | ||
1243 | /// ❰ | ||
1244 | /// { | ||
1245 | /// #![inner_attr] | ||
1246 | /// Pat1 => {} | ||
1247 | /// Pat2(_) => 42, | ||
1248 | /// } | ||
1249 | /// ❱ | ||
1250 | /// ``` | ||
1251 | /// | ||
1252 | /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) | ||
1253 | struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] } | ||
1254 | |||
1255 | |||
1256 | /// Match arm. | ||
1257 | /// Note: record struct literals are not valid as target match expression | ||
1258 | /// due to ambiguity. | ||
1259 | /// ``` | ||
1260 | /// match expr { | ||
1261 | /// ❰ #[attr] Pattern(it) if bool_cond => it ❱, | ||
1262 | /// } | ||
1263 | /// ``` | ||
1264 | /// | ||
1265 | /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html) | ||
1266 | struct MatchArm: AttrsOwner { | ||
1267 | pat: Pat, | ||
1268 | guard: MatchGuard, | ||
1269 | T![=>], | ||
1270 | Expr, | ||
1271 | } | ||
1272 | |||
1273 | /// Match guard. | ||
1274 | /// | ||
1275 | /// ``` | ||
1276 | /// match expr { | ||
1277 | /// Pattern(it) ❰ if bool_cond ❱ => it, | ||
1278 | /// } | ||
1279 | /// ``` | ||
1280 | /// | ||
1281 | /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards) | ||
1282 | struct MatchGuard { T![if], Expr } | ||
1283 | |||
1284 | /// Record literal expression. The same syntax is used for structs, | ||
1285 | /// unions and record enum variants. | ||
1286 | /// | ||
1287 | /// ``` | ||
1288 | /// ❰ | ||
1289 | /// foo::Bar { | ||
1290 | /// #![inner_attr] | ||
1291 | /// baz: 42, | ||
1292 | /// bruh: true, | ||
1293 | /// ..spread | ||
1294 | /// } | ||
1295 | /// ❱ | ||
1296 | /// ``` | ||
1297 | /// | ||
1298 | /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) | ||
1299 | struct RecordLit { Path, RecordFieldList} | ||
1300 | |||
1301 | /// Record field list including enclosing curly braces. | ||
1302 | /// | ||
1303 | /// foo::Bar ❰ | ||
1304 | /// { | ||
1305 | /// baz: 42, | ||
1306 | /// ..spread | ||
1307 | /// } | ||
1308 | /// ❱ | ||
1309 | /// | ||
1310 | /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) | ||
1311 | struct RecordFieldList { | ||
1312 | T!['{'], | ||
1313 | fields: [RecordField], | ||
1314 | T![..], | ||
1315 | spread: Expr, | ||
1316 | T!['}'] | ||
1317 | } | ||
1318 | |||
1319 | /// Record field. | ||
1320 | /// | ||
1321 | /// ``` | ||
1322 | /// foo::Bar { | ||
1323 | /// ❰ #[attr] baz: 42 ❱ | ||
1324 | /// } | ||
1325 | /// ``` | ||
1326 | /// | ||
1327 | /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html) | ||
1328 | struct RecordField: AttrsOwner { NameRef, T![:], Expr } | ||
1329 | |||
1330 | /// Disjunction of patterns. | ||
1331 | /// | ||
1332 | /// ``` | ||
1333 | /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh; | ||
1334 | /// ``` | ||
1335 | /// | ||
1336 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html) | ||
1337 | struct OrPat { pats: [Pat] } | ||
1338 | |||
1339 | /// Parenthesized pattern. | ||
1340 | /// Note: parens are only used for grouping, this is not a tuple pattern. | ||
1341 | /// | ||
1342 | /// ``` | ||
1343 | /// if let ❰ &(0..=42) ❱ = foo {} | ||
1344 | /// ``` | ||
1345 | /// | ||
1346 | /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns | ||
1347 | struct ParenPat { T!['('], Pat, T![')'] } | ||
1348 | |||
1349 | /// Reference pattern. | ||
1350 | /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns. | ||
1351 | /// | ||
1352 | /// ``` | ||
1353 | /// let ❰ &mut foo ❱ = bar; | ||
1354 | /// | ||
1355 | /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz; | ||
1356 | /// ``` | ||
1357 | /// | ||
1358 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns) | ||
1359 | struct RefPat { T![&], T![mut], Pat } | ||
1360 | |||
1361 | /// Box pattern. | ||
1362 | /// | ||
1363 | /// ``` | ||
1364 | /// let ❰ box foo ❱ = box 42; | ||
1365 | /// ``` | ||
1366 | /// | ||
1367 | /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html) | ||
1368 | struct BoxPat { T![box], Pat } | ||
1369 | |||
1370 | /// Bind pattern. | ||
1371 | /// | ||
1372 | /// ``` | ||
1373 | /// match foo { | ||
1374 | /// Some(❰ ref mut bar ❱) => {} | ||
1375 | /// ❰ baz @ None ❱ => {} | ||
1376 | /// } | ||
1377 | /// ``` | ||
1378 | /// | ||
1379 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns) | ||
1380 | struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat } | ||
1381 | |||
1382 | /// Placeholder pattern a.k.a. the wildcard pattern or the underscore. | ||
1383 | /// | ||
1384 | /// ``` | ||
1385 | /// let ❰ _ ❱ = foo; | ||
1386 | /// ``` | ||
1387 | /// | ||
1388 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern) | ||
1389 | struct PlaceholderPat { T![_] } | ||
1390 | |||
1391 | /// Rest-of-the record/tuple pattern. | ||
1392 | /// Note: this is not the unbonded range pattern (even more: it doesn't exist). | ||
1393 | /// | ||
1394 | /// ``` | ||
1395 | /// let Foo { bar, ❰ .. ❱ } = baz; | ||
1396 | /// let (❰ .. ❱, bruh) = (42, 24, 42); | ||
1397 | /// let Bruuh(❰ .. ❱) = bruuuh; | ||
1398 | /// ``` | ||
1399 | /// | ||
1400 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) | ||
1401 | struct DotDotPat { T![..] } | ||
1402 | |||
1403 | /// Path pattern. | ||
1404 | /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`). | ||
1405 | /// | ||
1406 | /// ``` | ||
1407 | /// let ❰ foo::bar::Baz ❱ { .. } = bruh; | ||
1408 | /// if let ❰ CONST ❱ = 42 {} | ||
1409 | /// ``` | ||
1410 | /// | ||
1411 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns) | ||
1412 | struct PathPat { Path } | ||
1413 | |||
1414 | /// Slice pattern. | ||
1415 | /// | ||
1416 | /// ``` | ||
1417 | /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3]; | ||
1418 | /// ``` | ||
1419 | /// | ||
1420 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns) | ||
1421 | struct SlicePat { T!['['], args: [Pat], T![']'] } | ||
1422 | |||
1423 | /// Range pattern. | ||
1424 | /// | ||
1425 | /// ``` | ||
1426 | /// match foo { | ||
1427 | /// ❰ 0..42 ❱ => {} | ||
1428 | /// ❰ 0..=42 ❱ => {} | ||
1429 | /// } | ||
1430 | /// ``` | ||
1431 | /// | ||
1432 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns) | ||
1433 | struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext | ||
1434 | |||
1435 | /// Literal pattern. | ||
1436 | /// Includes only bool, number, char, and string literals. | ||
1437 | /// | ||
1438 | /// ``` | ||
1439 | /// match foo { | ||
1440 | /// Number(❰ 42 ❱) => {} | ||
1441 | /// String(❰ "42" ❱) => {} | ||
1442 | /// Bool(❰ true ❱) => {} | ||
1443 | /// } | ||
1444 | /// ``` | ||
1445 | /// | ||
1446 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns) | ||
1447 | struct LiteralPat { Literal } | ||
1448 | |||
1449 | /// Macro invocation in pattern position. | ||
1450 | /// | ||
1451 | /// ``` | ||
1452 | /// let ❰ foo!(my custom syntax) ❱ = baz; | ||
1453 | /// | ||
1454 | /// ``` | ||
1455 | /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation) | ||
1456 | struct MacroPat { MacroCall } | ||
1457 | |||
1458 | /// Record literal pattern. | ||
1459 | /// | ||
1460 | /// ``` | ||
1461 | /// let ❰ foo::Bar { baz, .. } ❱ = bruh; | ||
1462 | /// ``` | ||
1463 | /// | ||
1464 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) | ||
1465 | struct RecordPat { RecordFieldPatList, Path } | ||
1466 | |||
1467 | /// Record literal's field patterns list including enclosing curly braces. | ||
1468 | /// | ||
1469 | /// ``` | ||
1470 | /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh; | ||
1471 | /// `` | ||
1472 | /// | ||
1473 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) | ||
1474 | struct RecordFieldPatList { | ||
1475 | T!['{'], | ||
1476 | pats: [RecordInnerPat], | ||
1477 | record_field_pats: [RecordFieldPat], | ||
1478 | bind_pats: [BindPat], | ||
1479 | T![..], | ||
1480 | T!['}'] | ||
1481 | } | ||
1482 | |||
1483 | /// Record literal's field pattern. | ||
1484 | /// Note: record literal can also match tuple structs. | ||
1485 | /// | ||
1486 | /// ``` | ||
1487 | /// let Foo { ❰ bar: _ ❱ } = baz; | ||
1488 | /// let TupleStruct { ❰ 0: _ ❱ } = bruh; | ||
1489 | /// ``` | ||
1490 | /// | ||
1491 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns) | ||
1492 | struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat } | ||
1493 | |||
1494 | /// Tuple struct literal pattern. | ||
1495 | /// | ||
1496 | /// ``` | ||
1497 | /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh; | ||
1498 | /// ``` | ||
1499 | /// | ||
1500 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns) | ||
1501 | struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } | ||
1502 | |||
1503 | /// Tuple pattern. | ||
1504 | /// Note: this doesn't include tuple structs (see `TupleStructPat`) | ||
1505 | /// | ||
1506 | /// ``` | ||
1507 | /// let ❰ (foo, bar, .., baz) ❱ = bruh; | ||
1508 | /// ``` | ||
1509 | /// | ||
1510 | /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns) | ||
1511 | struct TuplePat { T!['('], args: [Pat], T![')'] } | ||
1512 | |||
1513 | /// Visibility. | ||
1514 | /// | ||
1515 | /// ``` | ||
1516 | /// ❰ pub mod ❱ foo; | ||
1517 | /// ❰ pub(crate) ❱ struct Bar; | ||
1518 | /// ❰ pub(self) ❱ enum Baz {} | ||
1519 | /// ❰ pub(super) ❱ fn bruh() {} | ||
1520 | /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64; | ||
1521 | /// ``` | ||
1522 | /// | ||
1523 | /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html) | ||
1524 | struct Visibility { T![pub], T![super], T![self], T![crate] } | ||
1525 | |||
1526 | /// Single identifier. | ||
1527 | /// Note(@matklad): `Name` is for things that install a new name into the scope, | ||
1528 | /// `NameRef` is a usage of a name. Most of the time, this definition/reference | ||
1529 | /// distinction can be determined purely syntactically, ie in | ||
1530 | /// ``` | ||
1531 | /// fn foo() { foo() } | ||
1532 | /// ``` | ||
1533 | /// the first foo is `Name`, the second one is `NameRef`. | ||
1534 | /// The notable exception are patterns, where in | ||
1535 | /// `` | ||
1536 | /// let x = 92 | ||
1537 | /// ``` | ||
1538 | /// `x` can be semantically either a name or a name ref, depeding on | ||
1539 | /// wether there's an `x` constant in scope. | ||
1540 | /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db). | ||
1541 | /// | ||
1542 | /// ``` | ||
1543 | /// let ❰ foo ❱ = bar; | ||
1544 | /// struct ❰ Baz ❱; | ||
1545 | /// fn ❰ bruh ❱() {} | ||
1546 | /// ``` | ||
1547 | /// | ||
1548 | /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) | ||
1549 | struct Name { T![ident] } | ||
1550 | |||
1551 | /// Reference to a name. | ||
1552 | /// See the explanation on the difference between `Name` and `NameRef` | ||
1553 | /// in `Name` ast node docs. | ||
1554 | /// | ||
1555 | /// ``` | ||
1556 | /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱; | ||
1557 | /// ``` | ||
1558 | /// | ||
1559 | /// [Reference](https://doc.rust-lang.org/reference/identifiers.html) | ||
1560 | struct NameRef { } | ||
1561 | |||
1562 | /// Macro call. | ||
1563 | /// Includes all of its attributes and doc comments. | ||
1564 | /// | ||
1565 | /// ``` | ||
1566 | /// ❰ | ||
1567 | /// /// Docs | ||
1568 | /// #[attr] | ||
1569 | /// macro_rules! foo { // macro rules is also a macro call | ||
1570 | /// ($bar: tt) => {} | ||
1571 | /// } | ||
1572 | /// ❱ | ||
1573 | /// | ||
1574 | /// // semicolon is a part of `MacroCall` when it is used in item positions | ||
1575 | /// ❰ foo!(); ❱ | ||
1576 | /// | ||
1577 | /// fn main() { | ||
1578 | /// ❰ foo!() ❱; // macro call in expression positions doesn't include the semi | ||
1579 | /// } | ||
1580 | /// ``` | ||
1581 | /// | ||
1582 | /// [Reference](https://doc.rust-lang.org/reference/macros.html) | ||
1583 | struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner { | ||
1584 | Path, T![!], TokenTree, T![;] | ||
1585 | } | ||
1586 | |||
1587 | /// Attribute. | ||
1588 | /// | ||
1589 | /// ``` | ||
1590 | /// ❰ #![inner_attr] ❱ | ||
1591 | /// | ||
1592 | /// ❰ #[attr] ❱ | ||
1593 | /// ❰ #[foo = "bar"] ❱ | ||
1594 | /// ❰ #[baz(bruh::bruuh = "42")] ❱ | ||
1595 | /// struct Foo; | ||
1596 | /// ``` | ||
1597 | /// | ||
1598 | /// [Reference](https://doc.rust-lang.org/reference/attributes.html) | ||
1599 | struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] } | ||
1600 | |||
1601 | /// Stores a list of lexer tokens and other `TokenTree`s. | ||
1602 | /// It appears in attributes, macro_rules and macro call (foo!) | ||
1603 | /// | ||
1604 | /// ``` | ||
1605 | /// macro_call! ❰ { my syntax here } ❱; | ||
1606 | /// ``` | ||
1607 | /// | ||
1608 | /// [Reference](https://doc.rust-lang.org/reference/macros.html) | ||
1609 | struct TokenTree {} | ||
1610 | |||
1611 | /// Generic lifetime, type and constants parameters list **declaration**. | ||
1612 | /// | ||
1613 | /// ``` | ||
1614 | /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {} | ||
1615 | /// | ||
1616 | /// struct Baz❰ <T> ❱(T); | ||
1617 | /// | ||
1618 | /// impl❰ <T> ❱ Bruh<T> {} | ||
1619 | /// | ||
1620 | /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str; | ||
1621 | /// ``` | ||
1622 | /// | ||
1623 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) | ||
1624 | struct TypeParamList { | ||
1625 | T![<], | ||
1626 | generic_params: [GenericParam], | ||
1627 | type_params: [TypeParam], | ||
1628 | lifetime_params: [LifetimeParam], | ||
1629 | const_params: [ConstParam], | ||
1630 | T![>] | ||
1631 | } | ||
1632 | |||
1633 | /// Single type parameter **declaration**. | ||
1634 | /// | ||
1635 | /// ``` | ||
1636 | /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {} | ||
1637 | /// ``` | ||
1638 | /// | ||
1639 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) | ||
1640 | struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { | ||
1641 | T![=], | ||
1642 | default_type: TypeRef, | ||
1643 | } | ||
1644 | |||
1645 | /// Const generic parameter **declaration**. | ||
1646 | /// ``` | ||
1647 | /// fn foo<T, U, ❰ const BAR: usize ❱, ❰ const BAZ: bool ❱>() {} | ||
1648 | /// ``` | ||
1649 | /// | ||
1650 | /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) | ||
1651 | struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { | ||
1652 | T![=], | ||
1653 | default_val: Expr, | ||
1654 | } | ||
1655 | |||
1656 | /// Lifetime parameter **declaration**. | ||
1657 | /// | ||
1658 | /// ``` | ||
1659 | /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {} | ||
1660 | /// ``` | ||
1661 | /// | ||
1662 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html) | ||
1663 | struct LifetimeParam: AttrsOwner { T![lifetime] } | ||
1664 | |||
1665 | /// Type bound declaration clause. | ||
1666 | /// | ||
1667 | /// ``` | ||
1668 | /// fn foo<T: ❰ ?Sized ❱ + ❰ Debug ❱>() {} | ||
1669 | /// | ||
1670 | /// trait Bar<T> | ||
1671 | /// where | ||
1672 | /// T: ❰ Send ❱ + ❰ Sync ❱ | ||
1673 | /// { | ||
1674 | /// type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱; | ||
1675 | /// } | ||
1676 | /// ``` | ||
1677 | /// | ||
1678 | /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) | ||
1679 | struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef } | ||
1680 | |||
1681 | /// Type bounds list. | ||
1682 | /// | ||
1683 | /// ``` | ||
1684 | /// | ||
1685 | /// fn foo<T: ❰ ?Sized + Debug ❱>() {} | ||
1686 | /// | ||
1687 | /// trait Bar<T> | ||
1688 | /// where | ||
1689 | /// T: ❰ Send + Sync ❱ | ||
1690 | /// { | ||
1691 | /// type Baz: ❰ !Sync + Debug ❱; | ||
1692 | /// } | ||
1693 | /// ``` | ||
1694 | /// | ||
1695 | /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html) | ||
1696 | struct TypeBoundList { bounds: [TypeBound] } | ||
1697 | |||
1698 | /// Single where predicate. | ||
1699 | /// | ||
1700 | /// ``` | ||
1701 | /// trait Foo<'a, 'b, T> | ||
1702 | /// where | ||
1703 | /// ❰ 'a: 'b ❱, | ||
1704 | /// ❰ T: IntoIterator ❱, | ||
1705 | /// ❰ for<'c> <T as IntoIterator>::Item: Bar<'c> ❱ | ||
1706 | /// {} | ||
1707 | /// ``` | ||
1708 | /// | ||
1709 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) | ||
1710 | struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef } | ||
1711 | |||
1712 | /// Where clause. | ||
1713 | /// | ||
1714 | /// ``` | ||
1715 | /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {} | ||
1716 | /// | ||
1717 | /// ``` | ||
1718 | /// | ||
1719 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) | ||
1720 | struct WhereClause { T![where], predicates: [WherePred] } | ||
1721 | |||
1722 | /// Abi declaration. | ||
1723 | /// Note: the abi string is optional. | ||
1724 | /// | ||
1725 | /// ``` | ||
1726 | /// ❰ extern "C" ❱ { | ||
1727 | /// fn foo() {} | ||
1728 | /// } | ||
1729 | /// | ||
1730 | /// type Bar = ❰ extern ❱ fn() -> u32; | ||
1731 | /// | ||
1732 | /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool; | ||
1733 | /// ``` | ||
1734 | /// | ||
1735 | /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html) | ||
1736 | /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions) | ||
1737 | struct Abi { /*String*/ } | ||
1738 | |||
1739 | /// Expression statement. | ||
1740 | /// | ||
1741 | /// ``` | ||
1742 | /// ❰ 42; ❱ | ||
1743 | /// ❰ foo(); ❱ | ||
1744 | /// ❰ (); ❱ | ||
1745 | /// ❰ {}; ❱ | ||
1746 | /// | ||
1747 | /// // constructions with trailing curly brace can omit the semicolon | ||
1748 | /// // but only when there are satements immediately after them (this is important!) | ||
1749 | /// ❰ if bool_cond { } ❱ | ||
1750 | /// ❰ loop {} ❱ | ||
1751 | /// ❰ somestatment; ❱ | ||
1752 | /// ``` | ||
1753 | /// | ||
1754 | /// [Reference](https://doc.rust-lang.org/reference/statements.html) | ||
1755 | struct ExprStmt: AttrsOwner { Expr, T![;] } | ||
1756 | |||
1757 | /// Let statement. | ||
1758 | /// | ||
1759 | /// ``` | ||
1760 | /// ❰ #[attr] let foo; ❱ | ||
1761 | /// ❰ let bar: u64; ❱ | ||
1762 | /// ❰ let baz = 42; ❱ | ||
1763 | /// ❰ let bruh: bool = true; ❱ | ||
1764 | /// ``` | ||
1765 | /// | ||
1766 | /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements) | ||
1767 | struct LetStmt: AttrsOwner, TypeAscriptionOwner { | ||
1768 | T![let], | ||
1769 | Pat, | ||
1770 | T![=], | ||
1771 | initializer: Expr, | ||
1772 | T![;], | ||
1773 | } | ||
1774 | |||
1775 | /// Condition of `if` or `while` expression. | ||
1776 | /// | ||
1777 | /// ``` | ||
1778 | /// if ❰ true ❱ {} | ||
1779 | /// if ❰ let Pat(foo) = bar ❱ {} | ||
1780 | /// | ||
1781 | /// while ❰ true ❱ {} | ||
1782 | /// while ❰ let Pat(baz) = bruh ❱ {} | ||
1783 | /// ``` | ||
1784 | /// | ||
1785 | /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html) | ||
1786 | /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops) | ||
1787 | struct Condition { T![let], Pat, T![=], Expr } | ||
1788 | |||
1789 | /// Parameter list **declaration**. | ||
1790 | /// | ||
1791 | /// ``` | ||
1792 | /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {} | ||
1793 | /// let bar = ❰ |a, b| ❱ {}; | ||
1794 | /// | ||
1795 | /// impl Baz { | ||
1796 | /// fn bruh❰ (&self, a: u32) ❱ {} | ||
1797 | /// } | ||
1798 | /// ``` | ||
1799 | /// | ||
1800 | /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script | ||
1801 | struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens... | ||
1802 | T!['('], | ||
1803 | SelfParam, | ||
1804 | params: [Param], | ||
1805 | T![')'] | ||
1806 | } | ||
1807 | |||
1808 | /// Self parameter **declaration**. | ||
1809 | /// | ||
1810 | /// ``` | ||
1811 | /// impl Bruh { | ||
1812 | /// fn foo(❰ self ❱) {} | ||
1813 | /// fn bar(❰ &self ❱) {} | ||
1814 | /// fn baz(❰ &mut self ❱) {} | ||
1815 | /// fn blah<'a>(❰ &'a self ❱) {} | ||
1816 | /// fn blin(❰ self: Box<Self> ❱) {} | ||
1817 | /// } | ||
1818 | /// ``` | ||
1819 | /// | ||
1820 | /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) | ||
1821 | struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] } | ||
1822 | |||
1823 | /// Parameter **declaration**. | ||
1824 | /// | ||
1825 | /// ``` | ||
1826 | /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {} | ||
1827 | /// | ||
1828 | /// extern "C" { | ||
1829 | /// fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32; | ||
1830 | /// } | ||
1831 | /// ``` | ||
1832 | /// | ||
1833 | /// [Reference](https://doc.rust-lang.org/reference/items/functions.html) | ||
1834 | struct Param: TypeAscriptionOwner, AttrsOwner { | ||
1835 | Pat, | ||
1836 | T![...] | ||
1837 | } | ||
1838 | |||
1839 | /// Use declaration. | ||
1840 | /// | ||
1841 | /// ``` | ||
1842 | /// ❰ #[attr] pub use foo; ❱ | ||
1843 | /// ❰ use bar as baz; ❱ | ||
1844 | /// ❰ use bruh::{self, bruuh}; ❱ | ||
1845 | /// ❰ use { blin::blen, blah::* }; | ||
1846 | /// ``` | ||
1847 | /// | ||
1848 | /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) | ||
1849 | struct UseItem: AttrsOwner, VisibilityOwner { | ||
1850 | T![use], | ||
1851 | UseTree, | ||
1852 | } | ||
1853 | |||
1854 | /// Use tree. | ||
1855 | /// | ||
1856 | /// ``` | ||
1857 | /// pub use ❰ foo::❰ * ❱ ❱; | ||
1858 | /// use ❰ bar as baz ❱; | ||
1859 | /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱; | ||
1860 | /// use ❰ { ❰ blin::blen ❱ } ❱ | ||
1861 | /// ``` | ||
1862 | /// | ||
1863 | /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) | ||
1864 | struct UseTree { | ||
1865 | Path, T![*], UseTreeList, Alias | ||
1866 | } | ||
1867 | |||
1868 | /// Item alias. | ||
1869 | /// Note: this is not the type alias. | ||
1870 | /// | ||
1871 | /// ``` | ||
1872 | /// use foo ❰ as bar ❱; | ||
1873 | /// use baz::{bruh ❰ as _ ❱}; | ||
1874 | /// extern crate bruuh ❰ as blin ❱; | ||
1875 | /// ``` | ||
1876 | /// | ||
1877 | /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) | ||
1878 | struct Alias: NameOwner { T![as] } | ||
1879 | |||
1880 | /// Sublist of use trees. | ||
1881 | /// | ||
1882 | /// ``` | ||
1883 | /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱; | ||
1884 | /// use ❰ { blin::blen::❰ {} ❱ } ❱ | ||
1885 | /// ``` | ||
1886 | /// | ||
1887 | /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html) | ||
1888 | struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] } | ||
1889 | |||
1890 | /// Extern crate item. | ||
1891 | /// | ||
1892 | /// ``` | ||
1893 | /// ❰ #[attr] pub extern crate foo; ❱ | ||
1894 | /// ❰ extern crate self as bar; ❱ | ||
1895 | /// ``` | ||
1896 | /// | ||
1897 | /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html) | ||
1898 | struct ExternCrateItem: AttrsOwner, VisibilityOwner { | ||
1899 | T![extern], T![crate], NameRef, Alias, | ||
1900 | } | ||
1901 | |||
1902 | /// Call site arguments list. | ||
1903 | /// | ||
1904 | /// ``` | ||
1905 | /// foo::<T, U>❰ (42, true) ❱; | ||
1906 | /// ``` | ||
1907 | /// | ||
1908 | /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html) | ||
1909 | struct ArgList { | ||
1910 | T!['('], | ||
1911 | args: [Expr], | ||
1912 | T![')'] | ||
1913 | } | ||
1914 | |||
1915 | /// Path to a symbol. Includes single identifier names and elaborate paths with | ||
1916 | /// generic parameters. | ||
1917 | /// | ||
1918 | /// ``` | ||
1919 | /// (0..10).❰ ❰ collect ❱ ::<Vec<_>> ❱(); | ||
1920 | /// ❰ ❰ ❰ Vec ❱ ::<u8> ❱ ::with_capacity ❱(1024); | ||
1921 | /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱(); | ||
1922 | /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱(); | ||
1923 | /// ``` | ||
1924 | /// | ||
1925 | /// [Reference](https://doc.rust-lang.org/reference/paths.html) | ||
1926 | struct Path { | ||
1927 | segment: PathSegment, | ||
1928 | T![::], | ||
1929 | qualifier: Path, | ||
1930 | } | ||
1931 | |||
1932 | /// Segment of the path to a symbol. | ||
1933 | /// Only path segment of an absolute path holds the `::` token, | ||
1934 | /// all other `::` tokens that connect path segments reside under `Path` itself.` | ||
1935 | /// | ||
1936 | /// ``` | ||
1937 | /// (0..10).❰ collect ❱ :: ❰ <Vec<_>> ❱(); | ||
1938 | /// ❰ Vec ❱ :: ❰ <u8> ❱ :: ❰ with_capacity ❱(1024); | ||
1939 | /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱(); | ||
1940 | /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱(); | ||
1941 | /// | ||
1942 | /// // Note that only in this case `::` token is inlcuded: | ||
1943 | /// ❰ ::foo ❱; | ||
1944 | /// ``` | ||
1945 | /// | ||
1946 | /// [Reference](https://doc.rust-lang.org/reference/paths.html) | ||
1947 | struct PathSegment { | ||
1948 | T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] | ||
1949 | } | ||
1950 | |||
1951 | /// List of type arguments that are passed at generic instantiation site. | ||
1952 | /// | ||
1953 | /// ``` | ||
1954 | /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar; | ||
1955 | /// | ||
1956 | /// Vec❰ ::<bool> ❱::(); | ||
1957 | /// ``` | ||
1958 | /// | ||
1959 | /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) | ||
1960 | struct TypeArgList { | ||
1961 | T![::], | ||
1962 | T![<], | ||
1963 | generic_args: [GenericArg], | ||
1964 | type_args: [TypeArg], | ||
1965 | lifetime_args: [LifetimeArg], | ||
1966 | assoc_type_args: [AssocTypeArg], | ||
1967 | const_args: [ConstArg], | ||
1968 | T![>] | ||
1969 | } | ||
1970 | |||
1971 | /// Type argument that is passed at generic instantiation site. | ||
1972 | /// | ||
1973 | /// ``` | ||
1974 | /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz; | ||
1975 | /// ``` | ||
1976 | /// | ||
1977 | /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) | ||
1978 | struct TypeArg { TypeRef } | ||
1979 | |||
1980 | /// Associated type argument that is passed at generic instantiation site. | ||
1981 | /// ``` | ||
1982 | /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh; | ||
1983 | /// | ||
1984 | /// trait Bruh<T>: Iterator<❰ Item: Debug ❱> {} | ||
1985 | /// ``` | ||
1986 | /// | ||
1987 | struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef } | ||
1988 | |||
1989 | /// Lifetime argument that is passed at generic instantiation site. | ||
1990 | /// | ||
1991 | /// ``` | ||
1992 | /// fn foo<'a>(s: &'a str) { | ||
1993 | /// bar::<❰ 'a ❱>(s); | ||
1994 | /// } | ||
1995 | /// ``` | ||
1996 | /// | ||
1997 | /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) | ||
1998 | struct LifetimeArg { T![lifetime] } | ||
1999 | |||
2000 | /// Constant value argument that is passed at generic instantiation site. | ||
2001 | /// | ||
2002 | /// ``` | ||
2003 | /// foo::<u32, ❰ { true } ❱>(); | ||
2004 | /// | ||
2005 | /// bar::<❰ { 2 + 2} ❱>(); | ||
2006 | /// ``` | ||
2007 | /// | ||
2008 | /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter) | ||
2009 | struct ConstArg { Literal, BlockExpr } | ||
2010 | |||
2011 | |||
2012 | /// FIXME: (@edwin0cheng) Remove it to use ItemList instead | ||
2013 | /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243 | ||
2014 | /// | ||
2015 | /// [Reference](https://doc.rust-lang.org/reference/macros.html) | ||
2016 | struct MacroItems: ModuleItemOwner { } | ||
2017 | |||
2018 | /// FIXME: (@edwin0cheng) add some documentation here. As per the writing | ||
2019 | /// of this comment this ast node is not used. | ||
2020 | /// | ||
2021 | /// ``` | ||
2022 | /// // FIXME: example here | ||
2023 | /// ``` | ||
2024 | /// | ||
2025 | /// [Reference](https://doc.rust-lang.org/reference/macros.html) | ||
2026 | struct MacroStmts { | ||
2027 | statements: [Stmt], | ||
2028 | Expr, | ||
2029 | } | ||
2030 | |||
2031 | /// List of items in an extern block. | ||
2032 | /// | ||
2033 | /// ``` | ||
2034 | /// extern "C" ❰ | ||
2035 | /// { | ||
2036 | /// fn foo(); | ||
2037 | /// static var: u32; | ||
2038 | /// } | ||
2039 | /// ❱ | ||
2040 | /// ``` | ||
2041 | /// | ||
2042 | /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) | ||
2043 | struct ExternItemList: ModuleItemOwner { | ||
2044 | T!['{'], | ||
2045 | extern_items: [ExternItem], | ||
2046 | T!['}'] | ||
2047 | } | ||
2048 | |||
2049 | /// Extern block. | ||
2050 | /// | ||
2051 | /// ``` | ||
2052 | /// ❰ | ||
2053 | /// extern "C" { | ||
2054 | /// fn foo(); | ||
2055 | /// } | ||
2056 | /// ❱ | ||
2057 | /// | ||
2058 | /// ``` | ||
2059 | /// | ||
2060 | /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html) | ||
2061 | struct ExternBlock { | ||
2062 | Abi, | ||
2063 | ExternItemList | ||
2064 | } | ||
2065 | |||
2066 | /// Meta item in an attribute. | ||
2067 | /// | ||
2068 | /// ``` | ||
2069 | /// #[❰ bar::baz = "42" ❱] | ||
2070 | /// #[❰ bruh(bruuh("true")) ❱] | ||
2071 | /// struct Foo; | ||
2072 | /// ``` | ||
2073 | /// | ||
2074 | /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax) | ||
2075 | struct MetaItem { | ||
2076 | Path, T![=], AttrInput, nested_meta_items: [MetaItem] | ||
2077 | } | ||
2078 | |||
2079 | /// Macro 2.0 definition. | ||
2080 | /// Their syntax is still WIP by rustc team... | ||
2081 | /// ``` | ||
2082 | /// ❰ | ||
2083 | /// macro foo { } | ||
2084 | /// ❱ | ||
2085 | /// ``` | ||
2086 | /// | ||
2087 | /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md) | ||
2088 | struct MacroDef { | ||
2089 | Name, TokenTree | ||
2090 | } | ||
2091 | }, | ||
2092 | enums: &ast_enums! { | ||
2093 | /// Any kind of nominal type definition. | ||
2094 | enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { | ||
2095 | StructDef, EnumDef, UnionDef, | ||
2096 | } | ||
2097 | |||
2098 | /// Any kind of **declared** generic parameter | ||
2099 | enum GenericParam { | ||
2100 | LifetimeParam, | ||
2101 | TypeParam, | ||
2102 | ConstParam | ||
2103 | } | ||
2104 | |||
2105 | /// Any kind of generic argument passed at instantiation site | ||
2106 | enum GenericArg { | ||
2107 | LifetimeArg, | ||
2108 | TypeArg, | ||
2109 | ConstArg, | ||
2110 | AssocTypeArg | ||
2111 | } | ||
2112 | |||
2113 | /// Any kind of construct valid in type context | ||
2114 | enum TypeRef { | ||
2115 | ParenType, | ||
2116 | TupleType, | ||
2117 | NeverType, | ||
2118 | PathType, | ||
2119 | PointerType, | ||
2120 | ArrayType, | ||
2121 | SliceType, | ||
2122 | ReferenceType, | ||
2123 | PlaceholderType, | ||
2124 | FnPointerType, | ||
2125 | ForType, | ||
2126 | ImplTraitType, | ||
2127 | DynTraitType, | ||
2128 | } | ||
2129 | |||
2130 | /// Any kind of top-level item that may appear in a module | ||
2131 | enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { | ||
2132 | StructDef, | ||
2133 | UnionDef, | ||
2134 | EnumDef, | ||
2135 | FnDef, | ||
2136 | TraitDef, | ||
2137 | TypeAliasDef, | ||
2138 | ImplDef, | ||
2139 | UseItem, | ||
2140 | ExternCrateItem, | ||
2141 | ConstDef, | ||
2142 | StaticDef, | ||
2143 | Module, | ||
2144 | MacroCall, | ||
2145 | ExternBlock | ||
2146 | } | ||
2147 | |||
2148 | |||
2149 | |||
2150 | /// Any kind of item that may appear in an impl block | ||
2151 | /// | ||
2152 | /// // FIXME: impl blocks can also contain MacroCall | ||
2153 | enum AssocItem: NameOwner, AttrsOwner { | ||
2154 | FnDef, TypeAliasDef, ConstDef | ||
2155 | } | ||
2156 | |||
2157 | /// Any kind of item that may appear in an extern block | ||
2158 | /// | ||
2159 | /// // FIXME: extern blocks can also contain MacroCall | ||
2160 | enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { | ||
2161 | FnDef, StaticDef | ||
2162 | } | ||
2163 | |||
2164 | /// Any kind of expression | ||
2165 | enum Expr: AttrsOwner { | ||
2166 | TupleExpr, | ||
2167 | ArrayExpr, | ||
2168 | ParenExpr, | ||
2169 | PathExpr, | ||
2170 | LambdaExpr, | ||
2171 | IfExpr, | ||
2172 | LoopExpr, | ||
2173 | ForExpr, | ||
2174 | WhileExpr, | ||
2175 | ContinueExpr, | ||
2176 | BreakExpr, | ||
2177 | Label, | ||
2178 | BlockExpr, | ||
2179 | ReturnExpr, | ||
2180 | MatchExpr, | ||
2181 | RecordLit, | ||
2182 | CallExpr, | ||
2183 | IndexExpr, | ||
2184 | MethodCallExpr, | ||
2185 | FieldExpr, | ||
2186 | AwaitExpr, | ||
2187 | TryExpr, | ||
2188 | EffectExpr, | ||
2189 | CastExpr, | ||
2190 | RefExpr, | ||
2191 | PrefixExpr, | ||
2192 | RangeExpr, | ||
2193 | BinExpr, | ||
2194 | Literal, | ||
2195 | MacroCall, | ||
2196 | BoxExpr, | ||
2197 | } | ||
2198 | |||
2199 | /// Any kind of pattern | ||
2200 | enum Pat { | ||
2201 | OrPat, | ||
2202 | ParenPat, | ||
2203 | RefPat, | ||
2204 | BoxPat, | ||
2205 | BindPat, | ||
2206 | PlaceholderPat, | ||
2207 | DotDotPat, | ||
2208 | PathPat, | ||
2209 | RecordPat, | ||
2210 | TupleStructPat, | ||
2211 | TuplePat, | ||
2212 | SlicePat, | ||
2213 | RangePat, | ||
2214 | LiteralPat, | ||
2215 | MacroPat, | ||
2216 | } | ||
2217 | |||
2218 | /// Any kind of pattern that appears directly inside of the curly | ||
2219 | /// braces of a record pattern | ||
2220 | enum RecordInnerPat { | ||
2221 | RecordFieldPat, | ||
2222 | BindPat | ||
2223 | } | ||
2224 | |||
2225 | /// Any kind of input to an attribute | ||
2226 | enum AttrInput { Literal, TokenTree } | ||
2227 | |||
2228 | /// Any kind of statement | ||
2229 | /// Note: there are no empty statements, these are just represented as | ||
2230 | /// bare semicolons without a dedicated statement ast node. | ||
2231 | enum Stmt { | ||
2232 | LetStmt, | ||
2233 | ExprStmt, | ||
2234 | // macro calls are parsed as expression statements | ||
2235 | } | ||
2236 | |||
2237 | /// Any kind of fields list (record or tuple field lists) | ||
2238 | enum FieldDefList { | ||
2239 | RecordFieldDefList, | ||
2240 | TupleFieldDefList, | ||
2241 | } | ||
2242 | }, | ||
2243 | }; | ||
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 745a25862..cafad8070 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -3,34 +3,41 @@ | |||
3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype | 3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype |
4 | //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. | 4 | //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. |
5 | 5 | ||
6 | use std::{collections::HashSet, fmt::Write}; | 6 | use std::{ |
7 | collections::{BTreeSet, HashSet}, | ||
8 | fmt::Write, | ||
9 | }; | ||
7 | 10 | ||
8 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
9 | use quote::{format_ident, quote}; | 12 | use quote::{format_ident, quote}; |
13 | use ungrammar::{rust_grammar, Grammar, Rule}; | ||
10 | 14 | ||
11 | use crate::{ | 15 | use crate::{ |
12 | ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, | 16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, |
13 | codegen::{self, update, Mode}, | 17 | codegen::{self, update, Mode}, |
14 | project_root, Result, | 18 | project_root, Result, |
15 | }; | 19 | }; |
16 | 20 | ||
17 | pub fn generate_syntax(mode: Mode) -> Result<()> { | 21 | pub fn generate_syntax(mode: Mode) -> Result<()> { |
22 | let grammar = rust_grammar(); | ||
23 | let ast = lower(&grammar); | ||
24 | |||
18 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); | 25 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); |
19 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; | 26 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; |
20 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; | 27 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; |
21 | 28 | ||
22 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | 29 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); |
23 | let contents = generate_tokens(AST_SRC)?; | 30 | let contents = generate_tokens(&ast)?; |
24 | update(ast_tokens_file.as_path(), &contents, mode)?; | 31 | update(ast_tokens_file.as_path(), &contents, mode)?; |
25 | 32 | ||
26 | let ast_nodes_file = project_root().join(codegen::AST_NODES); | 33 | let ast_nodes_file = project_root().join(codegen::AST_NODES); |
27 | let contents = generate_nodes(KINDS_SRC, AST_SRC)?; | 34 | let contents = generate_nodes(KINDS_SRC, &ast)?; |
28 | update(ast_nodes_file.as_path(), &contents, mode)?; | 35 | update(ast_nodes_file.as_path(), &contents, mode)?; |
29 | 36 | ||
30 | Ok(()) | 37 | Ok(()) |
31 | } | 38 | } |
32 | 39 | ||
33 | fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { | 40 | fn generate_tokens(grammar: &AstSrc) -> Result<String> { |
34 | let tokens = grammar.tokens.iter().map(|token| { | 41 | let tokens = grammar.tokens.iter().map(|token| { |
35 | let name = format_ident!("{}", token); | 42 | let name = format_ident!("{}", token); |
36 | let kind = format_ident!("{}", to_upper_snake_case(token)); | 43 | let kind = format_ident!("{}", to_upper_snake_case(token)); |
@@ -62,13 +69,13 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { | |||
62 | Ok(pretty) | 69 | Ok(pretty) |
63 | } | 70 | } |
64 | 71 | ||
65 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | 72 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { |
66 | let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar | 73 | let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar |
67 | .nodes | 74 | .nodes |
68 | .iter() | 75 | .iter() |
69 | .map(|node| { | 76 | .map(|node| { |
70 | let name = format_ident!("{}", node.name); | 77 | let name = format_ident!("{}", node.name); |
71 | let kind = format_ident!("{}", to_upper_snake_case(node.name)); | 78 | let kind = format_ident!("{}", to_upper_snake_case(&node.name)); |
72 | let traits = node.traits.iter().map(|trait_name| { | 79 | let traits = node.traits.iter().map(|trait_name| { |
73 | let trait_name = format_ident!("{}", trait_name); | 80 | let trait_name = format_ident!("{}", trait_name); |
74 | quote!(impl ast::#trait_name for #name {}) | 81 | quote!(impl ast::#trait_name for #name {}) |
@@ -144,25 +151,10 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
144 | quote!(impl ast::#trait_name for #name {}) | 151 | quote!(impl ast::#trait_name for #name {}) |
145 | }); | 152 | }); |
146 | 153 | ||
147 | ( | 154 | let ast_node = if en.name == "Stmt" { |
148 | quote! { | 155 | quote! {} |
149 | #[pretty_doc_comment_placeholder_workaround] | 156 | } else { |
150 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
151 | pub enum #name { | ||
152 | #(#variants(#variants),)* | ||
153 | } | ||
154 | |||
155 | #(#traits)* | ||
156 | }, | ||
157 | quote! { | 157 | quote! { |
158 | #( | ||
159 | impl From<#variants> for #name { | ||
160 | fn from(node: #variants) -> #name { | ||
161 | #name::#variants(node) | ||
162 | } | ||
163 | } | ||
164 | )* | ||
165 | |||
166 | impl AstNode for #name { | 158 | impl AstNode for #name { |
167 | fn can_cast(kind: SyntaxKind) -> bool { | 159 | fn can_cast(kind: SyntaxKind) -> bool { |
168 | match kind { | 160 | match kind { |
@@ -187,13 +179,35 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
187 | } | 179 | } |
188 | } | 180 | } |
189 | } | 181 | } |
182 | } | ||
183 | }; | ||
184 | |||
185 | ( | ||
186 | quote! { | ||
187 | #[pretty_doc_comment_placeholder_workaround] | ||
188 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
189 | pub enum #name { | ||
190 | #(#variants(#variants),)* | ||
191 | } | ||
192 | |||
193 | #(#traits)* | ||
194 | }, | ||
195 | quote! { | ||
196 | #( | ||
197 | impl From<#variants> for #name { | ||
198 | fn from(node: #variants) -> #name { | ||
199 | #name::#variants(node) | ||
200 | } | ||
201 | } | ||
202 | )* | ||
203 | #ast_node | ||
190 | }, | 204 | }, |
191 | ) | 205 | ) |
192 | }) | 206 | }) |
193 | .unzip(); | 207 | .unzip(); |
194 | 208 | ||
195 | let enum_names = grammar.enums.iter().map(|it| it.name); | 209 | let enum_names = grammar.enums.iter().map(|it| &it.name); |
196 | let node_names = grammar.nodes.iter().map(|it| it.name); | 210 | let node_names = grammar.nodes.iter().map(|it| &it.name); |
197 | 211 | ||
198 | let display_impls = | 212 | let display_impls = |
199 | enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { | 213 | enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { |
@@ -212,9 +226,11 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
212 | .nodes | 226 | .nodes |
213 | .iter() | 227 | .iter() |
214 | .map(|kind| to_pascal_case(kind)) | 228 | .map(|kind| to_pascal_case(kind)) |
215 | .filter(|name| !defined_nodes.contains(name.as_str())) | 229 | .filter(|name| !defined_nodes.iter().any(|&it| it == name)) |
216 | { | 230 | { |
217 | eprintln!("Warning: node {} not defined in ast source", node); | 231 | drop(node) |
232 | // TODO: restore this | ||
233 | // eprintln!("Warning: node {} not defined in ast source", node); | ||
218 | } | 234 | } |
219 | 235 | ||
220 | let ast = quote! { | 236 | let ast = quote! { |
@@ -236,12 +252,12 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
236 | let mut res = String::with_capacity(ast.len() * 2); | 252 | let mut res = String::with_capacity(ast.len() * 2); |
237 | 253 | ||
238 | let mut docs = | 254 | let mut docs = |
239 | grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc)); | 255 | grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc)); |
240 | 256 | ||
241 | for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") { | 257 | for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") { |
242 | res.push_str(chunk); | 258 | res.push_str(chunk); |
243 | if let Some(doc) = docs.next() { | 259 | if let Some(doc) = docs.next() { |
244 | write_doc_comment(doc, &mut res); | 260 | write_doc_comment(&doc, &mut res); |
245 | } | 261 | } |
246 | } | 262 | } |
247 | 263 | ||
@@ -249,7 +265,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
249 | Ok(pretty) | 265 | Ok(pretty) |
250 | } | 266 | } |
251 | 267 | ||
252 | fn write_doc_comment(contents: &[&str], dest: &mut String) { | 268 | fn write_doc_comment(contents: &[String], dest: &mut String) { |
253 | for line in contents { | 269 | for line in contents { |
254 | writeln!(dest, "///{}", line).unwrap(); | 270 | writeln!(dest, "///{}", line).unwrap(); |
255 | } | 271 | } |
@@ -296,7 +312,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
296 | 312 | ||
297 | let ast = quote! { | 313 | let ast = quote! { |
298 | #![allow(bad_style, missing_docs, unreachable_pub)] | 314 | #![allow(bad_style, missing_docs, unreachable_pub)] |
299 | /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`. | 315 | /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`. |
300 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | 316 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
301 | #[repr(u16)] | 317 | #[repr(u16)] |
302 | pub enum SyntaxKind { | 318 | pub enum SyntaxKind { |
@@ -363,6 +379,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
363 | #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)* | 379 | #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)* |
364 | [lifetime] => { $crate::SyntaxKind::LIFETIME }; | 380 | [lifetime] => { $crate::SyntaxKind::LIFETIME }; |
365 | [ident] => { $crate::SyntaxKind::IDENT }; | 381 | [ident] => { $crate::SyntaxKind::IDENT }; |
382 | [shebang] => { $crate::SyntaxKind::SHEBANG }; | ||
366 | } | 383 | } |
367 | }; | 384 | }; |
368 | 385 | ||
@@ -413,9 +430,13 @@ fn to_pascal_case(s: &str) -> String { | |||
413 | buf | 430 | buf |
414 | } | 431 | } |
415 | 432 | ||
416 | impl Field<'_> { | 433 | fn pluralize(s: &str) -> String { |
434 | format!("{}s", s) | ||
435 | } | ||
436 | |||
437 | impl Field { | ||
417 | fn is_many(&self) -> bool { | 438 | fn is_many(&self) -> bool { |
418 | matches!(self, Field::Node { src: FieldSrc::Many(_), .. }) | 439 | matches!(self, Field::Node { cardinality: Cardinality::Many, .. }) |
419 | } | 440 | } |
420 | fn token_kind(&self) -> Option<proc_macro2::TokenStream> { | 441 | fn token_kind(&self) -> Option<proc_macro2::TokenStream> { |
421 | match self { | 442 | match self { |
@@ -429,7 +450,7 @@ impl Field<'_> { | |||
429 | fn method_name(&self) -> proc_macro2::Ident { | 450 | fn method_name(&self) -> proc_macro2::Ident { |
430 | match self { | 451 | match self { |
431 | Field::Token(name) => { | 452 | Field::Token(name) => { |
432 | let name = match *name { | 453 | let name = match name.as_str() { |
433 | ";" => "semicolon", | 454 | ";" => "semicolon", |
434 | "->" => "thin_arrow", | 455 | "->" => "thin_arrow", |
435 | "'{'" => "l_curly", | 456 | "'{'" => "l_curly", |
@@ -448,29 +469,273 @@ impl Field<'_> { | |||
448 | "." => "dot", | 469 | "." => "dot", |
449 | ".." => "dotdot", | 470 | ".." => "dotdot", |
450 | "..." => "dotdotdot", | 471 | "..." => "dotdotdot", |
472 | "..=" => "dotdoteq", | ||
451 | "=>" => "fat_arrow", | 473 | "=>" => "fat_arrow", |
452 | "@" => "at", | 474 | "@" => "at", |
453 | ":" => "colon", | 475 | ":" => "colon", |
454 | "::" => "coloncolon", | 476 | "::" => "coloncolon", |
455 | "#" => "pound", | 477 | "#" => "pound", |
456 | "?" => "question_mark", | 478 | "?" => "question_mark", |
479 | "," => "comma", | ||
457 | _ => name, | 480 | _ => name, |
458 | }; | 481 | }; |
459 | format_ident!("{}_token", name) | 482 | format_ident!("{}_token", name) |
460 | } | 483 | } |
461 | Field::Node { name, src } => match src { | 484 | Field::Node { name, .. } => { |
462 | FieldSrc::Shorthand => format_ident!("{}", to_lower_snake_case(name)), | 485 | if name == "type" { |
463 | _ => format_ident!("{}", name), | 486 | format_ident!("ty") |
464 | }, | 487 | } else { |
488 | format_ident!("{}", name) | ||
489 | } | ||
490 | } | ||
465 | } | 491 | } |
466 | } | 492 | } |
467 | fn ty(&self) -> proc_macro2::Ident { | 493 | fn ty(&self) -> proc_macro2::Ident { |
468 | match self { | 494 | match self { |
469 | Field::Token(_) => format_ident!("SyntaxToken"), | 495 | Field::Token(_) => format_ident!("SyntaxToken"), |
470 | Field::Node { name, src } => match src { | 496 | Field::Node { ty, .. } => format_ident!("{}", ty), |
471 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => format_ident!("{}", ty), | ||
472 | FieldSrc::Shorthand => format_ident!("{}", name), | ||
473 | }, | ||
474 | } | 497 | } |
475 | } | 498 | } |
476 | } | 499 | } |
500 | |||
501 | fn lower(grammar: &Grammar) -> AstSrc { | ||
502 | let mut res = AstSrc::default(); | ||
503 | res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()]; | ||
504 | |||
505 | let nodes = grammar.iter().collect::<Vec<_>>(); | ||
506 | |||
507 | for &node in &nodes { | ||
508 | let name = grammar[node].name.clone(); | ||
509 | let rule = &grammar[node].rule; | ||
510 | match lower_enum(grammar, rule) { | ||
511 | Some(variants) => { | ||
512 | let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants }; | ||
513 | res.enums.push(enum_src); | ||
514 | } | ||
515 | None => { | ||
516 | let mut fields = Vec::new(); | ||
517 | lower_rule(&mut fields, grammar, None, rule); | ||
518 | res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields }); | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | deduplicate_fields(&mut res); | ||
524 | extract_enums(&mut res); | ||
525 | extract_struct_traits(&mut res); | ||
526 | extract_enum_traits(&mut res); | ||
527 | res | ||
528 | } | ||
529 | |||
530 | fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> { | ||
531 | let alternatives = match rule { | ||
532 | Rule::Alt(it) => it, | ||
533 | _ => return None, | ||
534 | }; | ||
535 | let mut variants = Vec::new(); | ||
536 | for alternative in alternatives { | ||
537 | match alternative { | ||
538 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), | ||
539 | Rule::Token(it) if grammar[*it].name == ";" => (), | ||
540 | _ => return None, | ||
541 | } | ||
542 | } | ||
543 | Some(variants) | ||
544 | } | ||
545 | |||
546 | fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, rule: &Rule) { | ||
547 | if lower_comma_list(acc, grammar, label, rule) { | ||
548 | return; | ||
549 | } | ||
550 | |||
551 | match rule { | ||
552 | Rule::Node(node) => { | ||
553 | let ty = grammar[*node].name.clone(); | ||
554 | let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty)); | ||
555 | let field = Field::Node { name, ty, cardinality: Cardinality::Optional }; | ||
556 | acc.push(field); | ||
557 | } | ||
558 | Rule::Token(token) => { | ||
559 | assert!(label.is_none()); | ||
560 | let mut name = grammar[*token].name.clone(); | ||
561 | if name != "int_number" && name != "string" { | ||
562 | if "[]{}()".contains(&name) { | ||
563 | name = format!("'{}'", name); | ||
564 | } | ||
565 | let field = Field::Token(name); | ||
566 | acc.push(field); | ||
567 | } | ||
568 | } | ||
569 | Rule::Rep(inner) => { | ||
570 | if let Rule::Node(node) = &**inner { | ||
571 | let ty = grammar[*node].name.clone(); | ||
572 | let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty))); | ||
573 | let field = Field::Node { name, ty, cardinality: Cardinality::Many }; | ||
574 | acc.push(field); | ||
575 | return; | ||
576 | } | ||
577 | todo!("{:?}", rule) | ||
578 | } | ||
579 | Rule::Labeled { label: l, rule } => { | ||
580 | assert!(label.is_none()); | ||
581 | let manually_implemented = matches!( | ||
582 | l.as_str(), | ||
583 | "lhs" | ||
584 | | "rhs" | ||
585 | | "then_branch" | ||
586 | | "else_branch" | ||
587 | | "start" | ||
588 | | "end" | ||
589 | | "op" | ||
590 | | "index" | ||
591 | | "base" | ||
592 | | "value" | ||
593 | | "trait" | ||
594 | | "self_ty" | ||
595 | ); | ||
596 | if manually_implemented { | ||
597 | return; | ||
598 | } | ||
599 | lower_rule(acc, grammar, Some(l), rule); | ||
600 | } | ||
601 | Rule::Seq(rules) | Rule::Alt(rules) => { | ||
602 | for rule in rules { | ||
603 | lower_rule(acc, grammar, label, rule) | ||
604 | } | ||
605 | } | ||
606 | Rule::Opt(rule) => lower_rule(acc, grammar, label, rule), | ||
607 | } | ||
608 | } | ||
609 | |||
610 | // (T (',' T)* ','?) | ||
611 | fn lower_comma_list( | ||
612 | acc: &mut Vec<Field>, | ||
613 | grammar: &Grammar, | ||
614 | label: Option<&String>, | ||
615 | rule: &Rule, | ||
616 | ) -> bool { | ||
617 | let rule = match rule { | ||
618 | Rule::Seq(it) => it, | ||
619 | _ => return false, | ||
620 | }; | ||
621 | let (node, repeat, trailing_comma) = match rule.as_slice() { | ||
622 | [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => { | ||
623 | (node, repeat, trailing_comma) | ||
624 | } | ||
625 | _ => return false, | ||
626 | }; | ||
627 | let repeat = match &**repeat { | ||
628 | Rule::Seq(it) => it, | ||
629 | _ => return false, | ||
630 | }; | ||
631 | match repeat.as_slice() { | ||
632 | [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (), | ||
633 | _ => return false, | ||
634 | } | ||
635 | let ty = grammar[*node].name.clone(); | ||
636 | let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty))); | ||
637 | let field = Field::Node { name, ty, cardinality: Cardinality::Many }; | ||
638 | acc.push(field); | ||
639 | true | ||
640 | } | ||
641 | |||
642 | fn deduplicate_fields(ast: &mut AstSrc) { | ||
643 | for node in &mut ast.nodes { | ||
644 | let mut i = 0; | ||
645 | 'outer: while i < node.fields.len() { | ||
646 | for j in 0..i { | ||
647 | let f1 = &node.fields[i]; | ||
648 | let f2 = &node.fields[j]; | ||
649 | if f1 == f2 { | ||
650 | node.fields.remove(i); | ||
651 | continue 'outer; | ||
652 | } | ||
653 | } | ||
654 | i += 1; | ||
655 | } | ||
656 | } | ||
657 | } | ||
658 | |||
659 | fn extract_enums(ast: &mut AstSrc) { | ||
660 | for node in &mut ast.nodes { | ||
661 | for enm in &ast.enums { | ||
662 | let mut to_remove = Vec::new(); | ||
663 | for (i, field) in node.fields.iter().enumerate() { | ||
664 | let ty = field.ty().to_string(); | ||
665 | if enm.variants.iter().any(|it| it == &ty) { | ||
666 | to_remove.push(i); | ||
667 | } | ||
668 | } | ||
669 | if to_remove.len() == enm.variants.len() { | ||
670 | node.remove_field(to_remove); | ||
671 | let ty = enm.name.clone(); | ||
672 | let name = to_lower_snake_case(&ty); | ||
673 | node.fields.push(Field::Node { name, ty, cardinality: Cardinality::Optional }); | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | } | ||
678 | |||
679 | fn extract_struct_traits(ast: &mut AstSrc) { | ||
680 | let traits: &[(&str, &[&str])] = &[ | ||
681 | ("AttrsOwner", &["attrs"]), | ||
682 | ("NameOwner", &["name"]), | ||
683 | ("VisibilityOwner", &["visibility"]), | ||
684 | ("GenericParamsOwner", &["generic_param_list", "where_clause"]), | ||
685 | ("TypeBoundsOwner", &["type_bound_list", "colon_token"]), | ||
686 | ("ModuleItemOwner", &["items"]), | ||
687 | ("LoopBodyOwner", &["label", "loop_body"]), | ||
688 | ("ArgListOwner", &["arg_list"]), | ||
689 | ]; | ||
690 | |||
691 | for node in &mut ast.nodes { | ||
692 | for (name, methods) in traits { | ||
693 | extract_struct_trait(node, name, methods); | ||
694 | } | ||
695 | } | ||
696 | } | ||
697 | |||
698 | fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) { | ||
699 | let mut to_remove = Vec::new(); | ||
700 | for (i, field) in node.fields.iter().enumerate() { | ||
701 | let method_name = field.method_name().to_string(); | ||
702 | if methods.iter().any(|&it| it == &method_name) { | ||
703 | to_remove.push(i); | ||
704 | } | ||
705 | } | ||
706 | if to_remove.len() == methods.len() { | ||
707 | node.traits.push(trait_name.to_string()); | ||
708 | node.remove_field(to_remove); | ||
709 | } | ||
710 | } | ||
711 | |||
712 | fn extract_enum_traits(ast: &mut AstSrc) { | ||
713 | for enm in &mut ast.enums { | ||
714 | if enm.name == "Stmt" { | ||
715 | continue; | ||
716 | } | ||
717 | let nodes = &ast.nodes; | ||
718 | let mut variant_traits = enm | ||
719 | .variants | ||
720 | .iter() | ||
721 | .map(|var| nodes.iter().find(|it| &it.name == var).unwrap()) | ||
722 | .map(|node| node.traits.iter().cloned().collect::<BTreeSet<_>>()); | ||
723 | |||
724 | let mut enum_traits = match variant_traits.next() { | ||
725 | Some(it) => it, | ||
726 | None => continue, | ||
727 | }; | ||
728 | for traits in variant_traits { | ||
729 | enum_traits = enum_traits.intersection(&traits).cloned().collect(); | ||
730 | } | ||
731 | enm.traits = enum_traits.into_iter().collect(); | ||
732 | } | ||
733 | } | ||
734 | |||
735 | impl AstNodeSrc { | ||
736 | fn remove_field(&mut self, to_remove: Vec<usize>) { | ||
737 | to_remove.into_iter().rev().for_each(|idx| { | ||
738 | self.fields.remove(idx); | ||
739 | }); | ||
740 | } | ||
741 | } | ||
diff --git a/xtask/src/codegen/gen_unstable_future_descriptor.rs b/xtask/src/codegen/gen_unstable_future_descriptor.rs index 09c4f61f2..298696fbb 100644 --- a/xtask/src/codegen/gen_unstable_future_descriptor.rs +++ b/xtask/src/codegen/gen_unstable_future_descriptor.rs | |||
@@ -42,7 +42,7 @@ pub fn generate_unstable_future_descriptor(mode: Mode) -> Result<()> { | |||
42 | let ts = quote! { | 42 | let ts = quote! { |
43 | use crate::completion::LintCompletion; | 43 | use crate::completion::LintCompletion; |
44 | 44 | ||
45 | const UNSTABLE_FEATURE_DESCRIPTOR: &[LintCompletion] = &[ | 45 | pub const UNSTABLE_FEATURE_DESCRIPTOR: &[LintCompletion] = &[ |
46 | #(#definitions),* | 46 | #(#definitions),* |
47 | ]; | 47 | ]; |
48 | }; | 48 | }; |
diff --git a/xtask/src/codegen/rust.ungram b/xtask/src/codegen/rust.ungram new file mode 100644 index 000000000..aca23890c --- /dev/null +++ b/xtask/src/codegen/rust.ungram | |||
@@ -0,0 +1,587 @@ | |||
1 | //*************************// | ||
2 | // Names, Paths and Macros // | ||
3 | //*************************// | ||
4 | |||
5 | Name = | ||
6 | 'ident' | ||
7 | |||
8 | NameRef = | ||
9 | 'ident' | 'int_number' | ||
10 | |||
11 | Path = | ||
12 | (qualifier:Path '::')? segment:PathSegment | ||
13 | |||
14 | PathSegment = | ||
15 | 'crate' | 'self' | 'super' | ||
16 | | '::' NameRef | ||
17 | | NameRef GenericArgList? | ||
18 | | NameRef ParamList RetType? | ||
19 | | '<' PathType ('as' PathType)? '>' | ||
20 | |||
21 | GenericArgList = | ||
22 | '::'? '<' (GenericArg (',' GenericArg)* ','?)? '>' | ||
23 | |||
24 | GenericArg = | ||
25 | TypeArg | ||
26 | | AssocTypeArg | ||
27 | | LifetimeArg | ||
28 | | ConstArg | ||
29 | |||
30 | TypeArg = | ||
31 | Type | ||
32 | |||
33 | AssocTypeArg = | ||
34 | NameRef (':' TypeBoundList | '=' Type) | ||
35 | |||
36 | LifetimeArg = | ||
37 | 'lifetime' | ||
38 | |||
39 | ConstArg = | ||
40 | Expr | ||
41 | |||
42 | MacroCall = | ||
43 | Attr* Path '!' Name? TokenTree ';'? | ||
44 | |||
45 | TokenTree = | ||
46 | '(' ')' | ||
47 | | '{' '}' | ||
48 | | '[' ']' | ||
49 | |||
50 | MacroItems = | ||
51 | Item* | ||
52 | |||
53 | MacroStmts = | ||
54 | statements:Stmt* | ||
55 | Expr? | ||
56 | |||
57 | //*************************// | ||
58 | // Items // | ||
59 | //*************************// | ||
60 | |||
61 | SourceFile = | ||
62 | 'shebang'? | ||
63 | Attr* | ||
64 | Item* | ||
65 | |||
66 | Item = | ||
67 | Const | ||
68 | | Enum | ||
69 | | ExternBlock | ||
70 | | ExternCrate | ||
71 | | Fn | ||
72 | | Impl | ||
73 | | MacroCall | ||
74 | | Module | ||
75 | | Static | ||
76 | | Struct | ||
77 | | Trait | ||
78 | | TypeAlias | ||
79 | | Union | ||
80 | | Use | ||
81 | |||
82 | Module = | ||
83 | Attr* Visibility? 'mod' Name | ||
84 | (ItemList | ';') | ||
85 | |||
86 | ItemList = | ||
87 | '{' Attr* Item* '}' | ||
88 | |||
89 | ExternCrate = | ||
90 | Attr* Visibility? 'extern' 'crate' (NameRef | 'self') Rename? ';' | ||
91 | |||
92 | Rename = | ||
93 | 'as' (Name | '_') | ||
94 | |||
95 | Use = | ||
96 | Attr* Visibility? 'use' UseTree ';' | ||
97 | |||
98 | UseTree = | ||
99 | (Path? '::')? ('*' | UseTreeList ) | ||
100 | | Path Rename? | ||
101 | |||
102 | UseTreeList = | ||
103 | '{' (UseTree (',' UseTree)* ','?)? '}' | ||
104 | |||
105 | Fn = | ||
106 | Attr* Visibility? | ||
107 | 'default'? ('async' | 'const')? 'unsafe'? Abi? | ||
108 | 'fn' Name GenericParamList? ParamList RetType? | ||
109 | WhereClause? | ||
110 | (body:BlockExpr | ';') | ||
111 | |||
112 | Abi = | ||
113 | 'extern' 'string'? | ||
114 | |||
115 | ParamList = | ||
116 | '('( | ||
117 | SelfParam | ||
118 | | (SelfParam ',')? (Param (',' Param)* ','?)? | ||
119 | )')' | ||
120 | |||
121 | SelfParam = | ||
122 | Attr* ( | ||
123 | ('&' 'lifetime'?)? 'mut'? 'self' | ||
124 | | 'mut'? 'self' ':' Type | ||
125 | ) | ||
126 | |||
127 | Param = | ||
128 | Attr* ( | ||
129 | Pat (':' Type) | ||
130 | | Type | ||
131 | | '...' | ||
132 | ) | ||
133 | |||
134 | RetType = | ||
135 | '->' Type | ||
136 | |||
137 | TypeAlias = | ||
138 | Attr* Visibility? 'default'? 'type' Name GenericParamList? (':' TypeBoundList?)? WhereClause? | ||
139 | '=' Type ';' | ||
140 | |||
141 | Struct = | ||
142 | Attr* Visibility? 'struct' Name GenericParamList? ( | ||
143 | WhereClause? (RecordFieldList | ';') | ||
144 | | TupleFieldList WhereClause? ';' | ||
145 | ) | ||
146 | |||
147 | RecordFieldList = | ||
148 | '{' fields:(RecordField (',' RecordField)* ','?)? '}' | ||
149 | |||
150 | RecordField = | ||
151 | Attr* Visibility? Name ':' Type | ||
152 | |||
153 | TupleFieldList = | ||
154 | '(' fields:(TupleField (',' TupleField)* ','?)? ')' | ||
155 | |||
156 | TupleField = | ||
157 | Attr* Visibility? Type | ||
158 | |||
159 | FieldList = | ||
160 | RecordFieldList | ||
161 | | TupleFieldList | ||
162 | |||
163 | Enum = | ||
164 | Attr* Visibility? 'enum' Name GenericParamList? WhereClause? | ||
165 | VariantList | ||
166 | |||
167 | VariantList = | ||
168 | '{' (Variant (',' Variant)* ','?)? '}' | ||
169 | |||
170 | Variant = | ||
171 | Attr* Visibility? Name FieldList ('=' Expr)? | ||
172 | |||
173 | Union = | ||
174 | Attr* Visibility? 'union' Name GenericParamList? WhereClause? | ||
175 | RecordFieldList | ||
176 | |||
177 | AdtDef = | ||
178 | Enum | ||
179 | | Struct | ||
180 | | Union | ||
181 | |||
182 | Const = | ||
183 | Attr* Visibility? 'default'? 'const' (Name | '_') ':' Type | ||
184 | '=' body:Expr ';' | ||
185 | |||
186 | Static = | ||
187 | Attr* Visibility? 'static'? 'mut'? Name ':' Type | ||
188 | '=' body:Expr ';' | ||
189 | |||
190 | Trait = | ||
191 | Attr* Visibility? 'unsafe'? 'auto'? 'trait' Name GenericParamList | ||
192 | (':' TypeBoundList?)? WhereClause | ||
193 | AssocItemList | ||
194 | |||
195 | AssocItemList = | ||
196 | '{' Attr* AssocItem* '}' | ||
197 | |||
198 | AssocItem = | ||
199 | Const | ||
200 | | Fn | ||
201 | | MacroCall | ||
202 | | TypeAlias | ||
203 | |||
204 | Impl = | ||
205 | Attr* Visibility? | ||
206 | 'default'? 'unsafe'? 'impl' 'const'? GenericParamList? | ||
207 | ('!'? target_trait:Type 'for')? target_type:Type | ||
208 | WhereClause? | ||
209 | AssocItemList | ||
210 | |||
211 | ExternBlock = | ||
212 | Attr* Abi ExternItemList | ||
213 | |||
214 | ExternItemList = | ||
215 | '{' Attr* ExternItem* '}' | ||
216 | |||
217 | ExternItem = | ||
218 | Fn | Static | MacroCall | ||
219 | |||
220 | GenericParamList = | ||
221 | '<' (GenericParam (',' GenericParam)* ','?)? '>' | ||
222 | |||
223 | GenericParam = | ||
224 | ConstParam | ||
225 | | LifetimeParam | ||
226 | | TypeParam | ||
227 | |||
228 | TypeParam = | ||
229 | Attr* Name (':' TypeBoundList?)? | ||
230 | ('=' default_type:Type)? | ||
231 | |||
232 | ConstParam = | ||
233 | Attr* 'const' Name ':' Type | ||
234 | ('=' default_val:Expr)? | ||
235 | |||
236 | LifetimeParam = | ||
237 | Attr* 'lifetime' (':' TypeBoundList?)? | ||
238 | |||
239 | WhereClause = | ||
240 | 'where' predicates:(WherePred (',' WherePred)* ','?) | ||
241 | |||
242 | WherePred = | ||
243 | ('for' GenericParamList)? ('lifetime' | Type) ':' TypeBoundList | ||
244 | |||
245 | Visibility = | ||
246 | 'pub' ('(' | ||
247 | 'super' | ||
248 | | 'self' | ||
249 | | 'crate' | ||
250 | | 'in' Path | ||
251 | ')')? | ||
252 | |||
253 | Attr = | ||
254 | '#' '!'? '[' Path ('=' Literal | TokenTree)? ']' | ||
255 | |||
256 | //****************************// | ||
257 | // Statements and Expressions // | ||
258 | //****************************// | ||
259 | |||
260 | Stmt = | ||
261 | ExprStmt | ||
262 | | Item | ||
263 | | LetStmt | ||
264 | |||
265 | LetStmt = | ||
266 | Attr* 'let' Pat (':' Type)? | ||
267 | '=' initializer:Expr ';' | ||
268 | |||
269 | ExprStmt = | ||
270 | Attr* Expr ';'? | ||
271 | |||
272 | Expr = | ||
273 | ArrayExpr | ||
274 | | AwaitExpr | ||
275 | | BinExpr | ||
276 | | BlockExpr | ||
277 | | BoxExpr | ||
278 | | BreakExpr | ||
279 | | CallExpr | ||
280 | | CastExpr | ||
281 | | ClosureExpr | ||
282 | | ContinueExpr | ||
283 | | EffectExpr | ||
284 | | FieldExpr | ||
285 | | ForExpr | ||
286 | | IfExpr | ||
287 | | IndexExpr | ||
288 | | Literal | ||
289 | | LoopExpr | ||
290 | | MacroCall | ||
291 | | MatchExpr | ||
292 | | MethodCallExpr | ||
293 | | ParenExpr | ||
294 | | PathExpr | ||
295 | | PrefixExpr | ||
296 | | RangeExpr | ||
297 | | RecordExpr | ||
298 | | RefExpr | ||
299 | | ReturnExpr | ||
300 | | TryExpr | ||
301 | | TupleExpr | ||
302 | | WhileExpr | ||
303 | |||
304 | Literal = | ||
305 | Attr* value:( | ||
306 | 'int_number' | 'float_number' | ||
307 | | 'string' | 'raw_string' | ||
308 | | 'byte_string' | 'raw_byte_string' | ||
309 | | 'true' | 'false' | ||
310 | | 'char' | 'byte' | ||
311 | ) | ||
312 | |||
313 | PathExpr = | ||
314 | Attr* Path | ||
315 | |||
316 | BlockExpr = | ||
317 | '{' | ||
318 | Attr* | ||
319 | statements:Stmt* | ||
320 | Expr? | ||
321 | '}' | ||
322 | |||
323 | RefExpr = | ||
324 | Attr* '&' ('raw' |'mut' | 'const') Expr | ||
325 | |||
326 | TryExpr = | ||
327 | Attr* Expr '?' | ||
328 | |||
329 | EffectExpr = | ||
330 | Attr* Label? ('try' | 'unsafe' | 'async') BlockExpr | ||
331 | |||
332 | PrefixExpr = | ||
333 | Attr* op:('-' | '!' | '*') Expr | ||
334 | |||
335 | BinExpr = | ||
336 | Attr* | ||
337 | lhs:Expr | ||
338 | op:( | ||
339 | '||' | '&&' | ||
340 | | '==' | '!=' | '<=' | '>=' | '<' | '>' | ||
341 | | '+' | '*' | '-' | '/' | '%' | '<<' | '>>' | '^' | '|' | '&' | ||
342 | | '=' | '+=' | '/=' | '*=' | '%=' | '>>=' | '<<=' | '-=' | '|=' | '&=' | '^=' | ||
343 | ) | ||
344 | rhs:Expr | ||
345 | |||
346 | CastExpr = | ||
347 | Attr* Expr 'as' Type | ||
348 | |||
349 | ParenExpr = | ||
350 | Attr* '(' Attr* Expr ')' | ||
351 | |||
352 | ArrayExpr = | ||
353 | Attr* '[' Attr* ( | ||
354 | (Expr (',' Expr)* ','?)? | ||
355 | | Expr ';' Expr | ||
356 | ) ']' | ||
357 | |||
358 | IndexExpr = | ||
359 | Attr* base:Expr '[' index:Expr ']' | ||
360 | |||
361 | TupleExpr = | ||
362 | Attr* '(' Attr* fields:(Expr (',' Expr)* ','?)? ')' | ||
363 | |||
364 | RecordExpr = | ||
365 | Path RecordExprFieldList | ||
366 | |||
367 | RecordExprFieldList = | ||
368 | '{' | ||
369 | Attr* | ||
370 | fields:(RecordExprField (',' RecordExprField)* ','?) | ||
371 | ('..' spread:Expr)? | ||
372 | '}' | ||
373 | |||
374 | RecordExprField = | ||
375 | Attr* NameRef (':' Expr)? | ||
376 | |||
377 | CallExpr = | ||
378 | Attr* Expr ArgList | ||
379 | |||
380 | ArgList = | ||
381 | '(' args:(Expr (',' Expr)* ','?)? ')' | ||
382 | |||
383 | MethodCallExpr = | ||
384 | Attr* Expr '.' NameRef GenericArgList? ArgList | ||
385 | |||
386 | FieldExpr = | ||
387 | Attr* Expr '.' NameRef | ||
388 | |||
389 | ClosureExpr = | ||
390 | Attr* 'static'? 'async'? 'move'? ParamList RetType? | ||
391 | body:Expr | ||
392 | |||
393 | IfExpr = | ||
394 | Attr* 'if' Condition then_branch:BlockExpr | ||
395 | ('else' else_branch:(IfExpr | BlockExpr))? | ||
396 | |||
397 | Condition = | ||
398 | 'let' Pat '=' Expr | ||
399 | | Expr | ||
400 | |||
401 | LoopExpr = | ||
402 | Attr* Label? 'loop' | ||
403 | loop_body:BlockExpr | ||
404 | |||
405 | ForExpr = | ||
406 | Attr* Label? 'for' Pat 'in' iterable:Expr | ||
407 | loop_body:BlockExpr | ||
408 | |||
409 | WhileExpr = | ||
410 | Attr* Label? 'while' Condition | ||
411 | loop_body:BlockExpr | ||
412 | |||
413 | Label = | ||
414 | 'lifetime' | ||
415 | |||
416 | BreakExpr = | ||
417 | Attr* 'break' 'lifetime'? Expr? | ||
418 | |||
419 | ContinueExpr = | ||
420 | Attr* 'continue' 'lifetime'? | ||
421 | |||
422 | RangeExpr = | ||
423 | Attr* start:Expr? op:('..' | '..=') end:Expr? | ||
424 | |||
425 | MatchExpr = | ||
426 | Attr* 'match' Expr MatchArmList | ||
427 | |||
428 | MatchArmList = | ||
429 | '{' | ||
430 | Attr* | ||
431 | arms:MatchArm* | ||
432 | '}' | ||
433 | |||
434 | MatchArm = | ||
435 | Attr* Pat guard:MatchGuard? '=>' Expr ','? | ||
436 | |||
437 | MatchGuard = | ||
438 | 'if' Expr | ||
439 | |||
440 | ReturnExpr = | ||
441 | Attr* 'return' Expr? | ||
442 | |||
443 | AwaitExpr = | ||
444 | Attr* Expr '.' 'await' | ||
445 | |||
446 | BoxExpr = | ||
447 | Attr* 'box' Expr | ||
448 | |||
449 | //*************************// | ||
450 | // Types // | ||
451 | //*************************// | ||
452 | |||
453 | Type = | ||
454 | ArrayType | ||
455 | | DynTraitType | ||
456 | | FnPointerType | ||
457 | | ForType | ||
458 | | ImplTraitType | ||
459 | | InferType | ||
460 | | NeverType | ||
461 | | ParenType | ||
462 | | PathType | ||
463 | | PointerType | ||
464 | | ReferenceType | ||
465 | | SliceType | ||
466 | | TupleType | ||
467 | |||
468 | ParenType = | ||
469 | '(' Type ')' | ||
470 | |||
471 | NeverType = | ||
472 | '!' | ||
473 | |||
474 | PathType = | ||
475 | Path | ||
476 | |||
477 | TupleType = | ||
478 | '(' fields:(Type (',' Type)* ','?)? ')' | ||
479 | |||
480 | PointerType = | ||
481 | '*' ('const' | 'mut') Type | ||
482 | |||
483 | ReferenceType = | ||
484 | '&' 'lifetime'? 'mut'? Type | ||
485 | |||
486 | ArrayType = | ||
487 | '[' Type ';' Expr ']' | ||
488 | |||
489 | SliceType = | ||
490 | '[' Type ']' | ||
491 | |||
492 | InferType = | ||
493 | '_' | ||
494 | |||
495 | FnPointerType = | ||
496 | 'const'? 'async'? 'unsafe'? Abi? 'fn' ParamList RetType? | ||
497 | |||
498 | ForType = | ||
499 | 'for' GenericParamList Type | ||
500 | |||
501 | ImplTraitType = | ||
502 | 'impl' TypeBoundList | ||
503 | |||
504 | DynTraitType = | ||
505 | 'dyn' TypeBoundList | ||
506 | |||
507 | TypeBoundList = | ||
508 | bounds:(TypeBound ('+' TypeBound)* '+'?) | ||
509 | |||
510 | TypeBound = | ||
511 | 'lifetime' | ||
512 | | '?'? Type | ||
513 | |||
514 | //************************// | ||
515 | // Patterns // | ||
516 | //************************// | ||
517 | |||
518 | Pat = | ||
519 | IdentPat | ||
520 | | BoxPat | ||
521 | | RestPat | ||
522 | | LiteralPat | ||
523 | | MacroPat | ||
524 | | OrPat | ||
525 | | ParenPat | ||
526 | | PathPat | ||
527 | | WildcardPat | ||
528 | | RangePat | ||
529 | | RecordPat | ||
530 | | RefPat | ||
531 | | SlicePat | ||
532 | | TuplePat | ||
533 | | TupleStructPat | ||
534 | |||
535 | LiteralPat = | ||
536 | Literal | ||
537 | |||
538 | IdentPat = | ||
539 | Attr* 'ref'? 'mut'? Name ('@' Pat)? | ||
540 | |||
541 | WildcardPat = | ||
542 | '_' | ||
543 | |||
544 | RangePat = | ||
545 | start:Pat op:('..' | '..=') end:Pat | ||
546 | |||
547 | RefPat = | ||
548 | '&' 'mut'? Pat | ||
549 | |||
550 | RecordPat = | ||
551 | Path RecordPatFieldList | ||
552 | |||
553 | RecordPatFieldList = | ||
554 | '{' | ||
555 | fields:(RecordPatField (',' RecordPatField)* ','?) | ||
556 | '..'? | ||
557 | '}' | ||
558 | |||
559 | RecordPatField = | ||
560 | Attr* (NameRef ':')? Pat | ||
561 | |||
562 | TupleStructPat = | ||
563 | Path '(' fields:(Pat (',' Pat)* ','?)? ')' | ||
564 | |||
565 | TuplePat = | ||
566 | '(' fields:(Pat (',' Pat)* ','?)? ')' | ||
567 | |||
568 | ParenPat = | ||
569 | '(' Pat ')' | ||
570 | |||
571 | SlicePat = | ||
572 | '[' (Pat (',' Pat)* ','?)? ']' | ||
573 | |||
574 | PathPat = | ||
575 | Path | ||
576 | |||
577 | OrPat = | ||
578 | (Pat ('|' Pat)* '|'?) | ||
579 | |||
580 | BoxPat = | ||
581 | 'box' Pat | ||
582 | |||
583 | RestPat = | ||
584 | '..' | ||
585 | |||
586 | MacroPat = | ||
587 | MacroCall | ||
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index 9ac3fa51d..4bade2c7e 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | collections::BTreeMap, | 2 | collections::BTreeMap, |
3 | env, | 3 | env, |
4 | fmt::{self, Write as _}, | ||
5 | io::Write as _, | 4 | io::Write as _, |
6 | path::Path, | 5 | path::Path, |
7 | time::{Instant, SystemTime, UNIX_EPOCH}, | 6 | time::{Instant, SystemTime, UNIX_EPOCH}, |
@@ -127,40 +126,21 @@ impl Metrics { | |||
127 | self.metrics.insert(name.into(), (value, unit)); | 126 | self.metrics.insert(name.into(), (value, unit)); |
128 | } | 127 | } |
129 | 128 | ||
130 | fn json(&self) -> Json { | 129 | fn json(&self) -> String { |
131 | let mut json = Json::default(); | 130 | let mut buf = String::new(); |
132 | self.to_json(&mut json); | 131 | self.to_json(write_json::object(&mut buf)); |
133 | json | 132 | buf |
134 | } | 133 | } |
135 | fn to_json(&self, json: &mut Json) { | ||
136 | json.begin_object(); | ||
137 | { | ||
138 | json.field("host"); | ||
139 | self.host.to_json(json); | ||
140 | |||
141 | json.field("timestamp"); | ||
142 | let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap(); | ||
143 | json.number(timestamp.as_secs() as f64); | ||
144 | 134 | ||
145 | json.field("revision"); | 135 | fn to_json(&self, mut obj: write_json::Object<'_>) { |
146 | json.string(&self.revision); | 136 | self.host.to_json(obj.object("host")); |
147 | 137 | let timestamp = self.timestamp.duration_since(UNIX_EPOCH).unwrap(); | |
148 | json.field("metrics"); | 138 | obj.number("timestamp", timestamp.as_secs() as f64); |
149 | json.begin_object(); | 139 | obj.string("revision", &self.revision); |
150 | { | 140 | let mut metrics = obj.object("metrics"); |
151 | for (k, (value, unit)) in &self.metrics { | 141 | for (k, (value, unit)) in &self.metrics { |
152 | json.field(k); | 142 | metrics.array(k).number(*value as f64).string(unit); |
153 | json.begin_array(); | ||
154 | { | ||
155 | json.number(*value as f64); | ||
156 | json.string(unit); | ||
157 | } | ||
158 | json.end_array(); | ||
159 | } | ||
160 | } | ||
161 | json.end_object() | ||
162 | } | 143 | } |
163 | json.end_object(); | ||
164 | } | 144 | } |
165 | } | 145 | } |
166 | 146 | ||
@@ -189,91 +169,7 @@ impl Host { | |||
189 | Ok(line[field.len()..].trim().to_string()) | 169 | Ok(line[field.len()..].trim().to_string()) |
190 | } | 170 | } |
191 | } | 171 | } |
192 | fn to_json(&self, json: &mut Json) { | 172 | fn to_json(&self, mut obj: write_json::Object<'_>) { |
193 | json.begin_object(); | 173 | obj.string("os", &self.os).string("cpu", &self.cpu).string("mem", &self.mem); |
194 | { | ||
195 | json.field("os"); | ||
196 | json.string(&self.os); | ||
197 | |||
198 | json.field("cpu"); | ||
199 | json.string(&self.cpu); | ||
200 | |||
201 | json.field("mem"); | ||
202 | json.string(&self.mem); | ||
203 | } | ||
204 | json.end_object(); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | struct State { | ||
209 | obj: bool, | ||
210 | first: bool, | ||
211 | } | ||
212 | |||
213 | #[derive(Default)] | ||
214 | struct Json { | ||
215 | stack: Vec<State>, | ||
216 | buf: String, | ||
217 | } | ||
218 | |||
219 | impl Json { | ||
220 | fn begin_object(&mut self) { | ||
221 | self.stack.push(State { obj: true, first: true }); | ||
222 | self.buf.push('{'); | ||
223 | } | ||
224 | fn end_object(&mut self) { | ||
225 | self.stack.pop(); | ||
226 | self.buf.push('}') | ||
227 | } | ||
228 | fn begin_array(&mut self) { | ||
229 | self.stack.push(State { obj: false, first: true }); | ||
230 | self.buf.push('['); | ||
231 | } | ||
232 | fn end_array(&mut self) { | ||
233 | self.stack.pop(); | ||
234 | self.buf.push(']') | ||
235 | } | ||
236 | fn field(&mut self, name: &str) { | ||
237 | self.object_comma(); | ||
238 | self.string_token(name); | ||
239 | self.buf.push(':'); | ||
240 | } | ||
241 | fn string(&mut self, value: &str) { | ||
242 | self.array_comma(); | ||
243 | self.string_token(value); | ||
244 | } | ||
245 | fn string_token(&mut self, value: &str) { | ||
246 | self.buf.push('"'); | ||
247 | self.buf.extend(value.escape_default()); | ||
248 | self.buf.push('"'); | ||
249 | } | ||
250 | fn number(&mut self, value: f64) { | ||
251 | self.array_comma(); | ||
252 | write!(self.buf, "{}", value).unwrap(); | ||
253 | } | ||
254 | |||
255 | fn array_comma(&mut self) { | ||
256 | let state = self.stack.last_mut().unwrap(); | ||
257 | if state.obj { | ||
258 | return; | ||
259 | } | ||
260 | if !state.first { | ||
261 | self.buf.push(','); | ||
262 | } | ||
263 | state.first = false; | ||
264 | } | ||
265 | |||
266 | fn object_comma(&mut self) { | ||
267 | let state = self.stack.last_mut().unwrap(); | ||
268 | if !state.first { | ||
269 | self.buf.push(','); | ||
270 | } | ||
271 | state.first = false; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | impl fmt::Display for Json { | ||
276 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
277 | write!(f, "{}", self.buf) | ||
278 | } | 174 | } |
279 | } | 175 | } |
diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index adadffc53..d65a2acbc 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs | |||
@@ -55,7 +55,6 @@ fn check_licenses() { | |||
55 | 0BSD OR MIT OR Apache-2.0 | 55 | 0BSD OR MIT OR Apache-2.0 |
56 | Apache-2.0 OR BSL-1.0 | 56 | Apache-2.0 OR BSL-1.0 |
57 | Apache-2.0 OR MIT | 57 | Apache-2.0 OR MIT |
58 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | ||
59 | Apache-2.0/MIT | 58 | Apache-2.0/MIT |
60 | BSD-2-Clause | 59 | BSD-2-Clause |
61 | BSD-3-Clause | 60 | BSD-3-Clause |