From 42e3f97c300c24b6ff9ff96ad0c24d386d3a253b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 23 Dec 2020 17:15:01 +0100 Subject: Support labels in reference search --- crates/ide/src/display/navigation_target.rs | 25 +++++++++++++++++++++- crates/ide/src/doc_links.rs | 3 ++- crates/ide/src/goto_definition.rs | 15 +++++++++++++ crates/ide/src/hover.rs | 2 +- crates/ide/src/references.rs | 24 ++++++++++++++++++++- crates/ide/src/references/rename.rs | 25 ++++++++++++++++++++++ crates/ide/src/syntax_highlighting.rs | 19 ++++++++++++---- crates/ide/src/syntax_highlighting/html.rs | 1 + crates/ide/src/syntax_highlighting/tags.rs | 1 + .../test_data/highlight_assoc_functions.html | 1 + .../test_data/highlight_doctest.html | 1 + .../test_data/highlight_extern_crate.html | 1 + .../test_data/highlight_injection.html | 1 + .../test_data/highlight_strings.html | 1 + .../test_data/highlight_unsafe.html | 1 + .../test_data/highlighting.html | 6 ++++++ .../test_data/rainbow_highlighting.html | 1 + crates/ide/src/syntax_highlighting/tests.rs | 5 +++++ 18 files changed, 125 insertions(+), 8 deletions(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index cd8ec54fa..6431e7d6d 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs @@ -5,7 +5,7 @@ use std::fmt; use either::Either; use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource}; use ide_db::{ - base_db::{FileId, SourceDatabase}, + base_db::{FileId, FileRange, SourceDatabase}, symbol_index::FileSymbolKind, }; use ide_db::{defs::Definition, RootDatabase}; @@ -28,6 +28,7 @@ pub enum SymbolKind { ValueParam, SelfParam, Local, + Label, Function, Const, Static, @@ -223,6 +224,7 @@ impl TryToNav for Definition { Definition::Local(it) => Some(it.to_nav(db)), Definition::TypeParam(it) => Some(it.to_nav(db)), Definition::LifetimeParam(it) => Some(it.to_nav(db)), + Definition::Label(it) => Some(it.to_nav(db)), } } } @@ -421,6 +423,27 @@ impl ToNav for hir::Local { } } +impl ToNav for hir::Label { + fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { + let src = self.source(db); + let node = src.value.syntax(); + let FileRange { file_id, range } = src.with_value(node).original_file_range(db); + let focus_range = + src.value.lifetime().and_then(|lt| lt.lifetime_ident_token()).map(|lt| lt.text_range()); + let name = self.name(db).to_string().into(); + NavigationTarget { + file_id, + name, + kind: Some(SymbolKind::Label), + full_range: range, + focus_range, + container_name: None, + description: None, + docs: None, + } + } +} + impl ToNav for hir::TypeParam { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index b61ea0b3e..e10516f43 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -193,7 +193,8 @@ fn rewrite_intra_doc_link( Definition::SelfType(_) | Definition::Local(_) | Definition::TypeParam(_) - | Definition::LifetimeParam(_) => return None, + | Definition::LifetimeParam(_) + | Definition::Label(_) => return None, }?; let krate = resolved.module(db)?.krate(); let canonical_path = resolved.canonical_path(db)?; diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 431da5d9c..65e45c920 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -1105,4 +1105,19 @@ fn foo() where T: for<'a> Foo<&'a<|> (u8, u16)>, {} "#, ); } + + #[test] + fn goto_label() { + check( + r#" +fn foo<'foo>(_: &'foo ()) { + 'foo: { + //^^^^ + 'bar: loop { + break 'foo<|>; + } + } +}"#, + ) + } } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 52f993cc9..73245fbe7 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -370,7 +370,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option { Adt::Enum(it) => from_def_source(db, it, mod_path), }) } - Definition::TypeParam(_) | Definition::LifetimeParam(_) => { + Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => { // FIXME: Hover for generic param None } diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 33b7358f7..21b2d7ca1 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -130,7 +130,7 @@ pub(crate) fn find_all_refs( kind = ReferenceKind::FieldShorthandForLocal; } } - } else if let Definition::LifetimeParam(_) = def { + } else if matches!(def, Definition::LifetimeParam(_) | Definition::Label(_)) { kind = ReferenceKind::Lifetime; }; @@ -1122,4 +1122,26 @@ fn main() { "#]], ); } + + #[test] + fn test_find_labels() { + check( + r#" +fn foo<'a>() -> &'a () { + 'a: loop { + 'b: loop { + continue 'a<|>; + } + break 'a; + } +} +"#, + expect![[r#" + 'a Label FileId(0) 29..32 29..31 Lifetime + + FileId(0) 80..82 Lifetime + FileId(0) 108..110 Lifetime + "#]], + ); + } } diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index cd721b7eb..4f353852f 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs @@ -1523,4 +1523,29 @@ fn main() { }"#, ); } + + #[test] + fn test_rename_label() { + check( + "'foo", + r#" +fn foo<'a>() -> &'a () { + 'a: { + 'b: loop { + break 'a<|>; + } + } +} +"#, + r#" +fn foo<'a>() -> &'a () { + 'foo: { + 'b: loop { + break 'foo; + } + } +} +"#, + ) + } } diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 00c717c7c..5ad96581b 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -560,10 +560,20 @@ fn highlight_element( CHAR => HighlightTag::CharLiteral.into(), QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow, LIFETIME => { - let h = Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)); - match element.parent().map(|it| it.kind()) { - Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition, - _ => h, + let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap(); + + match NameClass::classify_lifetime(sema, &lifetime) { + Some(NameClass::Definition(def)) => { + highlight_def(db, def) | HighlightModifier::Definition + } + None => match NameRefClass::classify_lifetime(sema, &lifetime) { + Some(NameRefClass::Definition(def)) => highlight_def(db, def), + _ => Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)), + }, + _ => { + Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)) + | HighlightModifier::Definition + } } } p if p.is_punct() => match p { @@ -825,6 +835,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { return h; } Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam), + Definition::Label(_) => HighlightTag::Symbol(SymbolKind::Label), } .into() } diff --git a/crates/ide/src/syntax_highlighting/html.rs b/crates/ide/src/syntax_highlighting/html.rs index abcc5cccc..99ba3a59d 100644 --- a/crates/ide/src/syntax_highlighting/html.rs +++ b/crates/ide/src/syntax_highlighting/html.rs @@ -64,6 +64,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 974f54fa0..2a6cc0cab 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs @@ -80,6 +80,7 @@ impl HighlightTag { SymbolKind::LifetimeParam => "lifetime", SymbolKind::Macro => "macro", SymbolKind::Local => "variable", + SymbolKind::Label => "label", SymbolKind::ValueParam => "value_param", SymbolKind::SelfParam => "self_keyword", SymbolKind::Impl => "self_type", diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index db6f32d33..506ebe60e 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index 4e511baa9..4dd7413ba 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index 800d894c7..ed452586a 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 7f18ad297..92e7dc3e4 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index c843b5085..31dad5d42 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index d26f48516..e3a0aa317 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 588e86a34..72ff9dd40 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } @@ -194,6 +195,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd let baz = -baz; let _ = !true; + + 'foo: loop { + break 'foo; + continue 'foo; + } } enum Option<T> { diff --git a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html index c7589605f..8b3dfa69f 100644 --- a/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html @@ -4,6 +4,7 @@ body { margin: 0; } pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; } .lifetime { color: #DFAF8F; font-style: italic; } +.label { color: #DFAF8F; font-style: italic; } .comment { color: #7F9F7F; } .documentation { color: #629755; } .injected { opacity: 0.65 ; } diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index f53d2c3ba..e0df0d2b5 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -168,6 +168,11 @@ fn main() { let baz = -baz; let _ = !true; + + 'foo: loop { + break 'foo; + continue 'foo; + } } enum Option { -- cgit v1.2.3