aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/generate_function.rs132
-rw-r--r--crates/assists/src/tests/generated.rs4
-rw-r--r--crates/base_db/src/input.rs28
-rw-r--r--crates/hir/src/code_model.rs6
-rw-r--r--crates/hir_def/src/body/lower.rs5
-rw-r--r--crates/ide/src/inlay_hints.rs81
-rw-r--r--crates/ide/src/lib.rs8
-rw-r--r--crates/ide/src/prime_caches.rs43
-rw-r--r--crates/ide/src/syntax_highlighting.rs118
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html6
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs42
-rw-r--r--crates/rust-analyzer/src/thread_pool.rs11
-rw-r--r--crates/syntax/src/ast/make.rs12
-rw-r--r--editors/code/rust.tmGrammar.json1725
16 files changed, 1424 insertions, 803 deletions
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs
index b38d64058..d23f4293b 100644
--- a/crates/assists/src/handlers/generate_function.rs
+++ b/crates/assists/src/handlers/generate_function.rs
@@ -36,8 +36,8 @@ use crate::{
36// bar("", baz()); 36// bar("", baz());
37// } 37// }
38// 38//
39// fn bar(arg: &str, baz: Baz) { 39// fn bar(arg: &str, baz: Baz) ${0:-> ()} {
40// ${0:todo!()} 40// todo!()
41// } 41// }
42// 42//
43// ``` 43// ```
@@ -80,9 +80,9 @@ pub(crate) fn generate_function(acc: &mut Assists, ctx: &AssistContext) -> Optio
80 80
81struct FunctionTemplate { 81struct FunctionTemplate {
82 insert_offset: TextSize, 82 insert_offset: TextSize,
83 placeholder_expr: ast::MacroCall,
84 leading_ws: String, 83 leading_ws: String,
85 fn_def: ast::Fn, 84 fn_def: ast::Fn,
85 ret_type: ast::RetType,
86 trailing_ws: String, 86 trailing_ws: String,
87 file: FileId, 87 file: FileId,
88} 88}
@@ -90,11 +90,9 @@ struct FunctionTemplate {
90impl FunctionTemplate { 90impl FunctionTemplate {
91 fn to_string(&self, cap: Option<SnippetCap>) -> String { 91 fn to_string(&self, cap: Option<SnippetCap>) -> String {
92 let f = match cap { 92 let f = match cap {
93 Some(cap) => render_snippet( 93 Some(cap) => {
94 cap, 94 render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(self.ret_type.syntax()))
95 self.fn_def.syntax(), 95 }
96 Cursor::Replace(self.placeholder_expr.syntax()),
97 ),
98 None => self.fn_def.to_string(), 96 None => self.fn_def.to_string(),
99 }; 97 };
100 format!("{}{}{}", self.leading_ws, f, self.trailing_ws) 98 format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
@@ -141,8 +139,14 @@ impl FunctionBuilder {
141 let placeholder_expr = make::expr_todo(); 139 let placeholder_expr = make::expr_todo();
142 let fn_body = make::block_expr(vec![], Some(placeholder_expr)); 140 let fn_body = make::block_expr(vec![], Some(placeholder_expr));
143 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None }; 141 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
144 let mut fn_def = 142 let mut fn_def = make::fn_(
145 make::fn_(visibility, self.fn_name, self.type_params, self.params, fn_body); 143 visibility,
144 self.fn_name,
145 self.type_params,
146 self.params,
147 fn_body,
148 Some(make::ret_type(make::ty("()"))),
149 );
146 let leading_ws; 150 let leading_ws;
147 let trailing_ws; 151 let trailing_ws;
148 152
@@ -163,12 +167,10 @@ impl FunctionBuilder {
163 } 167 }
164 }; 168 };
165 169
166 let placeholder_expr =
167 fn_def.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
168 FunctionTemplate { 170 FunctionTemplate {
169 insert_offset, 171 insert_offset,
170 placeholder_expr,
171 leading_ws, 172 leading_ws,
173 ret_type: fn_def.ret_type().unwrap(),
172 fn_def, 174 fn_def,
173 trailing_ws, 175 trailing_ws,
174 file: self.file, 176 file: self.file,
@@ -349,8 +351,8 @@ fn foo() {
349 bar(); 351 bar();
350} 352}
351 353
352fn bar() { 354fn bar() ${0:-> ()} {
353 ${0:todo!()} 355 todo!()
354} 356}
355", 357",
356 ) 358 )
@@ -376,8 +378,8 @@ impl Foo {
376 } 378 }
377} 379}
378 380
379fn bar() { 381fn bar() ${0:-> ()} {
380 ${0:todo!()} 382 todo!()
381} 383}
382", 384",
383 ) 385 )
@@ -400,8 +402,8 @@ fn foo1() {
400 bar(); 402 bar();
401} 403}
402 404
403fn bar() { 405fn bar() ${0:-> ()} {
404 ${0:todo!()} 406 todo!()
405} 407}
406 408
407fn foo2() {} 409fn foo2() {}
@@ -426,8 +428,8 @@ mod baz {
426 bar(); 428 bar();
427 } 429 }
428 430
429 fn bar() { 431 fn bar() ${0:-> ()} {
430 ${0:todo!()} 432 todo!()
431 } 433 }
432} 434}
433", 435",
@@ -452,8 +454,8 @@ fn foo() {
452 bar(baz()); 454 bar(baz());
453} 455}
454 456
455fn bar(baz: Baz) { 457fn bar(baz: Baz) ${0:-> ()} {
456 ${0:todo!()} 458 todo!()
457} 459}
458", 460",
459 ); 461 );
@@ -485,8 +487,8 @@ impl Baz {
485 } 487 }
486} 488}
487 489
488fn bar(baz: Baz) { 490fn bar(baz: Baz) ${0:-> ()} {
489 ${0:todo!()} 491 todo!()
490} 492}
491", 493",
492 ) 494 )
@@ -506,8 +508,8 @@ fn foo() {
506 bar("bar") 508 bar("bar")
507} 509}
508 510
509fn bar(arg: &str) { 511fn bar(arg: &str) ${0:-> ()} {
510 ${0:todo!()} 512 todo!()
511} 513}
512"#, 514"#,
513 ) 515 )
@@ -527,8 +529,8 @@ fn foo() {
527 bar('x') 529 bar('x')
528} 530}
529 531
530fn bar(arg: char) { 532fn bar(arg: char) ${0:-> ()} {
531 ${0:todo!()} 533 todo!()
532} 534}
533"#, 535"#,
534 ) 536 )
@@ -548,8 +550,8 @@ fn foo() {
548 bar(42) 550 bar(42)
549} 551}
550 552
551fn bar(arg: i32) { 553fn bar(arg: i32) ${0:-> ()} {
552 ${0:todo!()} 554 todo!()
553} 555}
554", 556",
555 ) 557 )
@@ -569,8 +571,8 @@ fn foo() {
569 bar(42 as u8) 571 bar(42 as u8)
570} 572}
571 573
572fn bar(arg: u8) { 574fn bar(arg: u8) ${0:-> ()} {
573 ${0:todo!()} 575 todo!()
574} 576}
575", 577",
576 ) 578 )
@@ -594,8 +596,8 @@ fn foo() {
594 bar(x as u8) 596 bar(x as u8)
595} 597}
596 598
597fn bar(x: u8) { 599fn bar(x: u8) ${0:-> ()} {
598 ${0:todo!()} 600 todo!()
599} 601}
600", 602",
601 ) 603 )
@@ -617,8 +619,8 @@ fn foo() {
617 bar(worble) 619 bar(worble)
618} 620}
619 621
620fn bar(worble: ()) { 622fn bar(worble: ()) ${0:-> ()} {
621 ${0:todo!()} 623 todo!()
622} 624}
623", 625",
624 ) 626 )
@@ -646,8 +648,8 @@ fn baz() {
646 bar(foo()) 648 bar(foo())
647} 649}
648 650
649fn bar(foo: impl Foo) { 651fn bar(foo: impl Foo) ${0:-> ()} {
650 ${0:todo!()} 652 todo!()
651} 653}
652", 654",
653 ) 655 )
@@ -673,8 +675,8 @@ fn foo() {
673 bar(&baz()) 675 bar(&baz())
674} 676}
675 677
676fn bar(baz: &Baz) { 678fn bar(baz: &Baz) ${0:-> ()} {
677 ${0:todo!()} 679 todo!()
678} 680}
679", 681",
680 ) 682 )
@@ -702,8 +704,8 @@ fn foo() {
702 bar(Baz::baz()) 704 bar(Baz::baz())
703} 705}
704 706
705fn bar(baz: Baz::Bof) { 707fn bar(baz: Baz::Bof) ${0:-> ()} {
706 ${0:todo!()} 708 todo!()
707} 709}
708", 710",
709 ) 711 )
@@ -725,8 +727,8 @@ fn foo<T>(t: T) {
725 bar(t) 727 bar(t)
726} 728}
727 729
728fn bar<T>(t: T) { 730fn bar<T>(t: T) ${0:-> ()} {
729 ${0:todo!()} 731 todo!()
730} 732}
731", 733",
732 ) 734 )
@@ -756,8 +758,8 @@ fn foo() {
756 bar(Baz::new); 758 bar(Baz::new);
757} 759}
758 760
759fn bar(arg: fn() -> Baz) { 761fn bar(arg: fn() -> Baz) ${0:-> ()} {
760 ${0:todo!()} 762 todo!()
761} 763}
762", 764",
763 ) 765 )
@@ -781,8 +783,8 @@ fn foo() {
781 bar(closure) 783 bar(closure)
782} 784}
783 785
784fn bar(closure: impl Fn(i64) -> i64) { 786fn bar(closure: impl Fn(i64) -> i64) ${0:-> ()} {
785 ${0:todo!()} 787 todo!()
786} 788}
787", 789",
788 ) 790 )
@@ -802,8 +804,8 @@ fn foo() {
802 bar(baz) 804 bar(baz)
803} 805}
804 806
805fn bar(baz: ()) { 807fn bar(baz: ()) ${0:-> ()} {
806 ${0:todo!()} 808 todo!()
807} 809}
808", 810",
809 ) 811 )
@@ -827,8 +829,8 @@ fn foo() {
827 bar(baz(), baz()) 829 bar(baz(), baz())
828} 830}
829 831
830fn bar(baz_1: Baz, baz_2: Baz) { 832fn bar(baz_1: Baz, baz_2: Baz) ${0:-> ()} {
831 ${0:todo!()} 833 todo!()
832} 834}
833", 835",
834 ) 836 )
@@ -852,8 +854,8 @@ fn foo() {
852 bar(baz(), baz(), "foo", "bar") 854 bar(baz(), baz(), "foo", "bar")
853} 855}
854 856
855fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { 857fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) ${0:-> ()} {
856 ${0:todo!()} 858 todo!()
857} 859}
858"#, 860"#,
859 ) 861 )
@@ -872,8 +874,8 @@ fn foo() {
872", 874",
873 r" 875 r"
874mod bar { 876mod bar {
875 pub(crate) fn my_fn() { 877 pub(crate) fn my_fn() ${0:-> ()} {
876 ${0:todo!()} 878 todo!()
877 } 879 }
878} 880}
879 881
@@ -911,8 +913,8 @@ fn bar() {
911 baz(foo) 913 baz(foo)
912} 914}
913 915
914fn baz(foo: foo::Foo) { 916fn baz(foo: foo::Foo) ${0:-> ()} {
915 ${0:todo!()} 917 todo!()
916} 918}
917", 919",
918 ) 920 )
@@ -935,8 +937,8 @@ fn foo() {
935mod bar { 937mod bar {
936 fn something_else() {} 938 fn something_else() {}
937 939
938 pub(crate) fn my_fn() { 940 pub(crate) fn my_fn() ${0:-> ()} {
939 ${0:todo!()} 941 todo!()
940 } 942 }
941} 943}
942 944
@@ -963,8 +965,8 @@ fn foo() {
963 r" 965 r"
964mod bar { 966mod bar {
965 mod baz { 967 mod baz {
966 pub(crate) fn my_fn() { 968 pub(crate) fn my_fn() ${0:-> ()} {
967 ${0:todo!()} 969 todo!()
968 } 970 }
969 } 971 }
970} 972}
@@ -992,8 +994,8 @@ fn main() {
992 r" 994 r"
993 995
994 996
995pub(crate) fn bar() { 997pub(crate) fn bar() ${0:-> ()} {
996 ${0:todo!()} 998 todo!()
997}", 999}",
998 ) 1000 )
999 } 1001 }
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index 7f6e98a54..41f536574 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -454,8 +454,8 @@ fn foo() {
454 bar("", baz()); 454 bar("", baz());
455} 455}
456 456
457fn bar(arg: &str, baz: Baz) { 457fn bar(arg: &str, baz: Baz) ${0:-> ()} {
458 ${0:todo!()} 458 todo!()
459} 459}
460 460
461"#####, 461"#####,
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index c330314d4..215ac4b41 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -221,6 +221,34 @@ impl CrateGraph {
221 deps.into_iter() 221 deps.into_iter()
222 } 222 }
223 223
224 /// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
225 /// come before the crate itself).
226 pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
227 let mut res = Vec::new();
228 let mut visited = FxHashSet::default();
229
230 for krate in self.arena.keys().copied() {
231 go(self, &mut visited, &mut res, krate);
232 }
233
234 return res;
235
236 fn go(
237 graph: &CrateGraph,
238 visited: &mut FxHashSet<CrateId>,
239 res: &mut Vec<CrateId>,
240 source: CrateId,
241 ) {
242 if !visited.insert(source) {
243 return;
244 }
245 for dep in graph[source].dependencies.iter() {
246 go(graph, visited, res, dep.crate_id)
247 }
248 res.push(source)
249 }
250 }
251
224 // FIXME: this only finds one crate with the given root; we could have multiple 252 // FIXME: this only finds one crate with the given root; we could have multiple
225 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { 253 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
226 let (&crate_id, _) = 254 let (&crate_id, _) =
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index fb85041fd..b65be4fe1 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1411,7 +1411,7 @@ impl Type {
1411 r#trait: Trait, 1411 r#trait: Trait,
1412 args: &[Type], 1412 args: &[Type],
1413 alias: TypeAlias, 1413 alias: TypeAlias,
1414 ) -> Option<Ty> { 1414 ) -> Option<Type> {
1415 let subst = Substs::build_for_def(db, r#trait.id) 1415 let subst = Substs::build_for_def(db, r#trait.id)
1416 .push(self.ty.value.clone()) 1416 .push(self.ty.value.clone())
1417 .fill(args.iter().map(|t| t.ty.value.clone())) 1417 .fill(args.iter().map(|t| t.ty.value.clone()))
@@ -1432,6 +1432,10 @@ impl Type {
1432 Solution::Unique(SolutionVariables(subst)) => subst.value.first().cloned(), 1432 Solution::Unique(SolutionVariables(subst)) => subst.value.first().cloned(),
1433 Solution::Ambig(_) => None, 1433 Solution::Ambig(_) => None,
1434 } 1434 }
1435 .map(|ty| Type {
1436 krate: self.krate,
1437 ty: InEnvironment { value: ty, environment: Arc::clone(&self.ty.environment) },
1438 })
1435 } 1439 }
1436 1440
1437 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool { 1441 pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 2d91bb21f..01e72690a 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -107,7 +107,10 @@ impl ExprCollector<'_> {
107 let param_pat = self.alloc_pat( 107 let param_pat = self.alloc_pat(
108 Pat::Bind { 108 Pat::Bind {
109 name: name![self], 109 name: name![self],
110 mode: BindingAnnotation::Unannotated, 110 mode: BindingAnnotation::new(
111 self_param.mut_token().is_some() && self_param.amp_token().is_none(),
112 false,
113 ),
111 subpat: None, 114 subpat: None,
112 }, 115 },
113 Either::Right(ptr), 116 Either::Right(ptr),
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 7d716577e..e2079bbcf 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -220,8 +220,8 @@ fn hint_iterator(
220 } 220 }
221 let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; 221 let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?;
222 let iter_mod = FamousDefs(sema, krate).core_iter()?; 222 let iter_mod = FamousDefs(sema, krate).core_iter()?;
223 // assert this type comes from `core::iter` 223 // assert this struct comes from `core::iter`
224 iter_mod.visibility_of(db, &iter_trait.into()).filter(|&vis| vis == hir::Visibility::Public)?; 224 iter_mod.visibility_of(db, &strukt.into()).filter(|&vis| vis == hir::Visibility::Public)?;
225 if ty.impls_trait(db, iter_trait, &[]) { 225 if ty.impls_trait(db, iter_trait, &[]) {
226 let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item { 226 let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item {
227 hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), 227 hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias),
@@ -231,12 +231,17 @@ fn hint_iterator(
231 const LABEL_START: &str = "impl Iterator<Item = "; 231 const LABEL_START: &str = "impl Iterator<Item = ";
232 const LABEL_END: &str = ">"; 232 const LABEL_END: &str = ">";
233 233
234 let ty_display = ty.display_truncated( 234 let ty_display = hint_iterator(sema, config, &ty)
235 db, 235 .map(|assoc_type_impl| assoc_type_impl.to_string())
236 config 236 .unwrap_or_else(|| {
237 .max_length 237 ty.display_truncated(
238 .map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len())), 238 db,
239 ); 239 config
240 .max_length
241 .map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len())),
242 )
243 .to_string()
244 });
240 return Some(format!("{}{}{}", LABEL_START, ty_display, LABEL_END).into()); 245 return Some(format!("{}{}{}", LABEL_START, ty_display, LABEL_END).into());
241 } 246 }
242 } 247 }
@@ -1002,18 +1007,6 @@ fn main() {
1002 1007
1003 println!("Unit expr"); 1008 println!("Unit expr");
1004} 1009}
1005
1006//- /alloc.rs crate:alloc deps:core
1007mod collections {
1008 struct Vec<T> {}
1009 impl<T> Vec<T> {
1010 fn new() -> Self { Vec {} }
1011 fn push(&mut self, t: T) { }
1012 }
1013 impl<T> IntoIterator for Vec<T> {
1014 type Item=T;
1015 }
1016}
1017"#, 1010"#,
1018 ); 1011 );
1019 } 1012 }
@@ -1043,17 +1036,6 @@ fn main() {
1043 //^ &str 1036 //^ &str
1044 } 1037 }
1045} 1038}
1046//- /alloc.rs crate:alloc deps:core
1047mod collections {
1048 struct Vec<T> {}
1049 impl<T> Vec<T> {
1050 fn new() -> Self { Vec {} }
1051 fn push(&mut self, t: T) { }
1052 }
1053 impl<T> IntoIterator for Vec<T> {
1054 type Item=T;
1055 }
1056}
1057"#, 1039"#,
1058 ); 1040 );
1059 } 1041 }
@@ -1183,4 +1165,41 @@ fn main() {
1183 "#]], 1165 "#]],
1184 ); 1166 );
1185 } 1167 }
1168
1169 #[test]
1170 fn shorten_iterators_in_associated_params() {
1171 check_with_config(
1172 InlayHintsConfig {
1173 parameter_hints: false,
1174 type_hints: true,
1175 chaining_hints: false,
1176 max_length: None,
1177 },
1178 r#"
1179use core::iter;
1180
1181pub struct SomeIter<T> {}
1182
1183impl<T> SomeIter<T> {
1184 pub fn new() -> Self { SomeIter {} }
1185 pub fn push(&mut self, t: T) {}
1186}
1187
1188impl<T> Iterator for SomeIter<T> {
1189 type Item = T;
1190 fn next(&mut self) -> Option<Self::Item> {
1191 None
1192 }
1193}
1194
1195fn main() {
1196 let mut some_iter = SomeIter::new();
1197 //^^^^^^^^^^^^^ SomeIter<Take<Repeat<i32>>>
1198 some_iter.push(iter::repeat(2).take(2));
1199 let iter_of_iters = some_iter.take(2);
1200 //^^^^^^^^^^^^^ impl Iterator<Item = impl Iterator<Item = i32>>
1201}
1202"#,
1203 );
1204 }
1186} 1205}
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 686cee3a1..aaf9b3b4b 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -77,6 +77,7 @@ pub use crate::{
77 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 77 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
79 markup::Markup, 79 markup::Markup,
80 prime_caches::PrimeCachesProgress,
80 references::{ 81 references::{
81 Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, RenameError, 82 Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult, RenameError,
82 }, 83 },
@@ -223,8 +224,11 @@ impl Analysis {
223 self.with_db(|db| status::status(&*db, file_id)) 224 self.with_db(|db| status::status(&*db, file_id))
224 } 225 }
225 226
226 pub fn prime_caches(&self, files: Vec<FileId>) -> Cancelable<()> { 227 pub fn prime_caches<F>(&self, cb: F) -> Cancelable<()>
227 self.with_db(|db| prime_caches::prime_caches(db, files)) 228 where
229 F: Fn(PrimeCachesProgress) + Sync + std::panic::UnwindSafe,
230 {
231 self.with_db(move |db| prime_caches::prime_caches(db, &cb))
228 } 232 }
229 233
230 /// Gets the text of the source file. 234 /// Gets the text of the source file.
diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs
index c5ab5a1d8..9687c2734 100644
--- a/crates/ide/src/prime_caches.rs
+++ b/crates/ide/src/prime_caches.rs
@@ -3,10 +3,45 @@
3//! request takes longer to compute. This modules implemented prepopulating of 3//! request takes longer to compute. This modules implemented prepopulating of
4//! various caches, it's not really advanced at the moment. 4//! various caches, it's not really advanced at the moment.
5 5
6use crate::{FileId, RootDatabase}; 6use base_db::SourceDatabase;
7use hir::db::DefDatabase;
7 8
8pub(crate) fn prime_caches(db: &RootDatabase, files: Vec<FileId>) { 9use crate::RootDatabase;
9 for file in files { 10
10 let _ = crate::syntax_highlighting::highlight(db, file, None, false); 11#[derive(Debug)]
12pub enum PrimeCachesProgress {
13 Started,
14 /// We started indexing a crate.
15 StartedOnCrate {
16 on_crate: String,
17 n_done: usize,
18 n_total: usize,
19 },
20 /// We finished indexing all crates.
21 Finished,
22}
23
24pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress) + Sync)) {
25 let _p = profile::span("prime_caches");
26 let graph = db.crate_graph();
27 let topo = &graph.crates_in_topological_order();
28
29 cb(PrimeCachesProgress::Started);
30
31 // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that.
32 // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks
33 // cancellation, so we cannot use rayon.
34 for (i, krate) in topo.iter().enumerate() {
35 let crate_name =
36 graph[*krate].declaration_name.as_ref().map(ToString::to_string).unwrap_or_default();
37
38 cb(PrimeCachesProgress::StartedOnCrate {
39 on_crate: crate_name,
40 n_done: i,
41 n_total: topo.len(),
42 });
43 db.crate_def_map(*krate);
11 } 44 }
45
46 cb(PrimeCachesProgress::Finished);
12} 47}
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index d9fc25d88..6aafd6fd5 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -68,7 +68,7 @@ pub(crate) fn highlight(
68 // When we leave a node, the we use it to flatten the highlighted ranges. 68 // When we leave a node, the we use it to flatten the highlighted ranges.
69 let mut stack = HighlightedRangeStack::new(); 69 let mut stack = HighlightedRangeStack::new();
70 70
71 let mut current_macro_call: Option<ast::MacroCall> = None; 71 let mut current_macro_call: Option<(ast::MacroCall, Option<MacroMatcherParseState>)> = None;
72 let mut format_string: Option<SyntaxElement> = None; 72 let mut format_string: Option<SyntaxElement> = None;
73 73
74 // Walk all nodes, keeping track of whether we are inside a macro or not. 74 // Walk all nodes, keeping track of whether we are inside a macro or not.
@@ -92,7 +92,6 @@ pub(crate) fn highlight(
92 // Track "inside macro" state 92 // Track "inside macro" state
93 match event.clone().map(|it| it.into_node().and_then(ast::MacroCall::cast)) { 93 match event.clone().map(|it| it.into_node().and_then(ast::MacroCall::cast)) {
94 WalkEvent::Enter(Some(mc)) => { 94 WalkEvent::Enter(Some(mc)) => {
95 current_macro_call = Some(mc.clone());
96 if let Some(range) = macro_call_range(&mc) { 95 if let Some(range) = macro_call_range(&mc) {
97 stack.add(HighlightedRange { 96 stack.add(HighlightedRange {
98 range, 97 range,
@@ -100,7 +99,9 @@ pub(crate) fn highlight(
100 binding_hash: None, 99 binding_hash: None,
101 }); 100 });
102 } 101 }
102 let mut is_macro_rules = None;
103 if let Some(name) = mc.is_macro_rules() { 103 if let Some(name) = mc.is_macro_rules() {
104 is_macro_rules = Some(MacroMatcherParseState::new());
104 if let Some((highlight, binding_hash)) = highlight_element( 105 if let Some((highlight, binding_hash)) = highlight_element(
105 &sema, 106 &sema,
106 &mut bindings_shadow_count, 107 &mut bindings_shadow_count,
@@ -114,10 +115,11 @@ pub(crate) fn highlight(
114 }); 115 });
115 } 116 }
116 } 117 }
118 current_macro_call = Some((mc.clone(), is_macro_rules));
117 continue; 119 continue;
118 } 120 }
119 WalkEvent::Leave(Some(mc)) => { 121 WalkEvent::Leave(Some(mc)) => {
120 assert!(current_macro_call == Some(mc)); 122 assert!(current_macro_call.map(|it| it.0) == Some(mc));
121 current_macro_call = None; 123 current_macro_call = None;
122 format_string = None; 124 format_string = None;
123 } 125 }
@@ -146,6 +148,20 @@ pub(crate) fn highlight(
146 WalkEvent::Leave(_) => continue, 148 WalkEvent::Leave(_) => continue,
147 }; 149 };
148 150
151 // check if in matcher part of a macro_rules rule
152 if let Some((_, Some(ref mut state))) = current_macro_call {
153 if let Some(tok) = element.as_token() {
154 if matches!(
155 update_macro_rules_state(tok, state),
156 RuleState::Matcher | RuleState::Expander
157 ) {
158 if skip_metavariables(element.clone()) {
159 continue;
160 }
161 }
162 }
163 }
164
149 let range = element.text_range(); 165 let range = element.text_range();
150 166
151 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT { 167 let element_to_highlight = if current_macro_call.is_some() && element.kind() != COMMENT {
@@ -918,3 +934,99 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
918 _ => default.into(), 934 _ => default.into(),
919 } 935 }
920} 936}
937
938struct MacroMatcherParseState {
939 /// Opening and corresponding closing bracket of the matcher or expander of the current rule
940 paren_ty: Option<(SyntaxKind, SyntaxKind)>,
941 paren_level: usize,
942 rule_state: RuleState,
943 /// Whether we are inside the outer `{` `}` macro block that holds the rules
944 in_invoc_body: bool,
945}
946
947impl MacroMatcherParseState {
948 fn new() -> Self {
949 MacroMatcherParseState {
950 paren_ty: None,
951 paren_level: 0,
952 in_invoc_body: false,
953 rule_state: RuleState::None,
954 }
955 }
956}
957
958#[derive(Copy, Clone, PartialEq)]
959enum RuleState {
960 Matcher,
961 Expander,
962 Between,
963 None,
964}
965
966impl RuleState {
967 fn transition(&mut self) {
968 *self = match self {
969 RuleState::Matcher => RuleState::Between,
970 RuleState::Expander => RuleState::None,
971 RuleState::Between => RuleState::Expander,
972 RuleState::None => RuleState::Matcher,
973 };
974 }
975}
976
977fn update_macro_rules_state(tok: &SyntaxToken, state: &mut MacroMatcherParseState) -> RuleState {
978 if !state.in_invoc_body {
979 if tok.kind() == T!['{'] {
980 state.in_invoc_body = true;
981 }
982 return state.rule_state;
983 }
984
985 match state.paren_ty {
986 Some((open, close)) => {
987 if tok.kind() == open {
988 state.paren_level += 1;
989 } else if tok.kind() == close {
990 state.paren_level -= 1;
991 if state.paren_level == 0 {
992 let res = state.rule_state;
993 state.rule_state.transition();
994 state.paren_ty = None;
995 return res;
996 }
997 }
998 }
999 None => {
1000 match tok.kind() {
1001 T!['('] => {
1002 state.paren_ty = Some((T!['('], T![')']));
1003 }
1004 T!['{'] => {
1005 state.paren_ty = Some((T!['{'], T!['}']));
1006 }
1007 T!['['] => {
1008 state.paren_ty = Some((T!['['], T![']']));
1009 }
1010 _ => (),
1011 }
1012 if state.paren_ty.is_some() {
1013 state.paren_level = 1;
1014 state.rule_state.transition();
1015 }
1016 }
1017 }
1018 state.rule_state
1019}
1020
1021fn skip_metavariables(element: SyntaxElement) -> bool {
1022 let tok = match element.as_token() {
1023 Some(tok) => tok,
1024 None => return false,
1025 };
1026 let is_fragment = || tok.prev_token().map(|tok| tok.kind()) == Some(T![$]);
1027 match tok.kind() {
1028 IDENT if is_fragment() => true,
1029 kind if kind.is_keyword() && is_fragment() => true,
1030 _ => false,
1031 }
1032}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 1b681b2c6..43f1b32fd 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -37,7 +37,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
37</style> 37</style>
38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span> 38<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> <span class="punctuation">{</span>
39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span> 39 <span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">:</span>tt<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">{</span>
40 <span class="punctuation">$</span><span class="keyword">crate</span><span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span><span class="keyword">crate</span><span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span> 40 <span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>io<span class="punctuation">:</span><span class="punctuation">:</span>_print<span class="punctuation">(</span><span class="punctuation">$</span>crate<span class="punctuation">:</span><span class="punctuation">:</span>format_args_nl<span class="punctuation">!</span><span class="punctuation">(</span><span class="punctuation">$</span><span class="punctuation">(</span><span class="punctuation">$</span>arg<span class="punctuation">)</span><span class="punctuation">*</span><span class="punctuation">)</span><span class="punctuation">)</span><span class="punctuation">;</span>
41 <span class="punctuation">}</span><span class="punctuation">)</span> 41 <span class="punctuation">}</span><span class="punctuation">)</span>
42<span class="punctuation">}</span> 42<span class="punctuation">}</span>
43#[rustc_builtin_macro] 43#[rustc_builtin_macro]
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 1d8a3c404..0bb0928e4 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -62,7 +62,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
62 62
63<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span> 63<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
64 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span> 64 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
65 <span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword consuming">self</span><span class="punctuation">)</span> 65 <span class="value_param">f</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span>
66 <span class="punctuation">}</span> 66 <span class="punctuation">}</span>
67 67
68 <span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> 68 <span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
@@ -115,6 +115,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
115 <span class="punctuation">}</span> 115 <span class="punctuation">}</span>
116<span class="punctuation">}</span> 116<span class="punctuation">}</span>
117 117
118<span class="macro">macro_rules!</span> <span class="macro declaration">keyword_frag</span> <span class="punctuation">{</span>
119 <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">:</span>ty<span class="punctuation">)</span> <span class="operator">=</span><span class="punctuation">&gt;</span> <span class="punctuation">(</span><span class="punctuation">$</span>type<span class="punctuation">)</span>
120<span class="punctuation">}</span>
121
118<span class="comment">// comment</span> 122<span class="comment">// comment</span>
119<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> 123<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
120 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, {}!"</span><span class="punctuation">,</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span> 124 <span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"Hello, {}!"</span><span class="punctuation">,</span> <span class="numeric_literal">92</span><span class="punctuation">)</span><span class="punctuation">;</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 694c4b7fa..126363b8b 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -89,6 +89,10 @@ macro_rules! noop {
89 } 89 }
90} 90}
91 91
92macro_rules! keyword_frag {
93 ($type:ty) => ($type)
94}
95
92// comment 96// comment
93fn main() { 97fn main() {
94 println!("Hello, {}!", 92); 98 println!("Hello, {}!", 92);
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 06b38d99c..fb18f9014 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -7,6 +7,7 @@ use std::{
7 7
8use base_db::VfsPath; 8use base_db::VfsPath;
9use crossbeam_channel::{select, Receiver}; 9use crossbeam_channel::{select, Receiver};
10use ide::PrimeCachesProgress;
10use ide::{Canceled, FileId}; 11use ide::{Canceled, FileId};
11use lsp_server::{Connection, Notification, Request, Response}; 12use lsp_server::{Connection, Notification, Request, Response};
12use lsp_types::notification::Notification as _; 13use lsp_types::notification::Notification as _;
@@ -61,7 +62,7 @@ pub(crate) enum Task {
61 Response(Response), 62 Response(Response),
62 Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>), 63 Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
63 Workspaces(Vec<anyhow::Result<ProjectWorkspace>>), 64 Workspaces(Vec<anyhow::Result<ProjectWorkspace>>),
64 Unit, 65 PrimeCaches(PrimeCachesProgress),
65} 66}
66 67
67impl fmt::Debug for Event { 68impl fmt::Debug for Event {
@@ -197,7 +198,28 @@ impl GlobalState {
197 } 198 }
198 } 199 }
199 Task::Workspaces(workspaces) => self.switch_workspaces(workspaces), 200 Task::Workspaces(workspaces) => self.switch_workspaces(workspaces),
200 Task::Unit => (), 201 Task::PrimeCaches(progress) => {
202 let (state, message, fraction);
203 match progress {
204 PrimeCachesProgress::Started => {
205 state = Progress::Begin;
206 message = None;
207 fraction = 0.0;
208 }
209 PrimeCachesProgress::StartedOnCrate { on_crate, n_done, n_total } => {
210 state = Progress::Report;
211 message = Some(format!("{}/{} ({})", n_done, n_total, on_crate));
212 fraction = Progress::fraction(n_done, n_total);
213 }
214 PrimeCachesProgress::Finished => {
215 state = Progress::End;
216 message = None;
217 fraction = 1.0;
218 }
219 };
220
221 self.report_progress("indexing", state, message, Some(fraction));
222 }
201 }, 223 },
202 Event::Vfs(mut task) => { 224 Event::Vfs(mut task) => {
203 let _p = profile::span("GlobalState::handle_event/vfs"); 225 let _p = profile::span("GlobalState::handle_event/vfs");
@@ -573,12 +595,18 @@ impl GlobalState {
573 Task::Diagnostics(diagnostics) 595 Task::Diagnostics(diagnostics)
574 }) 596 })
575 } 597 }
576 self.task_pool.handle.spawn({ 598 self.task_pool.handle.spawn_with_sender({
577 let subs = subscriptions;
578 let snap = self.snapshot(); 599 let snap = self.snapshot();
579 move || { 600 move |sender| {
580 snap.analysis.prime_caches(subs).unwrap_or_else(|_: Canceled| ()); 601 snap.analysis
581 Task::Unit 602 .prime_caches(|progress| {
603 sender.send(Task::PrimeCaches(progress)).unwrap();
604 })
605 .unwrap_or_else(|_: Canceled| {
606 // Pretend that we're done, so that the progress bar is removed. Otherwise
607 // the editor may complain about it already existing.
608 sender.send(Task::PrimeCaches(PrimeCachesProgress::Finished)).unwrap()
609 });
582 } 610 }
583 }); 611 });
584 } 612 }
diff --git a/crates/rust-analyzer/src/thread_pool.rs b/crates/rust-analyzer/src/thread_pool.rs
index 4fa502925..833893739 100644
--- a/crates/rust-analyzer/src/thread_pool.rs
+++ b/crates/rust-analyzer/src/thread_pool.rs
@@ -23,6 +23,17 @@ impl<T> TaskPool<T> {
23 }) 23 })
24 } 24 }
25 25
26 pub(crate) fn spawn_with_sender<F>(&mut self, task: F)
27 where
28 F: FnOnce(Sender<T>) + Send + 'static,
29 T: Send + 'static,
30 {
31 self.inner.execute({
32 let sender = self.sender.clone();
33 move || task(sender)
34 })
35 }
36
26 pub(crate) fn len(&self) -> usize { 37 pub(crate) fn len(&self) -> usize {
27 self.inner.queued_count() 38 self.inner.queued_count()
28 } 39 }
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 3a184094c..74dbdfaf7 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -320,6 +320,10 @@ pub fn param(name: String, ty: String) -> ast::Param {
320 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) 320 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty))
321} 321}
322 322
323pub fn ret_type(ty: ast::Type) -> ast::RetType {
324 ast_from_text(&format!("fn f() -> {} {{ }}", ty))
325}
326
323pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList { 327pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList {
324 let args = pats.into_iter().join(", "); 328 let args = pats.into_iter().join(", ");
325 ast_from_text(&format!("fn f({}) {{ }}", args)) 329 ast_from_text(&format!("fn f({}) {{ }}", args))
@@ -350,14 +354,20 @@ pub fn fn_(
350 type_params: Option<ast::GenericParamList>, 354 type_params: Option<ast::GenericParamList>,
351 params: ast::ParamList, 355 params: ast::ParamList,
352 body: ast::BlockExpr, 356 body: ast::BlockExpr,
357 ret_type: Option<ast::RetType>,
353) -> ast::Fn { 358) -> ast::Fn {
354 let type_params = 359 let type_params =
355 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; 360 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() };
361 let ret_type = if let Some(ret_type) = ret_type { format!("{} ", ret_type) } else { "".into() };
356 let visibility = match visibility { 362 let visibility = match visibility {
357 None => String::new(), 363 None => String::new(),
358 Some(it) => format!("{} ", it), 364 Some(it) => format!("{} ", it),
359 }; 365 };
360 ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body)) 366
367 ast_from_text(&format!(
368 "{}fn {}{}{} {}{}",
369 visibility, fn_name, type_params, params, ret_type, body
370 ))
361} 371}
362 372
363fn ast_from_text<N: AstNode>(text: &str) -> N { 373fn ast_from_text<N: AstNode>(text: &str) -> N {
diff --git a/editors/code/rust.tmGrammar.json b/editors/code/rust.tmGrammar.json
index 0be2583db..3ddd14f9c 100644
--- a/editors/code/rust.tmGrammar.json
+++ b/editors/code/rust.tmGrammar.json
@@ -1,686 +1,1043 @@
1{ 1{
2 "name": "Rust", 2 "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3 "scopeName": "source.rust", 3 "name": "Rust",
4 "patterns": [ 4 "fileTypes": [
5 { 5 "rs"
6 "comment": "Implementation", 6 ],
7 "begin": "\\b(impl)\\b", 7 "scopeName": "source.rust",
8 "end": "\\{", 8 "patterns": [
9 "beginCaptures": { 9 {
10 "1": { 10 "comment": "boxed slice literal",
11 "name": "storage.type.rust" 11 "begin": "(<)(\\[)",
12 } 12 "beginCaptures": {
13 }, 13 "1": {
14 "patterns": [ 14 "name": "punctuation.brackets.angle.rust"
15 { 15 },
16 "include": "#block_comment" 16 "2": {
17 }, 17 "name": "punctuation.brackets.square.rust"
18 { 18 }
19 "include": "#line_comment" 19 },
20 }, 20 "end": ">",
21 { 21 "endCaptures": {
22 "include": "#sigils" 22 "0": {
23 }, 23 "name": "punctuation.brackets.angle.rust"
24 { 24 }
25 "include": "#mut" 25 },
26 }, 26 "patterns": [
27 { 27 {
28 "include": "#dyn" 28 "include": "#comments"
29 }, 29 },
30 { 30 {
31 "include": "#ref_lifetime" 31 "include": "#gtypes"
32 }, 32 },
33 { 33 {
34 "include": "#core_types" 34 "include": "#lvariables"
35 }, 35 },
36 { 36 {
37 "include": "#core_marker" 37 "include": "#lifetimes"
38 }, 38 },
39 { 39 {
40 "include": "#core_traits" 40 "include": "#punctuation"
41 }, 41 },
42 { 42 {
43 "include": "#std_types" 43 "include": "#types"
44 }, 44 }
45 { 45 ]
46 "include": "#std_traits" 46 },
47 }, 47 {
48 { 48 "comment": "macro type metavariables",
49 "include": "#type_params" 49 "name": "meta.macro.metavariable.type.rust",
50 }, 50 "match": "(\\$)((crate)|([A-Z][A-Za-z0-9_]*))((:)(block|expr|ident|item|lifetime|literal|meta|pat|path|stmt|tt|ty|vis))?",
51 { 51 "captures": {
52 "include": "#where" 52 "1": {
53 }, 53 "name": "keyword.operator.macro.dollar.rust"
54 { 54 },
55 "name": "storage.type.rust", 55 "3": {
56 "match": "\\bfor\\b" 56 "name": "keyword.other.crate.rust"
57 }, 57 },
58 { 58 "4": {
59 "include": "#type" 59 "name": "entity.name.type.metavariable.rust"
60 } 60 },
61 ] 61 "6": {
62 }, 62 "name": "keyword.operator.key-value.rust"
63 { 63 },
64 "include": "#block_doc_comment" 64 "7": {
65 }, 65 "name": "variable.other.metavariable.specifier.rust"
66 { 66 }
67 "include": "#block_comment" 67 },
68 }, 68 "patterns": [
69 { 69 {
70 "include": "#line_doc_comment" 70 "include": "#keywords"
71 }, 71 }
72 { 72 ]
73 "include": "#line_comment" 73 },
74 }, 74 {
75 { 75 "comment": "macro metavariables",
76 "comment": "Attribute", 76 "name": "meta.macro.metavariable.rust",
77 "name": "meta.attribute.rust", 77 "match": "(\\$)([a-z][A-Za-z0-9_]*)((:)(block|expr|ident|item|lifetime|literal|meta|pat|path|stmt|tt|ty|vis))?",
78 "begin": "#\\!?\\[(\\w*)", 78 "captures": {
79 "end": "\\]", 79 "1": {
80 "captures": { 80 "name": "keyword.operator.macro.dollar.rust"
81 "1": { 81 },
82 "name": "entity.name.function.attribute.rust" 82 "2": {
83 } 83 "name": "variable.other.metavariable.name.rust"
84 }, 84 },
85 "patterns": [ 85 "4": {
86 { 86 "name": "keyword.operator.key-value.rust"
87 "include": "#string_literal" 87 },
88 }, 88 "5": {
89 { 89 "name": "variable.other.metavariable.specifier.rust"
90 "include": "#block_doc_comment" 90 }
91 }, 91 },
92 { 92 "patterns": [
93 "include": "#block_comment" 93 {
94 }, 94 "include": "#keywords"
95 { 95 }
96 "include": "#line_doc_comment" 96 ]
97 }, 97 },
98 { 98 {
99 "include": "#line_comment" 99 "comment": "macro rules",
100 } 100 "name": "meta.macro.rules.rust",
101 ] 101 "match": "\\b(macro_rules!)\\s+(([a-z0-9_]+)|([A-Z][a-z0-9_]*))\\s+(\\{)",
102 }, 102 "captures": {
103 { 103 "1": {
104 "comment": "Single-quote string literal (character)", 104 "name": "entity.name.function.macro.rules.rust"
105 "name": "string.quoted.single.rust", 105 },
106 "match": "b?'([^'\\\\]|\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.))'" 106 "3": {
107 }, 107 "name": "entity.name.function.macro.rust"
108 { 108 },
109 "include": "#string_literal" 109 "4": {
110 }, 110 "name": "entity.name.type.macro.rust"
111 { 111 },
112 "include": "#raw_string_literal" 112 "5": {
113 }, 113 "name": "punctuation.brackets.curly.rust"
114 { 114 }
115 "comment": "Floating point literal (fraction)", 115 }
116 "name": "constant.numeric.float.rust", 116 },
117 "match": "\\b[0-9][0-9_]*\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\b" 117 {
118 }, 118 "comment": "attributes",
119 { 119 "name": "meta.attribute.rust",
120 "comment": "Floating point literal (exponent)", 120 "begin": "(#)(\\!?)(\\[)",
121 "name": "constant.numeric.float.rust", 121 "beginCaptures": {
122 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\b" 122 "1": {
123 }, 123 "name": "punctuation.definition.attribute.rust"
124 { 124 },
125 "comment": "Floating point literal (typed)", 125 "2": {
126 "name": "constant.numeric.float.rust", 126 "name": "keyword.operator.attribute.inner.rust"
127 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\b" 127 },
128 }, 128 "3": {
129 { 129 "name": "punctuation.brackets.attribute.rust"
130 "comment": "Integer literal (decimal)", 130 }
131 "name": "constant.numeric.integer.decimal.rust", 131 },
132 "match": "\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\b" 132 "end": "\\]",
133 }, 133 "endCaptures": {
134 { 134 "0": {
135 "comment": "Integer literal (hexadecimal)", 135 "name": "punctuation.brackets.attribute.rust"
136 "name": "constant.numeric.integer.hexadecimal.rust", 136 }
137 "match": "\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\b" 137 },
138 }, 138 "patterns": [
139 { 139 {
140 "comment": "Integer literal (octal)", 140 "include": "#keywords"
141 "name": "constant.numeric.integer.octal.rust", 141 },
142 "match": "\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\b" 142 {
143 }, 143 "include": "#punctuation"
144 { 144 },
145 "comment": "Integer literal (binary)", 145 {
146 "name": "constant.numeric.integer.binary.rust", 146 "include": "#strings"
147 "match": "\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\b" 147 },
148 }, 148 {
149 { 149 "include": "#gtypes"
150 "comment": "Static storage modifier", 150 },
151 "name": "storage.modifier.static.rust", 151 {
152 "match": "\\bstatic\\b" 152 "include": "#types"
153 }, 153 }
154 { 154 ]
155 "comment": "Boolean constant", 155 },
156 "name": "constant.language.boolean.rust", 156 {
157 "match": "\\b(true|false)\\b" 157 "comment": "modules",
158 }, 158 "match": "(mod)\\s+([a-z][A-Za-z0-9_]*)",
159 { 159 "captures": {
160 "comment": "Control keyword", 160 "1": {
161 "name": "keyword.control.rust", 161 "name": "keyword.control.rust"
162 "match": "\\b(async|await|break|continue|else|if|in|for|loop|match|return|try|while)\\b" 162 },
163 }, 163 "2": {
164 { 164 "name": "entity.name.module.rust"
165 "comment": "Keyword", 165 }
166 "name": "keyword.other.rust", 166 }
167 "match": "\\b(crate|extern|mod|let|ref|use|super|move|as)\\b" 167 },
168 }, 168 {
169 { 169 "comment": "external crate imports",
170 "comment": "Reserved keyword", 170 "name": "meta.import.rust",
171 "name": "invalid.deprecated.rust", 171 "begin": "\\b(extern)\\s+(crate)",
172 "match": "\\b(abstract|alignof|become|do|final|macro|offsetof|override|priv|proc|pure|sizeof|typeof|virtual|yield)\\b" 172 "beginCaptures": {
173 }, 173 "1": {
174 { 174 "name": "keyword.control.rust"
175 "include": "#unsafe" 175 },
176 }, 176 "2": {
177 { 177 "name": "keyword.other.crate.rust"
178 "include": "#sigils" 178 }
179 }, 179 },
180 { 180 "end": ";",
181 "include": "#self" 181 "endCaptures": {
182 }, 182 "0": {
183 { 183 "name": "punctuation.semi.rust"
184 "include": "#mut" 184 }
185 }, 185 },
186 { 186 "patterns": [
187 "include": "#dyn" 187 {
188 }, 188 "include": "#comments"
189 { 189 },
190 "include": "#impl" 190 {
191 }, 191 "include": "#keywords"
192 { 192 },
193 "include": "#box" 193 {
194 }, 194 "include": "#punctuation"
195 { 195 }
196 "include": "#lifetime" 196 ]
197 }, 197 },
198 { 198 {
199 "include": "#ref_lifetime" 199 "comment": "use statements",
200 }, 200 "name": "meta.use.rust",
201 { 201 "begin": "\\b(use)\\s",
202 "include": "#const" 202 "beginCaptures": {
203 }, 203 "1": {
204 { 204 "name": "keyword.control.rust"
205 "include": "#pub" 205 }
206 }, 206 },
207 { 207 "end": ";",
208 "comment": "Miscellaneous operator", 208 "endCaptures": {
209 "name": "keyword.operator.misc.rust", 209 "0": {
210 "match": "(=>|::|\\?)" 210 "name": "punctuation.semi.rust"
211 }, 211 }
212 { 212 },
213 "comment": "Comparison operator", 213 "patterns": [
214 "name": "keyword.operator.comparison.rust", 214 {
215 "match": "(&&|\\|\\||==|!=)" 215 "include": "#comments"
216 }, 216 },
217 { 217 {
218 "comment": "Assignment operator", 218 "include": "#keywords"
219 "name": "keyword.operator.assignment.rust", 219 },
220 "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)" 220 {
221 }, 221 "include": "#namespaces"
222 { 222 },
223 "comment": "Arithmetic operator", 223 {
224 "name": "keyword.operator.arithmetic.rust", 224 "include": "#punctuation"
225 "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)" 225 },
226 }, 226 {
227 { 227 "include": "#types"
228 "comment": "Comparison operator (second group because of regex precedence)", 228 },
229 "name": "keyword.operator.comparison.rust", 229 {
230 "match": "(<=|>=|<|>)" 230 "include": "#lvariables"
231 }, 231 }
232 { 232 ]
233 "include": "#core_types" 233 },
234 }, 234 {
235 { 235 "include": "#comments"
236 "include": "#core_vars" 236 },
237 }, 237 {
238 { 238 "include": "#lvariables"
239 "include": "#core_marker" 239 },
240 }, 240 {
241 { 241 "include": "#constants"
242 "include": "#core_traits" 242 },
243 }, 243 {
244 { 244 "include": "#gtypes"
245 "include": "#std_types" 245 },
246 }, 246 {
247 { 247 "include": "#functions"
248 "include": "#std_traits" 248 },
249 }, 249 {
250 { 250 "include": "#types"
251 "comment": "Built-in macro", 251 },
252 "name": "support.function.builtin.rust", 252 {
253 "match": "\\b(macro_rules|compile_error|format_args|env|option_env|concat_idents|concat|line|column|file|stringify|include|include_str|include_bytes|module_path|cfg)!" 253 "include": "#keywords"
254 }, 254 },
255 { 255 {
256 "comment": "Core macro", 256 "include": "#lifetimes"
257 "name": "support.function.core.rust", 257 },
258 "match": "\\b(panic|assert|assert_eq|assert_ne|debug_assert|debug_assert_eq|debug_assert_ne|try|write|writeln|unreachable|unimplemented)!" 258 {
259 }, 259 "include": "#macros"
260 { 260 },
261 "comment": "Standard library macro", 261 {
262 "name": "support.function.std.rust", 262 "include": "#namespaces"
263 "match": "\\b(format|print|println|eprint|eprintln|select|vec)!" 263 },
264 }, 264 {
265 { 265 "include": "#punctuation"
266 "comment": "Logging macro", 266 },
267 "name": "support.function.log.rust", 267 {
268 "match": "\\b(log|error|warn|info|debug|trace|log_enabled)!" 268 "include": "#strings"
269 }, 269 },
270 { 270 {
271 "comment": "Invocation of a macro", 271 "include": "#variables"
272 "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\!)\\s*[({\\[]", 272 }
273 "captures": { 273 ],
274 "1": { 274 "repository": {
275 "name": "entity.name.function.macro.rust" 275 "comments": {
276 } 276 "patterns": [
277 } 277 {
278 }, 278 "comment": "documentation comments",
279 { 279 "name": "comment.line.documentation.rust",
280 "comment": "Function call", 280 "match": "^\\s*///.*",
281 "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(", 281 "patterns": [
282 "captures": { 282 {
283 "1": { 283 "include": "#comments"
284 "name": "entity.name.function.rust" 284 }
285 } 285 ]
286 } 286 },
287 }, 287 {
288 { 288 "comment": "line comments",
289 "comment": "Function call with type parameters", 289 "name": "comment.line.double-slash.rust",
290 "begin": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*(::)(?=\\s*<.*>\\s*\\()", 290 "match": "\\s*//.*",
291 "end": "\\(", 291 "patterns": [
292 "captures": { 292 {
293 "1": { 293 "include": "#comments"
294 "name": "entity.name.function.rust" 294 }
295 }, 295 ]
296 "2": { 296 },
297 "name": "keyword.operator.misc.rust" 297 {
298 } 298 "comment": "block comments",
299 }, 299 "name": "comment.block.rust",
300 "patterns": [ 300 "begin": "/\\*(?!\\*)",
301 { 301 "end": "\\*/",
302 "include": "#type_params" 302 "patterns": [
303 } 303 {
304 ] 304 "include": "#comments"
305 }, 305 }
306 { 306 ]
307 "comment": "Function definition", 307 },
308 "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)", 308 {
309 "end": "[\\{;]", 309 "comment": "block documentation comments",
310 "beginCaptures": { 310 "name": "comment.block.documentation.rust",
311 "1": { 311 "begin": "/\\*\\*",
312 "name": "keyword.other.fn.rust" 312 "end": "\\*/",
313 }, 313 "patterns": [
314 "2": { 314 {
315 "name": "entity.name.function.rust" 315 "include": "#comments"
316 } 316 }
317 }, 317 ]
318 "patterns": [ 318 },
319 { 319 {
320 "include": "#block_comment" 320 "comment": "inferred types, wildcard patterns, ignored params",
321 }, 321 "name": "comment.char.underscore.rust",
322 { 322 "match": "\\b_\\w*\\b"
323 "include": "#line_comment" 323 }
324 }, 324 ]
325 { 325 },
326 "include": "#sigils" 326 "constants": {
327 }, 327 "patterns": [
328 { 328 {
329 "include": "#self" 329 "comment": "ALL CAPS constants",
330 }, 330 "name": "constant.other.caps.rust",
331 { 331 "match": "\\b[A-Z]{2}[A-Z0-9_]*\\b"
332 "include": "#mut" 332 },
333 }, 333 {
334 { 334 "comment": "constant declarations",
335 "include": "#dyn" 335 "match": "\\b(const)\\s+([A-Z][A-Za-z0-9_]*)\\b",
336 }, 336 "captures": {
337 { 337 "1": {
338 "include": "#impl" 338 "name": "keyword.control.rust"
339 }, 339 },
340 { 340 "2": {
341 "include": "#ref_lifetime" 341 "name": "constant.other.caps.rust"
342 }, 342 }
343 { 343 }
344 "include": "#core_types" 344 },
345 }, 345 {
346 { 346 "comment": "decimal integers and floats",
347 "include": "#core_marker" 347 "name": "constant.numeric.decimal.rust",
348 }, 348 "match": "\\b\\d[\\d_]*(\\.?)[\\d_]*(?:(E)([+-])([\\d_]+))?(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
349 { 349 "captures": {
350 "include": "#core_traits" 350 "1": {
351 }, 351 "name": "punctuation.separator.dot.decimal.rust"
352 { 352 },
353 "include": "#std_types" 353 "2": {
354 }, 354 "name": "keyword.operator.exponent.rust"
355 { 355 },
356 "include": "#std_traits" 356 "3": {
357 }, 357 "name": "keyword.operator.exponent.sign.rust"
358 { 358 },
359 "include": "#type_params" 359 "4": {
360 }, 360 "name": "constant.numeric.decimal.exponent.mantissa.rust"
361 { 361 },
362 "include": "#const" 362 "5": {
363 }, 363 "name": "entity.name.type.numeric.rust"
364 { 364 }
365 "include": "#where" 365 }
366 }, 366 },
367 { 367 {
368 "include": "#unsafe" 368 "comment": "hexadecimal integers",
369 }, 369 "name": "constant.numeric.hex.rust",
370 { 370 "match": "\\b0x[\\da-fA-F_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
371 "comment": "Function arguments", 371 "captures": {
372 "match": "\bfn\b", 372 "1": {
373 "name": "keyword.other.fn.rust" 373 "name": "entity.name.type.numeric.rust"
374 } 374 }
375 ] 375 }
376 }, 376 },
377 { 377 {
378 "comment": "Type declaration", 378 "comment": "octal integers",
379 "begin": "\\b(enum|struct|trait|union)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", 379 "name": "constant.numeric.oct.rust",
380 "end": "[\\{\\(;]", 380 "match": "\\b0o[0-7_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
381 "beginCaptures": { 381 "captures": {
382 "1": { 382 "1": {
383 "name": "storage.type.rust" 383 "name": "entity.name.type.numeric.rust"
384 }, 384 }
385 "2": { 385 }
386 "name": "entity.name.type.rust" 386 },
387 } 387 {
388 }, 388 "comment": "binary integers",
389 "patterns": [ 389 "name": "constant.numeric.bin.rust",
390 { 390 "match": "\\b0b[01_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
391 "include": "#block_comment" 391 "captures": {
392 }, 392 "1": {
393 { 393 "name": "entity.name.type.numeric.rust"
394 "include": "#line_comment" 394 }
395 }, 395 }
396 { 396 },
397 "include": "#core_traits" 397 {
398 }, 398 "comment": "booleans",
399 { 399 "name": "constant.language.bool.rust",
400 "include": "#std_traits" 400 "match": "\\btrue|false\\b"
401 }, 401 }
402 { 402 ]
403 "include": "#type_params" 403 },
404 }, 404 "escapes": {
405 { 405 "comment": "escapes: ASCII, byte, Unicode, quote, regex",
406 "include": "#core_types" 406 "name": "constant.character.escape.rust",
407 }, 407 "match": "(\\\\)(?:(?:(x[0-7][0-7a-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))",
408 { 408 "captures": {
409 "include": "#pub" 409 "1": {
410 }, 410 "name": "constant.character.escape.backslash.rust"
411 { 411 },
412 "include": "#where" 412 "2": {
413 } 413 "name": "constant.character.escape.bit.rust"
414 ] 414 },
415 }, 415 "3": {
416 { 416 "name": "constant.character.escape.unicode.rust"
417 "comment": "Type alias", 417 },
418 "begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z0-9_]*)", 418 "4": {
419 "end": ";", 419 "name": "constant.character.escape.unicode.punctuation.rust"
420 "beginCaptures": { 420 },
421 "1": { 421 "5": {
422 "name": "storage.type.rust" 422 "name": "constant.character.escape.unicode.punctuation.rust"
423 }, 423 }
424 "2": { 424 }
425 "name": "entity.name.type.rust" 425 },
426 } 426 "functions": {
427 }, 427 "patterns": [
428 "patterns": [ 428 {
429 { 429 "comment": "function definition",
430 "include": "#block_comment" 430 "name": "meta.function.definition.rust",
431 }, 431 "begin": "\\b(fn)\\s+([A-Za-z0-9_]+)((\\()|(<))",
432 { 432 "beginCaptures": {
433 "include": "#line_comment" 433 "1": {
434 }, 434 "name": "keyword.control.fn.rust"
435 { 435 },
436 "include": "#sigils" 436 "2": {
437 }, 437 "name": "entity.name.function.rust"
438 { 438 },
439 "include": "#mut" 439 "4": {
440 }, 440 "name": "punctuation.brackets.round.rust"
441 { 441 },
442 "include": "#dyn" 442 "5": {
443 }, 443 "name": "punctuation.brackets.angle.rust"
444 { 444 }
445 "include": "#impl" 445 },
446 }, 446 "end": "\\{",
447 { 447 "endCaptures": {
448 "include": "#lifetime" 448 "0": {
449 }, 449 "name": "punctuation.brackets.curly.rust"
450 { 450 }
451 "include": "#ref_lifetime" 451 },
452 }, 452 "patterns": [
453 { 453 {
454 "include": "#core_types" 454 "include": "#comments"
455 }, 455 },
456 { 456 {
457 "include": "#core_marker" 457 "include": "#keywords"
458 }, 458 },
459 { 459 {
460 "include": "#core_traits" 460 "include": "#lvariables"
461 }, 461 },
462 { 462 {
463 "include": "#std_types" 463 "include": "#constants"
464 }, 464 },
465 { 465 {
466 "include": "#std_traits" 466 "include": "#gtypes"
467 }, 467 },
468 { 468 {
469 "include": "#type_params" 469 "include": "#functions"
470 } 470 },
471 ] 471 {
472 } 472 "include": "#lifetimes"
473 ], 473 },
474 "repository": { 474 {
475 "block_doc_comment": { 475 "include": "#macros"
476 "comment": "Block documentation comment", 476 },
477 "name": "comment.block.documentation.rust", 477 {
478 "begin": "/\\*[\\*!](?![\\*/])", 478 "include": "#namespaces"
479 "end": "\\*/", 479 },
480 "patterns": [ 480 {
481 { 481 "include": "#punctuation"
482 "include": "#block_doc_comment" 482 },
483 }, 483 {
484 { 484 "include": "#strings"
485 "include": "#block_comment" 485 },
486 } 486 {
487 ] 487 "include": "#types"
488 }, 488 },
489 "block_comment": { 489 {
490 "comment": "Block comment", 490 "include": "#variables"
491 "name": "comment.block.rust", 491 }
492 "begin": "/\\*", 492 ]
493 "end": "\\*/", 493 },
494 "patterns": [ 494 {
495 { 495 "comment": "function/method calls, chaining",
496 "include": "#block_doc_comment" 496 "name": "meta.function.call.rust",
497 }, 497 "begin": "(?:(pub)|(?:(\\.)?([A-Za-z0-9_]+)))(\\()",
498 { 498 "beginCaptures": {
499 "include": "#block_comment" 499 "1": {
500 } 500 "name": "keyword.other.rust"
501 ] 501 },
502 }, 502 "2": {
503 "line_doc_comment": { 503 "name": "keyword.operator.access.dot.rust"
504 "comment": "Single-line documentation comment", 504 },
505 "name": "comment.line.documentation.rust", 505 "3": {
506 "begin": "//[!/](?=[^/])", 506 "name": "entity.name.function.rust"
507 "end": "$" 507 },
508 }, 508 "4": {
509 "line_comment": { 509 "name": "punctuation.brackets.round.rust"
510 "comment": "Single-line comment", 510 }
511 "name": "comment.line.double-slash.rust", 511 },
512 "begin": "//", 512 "end": "\\)",
513 "end": "$" 513 "endCaptures": {
514 }, 514 "0": {
515 "escaped_character": { 515 "name": "punctuation.brackets.round.rust"
516 "name": "constant.character.escape.rust", 516 }
517 "match": "\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)" 517 },
518 }, 518 "patterns": [
519 "string_literal": { 519 {
520 "comment": "Double-quote string literal", 520 "include": "#comments"
521 "name": "string.quoted.double.rust", 521 },
522 "begin": "b?\"", 522 {
523 "end": "\"", 523 "include": "#keywords"
524 "patterns": [ 524 },
525 { 525 {
526 "include": "#escaped_character" 526 "include": "#lvariables"
527 } 527 },
528 ] 528 {
529 }, 529 "include": "#namespaces"
530 "raw_string_literal": { 530 },
531 "comment": "Raw double-quote string literal", 531 {
532 "name": "string.quoted.double.raw.rust", 532 "include": "#constants"
533 "begin": "b?r(#*)\"", 533 },
534 "end": "\"\\1" 534 {
535 }, 535 "include": "#gtypes"
536 "sigils": { 536 },
537 "comment": "Sigil", 537 {
538 "name": "keyword.operator.sigil.rust", 538 "include": "#functions"
539 "match": "[&*](?=[a-zA-Z0-9_\\(\\[\\|\\\"]+)" 539 },
540 }, 540 {
541 "self": { 541 "include": "#lifetimes"
542 "comment": "Self variable", 542 },
543 "name": "variable.language.rust", 543 {
544 "match": "\\bself\\b" 544 "include": "#macros"
545 }, 545 },
546 "mut": { 546 {
547 "comment": "Mutable storage modifier", 547 "include": "#punctuation"
548 "name": "storage.modifier.mut.rust", 548 },
549 "match": "\\bmut\\b" 549 {
550 }, 550 "include": "#strings"
551 "dyn": { 551 },
552 "comment": "Dynamic modifier", 552 {
553 "name": "storage.modifier.dyn.rust", 553 "include": "#types"
554 "match": "\\bdyn\\b" 554 },
555 }, 555 {
556 "impl": { 556 "include": "#variables"
557 "comment": "Existential type modifier", 557 }
558 "name": "storage.modifier.impl.rust", 558 ]
559 "match": "\\bimpl\\b" 559 }
560 }, 560 ]
561 "box": { 561 },
562 "comment": "Box storage modifier", 562 "keywords": {
563 "name": "storage.modifier.box.rust", 563 "patterns": [
564 "match": "\\bbox\\b" 564 {
565 }, 565 "comment": "control flow keywords",
566 "const": { 566 "name": "keyword.control.rust",
567 "comment": "Const storage modifier", 567 "match": "\\b(async|await|break|continue|do|else|for|if|loop|match|move|return|try|where|while|yield)\\b"
568 "name": "storage.modifier.const.rust", 568 },
569 "match": "\\bconst\\b" 569 {
570 }, 570 "comment": "storage keywords",
571 "pub": { 571 "name": "storage.type.rust",
572 "comment": "Visibility modifier", 572 "match": "\\b(const|enum|extern|let|macro|mod|struct|trait|type)\\b"
573 "name": "storage.modifier.visibility.rust", 573 },
574 "match": "\\bpub\\b" 574 {
575 }, 575 "comment": "storage modifiers",
576 "unsafe": { 576 "name": "storage.modifier.rust",
577 "comment": "Unsafe code keyword", 577 "match": "\\b(abstract|static)\\b"
578 "name": "keyword.other.unsafe.rust", 578 },
579 "match": "\\bunsafe\\b" 579 {
580 }, 580 "comment": "other keywords",
581 "where": { 581 "name": "keyword.other.rust",
582 "comment": "Generic where clause", 582 "match": "\\b(as|become|box|dyn|final|impl|in|override|priv|pub|ref|typeof|union|unsafe|unsized|use|virtual)\\b"
583 "name": "keyword.other.where.rust", 583 },
584 "match": "\\bwhere\\b" 584 {
585 }, 585 "comment": "fn",
586 "lifetime": { 586 "name": "keyword.other.fn.rust",
587 "comment": "Named lifetime", 587 "match": "\\bfn\\b"
588 "name": "storage.modifier.lifetime.rust", 588 },
589 "match": "'([a-zA-Z_][a-zA-Z0-9_]*)\\b" 589 {
590 }, 590 "comment": "crate",
591 "ref_lifetime": { 591 "name": "keyword.other.crate.rust",
592 "comment": "Reference with named lifetime", 592 "match": "\\bcrate\\b"
593 "match": "(&)('[a-zA-Z_][a-zA-Z0-9_]*)\\b", 593 },
594 "captures": { 594 {
595 "1": { 595 "comment": "mut",
596 "name": "keyword.operator.sigil.rust" 596 "name": "storage.modifier.mut.rust",
597 }, 597 "match": "\\bmut\\b"
598 "2": { 598 },
599 "name": "storage.modifier.lifetime.rust" 599 {
600 } 600 "comment": "math operators",
601 } 601 "name": "keyword.operator.math.rust",
602 }, 602 "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))"
603 "core_types": { 603 },
604 "comment": "Built-in/core type", 604 {
605 "name": "support.type.primitive.rust", 605 "comment": "logical operators",
606 "match": "\\b(bool|char|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64|str|Self)\\b" 606 "name": "keyword.operator.logical.rust",
607 }, 607 "match": "(\\^|\\||\\|\\||&&|<<|>>|!)(?!=)"
608 "core_vars": { 608 },
609 "comment": "Core type variant", 609 {
610 "name": "support.constant.core.rust", 610 "comment": "logical AND, borrow references",
611 "match": "\\b(Some|None|Ok|Err)\\b" 611 "name": "keyword.operator.borrow.and.rust",
612 }, 612 "match": "&(?![&=])"
613 "core_marker": { 613 },
614 "comment": "Core trait (marker)", 614 {
615 "name": "entity.name.type.marker.rust", 615 "comment": "assignment operators",
616 "match": "\\b(Copy|Send|Sized|Sync)\\b" 616 "name": "keyword.operator.assignment.rust",
617 }, 617 "match": "(-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)"
618 "core_traits": { 618 },
619 "comment": "Core trait", 619 {
620 "name": "entity.name.type.core.rust", 620 "comment": "single equal",
621 "match": "\\b(Drop|Fn|FnMut|FnOnce|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator)\\b" 621 "name": "keyword.operator.assignment.equal.rust",
622 }, 622 "match": "(?<![<>])=(?!=|>)"
623 "std_types": { 623 },
624 "comment": "Standard library type", 624 {
625 "name": "entity.name.type.class.std.rust", 625 "comment": "comparison operators",
626 "match": "\\b(Box|String|Vec|Path|PathBuf|Option|Result)\\b" 626 "name": "keyword.operator.comparison.rust",
627 }, 627 "match": "(=(=)?(?!>)|!=|<=|(?<!=)>=)"
628 "std_traits": { 628 },
629 "comment": "Standard library trait", 629 {
630 "name": "entity.name.type.std.rust", 630 "comment": "less than, greater than (special case)",
631 "match": "\\b(ToOwned|ToString)\\b" 631 "match": "(^|\\s)(?<!=)([<>])\\s",
632 }, 632 "captures": {
633 "type": { 633 "2": {
634 "comment": "A type", 634 "name": "keyword.operator.comparison.rust"
635 "name": "entity.name.type.rust", 635 }
636 "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b" 636 }
637 }, 637 },
638 "type_params": { 638 {
639 "comment": "Type parameters", 639 "comment": "namespace operator",
640 "name": "meta.type_params.rust", 640 "name": "keyword.operator.namespace.rust",
641 "begin": "<(?![=<])", 641 "match": "::"
642 "end": "(?<![-])>", 642 },
643 "patterns": [ 643 {
644 { 644 "comment": "dereference asterisk",
645 "include": "#block_comment" 645 "match": "(\\*)(?=\\w+)",
646 }, 646 "captures": {
647 { 647 "1": {
648 "include": "#line_comment" 648 "name": "keyword.operator.dereference.rust"
649 }, 649 }
650 { 650 }
651 "include": "#sigils" 651 },
652 }, 652 {
653 { 653 "comment": "subpattern binding",
654 "include": "#mut" 654 "name": "keyword.operator.subpattern.rust",
655 }, 655 "match": "@"
656 { 656 },
657 "include": "#dyn" 657 {
658 }, 658 "comment": "dot access",
659 { 659 "name": "keyword.operator.access.dot.rust",
660 "include": "#impl" 660 "match": "\\.(?!\\.)"
661 }, 661 },
662 { 662 {
663 "include": "#lifetime" 663 "comment": "ranges, range patterns",
664 }, 664 "name": "keyword.operator.range.rust",
665 { 665 "match": "\\.{2}(=|\\.)?"
666 "include": "#core_types" 666 },
667 }, 667 {
668 { 668 "comment": "colon",
669 "include": "#core_marker" 669 "name": "keyword.operator.key-value.rust",
670 }, 670 "match": ":(?!:)"
671 { 671 },
672 "include": "#core_traits" 672 {
673 }, 673 "comment": "dashrocket, skinny arrow",
674 { 674 "name": "keyword.operator.arrow.skinny.rust",
675 "include": "#std_types" 675 "match": "->"
676 }, 676 },
677 { 677 {
678 "include": "#std_traits" 678 "comment": "hashrocket, fat arrow",
679 }, 679 "name": "keyword.operator.arrow.fat.rust",
680 { 680 "match": "=>"
681 "include": "#type_params" 681 },
682 } 682 {
683 ] 683 "comment": "dollar macros",
684 } 684 "name": "keyword.operator.macro.dollar.rust",
685 } 685 "match": "\\$"
686 },
687 {
688 "comment": "question mark operator, questionably sized, macro kleene matcher",
689 "name": "keyword.operator.question.rust",
690 "match": "\\?"
691 }
692 ]
693 },
694 "interpolations": {
695 "comment": "curly brace interpolations",
696 "name": "meta.interpolation.rust",
697 "begin": "{",
698 "beginCaptures": {
699 "0": {
700 "name": "punctuation.definition.interpolation.rust"
701 }
702 },
703 "end": "}",
704 "endCaptures": {
705 "0": {
706 "name": "punctuation.definition.interpolation.rust"
707 }
708 },
709 "patterns": [
710 {
711 "include": "#interpolations"
712 }
713 ]
714 },
715 "lifetimes": {
716 "patterns": [
717 {
718 "comment": "named lifetime parameters",
719 "match": "(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
720 "captures": {
721 "1": {
722 "name": "punctuation.definition.lifetime.rust"
723 },
724 "2": {
725 "name": "entity.name.type.lifetime.rust"
726 }
727 }
728 },
729 {
730 "comment": "borrowing references to named lifetimes",
731 "match": "(\\&)(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
732 "captures": {
733 "1": {
734 "name": "keyword.operator.borrow.rust"
735 },
736 "2": {
737 "name": "punctuation.definition.lifetime.rust"
738 },
739 "3": {
740 "name": "entity.name.type.lifetime.rust"
741 }
742 }
743 }
744 ]
745 },
746 "macros": {
747 "patterns": [
748 {
749 "comment": "macros",
750 "name": "meta.macro.rust",
751 "match": "(([a-z_][A-Za-z0-9_]*!)|([A-Z_][A-Za-z0-9_]*!))",
752 "captures": {
753 "2": {
754 "name": "entity.name.function.macro.rust"
755 },
756 "3": {
757 "name": "entity.name.type.macro.rust"
758 }
759 }
760 }
761 ]
762 },
763 "namespaces": {
764 "patterns": [
765 {
766 "comment": "namespace (non-type, non-function path segment)",
767 "match": "(?<![A-Za-z0-9_])([a-z0-9_]+)((?<!super|self)::)",
768 "captures": {
769 "1": {
770 "name": "entity.name.namespace.rust"
771 },
772 "2": {
773 "name": "keyword.operator.namespace.rust"
774 }
775 }
776 }
777 ]
778 },
779 "types": {
780 "patterns": [
781 {
782 "comment": "numeric types",
783 "match": "(?<![A-Za-z])(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)\\b",
784 "captures": {
785 "1": {
786 "name": "entity.name.type.numeric.rust"
787 }
788 }
789 },
790 {
791 "comment": "parameterized types",
792 "begin": "\\b([A-Z][A-Za-z0-9]*)(<)",
793 "beginCaptures": {
794 "1": {
795 "name": "entity.name.type.rust"
796 },
797 "2": {
798 "name": "punctuation.brackets.angle.rust"
799 }
800 },
801 "end": ">",
802 "endCaptures": {
803 "0": {
804 "name": "punctuation.brackets.angle.rust"
805 }
806 },
807 "patterns": [
808 {
809 "include": "#comments"
810 },
811 {
812 "include": "#keywords"
813 },
814 {
815 "include": "#lvariables"
816 },
817 {
818 "include": "#lifetimes"
819 },
820 {
821 "include": "#punctuation"
822 },
823 {
824 "include": "#types"
825 },
826 {
827 "include": "#variables"
828 }
829 ]
830 },
831 {
832 "comment": "primitive types",
833 "name": "entity.name.type.primitive.rust",
834 "match": "\\b(bool|char|str)\\b"
835 },
836 {
837 "comment": "trait declarations",
838 "match": "\\b(trait)\\s+([A-Z][A-Za-z0-9]*)\\b",
839 "captures": {
840 "1": {
841 "name": "storage.type.rust"
842 },
843 "2": {
844 "name": "entity.name.type.trait.rust"
845 }
846 }
847 },
848 {
849 "comment": "struct declarations",
850 "match": "\\b(struct)\\s+([A-Z][A-Za-z0-9]*)\\b",
851 "captures": {
852 "1": {
853 "name": "storage.type.rust"
854 },
855 "2": {
856 "name": "entity.name.type.struct.rust"
857 }
858 }
859 },
860 {
861 "comment": "enum declarations",
862 "match": "\\b(enum)\\s+([A-Z][A-Za-z0-9_]*)\\b",
863 "captures": {
864 "1": {
865 "name": "storage.type.rust"
866 },
867 "2": {
868 "name": "entity.name.type.enum.rust"
869 }
870 }
871 },
872 {
873 "comment": "type declarations",
874 "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_]*)\\b",
875 "captures": {
876 "1": {
877 "name": "storage.type.rust"
878 },
879 "2": {
880 "name": "entity.name.type.declaration.rust"
881 }
882 }
883 },
884 {
885 "comment": "types",
886 "name": "entity.name.type.rust",
887 "match": "\\b[A-Z][A-Za-z0-9]*\\b(?!!)"
888 }
889 ]
890 },
891 "gtypes": {
892 "patterns": [
893 {
894 "comment": "option types",
895 "name": "entity.name.type.option.rust",
896 "match": "\\b(Some|None)\\b"
897 },
898 {
899 "comment": "result types",
900 "name": "entity.name.type.result.rust",
901 "match": "\\b(Ok|Err)\\b"
902 }
903 ]
904 },
905 "punctuation": {
906 "patterns": [
907 {
908 "comment": "comma",
909 "name": "punctuation.comma.rust",
910 "match": ","
911 },
912 {
913 "comment": "curly braces",
914 "name": "punctuation.brackets.curly.rust",
915 "match": "[{}]"
916 },
917 {
918 "comment": "parentheses, round brackets",
919 "name": "punctuation.brackets.round.rust",
920 "match": "[()]"
921 },
922 {
923 "comment": "semicolon",
924 "name": "punctuation.semi.rust",
925 "match": ";"
926 },
927 {
928 "comment": "square brackets",
929 "name": "punctuation.brackets.square.rust",
930 "match": "[\\[\\]]"
931 },
932 {
933 "comment": "angle brackets",
934 "name": "punctuation.brackets.angle.rust",
935 "match": "(?<!=)[<>]"
936 }
937 ]
938 },
939 "strings": {
940 "patterns": [
941 {
942 "comment": "double-quoted strings and byte strings",
943 "name": "string.quoted.double.rust",
944 "begin": "(b?)(\")",
945 "beginCaptures": {
946 "1": {
947 "name": "string.quoted.byte.raw.rust"
948 },
949 "2": {
950 "name": "punctuation.definition.string.rust"
951 }
952 },
953 "end": "\"",
954 "endCaptures": {
955 "0": {
956 "name": "punctuation.definition.string.rust"
957 }
958 },
959 "patterns": [
960 {
961 "include": "#escapes"
962 },
963 {
964 "include": "#interpolations"
965 }
966 ]
967 },
968 {
969 "comment": "double-quoted raw strings and raw byte strings",
970 "name": "string.quoted.double.rust",
971 "begin": "(b?r)(#*)(\")",
972 "beginCaptures": {
973 "1": {
974 "name": "string.quoted.byte.raw.rust"
975 },
976 "2": {
977 "name": "punctuation.definition.string.raw.rust"
978 },
979 "3": {
980 "name": "punctuation.definition.string.rust"
981 }
982 },
983 "end": "(\")(#*)",
984 "endCaptures": {
985 "1": {
986 "name": "punctuation.definition.string.rust"
987 },
988 "2": {
989 "name": "punctuation.definition.string.raw.rust"
990 }
991 }
992 },
993 {
994 "comment": "characters and bytes",
995 "name": "string.quoted.single.char.rust",
996 "begin": "(b)?(')",
997 "beginCaptures": {
998 "1": {
999 "name": "string.quoted.byte.raw.rust"
1000 },
1001 "2": {
1002 "name": "punctuation.definition.char.rust"
1003 }
1004 },
1005 "end": "'",
1006 "endCaptures": {
1007 "0": {
1008 "name": "punctuation.definition.char.rust"
1009 }
1010 },
1011 "patterns": [
1012 {
1013 "include": "#escapes"
1014 }
1015 ]
1016 }
1017 ]
1018 },
1019 "lvariables": {
1020 "patterns": [
1021 {
1022 "comment": "self",
1023 "name": "variable.language.self.rust",
1024 "match": "\\b[Ss]elf\\b"
1025 },
1026 {
1027 "comment": "super",
1028 "name": "variable.language.super.rust",
1029 "match": "\\bsuper\\b"
1030 }
1031 ]
1032 },
1033 "variables": {
1034 "patterns": [
1035 {
1036 "comment": "variables",
1037 "name": "variable.other.rust",
1038 "match": "\\b(?<!\\.)[a-z0-9_]+\\b"
1039 }
1040 ]
1041 }
1042 }
686} 1043}