diff options
20 files changed, 320 insertions, 90 deletions
diff --git a/Cargo.lock b/Cargo.lock index 759895695..fd04ec3c5 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -168,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | |||
168 | 168 | ||
169 | [[package]] | 169 | [[package]] |
170 | name = "chalk-derive" | 170 | name = "chalk-derive" |
171 | version = "0.43.0" | 171 | version = "0.45.0" |
172 | source = "registry+https://github.com/rust-lang/crates.io-index" | 172 | source = "registry+https://github.com/rust-lang/crates.io-index" |
173 | checksum = "e2d9e0c8adcced1ab0fea5cb8a38647922893d5b495e363e1814299fd380469b" | 173 | checksum = "ec7dacf94958d1a930b95d049d9443860859af59eadc77849392093eb577bcee" |
174 | dependencies = [ | 174 | dependencies = [ |
175 | "proc-macro2", | 175 | "proc-macro2", |
176 | "quote", | 176 | "quote", |
@@ -180,19 +180,20 @@ dependencies = [ | |||
180 | 180 | ||
181 | [[package]] | 181 | [[package]] |
182 | name = "chalk-ir" | 182 | name = "chalk-ir" |
183 | version = "0.43.0" | 183 | version = "0.45.0" |
184 | source = "registry+https://github.com/rust-lang/crates.io-index" | 184 | source = "registry+https://github.com/rust-lang/crates.io-index" |
185 | checksum = "c5218266a5709bc4943de997e64d3fab41c9e9f68efd54a898de53135e987bd3" | 185 | checksum = "a1a5b38ede247def17da87f4badb62396a5753db6048e2011d3089d8b3796c67" |
186 | dependencies = [ | 186 | dependencies = [ |
187 | "bitflags", | ||
187 | "chalk-derive", | 188 | "chalk-derive", |
188 | "lazy_static", | 189 | "lazy_static", |
189 | ] | 190 | ] |
190 | 191 | ||
191 | [[package]] | 192 | [[package]] |
192 | name = "chalk-recursive" | 193 | name = "chalk-recursive" |
193 | version = "0.43.0" | 194 | version = "0.45.0" |
194 | source = "registry+https://github.com/rust-lang/crates.io-index" | 195 | source = "registry+https://github.com/rust-lang/crates.io-index" |
195 | checksum = "ed8f34f13fd4f30251f9f6f1dc56f80363201390ecbcac2fdfc8e33036cd9c4a" | 196 | checksum = "7a18db146d7a023edc20ad094e8c2284451f7888719645004979617d1f17c041" |
196 | dependencies = [ | 197 | dependencies = [ |
197 | "chalk-derive", | 198 | "chalk-derive", |
198 | "chalk-ir", | 199 | "chalk-ir", |
@@ -203,9 +204,9 @@ dependencies = [ | |||
203 | 204 | ||
204 | [[package]] | 205 | [[package]] |
205 | name = "chalk-solve" | 206 | name = "chalk-solve" |
206 | version = "0.43.0" | 207 | version = "0.45.0" |
207 | source = "registry+https://github.com/rust-lang/crates.io-index" | 208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
208 | checksum = "379c9f584488346044709d4c638c38d61a06fe593d4de2ac5f15fd2b0ba4cd9d" | 209 | checksum = "7f73e0de04a0f394e47ed8118e00541bcf681d7c3c2ef500fa743eb4cf3a4850" |
209 | dependencies = [ | 210 | dependencies = [ |
210 | "chalk-derive", | 211 | "chalk-derive", |
211 | "chalk-ir", | 212 | "chalk-ir", |
@@ -507,9 +508,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" | |||
507 | 508 | ||
508 | [[package]] | 509 | [[package]] |
509 | name = "heck" | 510 | name = "heck" |
510 | version = "0.3.1" | 511 | version = "0.3.2" |
511 | source = "registry+https://github.com/rust-lang/crates.io-index" | 512 | source = "registry+https://github.com/rust-lang/crates.io-index" |
512 | checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" | 513 | checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" |
513 | dependencies = [ | 514 | dependencies = [ |
514 | "unicode-segmentation", | 515 | "unicode-segmentation", |
515 | ] | 516 | ] |
@@ -1074,9 +1075,9 @@ dependencies = [ | |||
1074 | 1075 | ||
1075 | [[package]] | 1076 | [[package]] |
1076 | name = "parking_lot_core" | 1077 | name = "parking_lot_core" |
1077 | version = "0.8.1" | 1078 | version = "0.8.2" |
1078 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1079 | checksum = "d7c6d9b8427445284a09c55be860a15855ab580a417ccad9da88f5a06787ced0" | 1080 | checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" |
1080 | dependencies = [ | 1081 | dependencies = [ |
1081 | "cfg-if 1.0.0", | 1082 | "cfg-if 1.0.0", |
1082 | "instant", | 1083 | "instant", |
@@ -1377,9 +1378,9 @@ dependencies = [ | |||
1377 | 1378 | ||
1378 | [[package]] | 1379 | [[package]] |
1379 | name = "rustc-ap-rustc_lexer" | 1380 | name = "rustc-ap-rustc_lexer" |
1380 | version = "691.0.0" | 1381 | version = "695.0.0" |
1381 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1382 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1382 | checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec" | 1383 | checksum = "390bad134705b0bff02cd9541ac66df751a91c3cc734c3369cd6151ca269caed" |
1383 | dependencies = [ | 1384 | dependencies = [ |
1384 | "unicode-xid", | 1385 | "unicode-xid", |
1385 | ] | 1386 | ] |
@@ -1837,9 +1838,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" | |||
1837 | 1838 | ||
1838 | [[package]] | 1839 | [[package]] |
1839 | name = "ungrammar" | 1840 | name = "ungrammar" |
1840 | version = "1.4.0" | 1841 | version = "1.5.0" |
1841 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1842 | checksum = "68951379f3ced25754472ca5addbf74d7dab58c9818f49290a3d8caa3ab44fb7" | 1843 | checksum = "c11bffada52edc8f2a56160b286ea4640acf90ffcb21bded361ccb8ed43a1457" |
1843 | 1844 | ||
1844 | [[package]] | 1845 | [[package]] |
1845 | name = "unicase" | 1846 | name = "unicase" |
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs index 1300f00b2..882c4dcbc 100644 --- a/crates/completion/src/completions/qualified_path.rs +++ b/crates/completion/src/completions/qualified_path.rs | |||
@@ -118,6 +118,12 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
118 | _ => return, | 118 | _ => return, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | if let Some(Adt::Enum(e)) = ty.as_adt() { | ||
122 | for variant in e.variants(ctx.db) { | ||
123 | acc.add_enum_variant(ctx, variant, None); | ||
124 | } | ||
125 | } | ||
126 | |||
121 | let traits_in_scope = ctx.scope.traits_in_scope(); | 127 | let traits_in_scope = ctx.scope.traits_in_scope(); |
122 | let mut seen = FxHashSet::default(); | 128 | let mut seen = FxHashSet::default(); |
123 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { | 129 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { |
@@ -752,4 +758,27 @@ fn main() { | |||
752 | "#]], | 758 | "#]], |
753 | ); | 759 | ); |
754 | } | 760 | } |
761 | |||
762 | #[test] | ||
763 | fn completes_self_enum() { | ||
764 | check( | ||
765 | r#" | ||
766 | enum Foo { | ||
767 | Bar, | ||
768 | Baz, | ||
769 | } | ||
770 | |||
771 | impl Foo { | ||
772 | fn foo(self) { | ||
773 | Self::<|> | ||
774 | } | ||
775 | } | ||
776 | "#, | ||
777 | expect![[r#" | ||
778 | ev Bar () | ||
779 | ev Baz () | ||
780 | me foo(…) fn foo(self) | ||
781 | "#]], | ||
782 | ); | ||
783 | } | ||
755 | } | 784 | } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index 099ffb4d4..d09849752 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use std::iter; | ||
4 | |||
3 | use either::Either; | 5 | use either::Either; |
4 | use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type}; | 6 | use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type}; |
5 | use ide_db::helpers::insert_use::ImportScope; | 7 | use ide_db::helpers::insert_use::ImportScope; |
@@ -50,7 +52,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
50 | } | 52 | } |
51 | 53 | ||
52 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { | 54 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) { |
53 | if let Some(Adt::Enum(enum_data)) = ty.as_adt() { | 55 | if let Some(Adt::Enum(enum_data)) = |
56 | iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) | ||
57 | { | ||
54 | let variants = enum_data.variants(ctx.db); | 58 | let variants = enum_data.variants(ctx.db); |
55 | 59 | ||
56 | let module = if let Some(module) = ctx.scope.module() { | 60 | let module = if let Some(module) = ctx.scope.module() { |
@@ -701,6 +705,7 @@ fn main() { <|> } | |||
701 | "#]], | 705 | "#]], |
702 | ); | 706 | ); |
703 | } | 707 | } |
708 | |||
704 | #[test] | 709 | #[test] |
705 | fn completes_enum_variant_matcharm() { | 710 | fn completes_enum_variant_matcharm() { |
706 | check( | 711 | check( |
@@ -722,6 +727,26 @@ fn main() { | |||
722 | } | 727 | } |
723 | 728 | ||
724 | #[test] | 729 | #[test] |
730 | fn completes_enum_variant_matcharm_ref() { | ||
731 | check( | ||
732 | r#" | ||
733 | enum Foo { Bar, Baz, Quux } | ||
734 | |||
735 | fn main() { | ||
736 | let foo = Foo::Quux; | ||
737 | match &foo { Qu<|> } | ||
738 | } | ||
739 | "#, | ||
740 | expect![[r#" | ||
741 | ev Foo::Bar () | ||
742 | ev Foo::Baz () | ||
743 | ev Foo::Quux () | ||
744 | en Foo | ||
745 | "#]], | ||
746 | ) | ||
747 | } | ||
748 | |||
749 | #[test] | ||
725 | fn completes_enum_variant_iflet() { | 750 | fn completes_enum_variant_iflet() { |
726 | check( | 751 | check( |
727 | r#" | 752 | r#" |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 0f404be1b..978c3a324 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -933,7 +933,9 @@ impl ExprCollector<'_> { | |||
933 | Pat::Box { inner } | 933 | Pat::Box { inner } |
934 | } | 934 | } |
935 | // FIXME: implement | 935 | // FIXME: implement |
936 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 936 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => { |
937 | Pat::Missing | ||
938 | } | ||
937 | }; | 939 | }; |
938 | let ptr = AstPtr::new(&pat); | 940 | let ptr = AstPtr::new(&pat); |
939 | self.alloc_pat(pattern, Either::Left(ptr)) | 941 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 289e812fe..965c1780a 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.43", default-features = false } | 20 | chalk-solve = { version = "0.45", default-features = false } |
21 | chalk-ir = "0.43" | 21 | chalk-ir = "0.45" |
22 | chalk-recursive = "0.43" | 22 | chalk-recursive = "0.45" |
23 | 23 | ||
24 | stdx = { path = "../stdx", version = "0.0.0" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
25 | hir_def = { path = "../hir_def", version = "0.0.0" } | 25 | hir_def = { path = "../hir_def", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 69eae6f79..2196af677 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -56,8 +56,13 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
56 | fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> { | 56 | fn adt_datum(&self, struct_id: AdtId) -> Arc<StructDatum> { |
57 | self.db.struct_datum(self.krate, struct_id) | 57 | self.db.struct_datum(self.krate, struct_id) |
58 | } | 58 | } |
59 | fn adt_repr(&self, _struct_id: AdtId) -> rust_ir::AdtRepr { | 59 | fn adt_repr(&self, _struct_id: AdtId) -> Arc<rust_ir::AdtRepr<Interner>> { |
60 | rust_ir::AdtRepr { repr_c: false, repr_packed: false } | 60 | // FIXME: keep track of these |
61 | Arc::new(rust_ir::AdtRepr { c: false, packed: false, int: None }) | ||
62 | } | ||
63 | fn discriminant_type(&self, _ty: chalk_ir::Ty<Interner>) -> chalk_ir::Ty<Interner> { | ||
64 | // FIXME: keep track of this | ||
65 | chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(&Interner) | ||
61 | } | 66 | } |
62 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { | 67 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { |
63 | self.db.impl_datum(self.krate, impl_id) | 68 | self.db.impl_datum(self.krate, impl_id) |
@@ -457,6 +462,7 @@ fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> { | |||
457 | "fn" => WellKnownTrait::Fn, | 462 | "fn" => WellKnownTrait::Fn, |
458 | "unsize" => WellKnownTrait::Unsize, | 463 | "unsize" => WellKnownTrait::Unsize, |
459 | "coerce_unsized" => WellKnownTrait::CoerceUnsized, | 464 | "coerce_unsized" => WellKnownTrait::CoerceUnsized, |
465 | "discriminant_kind" => WellKnownTrait::DiscriminantKind, | ||
460 | _ => return None, | 466 | _ => return None, |
461 | }) | 467 | }) |
462 | } | 468 | } |
@@ -473,6 +479,7 @@ fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str { | |||
473 | WellKnownTrait::Unsize => "unsize", | 479 | WellKnownTrait::Unsize => "unsize", |
474 | WellKnownTrait::Unpin => "unpin", | 480 | WellKnownTrait::Unpin => "unpin", |
475 | WellKnownTrait::CoerceUnsized => "coerce_unsized", | 481 | WellKnownTrait::CoerceUnsized => "coerce_unsized", |
482 | WellKnownTrait::DiscriminantKind => "discriminant_kind", | ||
476 | } | 483 | } |
477 | } | 484 | } |
478 | 485 | ||
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index e897d5a52..c7a3556a7 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs | |||
@@ -46,6 +46,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = | |||
46 | T![continue], | 46 | T![continue], |
47 | T![async], | 47 | T![async], |
48 | T![try], | 48 | T![try], |
49 | T![const], | ||
49 | T![loop], | 50 | T![loop], |
50 | T![for], | 51 | T![for], |
51 | LIFETIME_IDENT, | 52 | LIFETIME_IDENT, |
@@ -115,6 +116,14 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar | |||
115 | block_expr(p); | 116 | block_expr(p); |
116 | m.complete(p, EFFECT_EXPR) | 117 | m.complete(p, EFFECT_EXPR) |
117 | } | 118 | } |
119 | // test const_block | ||
120 | // fn f() { const { } } | ||
121 | T![const] if la == T!['{'] => { | ||
122 | let m = p.start(); | ||
123 | p.bump(T![const]); | ||
124 | block_expr(p); | ||
125 | m.complete(p, EFFECT_EXPR) | ||
126 | } | ||
118 | T!['{'] => { | 127 | T!['{'] => { |
119 | // test for_range_from | 128 | // test for_range_from |
120 | // fn foo() { | 129 | // fn foo() { |
diff --git a/crates/parser/src/grammar/items.rs b/crates/parser/src/grammar/items.rs index 8999829b4..72b73f891 100644 --- a/crates/parser/src/grammar/items.rs +++ b/crates/parser/src/grammar/items.rs | |||
@@ -96,7 +96,10 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> { | |||
96 | let mut has_mods = false; | 96 | let mut has_mods = false; |
97 | 97 | ||
98 | // modifiers | 98 | // modifiers |
99 | has_mods |= p.eat(T![const]); | 99 | if p.at(T![const]) && p.nth(1) != T!['{'] { |
100 | p.eat(T![const]); | ||
101 | has_mods = true; | ||
102 | } | ||
100 | 103 | ||
101 | // test_err async_without_semicolon | 104 | // test_err async_without_semicolon |
102 | // fn foo() { let _ = async {} } | 105 | // fn foo() { let _ = async {} } |
@@ -167,7 +170,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker) -> Result<(), Marker> { | |||
167 | m.complete(p, TRAIT); | 170 | m.complete(p, TRAIT); |
168 | } | 171 | } |
169 | 172 | ||
170 | T![const] => { | 173 | T![const] if p.nth(1) != T!['{'] => { |
171 | consts::konst(p, m); | 174 | consts::konst(p, m); |
172 | } | 175 | } |
173 | 176 | ||
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs index 7e7f73dee..b53d5749f 100644 --- a/crates/parser/src/grammar/patterns.rs +++ b/crates/parser/src/grammar/patterns.rs | |||
@@ -89,6 +89,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | |||
89 | let m = match p.nth(0) { | 89 | let m = match p.nth(0) { |
90 | T![box] => box_pat(p), | 90 | T![box] => box_pat(p), |
91 | T![ref] | T![mut] => ident_pat(p, true), | 91 | T![ref] | T![mut] => ident_pat(p, true), |
92 | T![const] => const_block_pat(p), | ||
92 | IDENT => match p.nth(1) { | 93 | IDENT => match p.nth(1) { |
93 | // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro | 94 | // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro |
94 | // (T![x]). | 95 | // (T![x]). |
@@ -386,3 +387,16 @@ fn box_pat(p: &mut Parser) -> CompletedMarker { | |||
386 | pattern_single(p); | 387 | pattern_single(p); |
387 | m.complete(p, BOX_PAT) | 388 | m.complete(p, BOX_PAT) |
388 | } | 389 | } |
390 | |||
391 | // test const_block_pat | ||
392 | // fn main() { | ||
393 | // let const { 15 } = (); | ||
394 | // let const { foo(); bar() } = (); | ||
395 | // } | ||
396 | fn const_block_pat(p: &mut Parser) -> CompletedMarker { | ||
397 | assert!(p.at(T![const])); | ||
398 | let m = p.start(); | ||
399 | p.bump(T![const]); | ||
400 | expressions::block_expr(p); | ||
401 | m.complete(p, CONST_BLOCK_PAT) | ||
402 | } | ||
diff --git a/crates/parser/src/syntax_kind/generated.rs b/crates/parser/src/syntax_kind/generated.rs index 980aa5979..f69e71bdb 100644 --- a/crates/parser/src/syntax_kind/generated.rs +++ b/crates/parser/src/syntax_kind/generated.rs | |||
@@ -170,6 +170,7 @@ pub enum SyntaxKind { | |||
170 | RANGE_PAT, | 170 | RANGE_PAT, |
171 | LITERAL_PAT, | 171 | LITERAL_PAT, |
172 | MACRO_PAT, | 172 | MACRO_PAT, |
173 | CONST_BLOCK_PAT, | ||
173 | TUPLE_EXPR, | 174 | TUPLE_EXPR, |
174 | ARRAY_EXPR, | 175 | ARRAY_EXPR, |
175 | PAREN_EXPR, | 176 | PAREN_EXPR, |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 66f8bee99..55bc2bcec 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -5,11 +5,13 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | io::Write as _, | 6 | io::Write as _, |
7 | process::{self, Stdio}, | 7 | process::{self, Stdio}, |
8 | sync::Arc, | ||
8 | }; | 9 | }; |
9 | 10 | ||
10 | use ide::{ | 11 | use ide::{ |
11 | CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, | 12 | AssistConfig, CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, |
12 | NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit, | 13 | HoverGotoTypeData, LineIndex, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, |
14 | SearchScope, SymbolKind, TextEdit, | ||
13 | }; | 15 | }; |
14 | use itertools::Itertools; | 16 | use itertools::Itertools; |
15 | use lsp_server::ErrorCode; | 17 | use lsp_server::ErrorCode; |
@@ -865,58 +867,8 @@ pub(crate) fn handle_formatting( | |||
865 | } | 867 | } |
866 | } | 868 | } |
867 | 869 | ||
868 | fn handle_fixes( | ||
869 | snap: &GlobalStateSnapshot, | ||
870 | params: &lsp_types::CodeActionParams, | ||
871 | res: &mut Vec<lsp_ext::CodeAction>, | ||
872 | ) -> Result<()> { | ||
873 | let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; | ||
874 | let line_index = snap.analysis.file_line_index(file_id)?; | ||
875 | let range = from_proto::text_range(&line_index, params.range); | ||
876 | |||
877 | match ¶ms.context.only { | ||
878 | Some(v) => { | ||
879 | if !v.iter().any(|it| { | ||
880 | it == &lsp_types::CodeActionKind::EMPTY | ||
881 | || it == &lsp_types::CodeActionKind::QUICKFIX | ||
882 | }) { | ||
883 | return Ok(()); | ||
884 | } | ||
885 | } | ||
886 | None => {} | ||
887 | }; | ||
888 | |||
889 | let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, file_id)?; | ||
890 | |||
891 | for fix in diagnostics | ||
892 | .into_iter() | ||
893 | .filter_map(|d| d.fix) | ||
894 | .filter(|fix| fix.fix_trigger_range.intersect(range).is_some()) | ||
895 | { | ||
896 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; | ||
897 | let action = lsp_ext::CodeAction { | ||
898 | title: fix.label.to_string(), | ||
899 | group: None, | ||
900 | kind: Some(CodeActionKind::QUICKFIX), | ||
901 | edit: Some(edit), | ||
902 | is_preferred: Some(false), | ||
903 | data: None, | ||
904 | }; | ||
905 | res.push(action); | ||
906 | } | ||
907 | |||
908 | for fix in snap.check_fixes.get(&file_id).into_iter().flatten() { | ||
909 | let fix_range = from_proto::text_range(&line_index, fix.range); | ||
910 | if fix_range.intersect(range).is_none() { | ||
911 | continue; | ||
912 | } | ||
913 | res.push(fix.action.clone()); | ||
914 | } | ||
915 | Ok(()) | ||
916 | } | ||
917 | |||
918 | pub(crate) fn handle_code_action( | 870 | pub(crate) fn handle_code_action( |
919 | mut snap: GlobalStateSnapshot, | 871 | snap: GlobalStateSnapshot, |
920 | params: lsp_types::CodeActionParams, | 872 | params: lsp_types::CodeActionParams, |
921 | ) -> Result<Option<Vec<lsp_ext::CodeAction>>> { | 873 | ) -> Result<Option<Vec<lsp_ext::CodeAction>>> { |
922 | let _p = profile::span("handle_code_action"); | 874 | let _p = profile::span("handle_code_action"); |
@@ -932,24 +884,35 @@ pub(crate) fn handle_code_action( | |||
932 | let range = from_proto::text_range(&line_index, params.range); | 884 | let range = from_proto::text_range(&line_index, params.range); |
933 | let frange = FileRange { file_id, range }; | 885 | let frange = FileRange { file_id, range }; |
934 | 886 | ||
935 | snap.config.assist.allowed = params | 887 | let assists_config = AssistConfig { |
936 | .clone() | 888 | allowed: params |
937 | .context | 889 | .clone() |
938 | .only | 890 | .context |
939 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()); | 891 | .only |
892 | .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect()), | ||
893 | ..snap.config.assist | ||
894 | }; | ||
940 | 895 | ||
941 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); | 896 | let mut res: Vec<lsp_ext::CodeAction> = Vec::new(); |
942 | 897 | ||
943 | handle_fixes(&snap, ¶ms, &mut res)?; | 898 | let include_quick_fixes = match ¶ms.context.only { |
899 | Some(v) => v.iter().any(|it| { | ||
900 | it == &lsp_types::CodeActionKind::EMPTY || it == &lsp_types::CodeActionKind::QUICKFIX | ||
901 | }), | ||
902 | None => true, | ||
903 | }; | ||
904 | if include_quick_fixes { | ||
905 | add_quick_fixes(&snap, frange, &line_index, &mut res)?; | ||
906 | } | ||
944 | 907 | ||
945 | if snap.config.client_caps.code_action_resolve { | 908 | if snap.config.client_caps.code_action_resolve { |
946 | for (index, assist) in | 909 | for (index, assist) in |
947 | snap.analysis.unresolved_assists(&snap.config.assist, frange)?.into_iter().enumerate() | 910 | snap.analysis.unresolved_assists(&assists_config, frange)?.into_iter().enumerate() |
948 | { | 911 | { |
949 | res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?); | 912 | res.push(to_proto::unresolved_code_action(&snap, params.clone(), assist, index)?); |
950 | } | 913 | } |
951 | } else { | 914 | } else { |
952 | for assist in snap.analysis.resolved_assists(&snap.config.assist, frange)?.into_iter() { | 915 | for assist in snap.analysis.resolved_assists(&assists_config, frange)?.into_iter() { |
953 | res.push(to_proto::resolved_code_action(&snap, assist)?); | 916 | res.push(to_proto::resolved_code_action(&snap, assist)?); |
954 | } | 917 | } |
955 | } | 918 | } |
@@ -957,6 +920,40 @@ pub(crate) fn handle_code_action( | |||
957 | Ok(Some(res)) | 920 | Ok(Some(res)) |
958 | } | 921 | } |
959 | 922 | ||
923 | fn add_quick_fixes( | ||
924 | snap: &GlobalStateSnapshot, | ||
925 | frange: FileRange, | ||
926 | line_index: &Arc<LineIndex>, | ||
927 | acc: &mut Vec<lsp_ext::CodeAction>, | ||
928 | ) -> Result<()> { | ||
929 | let diagnostics = snap.analysis.diagnostics(&snap.config.diagnostics, frange.file_id)?; | ||
930 | |||
931 | for fix in diagnostics | ||
932 | .into_iter() | ||
933 | .filter_map(|d| d.fix) | ||
934 | .filter(|fix| fix.fix_trigger_range.intersect(frange.range).is_some()) | ||
935 | { | ||
936 | let edit = to_proto::snippet_workspace_edit(&snap, fix.source_change)?; | ||
937 | let action = lsp_ext::CodeAction { | ||
938 | title: fix.label.to_string(), | ||
939 | group: None, | ||
940 | kind: Some(CodeActionKind::QUICKFIX), | ||
941 | edit: Some(edit), | ||
942 | is_preferred: Some(false), | ||
943 | data: None, | ||
944 | }; | ||
945 | acc.push(action); | ||
946 | } | ||
947 | |||
948 | for fix in snap.check_fixes.get(&frange.file_id).into_iter().flatten() { | ||
949 | let fix_range = from_proto::text_range(&line_index, fix.range); | ||
950 | if fix_range.intersect(frange.range).is_some() { | ||
951 | acc.push(fix.action.clone()); | ||
952 | } | ||
953 | } | ||
954 | Ok(()) | ||
955 | } | ||
956 | |||
960 | pub(crate) fn handle_code_action_resolve( | 957 | pub(crate) fn handle_code_action_resolve( |
961 | mut snap: GlobalStateSnapshot, | 958 | mut snap: GlobalStateSnapshot, |
962 | mut code_action: lsp_ext::CodeAction, | 959 | mut code_action: lsp_ext::CodeAction, |
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml index c6a6f11e1..21015591c 100644 --- a/crates/syntax/Cargo.toml +++ b/crates/syntax/Cargo.toml | |||
@@ -13,7 +13,7 @@ doctest = false | |||
13 | [dependencies] | 13 | [dependencies] |
14 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
15 | rowan = "0.10.0" | 15 | rowan = "0.10.0" |
16 | rustc_lexer = { version = "691.0.0", package = "rustc-ap-rustc_lexer" } | 16 | rustc_lexer = { version = "695.0.0", package = "rustc-ap-rustc_lexer" } |
17 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
18 | arrayvec = "0.5.1" | 18 | arrayvec = "0.5.1" |
19 | once_cell = "1.3.1" | 19 | once_cell = "1.3.1" |
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 1588ba93e..c5b80bffe 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs | |||
@@ -763,6 +763,7 @@ impl EffectExpr { | |||
763 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | 763 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } |
764 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | 764 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } |
765 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | 765 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } |
766 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
766 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | 767 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } |
767 | } | 768 | } |
768 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 769 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -1251,6 +1252,14 @@ impl TupleStructPat { | |||
1251 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | 1252 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } |
1252 | } | 1253 | } |
1253 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1254 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1255 | pub struct ConstBlockPat { | ||
1256 | pub(crate) syntax: SyntaxNode, | ||
1257 | } | ||
1258 | impl ConstBlockPat { | ||
1259 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
1260 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
1261 | } | ||
1262 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1254 | pub struct RecordPatFieldList { | 1263 | pub struct RecordPatFieldList { |
1255 | pub(crate) syntax: SyntaxNode, | 1264 | pub(crate) syntax: SyntaxNode, |
1256 | } | 1265 | } |
@@ -1369,6 +1378,7 @@ pub enum Pat { | |||
1369 | SlicePat(SlicePat), | 1378 | SlicePat(SlicePat), |
1370 | TuplePat(TuplePat), | 1379 | TuplePat(TuplePat), |
1371 | TupleStructPat(TupleStructPat), | 1380 | TupleStructPat(TupleStructPat), |
1381 | ConstBlockPat(ConstBlockPat), | ||
1372 | } | 1382 | } |
1373 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1383 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
1374 | pub enum FieldList { | 1384 | pub enum FieldList { |
@@ -2772,6 +2782,17 @@ impl AstNode for TupleStructPat { | |||
2772 | } | 2782 | } |
2773 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2783 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2774 | } | 2784 | } |
2785 | impl AstNode for ConstBlockPat { | ||
2786 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT } | ||
2787 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
2788 | if Self::can_cast(syntax.kind()) { | ||
2789 | Some(Self { syntax }) | ||
2790 | } else { | ||
2791 | None | ||
2792 | } | ||
2793 | } | ||
2794 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
2795 | } | ||
2775 | impl AstNode for RecordPatFieldList { | 2796 | impl AstNode for RecordPatFieldList { |
2776 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST } | 2797 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST } |
2777 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2798 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -3242,12 +3263,15 @@ impl From<TuplePat> for Pat { | |||
3242 | impl From<TupleStructPat> for Pat { | 3263 | impl From<TupleStructPat> for Pat { |
3243 | fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) } | 3264 | fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) } |
3244 | } | 3265 | } |
3266 | impl From<ConstBlockPat> for Pat { | ||
3267 | fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) } | ||
3268 | } | ||
3245 | impl AstNode for Pat { | 3269 | impl AstNode for Pat { |
3246 | fn can_cast(kind: SyntaxKind) -> bool { | 3270 | fn can_cast(kind: SyntaxKind) -> bool { |
3247 | match kind { | 3271 | match kind { |
3248 | IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT | 3272 | IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT |
3249 | | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT | 3273 | | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT |
3250 | | TUPLE_PAT | TUPLE_STRUCT_PAT => true, | 3274 | | TUPLE_PAT | TUPLE_STRUCT_PAT | CONST_BLOCK_PAT => true, |
3251 | _ => false, | 3275 | _ => false, |
3252 | } | 3276 | } |
3253 | } | 3277 | } |
@@ -3268,6 +3292,7 @@ impl AstNode for Pat { | |||
3268 | SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), | 3292 | SLICE_PAT => Pat::SlicePat(SlicePat { syntax }), |
3269 | TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }), | 3293 | TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }), |
3270 | TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }), | 3294 | TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }), |
3295 | CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }), | ||
3271 | _ => return None, | 3296 | _ => return None, |
3272 | }; | 3297 | }; |
3273 | Some(res) | 3298 | Some(res) |
@@ -3289,6 +3314,7 @@ impl AstNode for Pat { | |||
3289 | Pat::SlicePat(it) => &it.syntax, | 3314 | Pat::SlicePat(it) => &it.syntax, |
3290 | Pat::TuplePat(it) => &it.syntax, | 3315 | Pat::TuplePat(it) => &it.syntax, |
3291 | Pat::TupleStructPat(it) => &it.syntax, | 3316 | Pat::TupleStructPat(it) => &it.syntax, |
3317 | Pat::ConstBlockPat(it) => &it.syntax, | ||
3292 | } | 3318 | } |
3293 | } | 3319 | } |
3294 | } | 3320 | } |
@@ -4137,6 +4163,11 @@ impl std::fmt::Display for TupleStructPat { | |||
4137 | std::fmt::Display::fmt(self.syntax(), f) | 4163 | std::fmt::Display::fmt(self.syntax(), f) |
4138 | } | 4164 | } |
4139 | } | 4165 | } |
4166 | impl std::fmt::Display for ConstBlockPat { | ||
4167 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
4168 | std::fmt::Display::fmt(self.syntax(), f) | ||
4169 | } | ||
4170 | } | ||
4140 | impl std::fmt::Display for RecordPatFieldList { | 4171 | impl std::fmt::Display for RecordPatFieldList { |
4141 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 4172 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
4142 | std::fmt::Display::fmt(self.syntax(), f) | 4173 | std::fmt::Display::fmt(self.syntax(), f) |
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs index ba7e5d2fb..cafa4c198 100644 --- a/crates/syntax/src/ast/make.rs +++ b/crates/syntax/src/ast/make.rs | |||
@@ -4,6 +4,11 @@ | |||
4 | //! Note that all functions here intended to be stupid constructors, which just | 4 | //! Note that all functions here intended to be stupid constructors, which just |
5 | //! assemble a finish node from immediate children. If you want to do something | 5 | //! assemble a finish node from immediate children. If you want to do something |
6 | //! smarter than that, it probably doesn't belong in this module. | 6 | //! smarter than that, it probably doesn't belong in this module. |
7 | //! | ||
8 | //! Keep in mind that `from_text` functions should be kept private. The public | ||
9 | //! API should require to assemble every node piecewise. The trick of | ||
10 | //! `parse(format!())` we use internally is an implementation detail -- long | ||
11 | //! term, it will be replaced with direct tree manipulation. | ||
7 | use itertools::Itertools; | 12 | use itertools::Itertools; |
8 | use stdx::format_to; | 13 | use stdx::format_to; |
9 | 14 | ||
@@ -16,7 +21,8 @@ pub fn name(text: &str) -> ast::Name { | |||
16 | pub fn name_ref(text: &str) -> ast::NameRef { | 21 | pub fn name_ref(text: &str) -> ast::NameRef { |
17 | ast_from_text(&format!("fn f() {{ {}; }}", text)) | 22 | ast_from_text(&format!("fn f() {{ {}; }}", text)) |
18 | } | 23 | } |
19 | 24 | // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la | |
25 | // `expr_xxx`. | ||
20 | pub fn ty(text: &str) -> ast::Type { | 26 | pub fn ty(text: &str) -> ast::Type { |
21 | ast_from_text(&format!("impl {} for D {{}};", text)) | 27 | ast_from_text(&format!("impl {} for D {{}};", text)) |
22 | } | 28 | } |
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast new file mode 100644 index 000000000..8ff4822c4 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rast | |||
@@ -0,0 +1,76 @@ | |||
1 | SOURCE_FILE@0..78 | ||
2 | FN@0..77 | ||
3 | FN_KW@0..2 "fn" | ||
4 | WHITESPACE@2..3 " " | ||
5 | NAME@3..7 | ||
6 | IDENT@3..7 "main" | ||
7 | PARAM_LIST@7..9 | ||
8 | L_PAREN@7..8 "(" | ||
9 | R_PAREN@8..9 ")" | ||
10 | WHITESPACE@9..10 " " | ||
11 | BLOCK_EXPR@10..77 | ||
12 | L_CURLY@10..11 "{" | ||
13 | WHITESPACE@11..16 "\n " | ||
14 | LET_STMT@16..38 | ||
15 | LET_KW@16..19 "let" | ||
16 | WHITESPACE@19..20 " " | ||
17 | CONST_BLOCK_PAT@20..32 | ||
18 | CONST_KW@20..25 "const" | ||
19 | WHITESPACE@25..26 " " | ||
20 | BLOCK_EXPR@26..32 | ||
21 | L_CURLY@26..27 "{" | ||
22 | WHITESPACE@27..28 " " | ||
23 | LITERAL@28..30 | ||
24 | INT_NUMBER@28..30 "15" | ||
25 | WHITESPACE@30..31 " " | ||
26 | R_CURLY@31..32 "}" | ||
27 | WHITESPACE@32..33 " " | ||
28 | EQ@33..34 "=" | ||
29 | WHITESPACE@34..35 " " | ||
30 | TUPLE_EXPR@35..37 | ||
31 | L_PAREN@35..36 "(" | ||
32 | R_PAREN@36..37 ")" | ||
33 | SEMICOLON@37..38 ";" | ||
34 | WHITESPACE@38..43 "\n " | ||
35 | LET_STMT@43..75 | ||
36 | LET_KW@43..46 "let" | ||
37 | WHITESPACE@46..47 " " | ||
38 | CONST_BLOCK_PAT@47..69 | ||
39 | CONST_KW@47..52 "const" | ||
40 | WHITESPACE@52..53 " " | ||
41 | BLOCK_EXPR@53..69 | ||
42 | L_CURLY@53..54 "{" | ||
43 | WHITESPACE@54..55 " " | ||
44 | EXPR_STMT@55..61 | ||
45 | CALL_EXPR@55..60 | ||
46 | PATH_EXPR@55..58 | ||
47 | PATH@55..58 | ||
48 | PATH_SEGMENT@55..58 | ||
49 | NAME_REF@55..58 | ||
50 | IDENT@55..58 "foo" | ||
51 | ARG_LIST@58..60 | ||
52 | L_PAREN@58..59 "(" | ||
53 | R_PAREN@59..60 ")" | ||
54 | SEMICOLON@60..61 ";" | ||
55 | WHITESPACE@61..62 " " | ||
56 | CALL_EXPR@62..67 | ||
57 | PATH_EXPR@62..65 | ||
58 | PATH@62..65 | ||
59 | PATH_SEGMENT@62..65 | ||
60 | NAME_REF@62..65 | ||
61 | IDENT@62..65 "bar" | ||
62 | ARG_LIST@65..67 | ||
63 | L_PAREN@65..66 "(" | ||
64 | R_PAREN@66..67 ")" | ||
65 | WHITESPACE@67..68 " " | ||
66 | R_CURLY@68..69 "}" | ||
67 | WHITESPACE@69..70 " " | ||
68 | EQ@70..71 "=" | ||
69 | WHITESPACE@71..72 " " | ||
70 | TUPLE_EXPR@72..74 | ||
71 | L_PAREN@72..73 "(" | ||
72 | R_PAREN@73..74 ")" | ||
73 | SEMICOLON@74..75 ";" | ||
74 | WHITESPACE@75..76 "\n" | ||
75 | R_CURLY@76..77 "}" | ||
76 | WHITESPACE@77..78 "\n" | ||
diff --git a/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs new file mode 100644 index 000000000..dce9defac --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0156_const_block_pat.rs | |||
@@ -0,0 +1,4 @@ | |||
1 | fn main() { | ||
2 | let const { 15 } = (); | ||
3 | let const { foo(); bar() } = (); | ||
4 | } | ||
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast new file mode 100644 index 000000000..d5d2c8fe3 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rast | |||
@@ -0,0 +1,23 @@ | |||
1 | SOURCE_FILE@0..21 | ||
2 | FN@0..20 | ||
3 | FN_KW@0..2 "fn" | ||
4 | WHITESPACE@2..3 " " | ||
5 | NAME@3..4 | ||
6 | IDENT@3..4 "f" | ||
7 | PARAM_LIST@4..6 | ||
8 | L_PAREN@4..5 "(" | ||
9 | R_PAREN@5..6 ")" | ||
10 | WHITESPACE@6..7 " " | ||
11 | BLOCK_EXPR@7..20 | ||
12 | L_CURLY@7..8 "{" | ||
13 | WHITESPACE@8..9 " " | ||
14 | EFFECT_EXPR@9..18 | ||
15 | CONST_KW@9..14 "const" | ||
16 | WHITESPACE@14..15 " " | ||
17 | BLOCK_EXPR@15..18 | ||
18 | L_CURLY@15..16 "{" | ||
19 | WHITESPACE@16..17 " " | ||
20 | R_CURLY@17..18 "}" | ||
21 | WHITESPACE@18..19 " " | ||
22 | R_CURLY@19..20 "}" | ||
23 | WHITESPACE@20..21 "\n" | ||
diff --git a/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs new file mode 100644 index 000000000..a2e3565a3 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0157_const_block.rs | |||
@@ -0,0 +1 @@ | |||
fn f() { const { } } | |||
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 78a0b54ba..96b4ea448 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -15,7 +15,7 @@ flate2 = "1.0" | |||
15 | pico-args = "0.3.1" | 15 | pico-args = "0.3.1" |
16 | proc-macro2 = "1.0.8" | 16 | proc-macro2 = "1.0.8" |
17 | quote = "1.0.2" | 17 | quote = "1.0.2" |
18 | ungrammar = "1.4" | 18 | ungrammar = "1.5" |
19 | walkdir = "2.3.1" | 19 | walkdir = "2.3.1" |
20 | write-json = "0.1.0" | 20 | write-json = "0.1.0" |
21 | xshell = "0.1" | 21 | xshell = "0.1" |
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index a69ced5cc..2b8012bdd 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -132,6 +132,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
132 | "RANGE_PAT", | 132 | "RANGE_PAT", |
133 | "LITERAL_PAT", | 133 | "LITERAL_PAT", |
134 | "MACRO_PAT", | 134 | "MACRO_PAT", |
135 | "CONST_BLOCK_PAT", | ||
135 | // atoms | 136 | // atoms |
136 | "TUPLE_EXPR", | 137 | "TUPLE_EXPR", |
137 | "ARRAY_EXPR", | 138 | "ARRAY_EXPR", |