aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/annotations.rs66
-rw-r--r--crates/ide/src/diagnostics.rs65
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs23
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html2
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs8
5 files changed, 101 insertions, 63 deletions
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 5ebe7fd0e..b0c4ed60a 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -5,7 +5,7 @@ use ide_db::{
5 helpers::visit_file_defs, 5 helpers::visit_file_defs,
6 RootDatabase, 6 RootDatabase,
7}; 7};
8use syntax::{ast::NameOwner, AstNode, TextRange, TextSize}; 8use syntax::{ast::NameOwner, AstNode, TextRange};
9 9
10use crate::{ 10use crate::{
11 fn_references::find_all_methods, 11 fn_references::find_all_methods,
@@ -80,26 +80,26 @@ pub(crate) fn annotations(
80 80
81 visit_file_defs(&Semantics::new(db), file_id, &mut |def| match def { 81 visit_file_defs(&Semantics::new(db), file_id, &mut |def| match def {
82 Either::Left(def) => { 82 Either::Left(def) => {
83 let node = match def { 83 let range = match def {
84 hir::ModuleDef::Const(konst) => { 84 hir::ModuleDef::Const(konst) => {
85 konst.source(db).and_then(|node| range_and_position_of(&node, file_id)) 85 konst.source(db).and_then(|node| name_range(&node, file_id))
86 } 86 }
87 hir::ModuleDef::Trait(trait_) => { 87 hir::ModuleDef::Trait(trait_) => {
88 trait_.source(db).and_then(|node| range_and_position_of(&node, file_id)) 88 trait_.source(db).and_then(|node| name_range(&node, file_id))
89 } 89 }
90 hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => { 90 hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
91 strukt.source(db).and_then(|node| range_and_position_of(&node, file_id)) 91 strukt.source(db).and_then(|node| name_range(&node, file_id))
92 } 92 }
93 hir::ModuleDef::Adt(hir::Adt::Enum(enum_)) => { 93 hir::ModuleDef::Adt(hir::Adt::Enum(enum_)) => {
94 enum_.source(db).and_then(|node| range_and_position_of(&node, file_id)) 94 enum_.source(db).and_then(|node| name_range(&node, file_id))
95 } 95 }
96 hir::ModuleDef::Adt(hir::Adt::Union(union)) => { 96 hir::ModuleDef::Adt(hir::Adt::Union(union)) => {
97 union.source(db).and_then(|node| range_and_position_of(&node, file_id)) 97 union.source(db).and_then(|node| name_range(&node, file_id))
98 } 98 }
99 _ => None, 99 _ => None,
100 }; 100 };
101 let (offset, range) = match node { 101 let (range, offset) = match range {
102 Some(node) => node, 102 Some(range) => (range, range.start()),
103 None => return, 103 None => return,
104 }; 104 };
105 105
@@ -122,18 +122,12 @@ pub(crate) fn annotations(
122 }); 122 });
123 } 123 }
124 124
125 fn range_and_position_of<T: NameOwner>( 125 fn name_range<T: NameOwner>(node: &InFile<T>, file_id: FileId) -> Option<TextRange> {
126 node: &InFile<T>, 126 if node.file_id == file_id.into() {
127 file_id: FileId, 127 node.value.name().map(|it| it.syntax().text_range())
128 ) -> Option<(TextSize, TextRange)> { 128 } else {
129 if node.file_id != file_id.into() {
130 // Node is outside the file we are adding annotations to (e.g. macros). 129 // Node is outside the file we are adding annotations to (e.g. macros).
131 None 130 None
132 } else {
133 Some((
134 node.value.name()?.syntax().text_range().start(),
135 node.value.syntax().text_range(),
136 ))
137 } 131 }
138 } 132 }
139 } 133 }
@@ -141,13 +135,15 @@ pub(crate) fn annotations(
141 }); 135 });
142 136
143 if config.annotate_method_references { 137 if config.annotate_method_references {
144 annotations.extend(find_all_methods(db, file_id).into_iter().map(|method| Annotation { 138 annotations.extend(find_all_methods(db, file_id).into_iter().map(
145 range: method.range, 139 |FileRange { file_id, range }| Annotation {
146 kind: AnnotationKind::HasReferences { 140 range,
147 position: FilePosition { file_id, offset: method.range.start() }, 141 kind: AnnotationKind::HasReferences {
148 data: None, 142 position: FilePosition { file_id, offset: range.start() },
143 data: None,
144 },
149 }, 145 },
150 })); 146 ));
151 } 147 }
152 148
153 annotations 149 annotations
@@ -266,7 +262,7 @@ fn main() {
266 }, 262 },
267 }, 263 },
268 Annotation { 264 Annotation {
269 range: 0..22, 265 range: 6..10,
270 kind: HasReferences { 266 kind: HasReferences {
271 position: FilePosition { 267 position: FilePosition {
272 file_id: FileId( 268 file_id: FileId(
@@ -287,7 +283,7 @@ fn main() {
287 }, 283 },
288 }, 284 },
289 Annotation { 285 Annotation {
290 range: 24..48, 286 range: 30..36,
291 kind: HasReferences { 287 kind: HasReferences {
292 position: FilePosition { 288 position: FilePosition {
293 file_id: FileId( 289 file_id: FileId(
@@ -370,7 +366,7 @@ fn main() {
370 }, 366 },
371 }, 367 },
372 Annotation { 368 Annotation {
373 range: 0..12, 369 range: 7..11,
374 kind: HasImpls { 370 kind: HasImpls {
375 position: FilePosition { 371 position: FilePosition {
376 file_id: FileId( 372 file_id: FileId(
@@ -384,7 +380,7 @@ fn main() {
384 }, 380 },
385 }, 381 },
386 Annotation { 382 Annotation {
387 range: 0..12, 383 range: 7..11,
388 kind: HasReferences { 384 kind: HasReferences {
389 position: FilePosition { 385 position: FilePosition {
390 file_id: FileId( 386 file_id: FileId(
@@ -478,7 +474,7 @@ fn main() {
478 }, 474 },
479 }, 475 },
480 Annotation { 476 Annotation {
481 range: 0..12, 477 range: 7..11,
482 kind: HasImpls { 478 kind: HasImpls {
483 position: FilePosition { 479 position: FilePosition {
484 file_id: FileId( 480 file_id: FileId(
@@ -502,7 +498,7 @@ fn main() {
502 }, 498 },
503 }, 499 },
504 Annotation { 500 Annotation {
505 range: 0..12, 501 range: 7..11,
506 kind: HasReferences { 502 kind: HasReferences {
507 position: FilePosition { 503 position: FilePosition {
508 file_id: FileId( 504 file_id: FileId(
@@ -529,7 +525,7 @@ fn main() {
529 }, 525 },
530 }, 526 },
531 Annotation { 527 Annotation {
532 range: 14..34, 528 range: 20..31,
533 kind: HasImpls { 529 kind: HasImpls {
534 position: FilePosition { 530 position: FilePosition {
535 file_id: FileId( 531 file_id: FileId(
@@ -553,7 +549,7 @@ fn main() {
553 }, 549 },
554 }, 550 },
555 Annotation { 551 Annotation {
556 range: 14..34, 552 range: 20..31,
557 kind: HasReferences { 553 kind: HasReferences {
558 position: FilePosition { 554 position: FilePosition {
559 file_id: FileId( 555 file_id: FileId(
@@ -712,7 +708,7 @@ fn main() {
712 }, 708 },
713 }, 709 },
714 Annotation { 710 Annotation {
715 range: 0..12, 711 range: 7..11,
716 kind: HasImpls { 712 kind: HasImpls {
717 position: FilePosition { 713 position: FilePosition {
718 file_id: FileId( 714 file_id: FileId(
@@ -736,7 +732,7 @@ fn main() {
736 }, 732 },
737 }, 733 },
738 Annotation { 734 Annotation {
739 range: 0..12, 735 range: 7..11,
740 kind: HasReferences { 736 kind: HasReferences {
741 position: FilePosition { 737 position: FilePosition {
742 file_id: FileId( 738 file_id: FileId(
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 27d347dbd..dcac7c76d 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -299,10 +299,10 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
299 299
300#[cfg(test)] 300#[cfg(test)]
301mod tests { 301mod tests {
302 use expect_test::{expect, Expect}; 302 use expect_test::Expect;
303 use ide_assists::AssistResolveStrategy; 303 use ide_assists::AssistResolveStrategy;
304 use stdx::trim_indent; 304 use stdx::trim_indent;
305 use test_utils::assert_eq_text; 305 use test_utils::{assert_eq_text, extract_annotations};
306 306
307 use crate::{fixture, DiagnosticsConfig}; 307 use crate::{fixture, DiagnosticsConfig};
308 308
@@ -396,26 +396,51 @@ mod tests {
396 expect.assert_debug_eq(&diagnostics) 396 expect.assert_debug_eq(&diagnostics)
397 } 397 }
398 398
399 pub(crate) fn check_diagnostics(ra_fixture: &str) {
400 let (analysis, file_id) = fixture::file(ra_fixture);
401 let diagnostics = analysis
402 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
403 .unwrap();
404
405 let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
406 let actual = diagnostics.into_iter().map(|d| (d.range, d.message)).collect::<Vec<_>>();
407 assert_eq!(expected, actual);
408 }
409
399 #[test] 410 #[test]
400 fn test_unresolved_macro_range() { 411 fn test_unresolved_macro_range() {
401 check_expect( 412 check_diagnostics(
402 r#"foo::bar!(92);"#, 413 r#"
403 expect![[r#" 414foo::bar!(92);
404 [ 415 //^^^ unresolved macro `foo::bar!`
405 Diagnostic { 416"#,
406 message: "unresolved macro `foo::bar!`", 417 );
407 range: 5..8, 418 }
408 severity: Error, 419
409 fixes: None, 420 #[test]
410 unused: false, 421 fn unresolved_import_in_use_tree() {
411 code: Some( 422 // Only the relevant part of a nested `use` item should be highlighted.
412 DiagnosticCode( 423 check_diagnostics(
413 "unresolved-macro-call", 424 r#"
414 ), 425use does_exist::{Exists, DoesntExist};
415 ), 426 //^^^^^^^^^^^ unresolved import
416 }, 427
417 ] 428use {does_not_exist::*, does_exist};
418 "#]], 429 //^^^^^^^^^^^^^^^^^ unresolved import
430
431use does_not_exist::{
432 a,
433 //^ unresolved import
434 b,
435 //^ unresolved import
436 c,
437 //^ unresolved import
438};
439
440mod does_exist {
441 pub struct Exists;
442}
443"#,
419 ); 444 );
420 } 445 }
421 446
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index b4a3d39c9..9503c936d 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -71,7 +71,7 @@ pub(super) fn element(
71 } 71 }
72 NAME_REF => { 72 NAME_REF => {
73 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); 73 let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
74 highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { 74 highlight_func_by_name_ref(sema, krate, &name_ref).unwrap_or_else(|| {
75 let is_self = name_ref.self_token().is_some(); 75 let is_self = name_ref.self_token().is_some();
76 let h = match NameRefClass::classify(sema, &name_ref) { 76 let h = match NameRefClass::classify(sema, &name_ref) {
77 Some(name_kind) => match name_kind { 77 Some(name_kind) => match name_kind {
@@ -108,7 +108,7 @@ pub(super) fn element(
108 NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(), 108 NameRefClass::FieldShorthand { .. } => SymbolKind::Field.into(),
109 }, 109 },
110 None if syntactic_name_ref_highlighting => { 110 None if syntactic_name_ref_highlighting => {
111 highlight_name_ref_by_syntax(name_ref, sema) 111 highlight_name_ref_by_syntax(name_ref, sema, krate)
112 } 112 }
113 None => HlTag::UnresolvedReference.into(), 113 None => HlTag::UnresolvedReference.into(),
114 }; 114 };
@@ -434,19 +434,23 @@ fn highlight_def(db: &RootDatabase, krate: Option<hir::Crate>, def: Definition)
434 434
435fn highlight_func_by_name_ref( 435fn highlight_func_by_name_ref(
436 sema: &Semantics<RootDatabase>, 436 sema: &Semantics<RootDatabase>,
437 krate: Option<hir::Crate>,
437 name_ref: &ast::NameRef, 438 name_ref: &ast::NameRef,
438) -> Option<Highlight> { 439) -> Option<Highlight> {
439 let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?; 440 let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
440 highlight_method_call(sema, &mc) 441 highlight_method_call(sema, krate, &mc)
441} 442}
442 443
443fn highlight_method_call( 444fn highlight_method_call(
444 sema: &Semantics<RootDatabase>, 445 sema: &Semantics<RootDatabase>,
446 krate: Option<hir::Crate>,
445 method_call: &ast::MethodCallExpr, 447 method_call: &ast::MethodCallExpr,
446) -> Option<Highlight> { 448) -> Option<Highlight> {
447 let func = sema.resolve_method_call(&method_call)?; 449 let func = sema.resolve_method_call(&method_call)?;
450
448 let mut h = SymbolKind::Function.into(); 451 let mut h = SymbolKind::Function.into();
449 h |= HlMod::Associated; 452 h |= HlMod::Associated;
453
450 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { 454 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
451 h |= HlMod::Unsafe; 455 h |= HlMod::Unsafe;
452 } 456 }
@@ -454,7 +458,10 @@ fn highlight_method_call(
454 h |= HlMod::Async; 458 h |= HlMod::Async;
455 } 459 }
456 if func.as_assoc_item(sema.db).and_then(|it| it.containing_trait(sema.db)).is_some() { 460 if func.as_assoc_item(sema.db).and_then(|it| it.containing_trait(sema.db)).is_some() {
457 h |= HlMod::Trait 461 h |= HlMod::Trait;
462 }
463 if Some(func.module(sema.db).krate()) != krate {
464 h |= HlMod::Library;
458 } 465 }
459 466
460 if let Some(self_param) = func.self_param(sema.db) { 467 if let Some(self_param) = func.self_param(sema.db) {
@@ -503,7 +510,11 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
503 tag.into() 510 tag.into()
504} 511}
505 512
506fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { 513fn highlight_name_ref_by_syntax(
514 name: ast::NameRef,
515 sema: &Semantics<RootDatabase>,
516 krate: Option<hir::Crate>,
517) -> Highlight {
507 let default = HlTag::UnresolvedReference; 518 let default = HlTag::UnresolvedReference;
508 519
509 let parent = match name.syntax().parent() { 520 let parent = match name.syntax().parent() {
@@ -514,7 +525,7 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
514 match parent.kind() { 525 match parent.kind() {
515 METHOD_CALL_EXPR => { 526 METHOD_CALL_EXPR => {
516 return ast::MethodCallExpr::cast(parent) 527 return ast::MethodCallExpr::cast(parent)
517 .and_then(|it| highlight_method_call(sema, &it)) 528 .and_then(|it| highlight_method_call(sema, krate, &it))
518 .unwrap_or_else(|| SymbolKind::Function.into()); 529 .unwrap_or_else(|| SymbolKind::Function.into());
519 } 530 }
520 FIELD_EXPR => { 531 FIELD_EXPR => {
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 055d21109..0264e39a3 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -258,7 +258,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
258 258
259 <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span> 259 <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span>
260 260
261 <span class="keyword control">if</span> <span class="keyword">let</span> <span class="module library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Die</span> <span class="operator">=</span> <span class="variable">control_flow</span> <span class="brace">{</span> 261 <span class="keyword control">if</span> <span class="variable">control_flow</span><span class="operator">.</span><span class="function associated consuming library">should_die</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
262 foo::<span class="macro">die!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> 262 foo::<span class="macro">die!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
263 <span class="brace">}</span> 263 <span class="brace">}</span>
264<span class="brace">}</span> 264<span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index be4447ebb..662b53481 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -232,7 +232,7 @@ fn use_foo_items() {
232 232
233 let control_flow = foo::identity(foo::ControlFlow::Continue); 233 let control_flow = foo::identity(foo::ControlFlow::Continue);
234 234
235 if let foo::ControlFlow::Die = control_flow { 235 if control_flow.should_die() {
236 foo::die!(); 236 foo::die!();
237 } 237 }
238} 238}
@@ -249,6 +249,12 @@ pub enum ControlFlow {
249 Die, 249 Die,
250} 250}
251 251
252impl ControlFlow {
253 pub fn should_die(self) -> bool {
254 matches!(self, ControlFlow::Die)
255 }
256}
257
252pub fn identity<T>(x: T) -> T { x } 258pub fn identity<T>(x: T) -> T { x }
253 259
254pub mod consts { 260pub mod consts {