mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-30 23:27:24 +00:00
Support labels in reference search
This commit is contained in:
parent
e1acb0ca5c
commit
42e3f97c30
21 changed files with 142 additions and 14 deletions
|
@ -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);
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -1105,4 +1105,19 @@ fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
|
|||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn goto_label() {
|
||||
check(
|
||||
r#"
|
||||
fn foo<'foo>(_: &'foo ()) {
|
||||
'foo: {
|
||||
//^^^^
|
||||
'bar: loop {
|
||||
break 'foo<|>;
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,7 +370,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -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
|
|||
<span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span>
|
||||
|
||||
<span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="operator">!</span><span class="bool_literal">true</span><span class="punctuation">;</span>
|
||||
|
||||
<span class="label declaration">'foo</span><span class="punctuation">:</span> <span class="keyword control">loop</span> <span class="punctuation">{</span>
|
||||
<span class="keyword control">break</span> <span class="label">'foo</span><span class="punctuation">;</span>
|
||||
<span class="keyword control">continue</span> <span class="label">'foo</span><span class="punctuation">;</span>
|
||||
<span class="punctuation">}</span>
|
||||
<span class="punctuation">}</span>
|
||||
|
||||
<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation"><</span><span class="type_param declaration">T</span><span class="punctuation">></span> <span class="punctuation">{</span>
|
||||
|
|
|
@ -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 ; }
|
||||
|
|
|
@ -168,6 +168,11 @@ fn main() {
|
|||
let baz = -baz;
|
||||
|
||||
let _ = !true;
|
||||
|
||||
'foo: loop {
|
||||
break 'foo;
|
||||
continue 'foo;
|
||||
}
|
||||
}
|
||||
|
||||
enum Option<T> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue