Skip to content

Commit 42e3f97

Browse files
committed
Support labels in reference search
1 parent e1acb0c commit 42e3f97

21 files changed

+142
-14
lines changed

crates/ide/src/display/navigation_target.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt;
55
use either::Either;
66
use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource};
77
use ide_db::{
8-
base_db::{FileId, SourceDatabase},
8+
base_db::{FileId, FileRange, SourceDatabase},
99
symbol_index::FileSymbolKind,
1010
};
1111
use ide_db::{defs::Definition, RootDatabase};
@@ -28,6 +28,7 @@ pub enum SymbolKind {
2828
ValueParam,
2929
SelfParam,
3030
Local,
31+
Label,
3132
Function,
3233
Const,
3334
Static,
@@ -223,6 +224,7 @@ impl TryToNav for Definition {
223224
Definition::Local(it) => Some(it.to_nav(db)),
224225
Definition::TypeParam(it) => Some(it.to_nav(db)),
225226
Definition::LifetimeParam(it) => Some(it.to_nav(db)),
227+
Definition::Label(it) => Some(it.to_nav(db)),
226228
}
227229
}
228230
}
@@ -421,6 +423,27 @@ impl ToNav for hir::Local {
421423
}
422424
}
423425

426+
impl ToNav for hir::Label {
427+
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
428+
let src = self.source(db);
429+
let node = src.value.syntax();
430+
let FileRange { file_id, range } = src.with_value(node).original_file_range(db);
431+
let focus_range =
432+
src.value.lifetime().and_then(|lt| lt.lifetime_ident_token()).map(|lt| lt.text_range());
433+
let name = self.name(db).to_string().into();
434+
NavigationTarget {
435+
file_id,
436+
name,
437+
kind: Some(SymbolKind::Label),
438+
full_range: range,
439+
focus_range,
440+
container_name: None,
441+
description: None,
442+
docs: None,
443+
}
444+
}
445+
}
446+
424447
impl ToNav for hir::TypeParam {
425448
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
426449
let src = self.source(db);

crates/ide/src/doc_links.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ fn rewrite_intra_doc_link(
193193
Definition::SelfType(_)
194194
| Definition::Local(_)
195195
| Definition::TypeParam(_)
196-
| Definition::LifetimeParam(_) => return None,
196+
| Definition::LifetimeParam(_)
197+
| Definition::Label(_) => return None,
197198
}?;
198199
let krate = resolved.module(db)?.krate();
199200
let canonical_path = resolved.canonical_path(db)?;

crates/ide/src/goto_definition.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,4 +1105,19 @@ fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
11051105
"#,
11061106
);
11071107
}
1108+
1109+
#[test]
1110+
fn goto_label() {
1111+
check(
1112+
r#"
1113+
fn foo<'foo>(_: &'foo ()) {
1114+
'foo: {
1115+
//^^^^
1116+
'bar: loop {
1117+
break 'foo<|>;
1118+
}
1119+
}
1120+
}"#,
1121+
)
1122+
}
11081123
}

crates/ide/src/hover.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
370370
Adt::Enum(it) => from_def_source(db, it, mod_path),
371371
})
372372
}
373-
Definition::TypeParam(_) | Definition::LifetimeParam(_) => {
373+
Definition::TypeParam(_) | Definition::LifetimeParam(_) | Definition::Label(_) => {
374374
// FIXME: Hover for generic param
375375
None
376376
}

crates/ide/src/references.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub(crate) fn find_all_refs(
130130
kind = ReferenceKind::FieldShorthandForLocal;
131131
}
132132
}
133-
} else if let Definition::LifetimeParam(_) = def {
133+
} else if matches!(def, Definition::LifetimeParam(_) | Definition::Label(_)) {
134134
kind = ReferenceKind::Lifetime;
135135
};
136136

@@ -1122,4 +1122,26 @@ fn main() {
11221122
"#]],
11231123
);
11241124
}
1125+
1126+
#[test]
1127+
fn test_find_labels() {
1128+
check(
1129+
r#"
1130+
fn foo<'a>() -> &'a () {
1131+
'a: loop {
1132+
'b: loop {
1133+
continue 'a<|>;
1134+
}
1135+
break 'a;
1136+
}
1137+
}
1138+
"#,
1139+
expect![[r#"
1140+
'a Label FileId(0) 29..32 29..31 Lifetime
1141+
1142+
FileId(0) 80..82 Lifetime
1143+
FileId(0) 108..110 Lifetime
1144+
"#]],
1145+
);
1146+
}
11251147
}

crates/ide/src/references/rename.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,4 +1523,29 @@ fn main() {
15231523
}"#,
15241524
);
15251525
}
1526+
1527+
#[test]
1528+
fn test_rename_label() {
1529+
check(
1530+
"'foo",
1531+
r#"
1532+
fn foo<'a>() -> &'a () {
1533+
'a: {
1534+
'b: loop {
1535+
break 'a<|>;
1536+
}
1537+
}
1538+
}
1539+
"#,
1540+
r#"
1541+
fn foo<'a>() -> &'a () {
1542+
'foo: {
1543+
'b: loop {
1544+
break 'foo;
1545+
}
1546+
}
1547+
}
1548+
"#,
1549+
)
1550+
}
15261551
}

crates/ide/src/syntax_highlighting.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,20 @@ fn highlight_element(
560560
CHAR => HighlightTag::CharLiteral.into(),
561561
QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow,
562562
LIFETIME => {
563-
let h = Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam));
564-
match element.parent().map(|it| it.kind()) {
565-
Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition,
566-
_ => h,
563+
let lifetime = element.into_node().and_then(ast::Lifetime::cast).unwrap();
564+
565+
match NameClass::classify_lifetime(sema, &lifetime) {
566+
Some(NameClass::Definition(def)) => {
567+
highlight_def(db, def) | HighlightModifier::Definition
568+
}
569+
None => match NameRefClass::classify_lifetime(sema, &lifetime) {
570+
Some(NameRefClass::Definition(def)) => highlight_def(db, def),
571+
_ => Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam)),
572+
},
573+
_ => {
574+
Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam))
575+
| HighlightModifier::Definition
576+
}
567577
}
568578
}
569579
p if p.is_punct() => match p {
@@ -825,6 +835,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
825835
return h;
826836
}
827837
Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam),
838+
Definition::Label(_) => HighlightTag::Symbol(SymbolKind::Label),
828839
}
829840
.into()
830841
}

crates/ide/src/syntax_highlighting/html.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ body { margin: 0; }
6464
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
6565
6666
.lifetime { color: #DFAF8F; font-style: italic; }
67+
.label { color: #DFAF8F; font-style: italic; }
6768
.comment { color: #7F9F7F; }
6869
.documentation { color: #629755; }
6970
.injected { opacity: 0.65 ; }

crates/ide/src/syntax_highlighting/tags.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ impl HighlightTag {
8080
SymbolKind::LifetimeParam => "lifetime",
8181
SymbolKind::Macro => "macro",
8282
SymbolKind::Local => "variable",
83+
SymbolKind::Label => "label",
8384
SymbolKind::ValueParam => "value_param",
8485
SymbolKind::SelfParam => "self_keyword",
8586
SymbolKind::Impl => "self_type",

crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
55

66
.lifetime { color: #DFAF8F; font-style: italic; }
7+
.label { color: #DFAF8F; font-style: italic; }
78
.comment { color: #7F9F7F; }
89
.documentation { color: #629755; }
910
.injected { opacity: 0.65 ; }

0 commit comments

Comments
 (0)