diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/change.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 18 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_postfix.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_context.rs | 21 | ||||
-rw-r--r-- | crates/ra_ide/src/display.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/expand_macro.rs | 13 | ||||
-rw-r--r-- | crates/ra_ide/src/extend_selection.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 110 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 80 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/src/marks.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/rainbow_highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 65 |
15 files changed, 194 insertions, 155 deletions
diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide/src/change.rs index 4a76d1dd8..387a9cafb 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide/src/change.rs | |||
@@ -270,7 +270,6 @@ impl RootDatabase { | |||
270 | 270 | ||
271 | self.query(hir::db::AstIdMapQuery).sweep(sweep); | 271 | self.query(hir::db::AstIdMapQuery).sweep(sweep); |
272 | 272 | ||
273 | self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); | ||
274 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); | 273 | self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); |
275 | 274 | ||
276 | self.query(hir::db::ExprScopesQuery).sweep(sweep); | 275 | self.query(hir::db::ExprScopesQuery).sweep(sweep); |
@@ -309,7 +308,6 @@ impl RootDatabase { | |||
309 | hir::db::StructDataQuery | 308 | hir::db::StructDataQuery |
310 | hir::db::EnumDataQuery | 309 | hir::db::EnumDataQuery |
311 | hir::db::TraitDataQuery | 310 | hir::db::TraitDataQuery |
312 | hir::db::RawItemsWithSourceMapQuery | ||
313 | hir::db::RawItemsQuery | 311 | hir::db::RawItemsQuery |
314 | hir::db::CrateDefMapQuery | 312 | hir::db::CrateDefMapQuery |
315 | hir::db::GenericParamsQuery | 313 | hir::db::GenericParamsQuery |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 28f94e0a7..cc1f7c830 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use either::Either; | 3 | use hir::{Adt, PathResolution, ScopeDef}; |
4 | use hir::{Adt, HasSource, PathResolution}; | ||
5 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
6 | use test_utils::tested_by; | 5 | use test_utils::tested_by; |
7 | 6 | ||
@@ -19,17 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
19 | match def { | 18 | match def { |
20 | hir::ModuleDef::Module(module) => { | 19 | hir::ModuleDef::Module(module) => { |
21 | let module_scope = module.scope(ctx.db); | 20 | let module_scope = module.scope(ctx.db); |
22 | for (name, def, import) in module_scope { | 21 | for (name, def) in module_scope { |
23 | if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { | 22 | if ctx.use_item_syntax.is_some() { |
24 | if ctx.use_item_syntax.is_some() { | 23 | if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { |
25 | tested_by!(dont_complete_primitive_in_use); | 24 | tested_by!(dont_complete_primitive_in_use); |
26 | continue; | 25 | continue; |
27 | } | 26 | } |
28 | } | 27 | if let ScopeDef::Unknown = def { |
29 | if Some(module) == ctx.module { | 28 | if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { |
30 | if let Some(import) = import { | 29 | if &name_ref.syntax().text() == name.to_string().as_str() { |
31 | if let Either::Left(use_tree) = import.source(ctx.db).value { | ||
32 | if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { | ||
33 | // for `use self::foo<|>`, don't suggest `foo` as a completion | 30 | // for `use self::foo<|>`, don't suggest `foo` as a completion |
34 | tested_by!(dont_complete_current_use); | 31 | tested_by!(dont_complete_current_use); |
35 | continue; | 32 | continue; |
@@ -37,6 +34,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
37 | } | 34 | } |
38 | } | 35 | } |
39 | } | 36 | } |
37 | |||
40 | acc.add_resolution(ctx, name.to_string(), &def); | 38 | acc.add_resolution(ctx, name.to_string(), &def); |
41 | } | 39 | } |
42 | } | 40 | } |
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 646a30c76..5470dc291 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | }; | 12 | }; |
13 | 13 | ||
14 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | 14 | pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { |
15 | if ctx.db.feature_flags.get("completion.enable-postfix") == false { | 15 | if !ctx.db.feature_flags.get("completion.enable-postfix") { |
16 | return; | 16 | return; |
17 | } | 17 | } |
18 | 18 | ||
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 981da2b79..48d69f7e5 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -19,6 +19,7 @@ pub(crate) struct CompletionContext<'a> { | |||
19 | pub(super) offset: TextUnit, | 19 | pub(super) offset: TextUnit, |
20 | pub(super) token: SyntaxToken, | 20 | pub(super) token: SyntaxToken, |
21 | pub(super) module: Option<hir::Module>, | 21 | pub(super) module: Option<hir::Module>, |
22 | pub(super) name_ref_syntax: Option<ast::NameRef>, | ||
22 | pub(super) function_syntax: Option<ast::FnDef>, | 23 | pub(super) function_syntax: Option<ast::FnDef>, |
23 | pub(super) use_item_syntax: Option<ast::UseItem>, | 24 | pub(super) use_item_syntax: Option<ast::UseItem>, |
24 | pub(super) record_lit_syntax: Option<ast::RecordLit>, | 25 | pub(super) record_lit_syntax: Option<ast::RecordLit>, |
@@ -69,6 +70,7 @@ impl<'a> CompletionContext<'a> { | |||
69 | token, | 70 | token, |
70 | offset: position.offset, | 71 | offset: position.offset, |
71 | module, | 72 | module, |
73 | name_ref_syntax: None, | ||
72 | function_syntax: None, | 74 | function_syntax: None, |
73 | use_item_syntax: None, | 75 | use_item_syntax: None, |
74 | record_lit_syntax: None, | 76 | record_lit_syntax: None, |
@@ -142,6 +144,8 @@ impl<'a> CompletionContext<'a> { | |||
142 | } | 144 | } |
143 | 145 | ||
144 | fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { | 146 | fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { |
147 | self.name_ref_syntax = | ||
148 | find_node_at_offset(original_file.syntax(), name_ref.syntax().text_range().start()); | ||
145 | let name_range = name_ref.syntax().text_range(); | 149 | let name_range = name_ref.syntax().text_range(); |
146 | if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { | 150 | if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { |
147 | self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); | 151 | self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); |
@@ -239,16 +243,15 @@ impl<'a> CompletionContext<'a> { | |||
239 | .expr() | 243 | .expr() |
240 | .map(|e| e.syntax().text_range()) | 244 | .map(|e| e.syntax().text_range()) |
241 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); | 245 | .and_then(|r| find_node_with_range(original_file.syntax(), r)); |
242 | self.dot_receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = | 246 | self.dot_receiver_is_ambiguous_float_literal = |
243 | &self.dot_receiver | 247 | if let Some(ast::Expr::Literal(l)) = &self.dot_receiver { |
244 | { | 248 | match l.kind() { |
245 | match l.kind() { | 249 | ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'), |
246 | ast::LiteralKind::FloatNumber { suffix: _ } => l.token().text().ends_with('.'), | 250 | _ => false, |
247 | _ => false, | 251 | } |
252 | } else { | ||
253 | false | ||
248 | } | 254 | } |
249 | } else { | ||
250 | false | ||
251 | } | ||
252 | } | 255 | } |
253 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { | 256 | if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { |
254 | // As above | 257 | // As above |
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 30617412a..fbe89841b 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs | |||
@@ -15,7 +15,7 @@ pub use function_signature::FunctionSignature; | |||
15 | pub use navigation_target::NavigationTarget; | 15 | pub use navigation_target::NavigationTarget; |
16 | pub use structure::{file_structure, StructureNode}; | 16 | pub use structure::{file_structure, StructureNode}; |
17 | 17 | ||
18 | pub(crate) use navigation_target::{description_from_symbol, docs_from_symbol, ToNav}; | 18 | pub(crate) use navigation_target::ToNav; |
19 | pub(crate) use short_label::ShortLabel; | 19 | pub(crate) use short_label::ShortLabel; |
20 | 20 | ||
21 | pub(crate) fn function_label(node: &ast::FnDef) -> String { | 21 | pub(crate) fn function_label(node: &ast::FnDef) -> String { |
diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs index 862c03304..bdbc31704 100644 --- a/crates/ra_ide/src/expand_macro.rs +++ b/crates/ra_ide/src/expand_macro.rs | |||
@@ -86,21 +86,18 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
86 | let mut is_next = |f: fn(SyntaxKind) -> bool, default| -> bool { | 86 | let mut is_next = |f: fn(SyntaxKind) -> bool, default| -> bool { |
87 | token_iter.peek().map(|it| f(it.kind())).unwrap_or(default) | 87 | token_iter.peek().map(|it| f(it.kind())).unwrap_or(default) |
88 | }; | 88 | }; |
89 | let is_last = |f: fn(SyntaxKind) -> bool, default| -> bool { | 89 | let is_last = |
90 | last.map(|it| f(it)).unwrap_or(default) | 90 | |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) }; |
91 | }; | ||
92 | 91 | ||
93 | res += &match token.kind() { | 92 | res += &match token.kind() { |
94 | k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { | 93 | k if is_text(k) && is_next(|it| !it.is_punct(), true) => token.text().to_string() + " ", |
95 | token.text().to_string() + " " | ||
96 | } | ||
97 | L_CURLY if is_next(|it| it != R_CURLY, true) => { | 94 | L_CURLY if is_next(|it| it != R_CURLY, true) => { |
98 | indent += 1; | 95 | indent += 1; |
99 | let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; | 96 | let leading_space = if is_last(is_text, false) { " " } else { "" }; |
100 | format!("{}{{\n{}", leading_space, " ".repeat(indent)) | 97 | format!("{}{{\n{}", leading_space, " ".repeat(indent)) |
101 | } | 98 | } |
102 | R_CURLY if is_last(|it| it != L_CURLY, true) => { | 99 | R_CURLY if is_last(|it| it != L_CURLY, true) => { |
103 | indent = indent.checked_sub(1).unwrap_or(0); | 100 | indent = indent.saturating_sub(1); |
104 | format!("\n{}}}", " ".repeat(indent)) | 101 | format!("\n{}}}", " ".repeat(indent)) |
105 | } | 102 | } |
106 | R_CURLY => format!("}}\n{}", " ".repeat(indent)), | 103 | R_CURLY => format!("}}\n{}", " ".repeat(indent)), |
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index c096ca6ae..1ec41a117 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs | |||
@@ -138,7 +138,7 @@ fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange | |||
138 | ws.text_range() | 138 | ws.text_range() |
139 | } | 139 | } |
140 | 140 | ||
141 | fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { | 141 | fn pick_best(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { |
142 | return if priority(&r) > priority(&l) { r } else { l }; | 142 | return if priority(&r) > priority(&l) { r } else { l }; |
143 | fn priority(n: &SyntaxToken) -> usize { | 143 | fn priority(n: &SyntaxToken) -> usize { |
144 | match n.kind() { | 144 | match n.kind() { |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 184555792..79d332e8c 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -258,7 +258,7 @@ mod tests { | |||
258 | } | 258 | } |
259 | 259 | ||
260 | #[test] | 260 | #[test] |
261 | fn goto_definition_works_in_items() { | 261 | fn goto_def_in_items() { |
262 | check_goto( | 262 | check_goto( |
263 | " | 263 | " |
264 | //- /lib.rs | 264 | //- /lib.rs |
@@ -271,7 +271,7 @@ mod tests { | |||
271 | } | 271 | } |
272 | 272 | ||
273 | #[test] | 273 | #[test] |
274 | fn goto_definition_works_at_start_of_item() { | 274 | fn goto_def_at_start_of_item() { |
275 | check_goto( | 275 | check_goto( |
276 | " | 276 | " |
277 | //- /lib.rs | 277 | //- /lib.rs |
@@ -305,7 +305,7 @@ mod tests { | |||
305 | } | 305 | } |
306 | 306 | ||
307 | #[test] | 307 | #[test] |
308 | fn goto_definition_works_for_module_declaration() { | 308 | fn goto_def_for_module_declaration() { |
309 | check_goto( | 309 | check_goto( |
310 | " | 310 | " |
311 | //- /lib.rs | 311 | //- /lib.rs |
@@ -332,8 +332,8 @@ mod tests { | |||
332 | } | 332 | } |
333 | 333 | ||
334 | #[test] | 334 | #[test] |
335 | fn goto_definition_works_for_macros() { | 335 | fn goto_def_for_macros() { |
336 | covers!(goto_definition_works_for_macros); | 336 | covers!(goto_def_for_macros); |
337 | check_goto( | 337 | check_goto( |
338 | " | 338 | " |
339 | //- /lib.rs | 339 | //- /lib.rs |
@@ -349,8 +349,8 @@ mod tests { | |||
349 | } | 349 | } |
350 | 350 | ||
351 | #[test] | 351 | #[test] |
352 | fn goto_definition_works_for_macros_from_other_crates() { | 352 | fn goto_def_for_macros_from_other_crates() { |
353 | covers!(goto_definition_works_for_macros); | 353 | covers!(goto_def_for_macros); |
354 | check_goto( | 354 | check_goto( |
355 | " | 355 | " |
356 | //- /lib.rs | 356 | //- /lib.rs |
@@ -369,7 +369,7 @@ mod tests { | |||
369 | } | 369 | } |
370 | 370 | ||
371 | #[test] | 371 | #[test] |
372 | fn goto_definition_works_for_macros_in_use_tree() { | 372 | fn goto_def_for_macros_in_use_tree() { |
373 | check_goto( | 373 | check_goto( |
374 | " | 374 | " |
375 | //- /lib.rs | 375 | //- /lib.rs |
@@ -385,7 +385,7 @@ mod tests { | |||
385 | } | 385 | } |
386 | 386 | ||
387 | #[test] | 387 | #[test] |
388 | fn goto_definition_works_for_macro_defined_fn_with_arg() { | 388 | fn goto_def_for_macro_defined_fn_with_arg() { |
389 | check_goto( | 389 | check_goto( |
390 | " | 390 | " |
391 | //- /lib.rs | 391 | //- /lib.rs |
@@ -405,7 +405,7 @@ mod tests { | |||
405 | } | 405 | } |
406 | 406 | ||
407 | #[test] | 407 | #[test] |
408 | fn goto_definition_works_for_macro_defined_fn_no_arg() { | 408 | fn goto_def_for_macro_defined_fn_no_arg() { |
409 | check_goto( | 409 | check_goto( |
410 | " | 410 | " |
411 | //- /lib.rs | 411 | //- /lib.rs |
@@ -425,8 +425,44 @@ mod tests { | |||
425 | } | 425 | } |
426 | 426 | ||
427 | #[test] | 427 | #[test] |
428 | fn goto_definition_works_for_methods() { | 428 | fn goto_definition_works_for_macro_inside_pattern() { |
429 | covers!(goto_definition_works_for_methods); | 429 | check_goto( |
430 | " | ||
431 | //- /lib.rs | ||
432 | macro_rules! foo {() => {0}} | ||
433 | |||
434 | fn bar() { | ||
435 | match (0,1) { | ||
436 | (<|>foo!(), _) => {} | ||
437 | } | ||
438 | } | ||
439 | ", | ||
440 | "foo MACRO_CALL FileId(1) [0; 28) [13; 16)", | ||
441 | "macro_rules! foo {() => {0}}|foo", | ||
442 | ); | ||
443 | } | ||
444 | |||
445 | #[test] | ||
446 | fn goto_definition_works_for_macro_inside_match_arm_lhs() { | ||
447 | check_goto( | ||
448 | " | ||
449 | //- /lib.rs | ||
450 | macro_rules! foo {() => {0}} | ||
451 | |||
452 | fn bar() { | ||
453 | match 0 { | ||
454 | <|>foo!() => {} | ||
455 | } | ||
456 | } | ||
457 | ", | ||
458 | "foo MACRO_CALL FileId(1) [0; 28) [13; 16)", | ||
459 | "macro_rules! foo {() => {0}}|foo", | ||
460 | ); | ||
461 | } | ||
462 | |||
463 | #[test] | ||
464 | fn goto_def_for_methods() { | ||
465 | covers!(goto_def_for_methods); | ||
430 | check_goto( | 466 | check_goto( |
431 | " | 467 | " |
432 | //- /lib.rs | 468 | //- /lib.rs |
@@ -445,8 +481,8 @@ mod tests { | |||
445 | } | 481 | } |
446 | 482 | ||
447 | #[test] | 483 | #[test] |
448 | fn goto_definition_works_for_fields() { | 484 | fn goto_def_for_fields() { |
449 | covers!(goto_definition_works_for_fields); | 485 | covers!(goto_def_for_fields); |
450 | check_goto( | 486 | check_goto( |
451 | " | 487 | " |
452 | //- /lib.rs | 488 | //- /lib.rs |
@@ -464,8 +500,8 @@ mod tests { | |||
464 | } | 500 | } |
465 | 501 | ||
466 | #[test] | 502 | #[test] |
467 | fn goto_definition_works_for_record_fields() { | 503 | fn goto_def_for_record_fields() { |
468 | covers!(goto_definition_works_for_record_fields); | 504 | covers!(goto_def_for_record_fields); |
469 | check_goto( | 505 | check_goto( |
470 | " | 506 | " |
471 | //- /lib.rs | 507 | //- /lib.rs |
@@ -502,7 +538,7 @@ mod tests { | |||
502 | } | 538 | } |
503 | 539 | ||
504 | #[test] | 540 | #[test] |
505 | fn goto_definition_works_for_ufcs_inherent_methods() { | 541 | fn goto_def_for_ufcs_inherent_methods() { |
506 | check_goto( | 542 | check_goto( |
507 | " | 543 | " |
508 | //- /lib.rs | 544 | //- /lib.rs |
@@ -521,7 +557,7 @@ mod tests { | |||
521 | } | 557 | } |
522 | 558 | ||
523 | #[test] | 559 | #[test] |
524 | fn goto_definition_works_for_ufcs_trait_methods_through_traits() { | 560 | fn goto_def_for_ufcs_trait_methods_through_traits() { |
525 | check_goto( | 561 | check_goto( |
526 | " | 562 | " |
527 | //- /lib.rs | 563 | //- /lib.rs |
@@ -539,7 +575,7 @@ mod tests { | |||
539 | } | 575 | } |
540 | 576 | ||
541 | #[test] | 577 | #[test] |
542 | fn goto_definition_works_for_ufcs_trait_methods_through_self() { | 578 | fn goto_def_for_ufcs_trait_methods_through_self() { |
543 | check_goto( | 579 | check_goto( |
544 | " | 580 | " |
545 | //- /lib.rs | 581 | //- /lib.rs |
@@ -654,7 +690,7 @@ mod tests { | |||
654 | } | 690 | } |
655 | 691 | ||
656 | #[test] | 692 | #[test] |
657 | fn goto_definition_works_when_used_on_definition_name_itself() { | 693 | fn goto_def_when_used_on_definition_name_itself() { |
658 | check_goto( | 694 | check_goto( |
659 | " | 695 | " |
660 | //- /lib.rs | 696 | //- /lib.rs |
@@ -858,4 +894,38 @@ mod tests { | |||
858 | "y", | 894 | "y", |
859 | ); | 895 | ); |
860 | } | 896 | } |
897 | |||
898 | #[test] | ||
899 | fn goto_def_in_local_fn() { | ||
900 | check_goto( | ||
901 | " | ||
902 | //- /lib.rs | ||
903 | fn main() { | ||
904 | fn foo() { | ||
905 | let x = 92; | ||
906 | <|>x; | ||
907 | } | ||
908 | } | ||
909 | ", | ||
910 | "x BIND_PAT FileId(1) [39; 40)", | ||
911 | "x", | ||
912 | ); | ||
913 | } | ||
914 | |||
915 | #[test] | ||
916 | fn goto_def_for_field_init_shorthand() { | ||
917 | covers!(goto_def_for_field_init_shorthand); | ||
918 | check_goto( | ||
919 | " | ||
920 | //- /lib.rs | ||
921 | struct Foo { x: i32 } | ||
922 | fn main() { | ||
923 | let x = 92; | ||
924 | Foo { x<|> }; | ||
925 | } | ||
926 | ", | ||
927 | "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", | ||
928 | "x: i32|x", | ||
929 | ) | ||
930 | } | ||
861 | } | 931 | } |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index a227bf546..35e39f965 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -12,10 +12,7 @@ use ra_syntax::{ | |||
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | db::RootDatabase, | 14 | db::RootDatabase, |
15 | display::{ | 15 | display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, |
16 | description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, | ||
17 | rust_code_markup_with_doc, ShortLabel, | ||
18 | }, | ||
19 | expand::descend_into_macros, | 16 | expand::descend_into_macros, |
20 | references::{classify_name, classify_name_ref, NameKind, NameKind::*}, | 17 | references::{classify_name, classify_name_ref, NameKind, NameKind::*}, |
21 | FilePosition, FileRange, RangeInfo, | 18 | FilePosition, FileRange, RangeInfo, |
@@ -95,11 +92,7 @@ fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> { | |||
95 | } | 92 | } |
96 | } | 93 | } |
97 | 94 | ||
98 | fn hover_text_from_name_kind( | 95 | fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<String> { |
99 | db: &RootDatabase, | ||
100 | name_kind: NameKind, | ||
101 | no_fallback: &mut bool, | ||
102 | ) -> Option<String> { | ||
103 | return match name_kind { | 96 | return match name_kind { |
104 | Macro(it) => { | 97 | Macro(it) => { |
105 | let src = it.source(db); | 98 | let src = it.source(db); |
@@ -135,11 +128,7 @@ fn hover_text_from_name_kind( | |||
135 | hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), | 128 | hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), |
136 | hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), | 129 | hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), |
137 | }, | 130 | }, |
138 | Local(_) => { | 131 | Local(_) => None, |
139 | // Hover for these shows type names | ||
140 | *no_fallback = true; | ||
141 | None | ||
142 | } | ||
143 | TypeParam(_) | SelfType(_) => { | 132 | TypeParam(_) | SelfType(_) => { |
144 | // FIXME: Hover for generic param | 133 | // FIXME: Hover for generic param |
145 | None | 134 | None |
@@ -163,60 +152,35 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
163 | 152 | ||
164 | let mut res = HoverResult::new(); | 153 | let mut res = HoverResult::new(); |
165 | 154 | ||
166 | let mut range = match_ast! { | 155 | if let Some((range, name_kind)) = match_ast! { |
167 | match (token.value.parent()) { | 156 | match (token.value.parent()) { |
168 | ast::NameRef(name_ref) => { | 157 | ast::NameRef(name_ref) => { |
169 | let mut no_fallback = false; | 158 | classify_name_ref(db, token.with_value(&name_ref)).map(|d| (name_ref.syntax().text_range(), d.kind)) |
170 | if let Some(name_kind) = | ||
171 | classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind) | ||
172 | { | ||
173 | res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) | ||
174 | } | ||
175 | |||
176 | if res.is_empty() && !no_fallback { | ||
177 | // Fallback index based approach: | ||
178 | let symbols = crate::symbol_index::index_resolve(db, &name_ref); | ||
179 | for sym in symbols { | ||
180 | let docs = docs_from_symbol(db, &sym); | ||
181 | let desc = description_from_symbol(db, &sym); | ||
182 | res.extend(hover_text(docs, desc)); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | if !res.is_empty() { | ||
187 | Some(name_ref.syntax().text_range()) | ||
188 | } else { | ||
189 | None | ||
190 | } | ||
191 | }, | 159 | }, |
192 | ast::Name(name) => { | 160 | ast::Name(name) => { |
193 | if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) { | 161 | classify_name(db, token.with_value(&name)).map(|d| (name.syntax().text_range(), d.kind)) |
194 | res.extend(hover_text_from_name_kind(db, name_kind, &mut true)); | ||
195 | } | ||
196 | |||
197 | if !res.is_empty() { | ||
198 | Some(name.syntax().text_range()) | ||
199 | } else { | ||
200 | None | ||
201 | } | ||
202 | }, | 162 | }, |
203 | _ => None, | 163 | _ => None, |
204 | } | 164 | } |
205 | }; | 165 | } { |
166 | res.extend(hover_text_from_name_kind(db, name_kind)); | ||
206 | 167 | ||
207 | if range.is_none() { | 168 | if !res.is_empty() { |
208 | let node = token.value.ancestors().find(|n| { | 169 | return Some(RangeInfo::new(range, res)); |
209 | ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() | 170 | } |
210 | })?; | 171 | } |
211 | let frange = FileRange { file_id: position.file_id, range: node.text_range() }; | ||
212 | res.extend(type_of(db, frange).map(rust_code_markup)); | ||
213 | range = Some(node.text_range()); | ||
214 | }; | ||
215 | 172 | ||
216 | let range = range?; | 173 | let node = token |
174 | .value | ||
175 | .ancestors() | ||
176 | .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; | ||
177 | let frange = FileRange { file_id: position.file_id, range: node.text_range() }; | ||
178 | res.extend(type_of(db, frange).map(rust_code_markup)); | ||
217 | if res.is_empty() { | 179 | if res.is_empty() { |
218 | return None; | 180 | return None; |
219 | } | 181 | } |
182 | let range = node.text_range(); | ||
183 | |||
220 | Some(RangeInfo::new(range, res)) | 184 | Some(RangeInfo::new(range, res)) |
221 | } | 185 | } |
222 | 186 | ||
@@ -314,7 +278,7 @@ mod tests { | |||
314 | &["pub fn foo() -> u32"], | 278 | &["pub fn foo() -> u32"], |
315 | ); | 279 | ); |
316 | 280 | ||
317 | // Multiple results | 281 | // Multiple candidates but results are ambiguous. |
318 | check_hover_result( | 282 | check_hover_result( |
319 | r#" | 283 | r#" |
320 | //- /a.rs | 284 | //- /a.rs |
@@ -335,7 +299,7 @@ mod tests { | |||
335 | let foo_test = fo<|>o(); | 299 | let foo_test = fo<|>o(); |
336 | } | 300 | } |
337 | "#, | 301 | "#, |
338 | &["pub fn foo() -> &str", "pub fn foo() -> u32", "pub fn foo(a: u32, b: u32)"], | 302 | &["{unknown}"], |
339 | ); | 303 | ); |
340 | } | 304 | } |
341 | 305 | ||
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3154df457..c5e406977 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -1,12 +1,15 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use crate::{db::RootDatabase, FileId}; | ||
4 | use hir::{HirDisplay, SourceAnalyzer}; | 3 | use hir::{HirDisplay, SourceAnalyzer}; |
4 | use once_cell::unsync::Lazy; | ||
5 | use ra_prof::profile; | ||
5 | use ra_syntax::{ | 6 | use ra_syntax::{ |
6 | ast::{self, AstNode, TypeAscriptionOwner}, | 7 | ast::{self, AstNode, TypeAscriptionOwner}, |
7 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, | 8 | match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, |
8 | }; | 9 | }; |
9 | 10 | ||
11 | use crate::{db::RootDatabase, FileId}; | ||
12 | |||
10 | #[derive(Debug, PartialEq, Eq)] | 13 | #[derive(Debug, PartialEq, Eq)] |
11 | pub enum InlayKind { | 14 | pub enum InlayKind { |
12 | TypeHint, | 15 | TypeHint, |
@@ -27,7 +30,7 @@ pub(crate) fn inlay_hints( | |||
27 | ) -> Vec<InlayHint> { | 30 | ) -> Vec<InlayHint> { |
28 | file.syntax() | 31 | file.syntax() |
29 | .descendants() | 32 | .descendants() |
30 | .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) | 33 | .flat_map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length)) |
31 | .flatten() | 34 | .flatten() |
32 | .collect() | 35 | .collect() |
33 | } | 36 | } |
@@ -38,7 +41,9 @@ fn get_inlay_hints( | |||
38 | node: &SyntaxNode, | 41 | node: &SyntaxNode, |
39 | max_inlay_hint_length: Option<usize>, | 42 | max_inlay_hint_length: Option<usize>, |
40 | ) -> Option<Vec<InlayHint>> { | 43 | ) -> Option<Vec<InlayHint>> { |
41 | let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None); | 44 | let _p = profile("get_inlay_hints"); |
45 | let analyzer = | ||
46 | Lazy::new(|| SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None)); | ||
42 | match_ast! { | 47 | match_ast! { |
43 | match node { | 48 | match node { |
44 | ast::LetStmt(it) => { | 49 | ast::LetStmt(it) => { |
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs index 848ae4dc7..077a44473 100644 --- a/crates/ra_ide/src/marks.rs +++ b/crates/ra_ide/src/marks.rs | |||
@@ -3,10 +3,11 @@ | |||
3 | test_utils::marks!( | 3 | test_utils::marks!( |
4 | inserts_angle_brackets_for_generics | 4 | inserts_angle_brackets_for_generics |
5 | inserts_parens_for_function_calls | 5 | inserts_parens_for_function_calls |
6 | goto_definition_works_for_macros | 6 | goto_def_for_macros |
7 | goto_definition_works_for_methods | 7 | goto_def_for_methods |
8 | goto_definition_works_for_fields | 8 | goto_def_for_fields |
9 | goto_definition_works_for_record_fields | 9 | goto_def_for_record_fields |
10 | goto_def_for_field_init_shorthand | ||
10 | call_info_bad_offset | 11 | call_info_bad_offset |
11 | dont_complete_current_use | 12 | dont_complete_current_use |
12 | dont_complete_primitive_in_use | 13 | dont_complete_primitive_in_use |
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index c1f091ec0..3483a7176 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -134,21 +134,22 @@ pub(crate) fn classify_name_ref( | |||
134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); | 134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); |
135 | 135 | ||
136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
137 | tested_by!(goto_definition_works_for_methods); | 137 | tested_by!(goto_def_for_methods); |
138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { |
139 | return Some(from_assoc_item(db, func.into())); | 139 | return Some(from_assoc_item(db, func.into())); |
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
144 | tested_by!(goto_definition_works_for_fields); | 144 | tested_by!(goto_def_for_fields); |
145 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 145 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
146 | return Some(from_struct_field(db, field)); | 146 | return Some(from_struct_field(db, field)); |
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 150 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
151 | tested_by!(goto_definition_works_for_record_fields); | 151 | tested_by!(goto_def_for_record_fields); |
152 | tested_by!(goto_def_for_field_init_shorthand); | ||
152 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | 153 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { |
153 | return Some(from_struct_field(db, field_def)); | 154 | return Some(from_struct_field(db, field_def)); |
154 | } | 155 | } |
@@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref( | |||
160 | let visibility = None; | 161 | let visibility = None; |
161 | 162 | ||
162 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 163 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
163 | tested_by!(goto_definition_works_for_macros); | 164 | tested_by!(goto_def_for_macros); |
164 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { | 165 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { |
165 | let kind = NameKind::Macro(macro_def); | 166 | let kind = NameKind::Macro(macro_def); |
166 | return Some(NameDefinition { kind, container, visibility }); | 167 | return Some(NameDefinition { kind, container, visibility }); |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 2157139f6..a097cf8e8 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
5 | 5 | ||
6 | .comment { color: #7F9F7F; } | 6 | .comment { color: #7F9F7F; } |
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .field { color: #94BFF3; } | ||
8 | .function { color: #93E0E3; } | 9 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 10 | .parameter { color: #94BFF3; } |
10 | .text { color: #DCDCCC; } | 11 | .text { color: #DCDCCC; } |
@@ -39,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
39 | 40 | ||
40 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); | 41 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); |
41 | <span class="keyword.control">if</span> <span class="keyword">true</span> { | 42 | <span class="keyword.control">if</span> <span class="keyword">true</span> { |
42 | <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal.numeric">0</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> }); | 43 | <span class="keyword">let</span> <span class="variable">x</span> = <span class="literal.numeric">92</span>; |
44 | <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> }); | ||
43 | } | 45 | } |
44 | <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); } | 46 | <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); } |
45 | 47 | ||
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 871a52cf6..110556c09 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
5 | 5 | ||
6 | .comment { color: #7F9F7F; } | 6 | .comment { color: #7F9F7F; } |
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .field { color: #94BFF3; } | ||
8 | .function { color: #93E0E3; } | 9 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 10 | .parameter { color: #94BFF3; } |
10 | .text { color: #DCDCCC; } | 11 | .text { color: #DCDCCC; } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 15e75709c..0228ee7e9 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -17,31 +17,31 @@ use crate::{ | |||
17 | }; | 17 | }; |
18 | 18 | ||
19 | pub mod tags { | 19 | pub mod tags { |
20 | pub(crate) const FIELD: &'static str = "field"; | 20 | pub(crate) const FIELD: &str = "field"; |
21 | pub(crate) const FUNCTION: &'static str = "function"; | 21 | pub(crate) const FUNCTION: &str = "function"; |
22 | pub(crate) const MODULE: &'static str = "module"; | 22 | pub(crate) const MODULE: &str = "module"; |
23 | pub(crate) const TYPE: &'static str = "type"; | 23 | pub(crate) const TYPE: &str = "type"; |
24 | pub(crate) const CONSTANT: &'static str = "constant"; | 24 | pub(crate) const CONSTANT: &str = "constant"; |
25 | pub(crate) const MACRO: &'static str = "macro"; | 25 | pub(crate) const MACRO: &str = "macro"; |
26 | pub(crate) const VARIABLE: &'static str = "variable"; | 26 | pub(crate) const VARIABLE: &str = "variable"; |
27 | pub(crate) const VARIABLE_MUT: &'static str = "variable.mut"; | 27 | pub(crate) const VARIABLE_MUT: &str = "variable.mut"; |
28 | pub(crate) const TEXT: &'static str = "text"; | 28 | pub(crate) const TEXT: &str = "text"; |
29 | 29 | ||
30 | pub(crate) const TYPE_BUILTIN: &'static str = "type.builtin"; | 30 | pub(crate) const TYPE_BUILTIN: &str = "type.builtin"; |
31 | pub(crate) const TYPE_SELF: &'static str = "type.self"; | 31 | pub(crate) const TYPE_SELF: &str = "type.self"; |
32 | pub(crate) const TYPE_PARAM: &'static str = "type.param"; | 32 | pub(crate) const TYPE_PARAM: &str = "type.param"; |
33 | pub(crate) const TYPE_LIFETIME: &'static str = "type.lifetime"; | 33 | pub(crate) const TYPE_LIFETIME: &str = "type.lifetime"; |
34 | 34 | ||
35 | pub(crate) const LITERAL_BYTE: &'static str = "literal.byte"; | 35 | pub(crate) const LITERAL_BYTE: &str = "literal.byte"; |
36 | pub(crate) const LITERAL_NUMERIC: &'static str = "literal.numeric"; | 36 | pub(crate) const LITERAL_NUMERIC: &str = "literal.numeric"; |
37 | pub(crate) const LITERAL_CHAR: &'static str = "literal.char"; | 37 | pub(crate) const LITERAL_CHAR: &str = "literal.char"; |
38 | pub(crate) const LITERAL_COMMENT: &'static str = "comment"; | 38 | pub(crate) const LITERAL_COMMENT: &str = "comment"; |
39 | pub(crate) const LITERAL_STRING: &'static str = "string"; | 39 | pub(crate) const LITERAL_STRING: &str = "string"; |
40 | pub(crate) const LITERAL_ATTRIBUTE: &'static str = "attribute"; | 40 | pub(crate) const LITERAL_ATTRIBUTE: &str = "attribute"; |
41 | 41 | ||
42 | pub(crate) const KEYWORD_UNSAFE: &'static str = "keyword.unsafe"; | 42 | pub(crate) const KEYWORD_UNSAFE: &str = "keyword.unsafe"; |
43 | pub(crate) const KEYWORD_CONTROL: &'static str = "keyword.control"; | 43 | pub(crate) const KEYWORD_CONTROL: &str = "keyword.control"; |
44 | pub(crate) const KEYWORD: &'static str = "keyword"; | 44 | pub(crate) const KEYWORD: &str = "keyword"; |
45 | } | 45 | } |
46 | 46 | ||
47 | #[derive(Debug)] | 47 | #[derive(Debug)] |
@@ -102,11 +102,10 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
102 | COMMENT => tags::LITERAL_COMMENT, | 102 | COMMENT => tags::LITERAL_COMMENT, |
103 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, | 103 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, |
104 | ATTR => tags::LITERAL_ATTRIBUTE, | 104 | ATTR => tags::LITERAL_ATTRIBUTE, |
105 | // Special-case field init shorthand | ||
106 | NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => tags::FIELD, | ||
107 | NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => continue, | ||
105 | NAME_REF => { | 108 | NAME_REF => { |
106 | if node.ancestors().any(|it| it.kind() == ATTR) { | ||
107 | continue; | ||
108 | } | ||
109 | |||
110 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); | 109 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
111 | let name_kind = | 110 | let name_kind = |
112 | classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); | 111 | classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); |
@@ -259,9 +258,7 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { | |||
259 | SelfType(_) => tags::TYPE_SELF, | 258 | SelfType(_) => tags::TYPE_SELF, |
260 | TypeParam(_) => tags::TYPE_PARAM, | 259 | TypeParam(_) => tags::TYPE_PARAM, |
261 | Local(local) => { | 260 | Local(local) => { |
262 | if local.is_mut(db) { | 261 | if local.is_mut(db) || local.ty(db).is_mutable_reference() { |
263 | tags::VARIABLE_MUT | ||
264 | } else if local.ty(db).is_mutable_reference() { | ||
265 | tags::VARIABLE_MUT | 262 | tags::VARIABLE_MUT |
266 | } else { | 263 | } else { |
267 | tags::VARIABLE | 264 | tags::VARIABLE |
@@ -282,6 +279,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
282 | 279 | ||
283 | .comment { color: #7F9F7F; } | 280 | .comment { color: #7F9F7F; } |
284 | .string { color: #CC9393; } | 281 | .string { color: #CC9393; } |
282 | .field { color: #94BFF3; } | ||
285 | .function { color: #93E0E3; } | 283 | .function { color: #93E0E3; } |
286 | .parameter { color: #94BFF3; } | 284 | .parameter { color: #94BFF3; } |
287 | .text { color: #DCDCCC; } | 285 | .text { color: #DCDCCC; } |
@@ -327,7 +325,8 @@ fn main() { | |||
327 | 325 | ||
328 | let mut vec = Vec::new(); | 326 | let mut vec = Vec::new(); |
329 | if true { | 327 | if true { |
330 | vec.push(Foo { x: 0, y: 1 }); | 328 | let x = 92; |
329 | vec.push(Foo { x, y: 1 }); | ||
331 | } | 330 | } |
332 | unsafe { vec.set_len(0); } | 331 | unsafe { vec.set_len(0); } |
333 | 332 | ||