aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs256
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs26
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs58
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs9
-rw-r--r--crates/ra_ide/src/lib.rs8
-rw-r--r--crates/ra_ide/src/references.rs25
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html4
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html23
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs33
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs21
11 files changed, 432 insertions, 33 deletions
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 6a0f0c72e..f2a52a407 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 {
@@ -37,8 +38,53 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
37 Some(it) => it, 38 Some(it) => it,
38 None => return, 39 None => return,
39 }; 40 };
41 let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty);
42 if let Some(try_enum) = &try_enum {
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);
40 54
41 if receiver_ty.is_bool() || receiver_ty.is_unknown() { 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,
@@ -58,7 +104,6 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
58 ) 104 )
59 .add_to(acc); 105 .add_to(acc);
60 } 106 }
61
62 // !&&&42 is a compiler error, ergo process it before considering the references 107 // !&&&42 is a compiler error, ergo process it before considering the references
63 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) 108 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
64 .add_to(acc); 109 .add_to(acc);
@@ -80,16 +125,45 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
80 let dot_receiver = include_references(dot_receiver); 125 let dot_receiver = include_references(dot_receiver);
81 let receiver_text = 126 let receiver_text =
82 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal); 127 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);
83 128 match try_enum {
84 postfix_snippet( 129 Some(try_enum) => {
85 ctx, 130 match try_enum {
86 cap, 131 TryEnum::Result => {
87 &dot_receiver, 132 postfix_snippet(
88 "match", 133 ctx,
89 "match expr {}", 134 cap,
90 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text), 135 &dot_receiver,
91 ) 136 "match",
92 .add_to(acc); 137 "match expr {}",
138 &format!("match {} {{\n Ok(${{1:_}}) => {{$2\\}},\n Err(${{3:_}}) => {{$0\\}},\n}}", receiver_text),
139 )
140 .add_to(acc);
141 }
142 TryEnum::Option => {
143 postfix_snippet(
144 ctx,
145 cap,
146 &dot_receiver,
147 "match",
148 "match expr {}",
149 &format!("match {} {{\n Some(${{1:_}}) => {{$2\\}},\n None => {{$0\\}},\n}}", receiver_text),
150 )
151 .add_to(acc);
152 }
153 }
154 }
155 None => {
156 postfix_snippet(
157 ctx,
158 cap,
159 &dot_receiver,
160 "match",
161 "match expr {}",
162 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
163 )
164 .add_to(acc);
165 }
166 }
93 167
94 postfix_snippet( 168 postfix_snippet(
95 ctx, 169 ctx,
@@ -236,6 +310,164 @@ mod tests {
236 } 310 }
237 311
238 #[test] 312 #[test]
313 fn postfix_completion_works_for_option() {
314 assert_debug_snapshot!(
315 do_postfix_completion(
316 r#"
317 enum Option<T> {
318 Some(T),
319 None,
320 }
321
322 fn main() {
323 let bar = Option::Some(true);
324 bar.<|>
325 }
326 "#,
327 ),
328 @r###"
329 [
330 CompletionItem {
331 label: "box",
332 source_range: 210..210,
333 delete: 206..210,
334 insert: "Box::new(bar)",
335 detail: "Box::new(expr)",
336 },
337 CompletionItem {
338 label: "dbg",
339 source_range: 210..210,
340 delete: 206..210,
341 insert: "dbg!(bar)",
342 detail: "dbg!(expr)",
343 },
344 CompletionItem {
345 label: "ifl",
346 source_range: 210..210,
347 delete: 206..210,
348 insert: "if let Some($1) = bar {\n $0\n}",
349 detail: "if let Some {}",
350 },
351 CompletionItem {
352 label: "match",
353 source_range: 210..210,
354 delete: 206..210,
355 insert: "match bar {\n Some(${1:_}) => {$2\\},\n None => {$0\\},\n}",
356 detail: "match expr {}",
357 },
358 CompletionItem {
359 label: "not",
360 source_range: 210..210,
361 delete: 206..210,
362 insert: "!bar",
363 detail: "!expr",
364 },
365 CompletionItem {
366 label: "ref",
367 source_range: 210..210,
368 delete: 206..210,
369 insert: "&bar",
370 detail: "&expr",
371 },
372 CompletionItem {
373 label: "refm",
374 source_range: 210..210,
375 delete: 206..210,
376 insert: "&mut bar",
377 detail: "&mut expr",
378 },
379 CompletionItem {
380 label: "while",
381 source_range: 210..210,
382 delete: 206..210,
383 insert: "while let Some($1) = bar {\n $0\n}",
384 detail: "while let Some {}",
385 },
386 ]
387 "###
388 );
389 }
390
391 #[test]
392 fn postfix_completion_works_for_result() {
393 assert_debug_snapshot!(
394 do_postfix_completion(
395 r#"
396 enum Result<T, E> {
397 Ok(T),
398 Err(E),
399 }
400
401 fn main() {
402 let bar = Result::Ok(true);
403 bar.<|>
404 }
405 "#,
406 ),
407 @r###"
408 [
409 CompletionItem {
410 label: "box",
411 source_range: 211..211,
412 delete: 207..211,
413 insert: "Box::new(bar)",
414 detail: "Box::new(expr)",
415 },
416 CompletionItem {
417 label: "dbg",
418 source_range: 211..211,
419 delete: 207..211,
420 insert: "dbg!(bar)",
421 detail: "dbg!(expr)",
422 },
423 CompletionItem {
424 label: "ifl",
425 source_range: 211..211,
426 delete: 207..211,
427 insert: "if let Ok($1) = bar {\n $0\n}",
428 detail: "if let Ok {}",
429 },
430 CompletionItem {
431 label: "match",
432 source_range: 211..211,
433 delete: 207..211,
434 insert: "match bar {\n Ok(${1:_}) => {$2\\},\n Err(${3:_}) => {$0\\},\n}",
435 detail: "match expr {}",
436 },
437 CompletionItem {
438 label: "not",
439 source_range: 211..211,
440 delete: 207..211,
441 insert: "!bar",
442 detail: "!expr",
443 },
444 CompletionItem {
445 label: "ref",
446 source_range: 211..211,
447 delete: 207..211,
448 insert: "&bar",
449 detail: "&expr",
450 },
451 CompletionItem {
452 label: "refm",
453 source_range: 211..211,
454 delete: 207..211,
455 insert: "&mut bar",
456 detail: "&mut expr",
457 },
458 CompletionItem {
459 label: "while",
460 source_range: 211..211,
461 delete: 207..211,
462 insert: "while let Ok($1) = bar {\n $0\n}",
463 detail: "while let Ok {}",
464 },
465 ]
466 "###
467 );
468 }
469
470 #[test]
239 fn some_postfix_completions_ignored() { 471 fn some_postfix_completions_ignored() {
240 assert_debug_snapshot!( 472 assert_debug_snapshot!(
241 do_postfix_completion( 473 do_postfix_completion(
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index a3f5d1b6a..0568d9ccf 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -36,6 +36,24 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
36 snippet( 36 snippet(
37 ctx, 37 ctx,
38 cap, 38 cap,
39 "Test module",
40 "\
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn ${1:test_name}() {
47 $0
48 }
49}",
50 )
51 .lookup_by("tmod")
52 .add_to(acc);
53
54 snippet(
55 ctx,
56 cap,
39 "Test function", 57 "Test function",
40 "\ 58 "\
41#[test] 59#[test]
@@ -118,6 +136,14 @@ mod tests {
118 lookup: "tfn", 136 lookup: "tfn",
119 }, 137 },
120 CompletionItem { 138 CompletionItem {
139 label: "Test module",
140 source_range: 78..78,
141 delete: 78..78,
142 insert: "#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn ${1:test_name}() {\n $0\n }\n}",
143 kind: Snippet,
144 lookup: "tmod",
145 },
146 CompletionItem {
121 label: "macro_rules", 147 label: "macro_rules",
122 source_range: 78..78, 148 source_range: 78..78,
123 delete: 78..78, 149 delete: 78..78,
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index b6b9627de..da336973c 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -34,7 +34,7 @@ pub(crate) struct CompletionContext<'a> {
34 pub(super) record_pat_syntax: Option<ast::RecordPat>, 34 pub(super) record_pat_syntax: Option<ast::RecordPat>,
35 pub(super) record_field_syntax: Option<ast::RecordField>, 35 pub(super) record_field_syntax: Option<ast::RecordField>,
36 pub(super) impl_def: Option<ast::ImplDef>, 36 pub(super) impl_def: Option<ast::ImplDef>,
37 /// FIXME: `ActiveParameter` is string-based, which is very wrong 37 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
38 pub(super) active_parameter: Option<ActiveParameter>, 38 pub(super) active_parameter: Option<ActiveParameter>,
39 pub(super) is_param: bool, 39 pub(super) is_param: bool,
40 /// If a name-binding or reference to a const in a pattern. 40 /// If a name-binding or reference to a const in a pattern.
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 2edb130cf..077cf9647 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -17,12 +17,11 @@ use crate::{
17impl Completions { 17impl Completions {
18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) { 18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) {
19 let is_deprecated = is_deprecated(field, ctx.db); 19 let is_deprecated = is_deprecated(field, ctx.db);
20 let ty = ty.display(ctx.db).to_string();
21 let name = field.name(ctx.db); 20 let name = field.name(ctx.db);
22 let mut completion_item = 21 let mut completion_item =
23 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 22 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
24 .kind(CompletionItemKind::Field) 23 .kind(CompletionItemKind::Field)
25 .detail(ty.clone()) 24 .detail(ty.display(ctx.db).to_string())
26 .set_documentation(field.docs(ctx.db)) 25 .set_documentation(field.docs(ctx.db))
27 .set_deprecated(is_deprecated); 26 .set_deprecated(is_deprecated);
28 27
@@ -107,6 +106,12 @@ impl Completions {
107 } 106 }
108 }; 107 };
109 108
109 if let ScopeDef::Local(local) = resolution {
110 if let Some(score) = compute_score(ctx, &local.ty(ctx.db), &local_name) {
111 completion_item = completion_item.set_score(score);
112 }
113 }
114
110 // Add `<>` for generic types 115 // Add `<>` for generic types
111 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { 116 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis {
112 if let Some(cap) = ctx.config.snippet_cap { 117 if let Some(cap) = ctx.config.snippet_cap {
@@ -319,10 +324,11 @@ impl Completions {
319 324
320pub(crate) fn compute_score( 325pub(crate) fn compute_score(
321 ctx: &CompletionContext, 326 ctx: &CompletionContext,
322 // FIXME: this definitely should be a `Type` 327 ty: &Type,
323 ty: &str,
324 name: &str, 328 name: &str,
325) -> Option<CompletionScore> { 329) -> Option<CompletionScore> {
330 // FIXME: this should not fall back to string equality.
331 let ty = &ty.display(ctx.db).to_string();
326 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
327 tested_by!(test_struct_field_completion_in_record_lit); 333 tested_by!(test_struct_field_completion_in_record_lit);
328 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
@@ -1405,4 +1411,48 @@ mod tests {
1405 "### 1411 "###
1406 ); 1412 );
1407 } 1413 }
1414
1415 #[test]
1416 fn prioritize_exact_ref_match() {
1417 assert_debug_snapshot!(
1418 do_reference_completion(
1419 r"
1420 struct WorldSnapshot { _f: () };
1421 fn go(world: &WorldSnapshot) {
1422 go(w<|>)
1423 }
1424 ",
1425 ),
1426 @r###"
1427 [
1428 CompletionItem {
1429 label: "WorldSnapshot",
1430 source_range: 132..133,
1431 delete: 132..133,
1432 insert: "WorldSnapshot",
1433 kind: Struct,
1434 },
1435 CompletionItem {
1436 label: "go(…)",
1437 source_range: 132..133,
1438 delete: 132..133,
1439 insert: "go(${1:world})$0",
1440 kind: Function,
1441 lookup: "go",
1442 detail: "fn go(world: &WorldSnapshot)",
1443 trigger_call_info: true,
1444 },
1445 CompletionItem {
1446 label: "world",
1447 source_range: 132..133,
1448 delete: 132..133,
1449 insert: "world",
1450 kind: Binding,
1451 detail: "&WorldSnapshot",
1452 score: TypeAndNameMatch,
1453 },
1454 ]
1455 "###
1456 );
1457 }
1408} 1458}
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index de35c6711..5da28edd2 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 TextRange, 11 TextRange,
12}; 12};
13 13
14use crate::FileSymbol; 14use crate::{FileRange, FileSymbol};
15 15
16use super::short_label::ShortLabel; 16use super::short_label::ShortLabel;
17 17
@@ -22,10 +22,11 @@ use super::short_label::ShortLabel;
22/// code, like a function or a struct, but this is not strictly required. 22/// code, like a function or a struct, but this is not strictly required.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)] 23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct NavigationTarget { 24pub struct NavigationTarget {
25 // FIXME: use FileRange?
25 file_id: FileId, 26 file_id: FileId,
27 full_range: TextRange,
26 name: SmolStr, 28 name: SmolStr,
27 kind: SyntaxKind, 29 kind: SyntaxKind,
28 full_range: TextRange,
29 focus_range: Option<TextRange>, 30 focus_range: Option<TextRange>,
30 container_name: Option<SmolStr>, 31 container_name: Option<SmolStr>,
31 description: Option<String>, 32 description: Option<String>,
@@ -63,6 +64,10 @@ impl NavigationTarget {
63 self.file_id 64 self.file_id
64 } 65 }
65 66
67 pub fn file_range(&self) -> FileRange {
68 FileRange { file_id: self.file_id, range: self.full_range }
69 }
70
66 pub fn full_range(&self) -> TextRange { 71 pub fn full_range(&self) -> TextRange {
67 self.full_range 72 self.full_range
68 } 73 }
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 915199bd8..78149ddfc 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -176,14 +176,10 @@ impl AnalysisHost {
176 pub fn request_cancellation(&mut self) { 176 pub fn request_cancellation(&mut self) {
177 self.db.request_cancellation(); 177 self.db.request_cancellation();
178 } 178 }
179 pub fn raw_database( 179 pub fn raw_database(&self) -> &RootDatabase {
180 &self,
181 ) -> &(impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
182 &self.db 180 &self.db
183 } 181 }
184 pub fn raw_database_mut( 182 pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
185 &mut self,
186 ) -> &mut (impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
187 &mut self.db 183 &mut self.db
188 } 184 }
189} 185}
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 555ccf295..074284b42 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -593,6 +593,31 @@ mod tests {
593 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]); 593 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]);
594 } 594 }
595 595
596 #[test]
597 fn test_find_struct_function_refs_outside_module() {
598 let code = r#"
599 mod foo {
600 pub struct Foo;
601
602 impl Foo {
603 pub fn new<|>() -> Foo {
604 Foo
605 }
606 }
607 }
608
609 fn main() {
610 let _f = foo::Foo::new();
611 }"#;
612
613 let refs = get_all_refs(code);
614 check_result(
615 refs,
616 "new FN_DEF FileId(1) 87..150 94..97 Other",
617 &["FileId(1) 227..230 StructLiteral"],
618 );
619 }
620
596 fn get_all_refs(text: &str) -> ReferenceSearchResult { 621 fn get_all_refs(text: &str) -> ReferenceSearchResult {
597 let (analysis, position) = single_file_with_position(text); 622 let (analysis, position) = single_file_with_position(text);
598 analysis.find_all_refs(position, None).unwrap().unwrap() 623 analysis.find_all_refs(position, None).unwrap().unwrap()
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html
index de06daf72..752b487e8 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/src/snapshots/highlight_strings.html
@@ -27,13 +27,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
27.keyword.unsafe { color: #BC8383; font-weight: bold; } 27.keyword.unsafe { color: #BC8383; font-weight: bold; }
28.control { font-style: italic; } 28.control { font-style: italic; }
29</style> 29</style>
30<pre><code><span class="macro">macro_rules!</span> println { 30<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> {
31 ($($arg:tt)*) =&gt; ({ 31 ($($arg:tt)*) =&gt; ({
32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*)); 32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*));
33 }) 33 })
34} 34}
35#[rustc_builtin_macro] 35#[rustc_builtin_macro]
36<span class="macro">macro_rules!</span> format_args_nl { 36<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> {
37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
39} 39}
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index 4b12fe823..635fe5cf9 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -33,11 +33,23 @@ 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
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>;
47
36<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> {
37 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;() 49 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;()
38} 50}
39 51
40<span class="macro">macro_rules!</span> def_fn { 52<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> {
41 ($($tt:tt)*) =&gt; {$($tt)*} 53 ($($tt:tt)*) =&gt; {$($tt)*}
42} 54}
43 55
@@ -56,7 +68,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
56 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; 68 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>;
57 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); 69 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> });
58 } 70 }
59 <span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>); } 71 <span class="keyword unsafe">unsafe</span> {
72 <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>);
73 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>;
74 }
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 }
60 79
61 <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>;
62 <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>;
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 6658c7bb2..be57eeb0a 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -167,6 +167,19 @@ pub(crate) fn highlight(
167 binding_hash: None, 167 binding_hash: None,
168 }); 168 });
169 } 169 }
170 if let Some(name) = mc.is_macro_rules() {
171 if let Some((highlight, binding_hash)) = highlight_element(
172 &sema,
173 &mut bindings_shadow_count,
174 name.syntax().clone().into(),
175 ) {
176 stack.add(HighlightedRange {
177 range: name.syntax().text_range(),
178 highlight,
179 binding_hash,
180 });
181 }
182 }
170 continue; 183 continue;
171 } 184 }
172 WalkEvent::Leave(Some(mc)) => { 185 WalkEvent::Leave(Some(mc)) => {
@@ -390,12 +403,13 @@ fn highlight_element(
390 T![break] 403 T![break]
391 | T![continue] 404 | T![continue]
392 | T![else] 405 | T![else]
393 | T![for]
394 | T![if] 406 | T![if]
395 | T![loop] 407 | T![loop]
396 | T![match] 408 | T![match]
397 | T![return] 409 | T![return]
398 | 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,
399 T![unsafe] => h | HighlightModifier::Unsafe, 413 T![unsafe] => h | HighlightModifier::Unsafe,
400 _ => h, 414 _ => h,
401 } 415 }
@@ -419,6 +433,13 @@ fn highlight_element(
419 } 433 }
420} 434}
421 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
422fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 443fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
423 match def { 444 match def {
424 Definition::Macro(_) => HighlightTag::Macro, 445 Definition::Macro(_) => HighlightTag::Macro,
@@ -431,10 +452,16 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
431 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union, 452 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
432 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant, 453 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant,
433 hir::ModuleDef::Const(_) => HighlightTag::Constant, 454 hir::ModuleDef::Const(_) => HighlightTag::Constant,
434 hir::ModuleDef::Static(_) => HighlightTag::Static,
435 hir::ModuleDef::Trait(_) => HighlightTag::Trait, 455 hir::ModuleDef::Trait(_) => HighlightTag::Trait,
436 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias, 456 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias,
437 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType, 457 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType,
458 hir::ModuleDef::Static(s) => {
459 let mut h = Highlight::new(HighlightTag::Static);
460 if s.is_mut(db) {
461 h |= HighlightModifier::Mutable;
462 }
463 return h;
464 }
438 }, 465 },
439 Definition::SelfType(_) => HighlightTag::SelfType, 466 Definition::SelfType(_) => HighlightTag::SelfType,
440 Definition::TypeParam(_) => HighlightTag::TypeParam, 467 Definition::TypeParam(_) => HighlightTag::TypeParam,
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index d2926ba78..eb43a23da 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -17,6 +17,18 @@ 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
30static mut STATIC_MUT: i32 = 0;
31
20fn foo<'a, T>() -> T { 32fn foo<'a, T>() -> T {
21 foo::<'a, i32>() 33 foo::<'a, i32>()
22} 34}
@@ -40,7 +52,14 @@ fn main() {
40 let x = 92; 52 let x = 92;
41 vec.push(Foo { x, y: 1 }); 53 vec.push(Foo { x, y: 1 });
42 } 54 }
43 unsafe { vec.set_len(0); } 55 unsafe {
56 vec.set_len(0);
57 STATIC_MUT = 1;
58 }
59
60 for e in vec {
61 // Do nothing
62 }
44 63
45 let mut x = 42; 64 let mut x = 42;
46 let y = &mut x; 65 let y = &mut x;