aboutsummaryrefslogtreecommitdiff
path: root/xtask
diff options
context:
space:
mode:
Diffstat (limited to 'xtask')
-rw-r--r--xtask/Cargo.toml9
-rw-r--r--xtask/src/ast_src.rs2033
-rw-r--r--xtask/src/codegen/gen_syntax.rs249
-rw-r--r--xtask/src/codegen/rust.ungram529
-rw-r--r--xtask/src/dist.rs27
-rw-r--r--xtask/src/lib.rs1
-rw-r--r--xtask/src/main.rs13
-rw-r--r--xtask/src/metrics.rs279
-rw-r--r--xtask/src/not_bash.rs3
-rw-r--r--xtask/tests/tidy.rs1
10 files changed, 1101 insertions, 2043 deletions
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index d1cfb5909..8140da87f 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -10,9 +10,10 @@ license = "MIT OR Apache-2.0"
10doctest = false 10doctest = false
11 11
12[dependencies] 12[dependencies]
13walkdir = "2.3.1"
14pico-args = "0.3.1"
15quote = "1.0.2"
16proc-macro2 = "1.0.8"
17anyhow = "1.0.26" 13anyhow = "1.0.26"
18flate2 = "1.0" 14flate2 = "1.0"
15pico-args = "0.3.1"
16proc-macro2 = "1.0.8"
17quote = "1.0.2"
18ungrammar = "0.1.0"
19walkdir = "2.3.1"
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 392648d71..83449437b 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -223,2021 +223,38 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
223 ], 223 ],
224}; 224};
225 225
226pub(crate) struct AstSrc<'a> { 226#[derive(Default, Debug)]
227 pub(crate) tokens: &'a [&'a str], 227pub(crate) struct AstSrc {
228 pub(crate) nodes: &'a [AstNodeSrc<'a>], 228 pub(crate) tokens: Vec<String>,
229 pub(crate) enums: &'a [AstEnumSrc<'a>], 229 pub(crate) nodes: Vec<AstNodeSrc>,
230 pub(crate) enums: Vec<AstEnumSrc>,
230} 231}
231 232
232pub(crate) struct AstNodeSrc<'a> { 233#[derive(Debug)]
233 pub(crate) doc: &'a [&'a str], 234pub(crate) struct AstNodeSrc {
234 pub(crate) name: &'a str, 235 pub(crate) doc: Vec<String>,
235 pub(crate) traits: &'a [&'a str], 236 pub(crate) name: String,
236 pub(crate) fields: &'a [Field<'a>], 237 pub(crate) traits: Vec<String>,
238 pub(crate) fields: Vec<Field>,
237} 239}
238 240
239pub(crate) enum Field<'a> { 241#[derive(Debug, Eq, PartialEq)]
240 Token(&'a str), 242pub(crate) enum Field {
241 Node { name: &'a str, src: FieldSrc<'a> }, 243 Token(String),
244 Node { name: String, src: FieldSrc },
242} 245}
243 246
244pub(crate) enum FieldSrc<'a> { 247#[derive(Debug, Eq, PartialEq)]
248pub(crate) enum FieldSrc {
245 Shorthand, 249 Shorthand,
246 Optional(&'a str), 250 Optional(String),
247 Many(&'a str), 251 Many(String),
248}
249
250pub(crate) struct AstEnumSrc<'a> {
251 pub(crate) doc: &'a [&'a str],
252 pub(crate) name: &'a str,
253 pub(crate) traits: &'a [&'a str],
254 pub(crate) variants: &'a [&'a str],
255}
256
257macro_rules! ast_nodes {
258 ($(
259 $(#[doc = $doc:expr])+
260 struct $name:ident$(: $($trait:ident),*)? {
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}
277
278macro_rules! field {
279 (T![$token:tt] T) => {
280 Field::Token(stringify!($token))
281 };
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} 252}
292 253
293macro_rules! ast_enums { 254#[derive(Debug)]
294 ($( 255pub(crate) struct AstEnumSrc {
295 $(#[doc = $doc:expr])+ 256 pub(crate) doc: Vec<String>,
296 enum $name:ident $(: $($trait:ident),*)? { 257 pub(crate) name: String,
297 $($variant:ident),*$(,)? 258 pub(crate) traits: Vec<String>,
298 } 259 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} 260}
310
311pub(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..24e8be1fb 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -3,34 +3,43 @@
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
6use std::{collections::HashSet, fmt::Write}; 6use std::{
7 collections::{BTreeSet, HashSet},
8 fmt::Write,
9};
7 10
8use proc_macro2::{Punct, Spacing}; 11use proc_macro2::{Punct, Spacing};
9use quote::{format_ident, quote}; 12use quote::{format_ident, quote};
13use ungrammar::{Grammar, Rule};
10 14
11use crate::{ 15use crate::{
12 ast_src::{AstSrc, Field, FieldSrc, KindsSrc, AST_SRC, KINDS_SRC}, 16 ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Field, FieldSrc, 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
17pub fn generate_syntax(mode: Mode) -> Result<()> { 21pub fn generate_syntax(mode: Mode) -> Result<()> {
22 let grammar = include_str!("rust.ungram")
23 .parse::<Grammar>()
24 .unwrap_or_else(|err| panic!("\n \x1b[91merror\x1b[0m: {}\n", err));
25 let ast = lower(&grammar);
26
18 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); 27 let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS);
19 let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; 28 let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?;
20 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; 29 update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?;
21 30
22 let ast_tokens_file = project_root().join(codegen::AST_TOKENS); 31 let ast_tokens_file = project_root().join(codegen::AST_TOKENS);
23 let contents = generate_tokens(AST_SRC)?; 32 let contents = generate_tokens(&ast)?;
24 update(ast_tokens_file.as_path(), &contents, mode)?; 33 update(ast_tokens_file.as_path(), &contents, mode)?;
25 34
26 let ast_nodes_file = project_root().join(codegen::AST_NODES); 35 let ast_nodes_file = project_root().join(codegen::AST_NODES);
27 let contents = generate_nodes(KINDS_SRC, AST_SRC)?; 36 let contents = generate_nodes(KINDS_SRC, &ast)?;
28 update(ast_nodes_file.as_path(), &contents, mode)?; 37 update(ast_nodes_file.as_path(), &contents, mode)?;
29 38
30 Ok(()) 39 Ok(())
31} 40}
32 41
33fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { 42fn generate_tokens(grammar: &AstSrc) -> Result<String> {
34 let tokens = grammar.tokens.iter().map(|token| { 43 let tokens = grammar.tokens.iter().map(|token| {
35 let name = format_ident!("{}", token); 44 let name = format_ident!("{}", token);
36 let kind = format_ident!("{}", to_upper_snake_case(token)); 45 let kind = format_ident!("{}", to_upper_snake_case(token));
@@ -62,13 +71,13 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> {
62 Ok(pretty) 71 Ok(pretty)
63} 72}
64 73
65fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { 74fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> {
66 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar 75 let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
67 .nodes 76 .nodes
68 .iter() 77 .iter()
69 .map(|node| { 78 .map(|node| {
70 let name = format_ident!("{}", node.name); 79 let name = format_ident!("{}", node.name);
71 let kind = format_ident!("{}", to_upper_snake_case(node.name)); 80 let kind = format_ident!("{}", to_upper_snake_case(&node.name));
72 let traits = node.traits.iter().map(|trait_name| { 81 let traits = node.traits.iter().map(|trait_name| {
73 let trait_name = format_ident!("{}", trait_name); 82 let trait_name = format_ident!("{}", trait_name);
74 quote!(impl ast::#trait_name for #name {}) 83 quote!(impl ast::#trait_name for #name {})
@@ -192,8 +201,8 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
192 }) 201 })
193 .unzip(); 202 .unzip();
194 203
195 let enum_names = grammar.enums.iter().map(|it| it.name); 204 let enum_names = grammar.enums.iter().map(|it| &it.name);
196 let node_names = grammar.nodes.iter().map(|it| it.name); 205 let node_names = grammar.nodes.iter().map(|it| &it.name);
197 206
198 let display_impls = 207 let display_impls =
199 enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { 208 enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
@@ -212,9 +221,11 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
212 .nodes 221 .nodes
213 .iter() 222 .iter()
214 .map(|kind| to_pascal_case(kind)) 223 .map(|kind| to_pascal_case(kind))
215 .filter(|name| !defined_nodes.contains(name.as_str())) 224 .filter(|name| !defined_nodes.iter().any(|&it| it == name))
216 { 225 {
217 eprintln!("Warning: node {} not defined in ast source", node); 226 drop(node)
227 // TODO: restore this
228 // eprintln!("Warning: node {} not defined in ast source", node);
218 } 229 }
219 230
220 let ast = quote! { 231 let ast = quote! {
@@ -236,12 +247,12 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
236 let mut res = String::with_capacity(ast.len() * 2); 247 let mut res = String::with_capacity(ast.len() * 2);
237 248
238 let mut docs = 249 let mut docs =
239 grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc)); 250 grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));
240 251
241 for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") { 252 for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") {
242 res.push_str(chunk); 253 res.push_str(chunk);
243 if let Some(doc) = docs.next() { 254 if let Some(doc) = docs.next() {
244 write_doc_comment(doc, &mut res); 255 write_doc_comment(&doc, &mut res);
245 } 256 }
246 } 257 }
247 258
@@ -249,7 +260,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
249 Ok(pretty) 260 Ok(pretty)
250} 261}
251 262
252fn write_doc_comment(contents: &[&str], dest: &mut String) { 263fn write_doc_comment(contents: &[String], dest: &mut String) {
253 for line in contents { 264 for line in contents {
254 writeln!(dest, "///{}", line).unwrap(); 265 writeln!(dest, "///{}", line).unwrap();
255 } 266 }
@@ -413,7 +424,11 @@ fn to_pascal_case(s: &str) -> String {
413 buf 424 buf
414} 425}
415 426
416impl Field<'_> { 427fn pluralize(s: &str) -> String {
428 format!("{}s", s)
429}
430
431impl Field {
417 fn is_many(&self) -> bool { 432 fn is_many(&self) -> bool {
418 matches!(self, Field::Node { src: FieldSrc::Many(_), .. }) 433 matches!(self, Field::Node { src: FieldSrc::Many(_), .. })
419 } 434 }
@@ -429,7 +444,7 @@ impl Field<'_> {
429 fn method_name(&self) -> proc_macro2::Ident { 444 fn method_name(&self) -> proc_macro2::Ident {
430 match self { 445 match self {
431 Field::Token(name) => { 446 Field::Token(name) => {
432 let name = match *name { 447 let name = match name.as_str() {
433 ";" => "semicolon", 448 ";" => "semicolon",
434 "->" => "thin_arrow", 449 "->" => "thin_arrow",
435 "'{'" => "l_curly", 450 "'{'" => "l_curly",
@@ -448,6 +463,7 @@ impl Field<'_> {
448 "." => "dot", 463 "." => "dot",
449 ".." => "dotdot", 464 ".." => "dotdot",
450 "..." => "dotdotdot", 465 "..." => "dotdotdot",
466 "..=" => "dotdoteq",
451 "=>" => "fat_arrow", 467 "=>" => "fat_arrow",
452 "@" => "at", 468 "@" => "at",
453 ":" => "colon", 469 ":" => "colon",
@@ -474,3 +490,204 @@ impl Field<'_> {
474 } 490 }
475 } 491 }
476} 492}
493
494fn lower(grammar: &Grammar) -> AstSrc {
495 let mut res = AstSrc::default();
496 res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()];
497
498 let nodes = grammar
499 .iter()
500 .filter(|&node| match grammar[node].rule {
501 Rule::Node(it) if it == node => false,
502 _ => true,
503 })
504 .collect::<Vec<_>>();
505
506 for &node in &nodes {
507 let name = grammar[node].name.clone();
508 let rule = &grammar[node].rule;
509 match lower_enum(grammar, rule) {
510 Some(variants) => {
511 let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants };
512 res.enums.push(enum_src);
513 }
514 None => {
515 let mut fields = Vec::new();
516 lower_rule(&mut fields, grammar, rule);
517 res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields });
518 }
519 }
520 }
521
522 deduplicate_fields(&mut res);
523 extract_enums(&mut res);
524 extract_struct_traits(&mut res);
525 extract_enum_traits(&mut res);
526 res
527}
528
529fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
530 let alternatives = match rule {
531 Rule::Alt(it) => it,
532 _ => return None,
533 };
534 let mut variants = Vec::new();
535 for alternative in alternatives {
536 match alternative {
537 Rule::Node(it) => variants.push(grammar[*it].name.clone()),
538 _ => return None,
539 }
540 }
541 Some(variants)
542}
543
544fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, rule: &Rule) {
545 match rule {
546 Rule::Node(node) => {
547 let field = Field::Node { name: grammar[*node].name.clone(), src: FieldSrc::Shorthand };
548 acc.push(field);
549 }
550 Rule::Token(token) => {
551 let mut name = grammar[*token].name.clone();
552 if name != "int_number" && name != "string" {
553 if "[]{}()".contains(&name) {
554 name = format!("'{}'", name);
555 }
556 let field = Field::Token(name);
557 acc.push(field);
558 }
559 }
560 Rule::Rep(inner) => {
561 if let Rule::Node(node) = &**inner {
562 let name = grammar[*node].name.clone();
563 let label = pluralize(&to_lower_snake_case(&name));
564 let field = Field::Node { name: label.clone(), src: FieldSrc::Many(name) };
565 acc.push(field);
566 return;
567 }
568 todo!("{:?}", rule)
569 }
570 Rule::Labeled { label, rule } => {
571 let node = match &**rule {
572 Rule::Rep(inner) | Rule::Opt(inner) => match &**inner {
573 Rule::Node(node) => node,
574 _ => todo!("{:?}", rule),
575 },
576 Rule::Node(node) => node,
577 _ => todo!("{:?}", rule),
578 };
579 let field = Field::Node {
580 name: label.clone(),
581 src: match &**rule {
582 Rule::Rep(_) => FieldSrc::Many(grammar[*node].name.clone()),
583 _ => FieldSrc::Optional(grammar[*node].name.clone()),
584 },
585 };
586 acc.push(field);
587 }
588 Rule::Seq(rules) | Rule::Alt(rules) => {
589 for rule in rules {
590 lower_rule(acc, grammar, rule)
591 }
592 }
593 Rule::Opt(rule) => lower_rule(acc, grammar, rule),
594 }
595}
596
597fn deduplicate_fields(ast: &mut AstSrc) {
598 eprintln!();
599 for node in &mut ast.nodes {
600 let mut i = 0;
601 'outer: while i < node.fields.len() {
602 for j in 0..i {
603 let f1 = &node.fields[i];
604 let f2 = &node.fields[j];
605 if f1 == f2 {
606 node.fields.remove(i);
607 continue 'outer;
608 }
609 }
610 i += 1;
611 }
612 }
613}
614
615fn extract_enums(ast: &mut AstSrc) {
616 for node in &mut ast.nodes {
617 for enm in &ast.enums {
618 let mut to_remove = Vec::new();
619 for (i, field) in node.fields.iter().enumerate() {
620 let ty = field.ty().to_string();
621 if enm.variants.iter().any(|it| it == &ty) {
622 to_remove.push(i);
623 }
624 }
625 if to_remove.len() == enm.variants.len() {
626 node.remove_field(to_remove);
627 node.fields.push(Field::Node { name: enm.name.clone(), src: FieldSrc::Shorthand });
628 }
629 }
630 }
631}
632
633fn extract_struct_traits(ast: &mut AstSrc) {
634 let traits: &[(&str, &[&str])] = &[
635 ("AttrsOwner", &["attrs"]),
636 ("NameOwner", &["name"]),
637 ("VisibilityOwner", &["visibility"]),
638 ("TypeParamsOwner", &["type_param_list", "where_clause"]),
639 ("TypeBoundsOwner", &["type_bound_list", "colon_token"]),
640 ("ModuleItemOwner", &["items"]),
641 ("TypeAscriptionOwner", &["ascribed_type"]),
642 ("LoopBodyOwner", &["label", "loop_body"]),
643 ("ArgListOwner", &["arg_list"]),
644 ];
645
646 for node in &mut ast.nodes {
647 for (name, methods) in traits {
648 extract_struct_trait(node, name, methods);
649 }
650 }
651}
652
653fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) {
654 let mut to_remove = Vec::new();
655 for (i, field) in node.fields.iter().enumerate() {
656 let method_name = field.method_name().to_string();
657 if methods.iter().any(|&it| it == &method_name) {
658 to_remove.push(i);
659 }
660 }
661 if to_remove.len() == methods.len() {
662 node.traits.push(trait_name.to_string());
663 node.remove_field(to_remove);
664 }
665}
666
667fn extract_enum_traits(ast: &mut AstSrc) {
668 for enm in &mut ast.enums {
669 let nodes = &ast.nodes;
670 let mut variant_traits = enm
671 .variants
672 .iter()
673 .map(|var| nodes.iter().find(|it| &it.name == var).unwrap())
674 .map(|node| node.traits.iter().cloned().collect::<BTreeSet<_>>());
675
676 let mut enum_traits = match variant_traits.next() {
677 Some(it) => it,
678 None => continue,
679 };
680 for traits in variant_traits {
681 enum_traits = enum_traits.intersection(&traits).cloned().collect();
682 }
683 enm.traits = enum_traits.into_iter().collect();
684 }
685}
686
687impl AstNodeSrc {
688 fn remove_field(&mut self, to_remove: Vec<usize>) {
689 to_remove.into_iter().rev().for_each(|idx| {
690 self.fields.remove(idx);
691 });
692 }
693}
diff --git a/xtask/src/codegen/rust.ungram b/xtask/src/codegen/rust.ungram
new file mode 100644
index 000000000..b6ec5d5e7
--- /dev/null
+++ b/xtask/src/codegen/rust.ungram
@@ -0,0 +1,529 @@
1SourceFile =
2 Attr*
3 items:ModuleItem*
4
5FnDef =
6 Attr* Visibility? Abi? 'const' 'default' 'async' 'unsafe' 'fn' Name TypeParamList?
7 ParamList RetType?
8 WhereClause?
9 (body:BlockExpr | ';')
10
11RetType =
12 '->' TypeRef
13
14StructDef =
15 Attr* Visibility? 'struct' Name TypeParamList? (
16 WhereClause? (RecordFieldDefList | ';')
17 | TupleFieldDefList WhereClause? ';'
18 )
19
20UnionDef =
21 Attr* Visibility? 'union' Name TypeParamList? WhereClause?
22 RecordFieldDefList
23
24RecordFieldDefList =
25 '{' fields:RecordFieldDef* '}'
26
27RecordFieldDef =
28 Attr* Visibility? Name ':' ascribed_type:TypeRef
29
30TupleFieldDefList =
31 '(' fields:TupleFieldDef* ')'
32
33TupleFieldDef =
34 Attr* Visibility? Name TypeRef
35
36FieldDefList =
37 RecordFieldDefList
38| TupleFieldDefList
39
40EnumDef =
41 Attr* Visibility? 'enum' Name TypeParamList? WhereClause?
42 variant_list:EnumVariantList
43
44EnumVariantList =
45 '{' variants:EnumVariant* '}'
46
47EnumVariant =
48 Attr* Visibility? Name FieldDefList ('=' Expr)?
49
50TraitDef =
51 Attr* Visibility? 'unsafe'? 'auto'? 'trait' Name TypeParamList
52 (':' TypeBoundList?)? WhereClause
53 ItemList
54
55Module =
56 Attr* Visibility? 'mod' Name
57 (ItemList | ';')
58
59ItemList =
60 '{'
61 AssocItem*
62 items:ModuleItem*
63 '}'
64
65ConstDef =
66 Attr* Visibility? 'default'? 'const' Name ':' ascribed_type:TypeRef
67 '=' body:Expr ';'
68
69StaticDef =
70 Attr* Visibility? 'static'? 'mut'? 'static' Name ':' ascribed_type:TypeRef
71 '=' body:Expr ';'
72
73TypeAliasDef =
74 Attr* Visibility? 'default'? 'type' Name TypeParamList? WhereClause? (':' TypeBoundList?)?
75 '=' TypeRef ';'
76
77ImplDef =
78 Attr* Visibility? 'const'? 'default'? 'unsafe'? 'impl' TypeParamList? '!'? 'for'
79 WhereClause?
80 ItemList
81
82ParenType =
83 '(' TypeRef ')'
84
85TupleType =
86 '(' fields:TypeRef* ')'
87
88NeverType =
89 '!'
90
91PathType =
92 Path
93
94PointerType =
95 '*' ('const' | 'mut') TypeRef
96
97ArrayType =
98 '[' TypeRef ';' Expr ']'
99
100SliceType =
101 '[' TypeRef ']'
102
103ReferenceType =
104 '&' 'lifetime'? 'mut'? TypeRef
105
106PlaceholderType =
107 '_'
108
109FnPointerType =
110 Abi 'unsafe'? 'fn' ParamList RetType?
111
112ForType =
113 'for' TypeParamList TypeRef
114
115ImplTraitType =
116 'impl' TypeBoundList
117
118DynTraitType =
119 'dyn' TypeBoundList
120
121TupleExpr =
122 Attr* '(' Expr* ')'
123
124ArrayExpr =
125 Attr* '[' (Expr* | Expr ';' Expr) ']'
126
127ParenExpr =
128 Attr* '(' Expr ')'
129
130PathExpr =
131 Path
132
133LambdaExpr =
134 Attr* 'static'? 'async'? 'move'? ParamList RetType?
135 body:Expr
136
137IfExpr =
138 Attr* 'if' Condition
139
140Condition =
141 'let' Pat '=' Expr
142| Expr
143
144EffectExpr =
145 Attr* Label? ('try' | 'unsafe' | 'async') BlockExpr
146
147LoopExpr =
148 Attr* Label? 'loop'
149 loop_body:BlockExpr?
150
151ForExpr =
152 Attr* Label? 'for' Pat 'in' iterable:Expr
153 loop_body:BlockExpr?
154
155WhileExpr =
156 Attr* Label? 'while' Condition
157 loop_body:BlockExpr?
158
159ContinueExpr =
160 Attr* 'continue' 'lifetime'?
161
162BreakExpr =
163 Attr* 'break' 'lifetime'? Expr?
164
165Label =
166 'lifetime'
167
168BlockExpr =
169 Attr* Label
170 '{'
171 items:ModuleItem*
172 statements:Stmt*
173 Expr?
174 '}'
175
176ReturnExpr =
177 Attr* 'return' Expr
178
179CallExpr =
180 Attr* Expr ArgList
181
182MethodCallExpr =
183 Attr* Expr '.' NameRef TypeArgList? ArgList
184
185ArgList =
186 '(' args:Expr* ')'
187
188FieldExpr =
189 Attr* Expr '.' NameRef
190
191IndexExpr =
192 Attr* '[' ']'
193
194AwaitExpr =
195 Attr* Expr '.' 'await'
196
197TryExpr =
198 Attr* Expr '?'
199
200CastExpr =
201 Attr* Expr 'as' TypeRef
202
203RefExpr =
204 Attr* '&' ('raw' | 'mut' | 'const') Expr
205
206PrefixExpr =
207 Attr* Expr
208
209BoxExpr =
210 Attr* 'box' Expr
211
212RangeExpr =
213 Attr*
214
215BinExpr =
216 Attr*
217
218Literal =
219 'int_number'
220
221MatchExpr =
222 Attr* 'match' Expr MatchArmList
223
224MatchArmList =
225 '{' arms:MatchArm* '}'
226
227MatchArm =
228 Attr* Pat guard:MatchGuard? '=>' Expr
229
230MatchGuard =
231 'if' Expr
232
233RecordLit =
234 Path RecordFieldList
235
236RecordFieldList =
237 '{'
238 fields:RecordField*
239 ('..' spread:Expr)?
240 '}'
241
242RecordField =
243 Attr* NameRef (':' Expr)?
244
245OrPat =
246 Pat*
247
248ParenPat =
249 '(' Pat ')'
250
251RefPat =
252 '&' 'mut'? Pat
253
254BoxPat =
255 'box' Path
256
257BindPat =
258 Attr* 'ref'? 'mut'? Name ('@' Pat)?
259
260PlaceholderPat =
261 '_'
262
263DotDotPat =
264 '..'
265
266PathPat =
267 Path
268
269SlicePat =
270 '[' args:Pat* ']'
271
272RangePat =
273 '..' | '..='
274
275LiteralPat =
276 Literal
277
278MacroPat =
279 MacroCall
280
281RecordPat =
282 Path RecordFieldPatList
283
284RecordFieldPatList =
285 '{'
286 record_field_pats:RecordFieldPat*
287 BindPat*
288 '..'?
289 '}'
290
291RecordFieldPat =
292 Attr* NameRef ':' Pat
293
294TupleStructPat =
295 Path '(' args:Pat* ')'
296
297TuplePat =
298 '(' args:Pat* ')'
299
300Visibility =
301 'pub' ('(' 'super' | 'self' | 'crate' | 'in' Path ')')?
302
303Name =
304 'ident'
305
306NameRef =
307 'ident' | 'int_number'
308
309MacroCall =
310 Attr* Path '!' Name? TokenTree ';'?
311
312MacroDef =
313 Name TokenTree
314
315TokenTree =
316 '(' ')' | '{' '}' | '[' ']'
317
318MacroItems =
319 items:ModuleItem*
320
321MacroStmts =
322 statements:Stmt*
323 Expr?
324
325Attr =
326 '#' '!'? '[' Path ('=' input:AttrInput)? ']'
327
328TypeParamList =
329 '<'
330 TypeParam*
331 LifetimeParam*
332 ConstParam*
333 '>'
334
335TypeParam =
336 Attr* Name (':' TypeBoundList?)?
337 ('=' default_type:TypeRef)?
338
339ConstParam =
340 Attr* 'const' Name ':' ascribed_type:TypeRef
341 ('=' default_val:Expr)?
342
343LifetimeParam =
344 Attr* 'lifetime'
345
346TypeBound =
347 'lifetime' | 'const'? TypeRef
348
349TypeBoundList =
350 bounds:TypeBound*
351
352WherePred =
353 ('for' TypeParamList)? ('lifetime' | TypeRef) ':' TypeBoundList
354
355WhereClause =
356 'where' predicates:WherePred*
357
358Abi =
359 'string'
360
361ExprStmt =
362 Attr* Expr ';'
363
364LetStmt =
365 Attr* 'let' Pat (':' ascribed_type:TypeRef)
366 '=' initializer:Expr ';'
367
368ParamList =
369 '(' SelfParam Param* ')'
370
371SelfParam =
372 Attr* ('&' 'lifetime'?)? 'mut'? 'self' (':' ascribed_type:TypeRef)
373
374Param =
375 Attr* Pat (':' ascribed_type:TypeRef)
376| '...'
377
378UseItem =
379 Attr* Visibility? 'use' UseTree ';'
380
381UseTree =
382 Path ('::' ('*' | UseTreeList)) Alias?
383
384UseTreeList =
385 '{' UseTree* '}'
386
387Alias =
388 'as' Name
389
390ExternCrateItem =
391 Attr* Visibility? 'extern' 'crate' (NameRef | 'self') Alias? ';'
392
393Path =
394 (qualifier:Path '::')? segment:PathSegment
395
396PathSegment =
397 '::' | 'crate' | 'self' | 'super'
398| '<' NameRef TypeArgList ParamList RetType PathType '>'
399
400TypeArgList =
401 '::'? '<'
402 TypeArg*
403 LifetimeArg*
404 AssocTypeArg*
405 ConstArg*
406 '>'
407
408TypeArg =
409 TypeRef
410
411AssocTypeArg =
412 NameRef (':' TypeBoundList | '=' TypeRef)
413
414LifetimeArg =
415 'lifetime'
416
417ConstArg =
418 Literal | BlockExpr BlockExpr
419
420ExternBlock =
421 Attr* Abi ExternItemList
422
423ExternItemList =
424 '{' extern_items:ExternItem* '}'
425
426MetaItem =
427 Path '=' AttrInput nested_meta_items:MetaItem*
428
429AdtDef =
430 StructDef
431| EnumDef
432| UnionDef
433
434TypeRef =
435 ParenType
436| TupleType
437| NeverType
438| PathType
439| PointerType
440| ArrayType
441| SliceType
442| ReferenceType
443| PlaceholderType
444| FnPointerType
445| ForType
446| ImplTraitType
447| DynTraitType
448
449AssocItem =
450 FnDef
451| TypeAliasDef
452| ConstDef
453
454ExternItem =
455 FnDef | StaticDef
456
457ModuleItem =
458 StructDef
459| UnionDef
460| EnumDef
461| FnDef
462| TraitDef
463| TypeAliasDef
464| ImplDef
465| UseItem
466| ExternCrateItem
467| ConstDef
468| StaticDef
469| Module
470| MacroCall
471| ExternBlock
472
473AttrInput =
474 Literal
475| TokenTree
476
477Stmt =
478 LetStmt
479| ExprStmt
480
481Pat =
482 OrPat
483| ParenPat
484| RefPat
485| BoxPat
486| BindPat
487| PlaceholderPat
488| DotDotPat
489| PathPat
490| RecordPat
491| TupleStructPat
492| TuplePat
493| SlicePat
494| RangePat
495| LiteralPat
496| MacroPat
497
498Expr =
499 TupleExpr
500| ArrayExpr
501| ParenExpr
502| PathExpr
503| LambdaExpr
504| IfExpr
505| LoopExpr
506| ForExpr
507| WhileExpr
508| ContinueExpr
509| BreakExpr
510| Label
511| BlockExpr
512| ReturnExpr
513| MatchExpr
514| RecordLit
515| CallExpr
516| IndexExpr
517| MethodCallExpr
518| FieldExpr
519| AwaitExpr
520| TryExpr
521| EffectExpr
522| CastExpr
523| RefExpr
524| PrefixExpr
525| RangeExpr
526| BinExpr
527| Literal
528| MacroCall
529| BoxExpr
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index c198c0907..01d903cde 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -13,17 +13,24 @@ use crate::{
13 project_root, 13 project_root,
14}; 14};
15 15
16pub fn run_dist(nightly: bool, client_version: Option<String>) -> Result<()> { 16pub struct DistCmd {
17 let dist = project_root().join("dist"); 17 pub nightly: bool,
18 rm_rf(&dist)?; 18 pub client_version: Option<String>,
19 fs2::create_dir_all(&dist)?; 19}
20 20
21 if let Some(version) = client_version { 21impl DistCmd {
22 let release_tag = if nightly { "nightly".to_string() } else { date_iso()? }; 22 pub fn run(self) -> Result<()> {
23 dist_client(&version, &release_tag)?; 23 let dist = project_root().join("dist");
24 rm_rf(&dist)?;
25 fs2::create_dir_all(&dist)?;
26
27 if let Some(version) = self.client_version {
28 let release_tag = if self.nightly { "nightly".to_string() } else { date_iso()? };
29 dist_client(&version, &release_tag)?;
30 }
31 dist_server()?;
32 Ok(())
24 } 33 }
25 dist_server()?;
26 Ok(())
27} 34}
28 35
29fn dist_client(version: &str, release_tag: &str) -> Result<()> { 36fn dist_client(version: &str, release_tag: &str) -> Result<()> {
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs
index 94d451e23..2fdb08f2e 100644
--- a/xtask/src/lib.rs
+++ b/xtask/src/lib.rs
@@ -7,6 +7,7 @@ pub mod install;
7pub mod release; 7pub mod release;
8pub mod dist; 8pub mod dist;
9pub mod pre_commit; 9pub mod pre_commit;
10pub mod metrics;
10 11
11pub mod codegen; 12pub mod codegen;
12mod ast_src; 13mod ast_src;
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 53d3ce3e7..b69b884e5 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -13,8 +13,9 @@ use std::env;
13use pico_args::Arguments; 13use pico_args::Arguments;
14use xtask::{ 14use xtask::{
15 codegen::{self, Mode}, 15 codegen::{self, Mode},
16 dist::run_dist, 16 dist::DistCmd,
17 install::{ClientOpt, InstallCmd, Malloc, ServerOpt}, 17 install::{ClientOpt, InstallCmd, Malloc, ServerOpt},
18 metrics::MetricsCmd,
18 not_bash::pushd, 19 not_bash::pushd,
19 pre_commit, project_root, 20 pre_commit, project_root,
20 release::{PromoteCmd, ReleaseCmd}, 21 release::{PromoteCmd, ReleaseCmd},
@@ -115,7 +116,12 @@ FLAGS:
115 let nightly = args.contains("--nightly"); 116 let nightly = args.contains("--nightly");
116 let client_version: Option<String> = args.opt_value_from_str("--client")?; 117 let client_version: Option<String> = args.opt_value_from_str("--client")?;
117 args.finish()?; 118 args.finish()?;
118 run_dist(nightly, client_version) 119 DistCmd { nightly, client_version }.run()
120 }
121 "metrics" => {
122 let dry_run = args.contains("--dry-run");
123 args.finish()?;
124 MetricsCmd { dry_run }.run()
119 } 125 }
120 _ => { 126 _ => {
121 eprintln!( 127 eprintln!(
@@ -133,7 +139,8 @@ SUBCOMMANDS:
133 codegen 139 codegen
134 install 140 install
135 lint 141 lint
136 dist" 142 dist
143 promote"
137 ); 144 );
138 Ok(()) 145 Ok(())
139 } 146 }
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs
new file mode 100644
index 000000000..9ac3fa51d
--- /dev/null
+++ b/xtask/src/metrics.rs
@@ -0,0 +1,279 @@
1use std::{
2 collections::BTreeMap,
3 env,
4 fmt::{self, Write as _},
5 io::Write as _,
6 path::Path,
7 time::{Instant, SystemTime, UNIX_EPOCH},
8};
9
10use anyhow::{bail, format_err, Result};
11
12use crate::not_bash::{fs2, pushd, pushenv, rm_rf, run};
13
14type Unit = String;
15
16pub struct MetricsCmd {
17 pub dry_run: bool,
18}
19
20impl MetricsCmd {
21 pub fn run(self) -> Result<()> {
22 let mut metrics = Metrics::new()?;
23 if !self.dry_run {
24 rm_rf("./target/release")?;
25 }
26 if !Path::new("./target/rustc-perf").exists() {
27 fs2::create_dir_all("./target/rustc-perf")?;
28 run!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")?;
29 }
30 {
31 let _d = pushd("./target/rustc-perf");
32 run!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033")?;
33 }
34
35 let _env = pushenv("RA_METRICS", "1");
36
37 metrics.measure_build()?;
38 metrics.measure_analysis_stats_self()?;
39 metrics.measure_analysis_stats("ripgrep")?;
40 metrics.measure_analysis_stats("webrender")?;
41
42 if !self.dry_run {
43 let _d = pushd("target");
44 let metrics_token = env::var("METRICS_TOKEN").unwrap();
45 let repo = format!("https://{}@github.com/rust-analyzer/metrics.git", metrics_token);
46 run!("git clone --depth 1 {}", repo)?;
47 let _d = pushd("metrics");
48
49 let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?;
50 writeln!(file, "{}", metrics.json())?;
51 run!("git add .")?;
52 run!("git -c user.name=Bot -c [email protected] commit --message 📈")?;
53 run!("git push origin master")?;
54 }
55 eprintln!("{:#?}", metrics);
56 Ok(())
57 }
58}
59
60impl Metrics {
61 fn measure_build(&mut self) -> Result<()> {
62 eprintln!("\nMeasuring build");
63 run!("cargo fetch")?;
64
65 let time = Instant::now();
66 run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?;
67 let time = time.elapsed();
68 self.report("build", time.as_millis() as u64, "ms".into());
69 Ok(())
70 }
71 fn measure_analysis_stats_self(&mut self) -> Result<()> {
72 self.measure_analysis_stats_path("self", &".")
73 }
74 fn measure_analysis_stats(&mut self, bench: &str) -> Result<()> {
75 self.measure_analysis_stats_path(
76 bench,
77 &format!("./target/rustc-perf/collector/benchmarks/{}", bench),
78 )
79 }
80 fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> {
81 eprintln!("\nMeasuring analysis-stats/{}", name);
82 let output = run!("./target/release/rust-analyzer analysis-stats --quiet {}", path)?;
83 for (metric, value, unit) in parse_metrics(&output) {
84 self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into());
85 }
86 Ok(())
87 }
88}
89
90fn parse_metrics(output: &str) -> Vec<(&str, u64, &str)> {
91 output
92 .lines()
93 .filter_map(|it| {
94 let entry = it.split(':').collect::<Vec<_>>();
95 match entry.as_slice() {
96 ["METRIC", name, value, unit] => Some((*name, value.parse().unwrap(), *unit)),
97 _ => None,
98 }
99 })
100 .collect()
101}
102
103#[derive(Debug)]
104struct Metrics {
105 host: Host,
106 timestamp: SystemTime,
107 revision: String,
108 metrics: BTreeMap<String, (u64, Unit)>,
109}
110
111#[derive(Debug)]
112struct Host {
113 os: String,
114 cpu: String,
115 mem: String,
116}
117
118impl Metrics {
119 fn new() -> Result<Metrics> {
120 let host = Host::new()?;
121 let timestamp = SystemTime::now();
122 let revision = run!("git rev-parse HEAD")?;
123 Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() })
124 }
125
126 fn report(&mut self, name: &str, value: u64, unit: Unit) {
127 self.metrics.insert(name.into(), (value, unit));
128 }
129
130 fn json(&self) -> Json {
131 let mut json = Json::default();
132 self.to_json(&mut json);
133 json
134 }
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
145 json.field("revision");
146 json.string(&self.revision);
147
148 json.field("metrics");
149 json.begin_object();
150 {
151 for (k, (value, unit)) in &self.metrics {
152 json.field(k);
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 }
163 json.end_object();
164 }
165}
166
167impl Host {
168 fn new() -> Result<Host> {
169 if cfg!(not(target_os = "linux")) {
170 bail!("can only collect metrics on Linux ");
171 }
172
173 let os = read_field("/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string();
174
175 let cpu =
176 read_field("/proc/cpuinfo", "model name")?.trim_start_matches(':').trim().to_string();
177
178 let mem = read_field("/proc/meminfo", "MemTotal:")?;
179
180 return Ok(Host { os, cpu, mem });
181
182 fn read_field<'a>(path: &str, field: &str) -> Result<String> {
183 let text = fs2::read_to_string(path)?;
184
185 let line = text
186 .lines()
187 .find(|it| it.starts_with(field))
188 .ok_or_else(|| format_err!("can't parse {}", path))?;
189 Ok(line[field.len()..].trim().to_string())
190 }
191 }
192 fn to_json(&self, json: &mut Json) {
193 json.begin_object();
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
208struct State {
209 obj: bool,
210 first: bool,
211}
212
213#[derive(Default)]
214struct Json {
215 stack: Vec<State>,
216 buf: String,
217}
218
219impl 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
275impl fmt::Display for Json {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 write!(f, "{}", self.buf)
278 }
279}
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs
index 0f3a56b25..ef811e5bf 100644
--- a/xtask/src/not_bash.rs
+++ b/xtask/src/not_bash.rs
@@ -186,7 +186,8 @@ impl Env {
186 fn pushd(&mut self, dir: PathBuf) { 186 fn pushd(&mut self, dir: PathBuf) {
187 let dir = self.cwd().join(dir); 187 let dir = self.cwd().join(dir);
188 self.pushd_stack.push(dir); 188 self.pushd_stack.push(dir);
189 env::set_current_dir(self.cwd()).unwrap(); 189 env::set_current_dir(self.cwd())
190 .unwrap_or_else(|err| panic!("Failed to set cwd to {}: {}", self.cwd().display(), err));
190 } 191 }
191 fn popd(&mut self) { 192 fn popd(&mut self) {
192 self.pushd_stack.pop().unwrap(); 193 self.pushd_stack.pop().unwrap();
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() {
550BSD OR MIT OR Apache-2.0 550BSD OR MIT OR Apache-2.0
56Apache-2.0 OR BSL-1.0 56Apache-2.0 OR BSL-1.0
57Apache-2.0 OR MIT 57Apache-2.0 OR MIT
58Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
59Apache-2.0/MIT 58Apache-2.0/MIT
60BSD-2-Clause 59BSD-2-Clause
61BSD-3-Clause 60BSD-3-Clause