aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
10 files changed, 299 insertions, 40 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,