aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/utils.rs4
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs206
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html14
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs12
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs14
-rw-r--r--crates/rust-analyzer/src/bin/main.rs7
-rw-r--r--crates/rust-analyzer/src/config.rs60
-rw-r--r--crates/rust-analyzer/src/main_loop.rs19
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs1
-rw-r--r--docs/dev/README.md2
-rw-r--r--docs/user/readme.adoc2
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--editors/code/package.json21
-rw-r--r--editors/code/rust.tmGrammar.json681
15 files changed, 996 insertions, 50 deletions
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 2f15a3f15..f3fc92ebf 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -103,7 +103,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
103} 103}
104 104
105#[derive(Clone, Copy)] 105#[derive(Clone, Copy)]
106pub(crate) enum TryEnum { 106pub enum TryEnum {
107 Result, 107 Result,
108 Option, 108 Option,
109} 109}
@@ -111,7 +111,7 @@ pub(crate) enum TryEnum {
111impl TryEnum { 111impl TryEnum {
112 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result]; 112 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result];
113 113
114 pub(crate) fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> { 114 pub fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> {
115 let enum_ = match ty.as_adt() { 115 let enum_ = match ty.as_adt() {
116 Some(Adt::Enum(it)) => it, 116 Some(Adt::Enum(it)) => it,
117 _ => return None, 117 _ => return None,
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 6a0f0c72e..c5c4426cc 100644
--- a/crates/ra_ide/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/src/completion/complete_postfix.rs
@@ -14,6 +14,7 @@ use crate::{
14 }, 14 },
15 CompletionItem, 15 CompletionItem,
16}; 16};
17use ra_assists::utils::TryEnum;
17 18
18pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { 19pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
19 if !ctx.config.enable_postfix_completions { 20 if !ctx.config.enable_postfix_completions {
@@ -38,7 +39,52 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
38 None => return, 39 None => return,
39 }; 40 };
40 41
41 if receiver_ty.is_bool() || receiver_ty.is_unknown() { 42 if let Some(try_enum) = TryEnum::from_ty(&ctx.sema, &receiver_ty) {
43 match try_enum {
44 TryEnum::Result => {
45 postfix_snippet(
46 ctx,
47 cap,
48 &dot_receiver,
49 "ifl",
50 "if let Ok {}",
51 &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text),
52 )
53 .add_to(acc);
54
55 postfix_snippet(
56 ctx,
57 cap,
58 &dot_receiver,
59 "while",
60 "while let Ok {}",
61 &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text),
62 )
63 .add_to(acc);
64 }
65 TryEnum::Option => {
66 postfix_snippet(
67 ctx,
68 cap,
69 &dot_receiver,
70 "ifl",
71 "if let Some {}",
72 &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text),
73 )
74 .add_to(acc);
75
76 postfix_snippet(
77 ctx,
78 cap,
79 &dot_receiver,
80 "while",
81 "while let Some {}",
82 &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text),
83 )
84 .add_to(acc);
85 }
86 }
87 } else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
42 postfix_snippet( 88 postfix_snippet(
43 ctx, 89 ctx,
44 cap, 90 cap,
@@ -236,6 +282,164 @@ mod tests {
236 } 282 }
237 283
238 #[test] 284 #[test]
285 fn postfix_completion_works_for_option() {
286 assert_debug_snapshot!(
287 do_postfix_completion(
288 r#"
289 enum Option<T> {
290 Some(T),
291 None,
292 }
293
294 fn main() {
295 let bar = Option::Some(true);
296 bar.<|>
297 }
298 "#,
299 ),
300 @r###"
301 [
302 CompletionItem {
303 label: "box",
304 source_range: 210..210,
305 delete: 206..210,
306 insert: "Box::new(bar)",
307 detail: "Box::new(expr)",
308 },
309 CompletionItem {
310 label: "dbg",
311 source_range: 210..210,
312 delete: 206..210,
313 insert: "dbg!(bar)",
314 detail: "dbg!(expr)",
315 },
316 CompletionItem {
317 label: "ifl",
318 source_range: 210..210,
319 delete: 206..210,
320 insert: "if let Some($1) = bar {\n $0\n}",
321 detail: "if let Some {}",
322 },
323 CompletionItem {
324 label: "match",
325 source_range: 210..210,
326 delete: 206..210,
327 insert: "match bar {\n ${1:_} => {$0\\},\n}",
328 detail: "match expr {}",
329 },
330 CompletionItem {
331 label: "not",
332 source_range: 210..210,
333 delete: 206..210,
334 insert: "!bar",
335 detail: "!expr",
336 },
337 CompletionItem {
338 label: "ref",
339 source_range: 210..210,
340 delete: 206..210,
341 insert: "&bar",
342 detail: "&expr",
343 },
344 CompletionItem {
345 label: "refm",
346 source_range: 210..210,
347 delete: 206..210,
348 insert: "&mut bar",
349 detail: "&mut expr",
350 },
351 CompletionItem {
352 label: "while",
353 source_range: 210..210,
354 delete: 206..210,
355 insert: "while let Some($1) = bar {\n $0\n}",
356 detail: "while let Some {}",
357 },
358 ]
359 "###
360 );
361 }
362
363 #[test]
364 fn postfix_completion_works_for_result() {
365 assert_debug_snapshot!(
366 do_postfix_completion(
367 r#"
368 enum Result<T, E> {
369 Ok(T),
370 Err(E),
371 }
372
373 fn main() {
374 let bar = Result::Ok(true);
375 bar.<|>
376 }
377 "#,
378 ),
379 @r###"
380 [
381 CompletionItem {
382 label: "box",
383 source_range: 211..211,
384 delete: 207..211,
385 insert: "Box::new(bar)",
386 detail: "Box::new(expr)",
387 },
388 CompletionItem {
389 label: "dbg",
390 source_range: 211..211,
391 delete: 207..211,
392 insert: "dbg!(bar)",
393 detail: "dbg!(expr)",
394 },
395 CompletionItem {
396 label: "ifl",
397 source_range: 211..211,
398 delete: 207..211,
399 insert: "if let Ok($1) = bar {\n $0\n}",
400 detail: "if let Ok {}",
401 },
402 CompletionItem {
403 label: "match",
404 source_range: 211..211,
405 delete: 207..211,
406 insert: "match bar {\n ${1:_} => {$0\\},\n}",
407 detail: "match expr {}",
408 },
409 CompletionItem {
410 label: "not",
411 source_range: 211..211,
412 delete: 207..211,
413 insert: "!bar",
414 detail: "!expr",
415 },
416 CompletionItem {
417 label: "ref",
418 source_range: 211..211,
419 delete: 207..211,
420 insert: "&bar",
421 detail: "&expr",
422 },
423 CompletionItem {
424 label: "refm",
425 source_range: 211..211,
426 delete: 207..211,
427 insert: "&mut bar",
428 detail: "&mut expr",
429 },
430 CompletionItem {
431 label: "while",
432 source_range: 211..211,
433 delete: 207..211,
434 insert: "while let Ok($1) = bar {\n $0\n}",
435 detail: "while let Ok {}",
436 },
437 ]
438 "###
439 );
440 }
441
442 #[test]
239 fn some_postfix_completions_ignored() { 443 fn some_postfix_completions_ignored() {
240 assert_debug_snapshot!( 444 assert_debug_snapshot!(
241 do_postfix_completion( 445 do_postfix_completion(
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index 4c27aade4..635fe5cf9 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -33,6 +33,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>, 33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>,
34} 34}
35 35
36<span class="keyword">trait</span> <span class="trait declaration">Bar</span> {
37 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span>;
38}
39
40<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> {
41 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span> {
42 <span class="keyword">self</span>.<span class="field">x</span>
43 }
44}
45
36<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span>: <span class="builtin_type">i32</span> = <span class="numeric_literal">0</span>; 46<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span>: <span class="builtin_type">i32</span> = <span class="numeric_literal">0</span>;
37 47
38<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> { 48<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> {
@@ -63,6 +73,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
63 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>; 73 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>;
64 } 74 }
65 75
76 <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> {
77 <span class="comment">// Do nothing</span>
78 }
79
66 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; 80 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>;
67 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; 81 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
68 <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>; 82 <span class="keyword">let</span> <span class="variable declaration">z</span> = &<span class="variable mutable">y</span>;
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index d53a39f57..be57eeb0a 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -403,12 +403,13 @@ fn highlight_element(
403 T![break] 403 T![break]
404 | T![continue] 404 | T![continue]
405 | T![else] 405 | T![else]
406 | T![for]
407 | T![if] 406 | T![if]
408 | T![loop] 407 | T![loop]
409 | T![match] 408 | T![match]
410 | T![return] 409 | T![return]
411 | T![while] => h | HighlightModifier::ControlFlow, 410 | T![while]
411 | T![in] => h | HighlightModifier::ControlFlow,
412 T![for] if !is_child_of_impl(element) => h | HighlightModifier::ControlFlow,
412 T![unsafe] => h | HighlightModifier::Unsafe, 413 T![unsafe] => h | HighlightModifier::Unsafe,
413 _ => h, 414 _ => h,
414 } 415 }
@@ -432,6 +433,13 @@ fn highlight_element(
432 } 433 }
433} 434}
434 435
436fn is_child_of_impl(element: SyntaxElement) -> bool {
437 match element.parent() {
438 Some(e) => e.kind() == IMPL_DEF,
439 _ => false,
440 }
441}
442
435fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 443fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
436 match def { 444 match def {
437 Definition::Macro(_) => HighlightTag::Macro, 445 Definition::Macro(_) => HighlightTag::Macro,
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index 13894869c..eb43a23da 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -17,6 +17,16 @@ struct Foo {
17 pub y: i32, 17 pub y: i32,
18} 18}
19 19
20trait Bar {
21 fn bar(&self) -> i32;
22}
23
24impl Bar for Foo {
25 fn bar(&self) -> i32 {
26 self.x
27 }
28}
29
20static mut STATIC_MUT: i32 = 0; 30static mut STATIC_MUT: i32 = 0;
21 31
22fn foo<'a, T>() -> T { 32fn foo<'a, T>() -> T {
@@ -47,6 +57,10 @@ fn main() {
47 STATIC_MUT = 1; 57 STATIC_MUT = 1;
48 } 58 }
49 59
60 for e in vec {
61 // Do nothing
62 }
63
50 let mut x = 42; 64 let mut x = 42;
51 let y = &mut x; 65 let y = &mut x;
52 let z = &y; 66 let z = &y;
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 22a84b50c..09908458d 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -60,7 +60,7 @@ fn main() -> Result<()> {
60 60
61fn setup_logging() -> Result<()> { 61fn setup_logging() -> Result<()> {
62 std::env::set_var("RUST_BACKTRACE", "short"); 62 std::env::set_var("RUST_BACKTRACE", "short");
63 env_logger::try_init()?; 63 env_logger::try_init_from_env("RA_LOG")?;
64 ra_prof::init(); 64 ra_prof::init();
65 Ok(()) 65 Ok(())
66} 66}
@@ -100,9 +100,8 @@ fn run_server() -> Result<()> {
100 if let Some(value) = &initialize_params.initialization_options { 100 if let Some(value) = &initialize_params.initialization_options {
101 config.update(value); 101 config.update(value);
102 } 102 }
103 if let Some(caps) = &initialize_params.capabilities.text_document { 103 config.update_caps(&initialize_params.capabilities);
104 config.update_caps(caps); 104
105 }
106 config 105 config
107 }; 106 };
108 107
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index ccc38e3bb..53aee833d 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -9,7 +9,7 @@
9 9
10use std::{ffi::OsString, path::PathBuf}; 10use std::{ffi::OsString, path::PathBuf};
11 11
12use lsp_types::TextDocumentClientCapabilities; 12use lsp_types::ClientCapabilities;
13use ra_flycheck::FlycheckConfig; 13use ra_flycheck::FlycheckConfig;
14use ra_ide::{CompletionConfig, InlayHintsConfig}; 14use ra_ide::{CompletionConfig, InlayHintsConfig};
15use ra_project_model::CargoConfig; 15use ra_project_model::CargoConfig;
@@ -70,6 +70,7 @@ pub struct ClientCapsConfig {
70 pub line_folding_only: bool, 70 pub line_folding_only: bool,
71 pub hierarchical_symbols: bool, 71 pub hierarchical_symbols: bool,
72 pub code_action_literals: bool, 72 pub code_action_literals: bool,
73 pub work_done_progress: bool,
73} 74}
74 75
75impl Default for Config { 76impl Default for Config {
@@ -208,30 +209,43 @@ impl Config {
208 } 209 }
209 } 210 }
210 211
211 pub fn update_caps(&mut self, caps: &TextDocumentClientCapabilities) { 212 pub fn update_caps(&mut self, caps: &ClientCapabilities) {
212 if let Some(value) = caps.definition.as_ref().and_then(|it| it.link_support) { 213 if let Some(doc_caps) = caps.text_document.as_ref() {
213 self.client_caps.location_link = value; 214 if let Some(value) = doc_caps.definition.as_ref().and_then(|it| it.link_support) {
214 } 215 self.client_caps.location_link = value;
215 if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { 216 }
216 self.client_caps.line_folding_only = value 217 if let Some(value) = doc_caps.folding_range.as_ref().and_then(|it| it.line_folding_only)
217 } 218 {
218 if let Some(value) = 219 self.client_caps.line_folding_only = value
219 caps.document_symbol.as_ref().and_then(|it| it.hierarchical_document_symbol_support) 220 }
220 { 221 if let Some(value) = doc_caps
221 self.client_caps.hierarchical_symbols = value 222 .document_symbol
222 } 223 .as_ref()
223 if let Some(value) = 224 .and_then(|it| it.hierarchical_document_symbol_support)
224 caps.code_action.as_ref().and_then(|it| Some(it.code_action_literal_support.is_some())) 225 {
225 { 226 self.client_caps.hierarchical_symbols = value
226 self.client_caps.code_action_literals = value; 227 }
227 } 228 if let Some(value) = doc_caps
228 self.completion.allow_snippets(false); 229 .code_action
229 if let Some(completion) = &caps.completion { 230 .as_ref()
230 if let Some(completion_item) = &completion.completion_item { 231 .and_then(|it| Some(it.code_action_literal_support.is_some()))
231 if let Some(value) = completion_item.snippet_support { 232 {
232 self.completion.allow_snippets(value); 233 self.client_caps.code_action_literals = value;
234 }
235 self.completion.allow_snippets(false);
236 if let Some(completion) = &doc_caps.completion {
237 if let Some(completion_item) = &completion.completion_item {
238 if let Some(value) = completion_item.snippet_support {
239 self.completion.allow_snippets(value);
240 }
233 } 241 }
234 } 242 }
235 } 243 }
244
245 if let Some(window_caps) = caps.window.as_ref() {
246 if let Some(value) = window_caps.work_done_progress {
247 self.client_caps.work_done_progress = value;
248 }
249 }
236 } 250 }
237} 251}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 3f12dd718..13d305b97 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -415,7 +415,8 @@ fn loop_turn(
415 }); 415 });
416 } 416 }
417 417
418 let show_progress = !loop_state.workspace_loaded; 418 let show_progress =
419 !loop_state.workspace_loaded && world_state.config.client_caps.work_done_progress;
419 420
420 if !loop_state.workspace_loaded 421 if !loop_state.workspace_loaded
421 && loop_state.roots_scanned == loop_state.roots_total 422 && loop_state.roots_scanned == loop_state.roots_total
@@ -750,12 +751,16 @@ fn on_check_task(
750 } 751 }
751 752
752 CheckTask::Status(progress) => { 753 CheckTask::Status(progress) => {
753 let params = lsp_types::ProgressParams { 754 if world_state.config.client_caps.work_done_progress {
754 token: lsp_types::ProgressToken::String("rustAnalyzer/cargoWatcher".to_string()), 755 let params = lsp_types::ProgressParams {
755 value: lsp_types::ProgressParamsValue::WorkDone(progress), 756 token: lsp_types::ProgressToken::String(
756 }; 757 "rustAnalyzer/cargoWatcher".to_string(),
757 let not = notification_new::<lsp_types::notification::Progress>(params); 758 ),
758 task_sender.send(Task::Notify(not)).unwrap(); 759 value: lsp_types::ProgressParamsValue::WorkDone(progress),
760 };
761 let not = notification_new::<lsp_types::notification::Progress>(params);
762 task_sender.send(Task::Notify(not)).unwrap();
763 }
759 } 764 }
760 }; 765 };
761 766
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index 4500d4982..33c2fd595 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -264,7 +264,7 @@ fn semantic_token_type_and_modifiers(
264 HighlightTag::Trait => lsp_types::SemanticTokenType::INTERFACE, 264 HighlightTag::Trait => lsp_types::SemanticTokenType::INTERFACE,
265 HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE, 265 HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
266 HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE, 266 HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE,
267 HighlightTag::Field => lsp_types::SemanticTokenType::MEMBER, 267 HighlightTag::Field => lsp_types::SemanticTokenType::PROPERTY,
268 HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION, 268 HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION,
269 HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE, 269 HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE,
270 HighlightTag::Constant => { 270 HighlightTag::Constant => {
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs
index 8756ad4a3..9acbae066 100644
--- a/crates/rust-analyzer/tests/heavy_tests/support.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/support.rs
@@ -80,6 +80,7 @@ impl<'a> Project<'a> {
80 client_caps: ClientCapsConfig { 80 client_caps: ClientCapsConfig {
81 location_link: true, 81 location_link: true,
82 code_action_literals: true, 82 code_action_literals: true,
83 work_done_progress: true,
83 ..Default::default() 84 ..Default::default()
84 }, 85 },
85 with_sysroot: self.with_sysroot, 86 with_sysroot: self.with_sysroot,
diff --git a/docs/dev/README.md b/docs/dev/README.md
index f230dc1db..a20ead0b6 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -134,7 +134,7 @@ To log all communication between the server and the client, there are two choice
134 134
135* you can log on the server side, by running something like 135* you can log on the server side, by running something like
136 ``` 136 ```
137 env RUST_LOG=gen_lsp_server=trace code . 137 env RA_LOG=gen_lsp_server=trace code .
138 ``` 138 ```
139 139
140* you can log on the client side, by enabling `"rust-analyzer.trace.server": 140* you can log on the client side, by enabling `"rust-analyzer.trace.server":
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index f6ce0accf..d750c7705 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -108,7 +108,7 @@ Here are some useful self-diagnostic commands:
108 108
109* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary 109* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary
110* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests 110* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests
111* To enable server-side logging, run with `env RUST_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel. 111* To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel.
112* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel. 112* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel.
113* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools. 113* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools.
114 114
diff --git a/editors/code/.vscodeignore b/editors/code/.vscodeignore
index ac411f8e2..257b744bf 100644
--- a/editors/code/.vscodeignore
+++ b/editors/code/.vscodeignore
@@ -3,5 +3,6 @@
3!package.json 3!package.json
4!package-lock.json 4!package-lock.json
5!ra_syntax_tree.tmGrammar.json 5!ra_syntax_tree.tmGrammar.json
6!rust.tmGrammar.json
6!icon.png 7!icon.png
7!README.md 8!README.md
diff --git a/editors/code/package.json b/editors/code/package.json
index c6fc13519..f46684c76 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -479,6 +479,11 @@
479 ], 479 ],
480 "grammars": [ 480 "grammars": [
481 { 481 {
482 "language": "rust",
483 "scopeName": "source.rust",
484 "path": "rust.tmGrammar.json"
485 },
486 {
482 "language": "ra_syntax_tree", 487 "language": "ra_syntax_tree",
483 "scopeName": "source.ra_syntax_tree", 488 "scopeName": "source.ra_syntax_tree",
484 "path": "ra_syntax_tree.tmGrammar.json" 489 "path": "ra_syntax_tree.tmGrammar.json"
@@ -596,28 +601,28 @@
596 "support.type.primitive" 601 "support.type.primitive"
597 ], 602 ],
598 "lifetime": [ 603 "lifetime": [
599 "entity.name.lifetime.rust" 604 "storage.modifier.lifetime.rust"
600 ], 605 ],
601 "typeAlias": [ 606 "typeAlias": [
602 "entity.name.typeAlias" 607 "entity.name.type.typeAlias"
603 ], 608 ],
604 "union": [ 609 "union": [
605 "entity.name.union" 610 "entity.name.type.union"
606 ], 611 ],
607 "struct": [ 612 "struct": [
608 "entity.name.type.struct" 613 "entity.name.type.struct"
609 ], 614 ],
610 "keyword.unsafe": [
611 "keyword.other.unsafe"
612 ],
613 "keyword": [ 615 "keyword": [
614 "keyword" 616 "keyword.other"
615 ], 617 ],
616 "keyword.controlFlow": [ 618 "keyword.controlFlow": [
617 "keyword.control" 619 "keyword.control"
618 ], 620 ],
619 "variable.constant": [ 621 "variable.constant": [
620 "entity.name.constant" 622 "variable.other.constant"
623 ],
624 "formatSpecifier": [
625 "punctuation.section.embedded"
621 ] 626 ]
622 } 627 }
623 } 628 }
diff --git a/editors/code/rust.tmGrammar.json b/editors/code/rust.tmGrammar.json
new file mode 100644
index 000000000..27982c13a
--- /dev/null
+++ b/editors/code/rust.tmGrammar.json
@@ -0,0 +1,681 @@
1{
2 "name": "Rust",
3 "scopeName": "source.rust",
4 "patterns": [
5 {
6 "comment": "Implementation",
7 "begin": "\\b(impl)\\b",
8 "end": "\\{",
9 "beginCaptures": {
10 "1": {
11 "name": "storage.type.rust"
12 }
13 },
14 "patterns": [
15 {
16 "include": "#block_comment"
17 },
18 {
19 "include": "#line_comment"
20 },
21 {
22 "include": "#sigils"
23 },
24 {
25 "include": "#mut"
26 },
27 {
28 "include": "#dyn"
29 },
30 {
31 "include": "#ref_lifetime"
32 },
33 {
34 "include": "#core_types"
35 },
36 {
37 "include": "#core_marker"
38 },
39 {
40 "include": "#core_traits"
41 },
42 {
43 "include": "#std_types"
44 },
45 {
46 "include": "#std_traits"
47 },
48 {
49 "include": "#type_params"
50 },
51 {
52 "include": "#where"
53 },
54 {
55 "name": "storage.type.rust",
56 "match": "\\bfor\\b"
57 },
58 {
59 "include": "#type"
60 }
61 ]
62 },
63 {
64 "include": "#block_doc_comment"
65 },
66 {
67 "include": "#block_comment"
68 },
69 {
70 "include": "#line_doc_comment"
71 },
72 {
73 "include": "#line_comment"
74 },
75 {
76 "comment": "Attribute",
77 "name": "meta.attribute.rust",
78 "begin": "#\\!?\\[",
79 "end": "\\]",
80 "patterns": [
81 {
82 "include": "#string_literal"
83 },
84 {
85 "include": "#block_doc_comment"
86 },
87 {
88 "include": "#block_comment"
89 },
90 {
91 "include": "#line_doc_comment"
92 },
93 {
94 "include": "#line_comment"
95 }
96 ]
97 },
98 {
99 "comment": "Single-quote string literal (character)",
100 "name": "string.quoted.single.rust",
101 "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]?|.))'"
102 },
103 {
104 "include": "#string_literal"
105 },
106 {
107 "include": "#raw_string_literal"
108 },
109 {
110 "comment": "Floating point literal (fraction)",
111 "name": "constant.numeric.float.rust",
112 "match": "\\b[0-9][0-9_]*\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\b"
113 },
114 {
115 "comment": "Floating point literal (exponent)",
116 "name": "constant.numeric.float.rust",
117 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\b"
118 },
119 {
120 "comment": "Floating point literal (typed)",
121 "name": "constant.numeric.float.rust",
122 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\b"
123 },
124 {
125 "comment": "Integer literal (decimal)",
126 "name": "constant.numeric.integer.decimal.rust",
127 "match": "\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\b"
128 },
129 {
130 "comment": "Integer literal (hexadecimal)",
131 "name": "constant.numeric.integer.hexadecimal.rust",
132 "match": "\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\b"
133 },
134 {
135 "comment": "Integer literal (octal)",
136 "name": "constant.numeric.integer.octal.rust",
137 "match": "\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\b"
138 },
139 {
140 "comment": "Integer literal (binary)",
141 "name": "constant.numeric.integer.binary.rust",
142 "match": "\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\b"
143 },
144 {
145 "comment": "Static storage modifier",
146 "name": "storage.modifier.static.rust",
147 "match": "\\bstatic\\b"
148 },
149 {
150 "comment": "Boolean constant",
151 "name": "constant.language.boolean.rust",
152 "match": "\\b(true|false)\\b"
153 },
154 {
155 "comment": "Control keyword",
156 "name": "keyword.control.rust",
157 "match": "\\b(async|await|break|continue|else|if|in|for|loop|match|return|try|while)\\b"
158 },
159 {
160 "comment": "Keyword",
161 "name": "keyword.other.rust",
162 "match": "\\b(crate|extern|mod|let|ref|use|super|move|as)\\b"
163 },
164 {
165 "comment": "Reserved keyword",
166 "name": "invalid.deprecated.rust",
167 "match": "\\b(abstract|alignof|become|do|final|macro|offsetof|override|priv|proc|pure|sizeof|typeof|virtual|yield)\\b"
168 },
169 {
170 "include": "#unsafe"
171 },
172 {
173 "include": "#sigils"
174 },
175 {
176 "include": "#self"
177 },
178 {
179 "include": "#mut"
180 },
181 {
182 "include": "#dyn"
183 },
184 {
185 "include": "#impl"
186 },
187 {
188 "include": "#box"
189 },
190 {
191 "include": "#lifetime"
192 },
193 {
194 "include": "#ref_lifetime"
195 },
196 {
197 "include": "#const"
198 },
199 {
200 "include": "#pub"
201 },
202 {
203 "comment": "Miscellaneous operator",
204 "name": "keyword.operator.misc.rust",
205 "match": "(=>|::)"
206 },
207 {
208 "comment": "Comparison operator",
209 "name": "keyword.operator.comparison.rust",
210 "match": "(&&|\\|\\||==|!=)"
211 },
212 {
213 "comment": "Assignment operator",
214 "name": "keyword.operator.assignment.rust",
215 "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)"
216 },
217 {
218 "comment": "Arithmetic operator",
219 "name": "keyword.operator.arithmetic.rust",
220 "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)"
221 },
222 {
223 "comment": "Comparison operator (second group because of regex precedence)",
224 "name": "keyword.operator.comparison.rust",
225 "match": "(<=|>=|<|>)"
226 },
227 {
228 "include": "#core_types"
229 },
230 {
231 "include": "#core_vars"
232 },
233 {
234 "include": "#core_marker"
235 },
236 {
237 "include": "#core_traits"
238 },
239 {
240 "include": "#std_types"
241 },
242 {
243 "include": "#std_traits"
244 },
245 {
246 "comment": "Built-in macro",
247 "name": "support.function.builtin.rust",
248 "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)!"
249 },
250 {
251 "comment": "Core macro",
252 "name": "support.function.core.rust",
253 "match": "\\b(panic|assert|assert_eq|assert_ne|debug_assert|debug_assert_eq|debug_assert_ne|try|write|writeln|unreachable|unimplemented)!"
254 },
255 {
256 "comment": "Standard library macro",
257 "name": "support.function.std.rust",
258 "match": "\\b(format|print|println|eprint|eprintln|select|vec)!"
259 },
260 {
261 "comment": "Logging macro",
262 "name": "support.function.log.rust",
263 "match": "\\b(log|error|warn|info|debug|trace|log_enabled)!"
264 },
265 {
266 "comment": "Invokation of a macro",
267 "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\!)\\s*[({\\[]",
268 "captures": {
269 "1": {
270 "name": "entity.name.function.macro.rust"
271 }
272 }
273 },
274 {
275 "comment": "Function call",
276 "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(",
277 "captures": {
278 "1": {
279 "name": "entity.name.function.rust"
280 }
281 }
282 },
283 {
284 "comment": "Function call with type parameters",
285 "begin": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*(::)(?=\\s*<.*>\\s*\\()",
286 "end": "\\(",
287 "captures": {
288 "1": {
289 "name": "entity.name.function.rust"
290 },
291 "2": {
292 "name": "keyword.operator.misc.rust"
293 }
294 },
295 "patterns": [
296 {
297 "include": "#type_params"
298 }
299 ]
300 },
301 {
302 "comment": "Function definition",
303 "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)",
304 "end": "[\\{;]",
305 "beginCaptures": {
306 "1": {
307 "name": "keyword.other.fn.rust"
308 },
309 "2": {
310 "name": "entity.name.function.rust"
311 }
312 },
313 "patterns": [
314 {
315 "include": "#block_comment"
316 },
317 {
318 "include": "#line_comment"
319 },
320 {
321 "include": "#sigils"
322 },
323 {
324 "include": "#self"
325 },
326 {
327 "include": "#mut"
328 },
329 {
330 "include": "#dyn"
331 },
332 {
333 "include": "#impl"
334 },
335 {
336 "include": "#ref_lifetime"
337 },
338 {
339 "include": "#core_types"
340 },
341 {
342 "include": "#core_marker"
343 },
344 {
345 "include": "#core_traits"
346 },
347 {
348 "include": "#std_types"
349 },
350 {
351 "include": "#std_traits"
352 },
353 {
354 "include": "#type_params"
355 },
356 {
357 "include": "#const"
358 },
359 {
360 "include": "#where"
361 },
362 {
363 "include": "#unsafe"
364 },
365 {
366 "comment": "Function arguments",
367 "match": "\bfn\b",
368 "name": "keyword.other.fn.rust"
369 }
370 ]
371 },
372 {
373 "comment": "Type declaration",
374 "begin": "\\b(enum|struct|trait|union)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
375 "end": "[\\{\\(;]",
376 "beginCaptures": {
377 "1": {
378 "name": "storage.type.rust"
379 },
380 "2": {
381 "name": "entity.name.type.rust"
382 }
383 },
384 "patterns": [
385 {
386 "include": "#block_comment"
387 },
388 {
389 "include": "#line_comment"
390 },
391 {
392 "include": "#core_traits"
393 },
394 {
395 "include": "#std_traits"
396 },
397 {
398 "include": "#type_params"
399 },
400 {
401 "include": "#core_types"
402 },
403 {
404 "include": "#pub"
405 },
406 {
407 "include": "#where"
408 }
409 ]
410 },
411 {
412 "comment": "Type alias",
413 "begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
414 "end": ";",
415 "beginCaptures": {
416 "1": {
417 "name": "storage.type.rust"
418 },
419 "2": {
420 "name": "entity.name.type.rust"
421 }
422 },
423 "patterns": [
424 {
425 "include": "#block_comment"
426 },
427 {
428 "include": "#line_comment"
429 },
430 {
431 "include": "#sigils"
432 },
433 {
434 "include": "#mut"
435 },
436 {
437 "include": "#dyn"
438 },
439 {
440 "include": "#impl"
441 },
442 {
443 "include": "#lifetime"
444 },
445 {
446 "include": "#ref_lifetime"
447 },
448 {
449 "include": "#core_types"
450 },
451 {
452 "include": "#core_marker"
453 },
454 {
455 "include": "#core_traits"
456 },
457 {
458 "include": "#std_types"
459 },
460 {
461 "include": "#std_traits"
462 },
463 {
464 "include": "#type_params"
465 }
466 ]
467 }
468 ],
469 "repository": {
470 "block_doc_comment": {
471 "comment": "Block documentation comment",
472 "name": "comment.block.documentation.rust",
473 "begin": "/\\*[\\*!](?![\\*/])",
474 "end": "\\*/",
475 "patterns": [
476 {
477 "include": "#block_doc_comment"
478 },
479 {
480 "include": "#block_comment"
481 }
482 ]
483 },
484 "block_comment": {
485 "comment": "Block comment",
486 "name": "comment.block.rust",
487 "begin": "/\\*",
488 "end": "\\*/",
489 "patterns": [
490 {
491 "include": "#block_doc_comment"
492 },
493 {
494 "include": "#block_comment"
495 }
496 ]
497 },
498 "line_doc_comment": {
499 "comment": "Single-line documentation comment",
500 "name": "comment.line.documentation.rust",
501 "begin": "//[!/](?=[^/])",
502 "end": "$"
503 },
504 "line_comment": {
505 "comment": "Single-line comment",
506 "name": "comment.line.double-slash.rust",
507 "begin": "//",
508 "end": "$"
509 },
510 "escaped_character": {
511 "name": "constant.character.escape.rust",
512 "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]?|.)"
513 },
514 "string_literal": {
515 "comment": "Double-quote string literal",
516 "name": "string.quoted.double.rust",
517 "begin": "b?\"",
518 "end": "\"",
519 "patterns": [
520 {
521 "include": "#escaped_character"
522 }
523 ]
524 },
525 "raw_string_literal": {
526 "comment": "Raw double-quote string literal",
527 "name": "string.quoted.double.raw.rust",
528 "begin": "b?r(#*)\"",
529 "end": "\"\\1"
530 },
531 "sigils": {
532 "comment": "Sigil",
533 "name": "keyword.operator.sigil.rust",
534 "match": "[&*](?=[a-zA-Z0-9_\\(\\[\\|\\\"]+)"
535 },
536 "self": {
537 "comment": "Self variable",
538 "name": "variable.language.rust",
539 "match": "\\bself\\b"
540 },
541 "mut": {
542 "comment": "Mutable storage modifier",
543 "name": "storage.modifier.mut.rust",
544 "match": "\\bmut\\b"
545 },
546 "dyn": {
547 "comment": "Dynamic modifier",
548 "name": "storage.modifier.dyn.rust",
549 "match": "\\bdyn\\b"
550 },
551 "impl": {
552 "comment": "Existential type modifier",
553 "name": "storage.modifier.impl.rust",
554 "match": "\\bimpl\\b"
555 },
556 "box": {
557 "comment": "Box storage modifier",
558 "name": "storage.modifier.box.rust",
559 "match": "\\bbox\\b"
560 },
561 "const": {
562 "comment": "Const storage modifier",
563 "name": "storage.modifier.const.rust",
564 "match": "\\bconst\\b"
565 },
566 "pub": {
567 "comment": "Visibility modifier",
568 "name": "storage.modifier.visibility.rust",
569 "match": "\\bpub\\b"
570 },
571 "unsafe": {
572 "comment": "Unsafe code keyword",
573 "name": "keyword.other.unsafe.rust",
574 "match": "\\bunsafe\\b"
575 },
576 "where": {
577 "comment": "Generic where clause",
578 "name": "keyword.other.where.rust",
579 "match": "\\bwhere\\b"
580 },
581 "lifetime": {
582 "comment": "Named lifetime",
583 "name": "storage.modifier.lifetime.rust",
584 "match": "'([a-zA-Z_][a-zA-Z0-9_]*)\\b"
585 },
586 "ref_lifetime": {
587 "comment": "Reference with named lifetime",
588 "match": "(&)('[a-zA-Z_][a-zA-Z0-9_]*)\\b",
589 "captures": {
590 "1": {
591 "name": "keyword.operator.sigil.rust"
592 },
593 "2": {
594 "name": "storage.modifier.lifetime.rust"
595 }
596 }
597 },
598 "core_types": {
599 "comment": "Built-in/core type",
600 "name": "support.type.primitive",
601 "match": "\\b(bool|char|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64|str|Self)\\b"
602 },
603 "core_vars": {
604 "comment": "Core type variant",
605 "name": "support.constant.core.rust",
606 "match": "\\b(Some|None|Ok|Err)\\b"
607 },
608 "core_marker": {
609 "comment": "Core trait (marker)",
610 "name": "entity.name.type.marker.rust",
611 "match": "\\b(Copy|Send|Sized|Sync)\\b"
612 },
613 "core_traits": {
614 "comment": "Core trait",
615 "name": "entity.name.type.core.rust",
616 "match": "\\b(Drop|Fn|FnMut|FnOnce|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator)\\b"
617 },
618 "std_types": {
619 "comment": "Standard library type",
620 "name": "entity.name.type.class.std.rust",
621 "match": "\\b(Box|String|Vec|Path|PathBuf|Option|Result)\\b"
622 },
623 "std_traits": {
624 "comment": "Standard library trait",
625 "name": "entity.name.type.std.rust",
626 "match": "\\b(ToOwned|ToString)\\b"
627 },
628 "type": {
629 "comment": "A type",
630 "name": "entity.name.type.rust",
631 "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b"
632 },
633 "type_params": {
634 "comment": "Type parameters",
635 "name": "meta.type_params.rust",
636 "begin": "<(?![=<])",
637 "end": "(?<![-])>",
638 "patterns": [
639 {
640 "include": "#block_comment"
641 },
642 {
643 "include": "#line_comment"
644 },
645 {
646 "include": "#sigils"
647 },
648 {
649 "include": "#mut"
650 },
651 {
652 "include": "#dyn"
653 },
654 {
655 "include": "#impl"
656 },
657 {
658 "include": "#lifetime"
659 },
660 {
661 "include": "#core_types"
662 },
663 {
664 "include": "#core_marker"
665 },
666 {
667 "include": "#core_traits"
668 },
669 {
670 "include": "#std_types"
671 },
672 {
673 "include": "#std_traits"
674 },
675 {
676 "include": "#type_params"
677 }
678 ]
679 }
680 }
681} \ No newline at end of file