Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #16163 - Veykril:goto-impl-fix, r=Veykril
fix: Deduplicate annotations Fixes https://github.com/rust-lang/rust-analyzer/issues/16157
bors 2023-12-19
parent dbd0b03 · parent 002e611 · commit 7204ee1
-rw-r--r--crates/hir-expand/src/files.rs2
-rw-r--r--crates/hir/src/semantics.rs5
-rw-r--r--crates/ide-assists/src/handlers/generate_enum_variant.rs2
-rw-r--r--crates/ide-db/src/rename.rs4
-rw-r--r--crates/ide/src/annotations.rs289
-rw-r--r--crates/ide/src/goto_implementation.rs15
-rw-r--r--crates/span/src/lib.rs2
7 files changed, 158 insertions, 161 deletions
diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs
index 40553d3e96..d0a1bef11c 100644
--- a/crates/hir-expand/src/files.rs
+++ b/crates/hir-expand/src/files.rs
@@ -342,7 +342,7 @@ impl InFile<TextRange> {
}
impl<N: AstNode> InFile<N> {
- pub fn original_ast_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<N>> {
+ pub fn original_ast_node_rooted(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<N>> {
// This kind of upmapping can only be achieved in attribute expanded files,
// as we don't have node inputs otherwise and therefore can't find an `N` node in the input
let file_id = match self.file_id.repr() {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index a03ff22074..95ed83a49a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -512,8 +512,7 @@ impl<'db> SemanticsImpl<'db> {
}
/// Descend the token into its macro call if it is part of one, returning the tokens in the
- /// expansion that it is associated with. If `offset` points into the token's range, it will
- /// be considered for the mapping in case of inline format args.
+ /// expansion that it is associated with.
pub fn descend_into_macros(
&self,
mode: DescendPreference,
@@ -850,7 +849,7 @@ impl<'db> SemanticsImpl<'db> {
/// Attempts to map the node out of macro expanded files.
/// This only work for attribute expansions, as other ones do not have nodes as input.
pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
- self.wrap_node_infile(node).original_ast_node(self.db.upcast()).map(
+ self.wrap_node_infile(node).original_ast_node_rooted(self.db.upcast()).map(
|InRealFile { file_id, value }| {
self.cache(find_root(value.syntax()), file_id.into());
value
diff --git a/crates/ide-assists/src/handlers/generate_enum_variant.rs b/crates/ide-assists/src/handlers/generate_enum_variant.rs
index 1a1e992e28..2aaf9d0679 100644
--- a/crates/ide-assists/src/handlers/generate_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/generate_enum_variant.rs
@@ -114,7 +114,7 @@ fn add_variant_to_accumulator(
parent: PathParent,
) -> Option<()> {
let db = ctx.db();
- let InRealFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node(db)?;
+ let InRealFile { file_id, value: enum_node } = adt.source(db)?.original_ast_node_rooted(db)?;
acc.add(
AssistId("generate_enum_variant", AssistKind::Generate),
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index c653264006..7f28965885 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -516,7 +516,7 @@ fn source_edit_from_def(
if let Definition::Local(local) = def {
let mut file_id = None;
for source in local.sources(sema.db) {
- let source = match source.source.clone().original_ast_node(sema.db) {
+ let source = match source.source.clone().original_ast_node_rooted(sema.db) {
Some(source) => source,
None => match source
.source
@@ -560,7 +560,7 @@ fn source_edit_from_def(
}
} else {
// Foo { ref mut field } -> Foo { field: ref mut new_name }
- // ^ insert `field: `
+ // original_ast_node_rootedd: `
// ^^^^^ replace this with `new_name`
edit.insert(
pat.syntax().text_range().start(),
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index d7f82b4af3..f49c5af0af 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -3,8 +3,9 @@ use ide_db::{
base_db::{FileId, FilePosition, FileRange},
defs::Definition,
helpers::visit_file_defs,
- RootDatabase,
+ FxHashSet, RootDatabase,
};
+use itertools::Itertools;
use syntax::{ast::HasName, AstNode, TextRange};
use crate::{
@@ -23,13 +24,13 @@ mod fn_references;
// and running/debugging binaries.
//
// image::https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png[]
-#[derive(Debug)]
+#[derive(Debug, Hash, PartialEq, Eq)]
pub struct Annotation {
pub range: TextRange,
pub kind: AnnotationKind,
}
-#[derive(Debug)]
+#[derive(Debug, Hash, PartialEq, Eq)]
pub enum AnnotationKind {
Runnable(Runnable),
HasImpls { pos: FilePosition, data: Option<Vec<NavigationTarget>> },
@@ -56,7 +57,7 @@ pub(crate) fn annotations(
config: &AnnotationConfig,
file_id: FileId,
) -> Vec<Annotation> {
- let mut annotations = Vec::default();
+ let mut annotations = FxHashSet::default();
if config.annotate_runnables {
for runnable in runnables(db, file_id) {
@@ -66,7 +67,7 @@ pub(crate) fn annotations(
let range = runnable.nav.focus_or_full_range();
- annotations.push(Annotation { range, kind: AnnotationKind::Runnable(runnable) });
+ annotations.insert(Annotation { range, kind: AnnotationKind::Runnable(runnable) });
}
}
@@ -99,13 +100,13 @@ pub(crate) fn annotations(
})
.for_each(|range| {
let (annotation_range, target_position) = mk_ranges(range);
- annotations.push(Annotation {
+ annotations.insert(Annotation {
range: annotation_range,
kind: AnnotationKind::HasReferences {
pos: target_position,
data: None,
},
- })
+ });
})
}
if config.annotate_references || config.annotate_impls {
@@ -131,14 +132,14 @@ pub(crate) fn annotations(
};
let (annotation_range, target_pos) = mk_ranges(range);
if config.annotate_impls && !matches!(def, Definition::Const(_)) {
- annotations.push(Annotation {
+ annotations.insert(Annotation {
range: annotation_range,
kind: AnnotationKind::HasImpls { pos: target_pos, data: None },
});
}
if config.annotate_references {
- annotations.push(Annotation {
+ annotations.insert(Annotation {
range: annotation_range,
kind: AnnotationKind::HasReferences { pos: target_pos, data: None },
});
@@ -149,7 +150,7 @@ pub(crate) fn annotations(
node: InFile<T>,
source_file_id: FileId,
) -> Option<(TextRange, Option<TextRange>)> {
- if let Some(InRealFile { file_id, value }) = node.original_ast_node(db) {
+ if let Some(InRealFile { file_id, value }) = node.original_ast_node_rooted(db) {
if file_id == source_file_id {
return Some((
value.syntax().text_range(),
@@ -171,7 +172,7 @@ pub(crate) fn annotations(
}));
}
- annotations
+ annotations.into_iter().sorted_by_key(|a| (a.range.start(), a.range.end())).collect()
}
pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) -> Annotation {
@@ -253,25 +254,6 @@ fn main() {
expect![[r#"
[
Annotation {
- range: 53..57,
- kind: Runnable(
- Runnable {
- use_name_in_title: false,
- nav: NavigationTarget {
- file_id: FileId(
- 0,
- ),
- full_range: 50..85,
- focus_range: 53..57,
- name: "main",
- kind: Function,
- },
- kind: Bin,
- cfg: None,
- },
- ),
- },
- Annotation {
range: 6..10,
kind: HasReferences {
pos: FilePosition {
@@ -308,6 +290,25 @@ fn main() {
},
Annotation {
range: 53..57,
+ kind: Runnable(
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 50..85,
+ focus_range: 53..57,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ ),
+ },
+ Annotation {
+ range: 53..57,
kind: HasReferences {
pos: FilePosition {
file_id: FileId(
@@ -338,27 +339,8 @@ fn main() {
expect![[r#"
[
Annotation {
- range: 17..21,
- kind: Runnable(
- Runnable {
- use_name_in_title: false,
- nav: NavigationTarget {
- file_id: FileId(
- 0,
- ),
- full_range: 14..48,
- focus_range: 17..21,
- name: "main",
- kind: Function,
- },
- kind: Bin,
- cfg: None,
- },
- ),
- },
- Annotation {
range: 7..11,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePosition {
file_id: FileId(
0,
@@ -366,13 +348,20 @@ fn main() {
offset: 7,
},
data: Some(
- [],
+ [
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 41..45,
+ },
+ ],
),
},
},
Annotation {
range: 7..11,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePosition {
file_id: FileId(
0,
@@ -380,19 +369,31 @@ fn main() {
offset: 7,
},
data: Some(
- [
- FileRange {
- file_id: FileId(
- 0,
- ),
- range: 41..45,
- },
- ],
+ [],
),
},
},
Annotation {
range: 17..21,
+ kind: Runnable(
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 14..48,
+ focus_range: 17..21,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ ),
+ },
+ Annotation {
+ range: 17..21,
kind: HasReferences {
pos: FilePosition {
file_id: FileId(
@@ -427,27 +428,8 @@ fn main() {
expect![[r#"
[
Annotation {
- range: 69..73,
- kind: Runnable(
- Runnable {
- use_name_in_title: false,
- nav: NavigationTarget {
- file_id: FileId(
- 0,
- ),
- full_range: 66..100,
- focus_range: 69..73,
- name: "main",
- kind: Function,
- },
- kind: Bin,
- cfg: None,
- },
- ),
- },
- Annotation {
range: 7..11,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePosition {
file_id: FileId(
0,
@@ -456,14 +438,17 @@ fn main() {
},
data: Some(
[
- NavigationTarget {
+ FileRange {
file_id: FileId(
0,
),
- full_range: 36..64,
- focus_range: 57..61,
- name: "impl",
- kind: Impl,
+ range: 57..61,
+ },
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 93..97,
},
],
),
@@ -471,7 +456,7 @@ fn main() {
},
Annotation {
range: 7..11,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePosition {
file_id: FileId(
0,
@@ -480,17 +465,14 @@ fn main() {
},
data: Some(
[
- FileRange {
- file_id: FileId(
- 0,
- ),
- range: 57..61,
- },
- FileRange {
+ NavigationTarget {
file_id: FileId(
0,
),
- range: 93..97,
+ full_range: 36..64,
+ focus_range: 57..61,
+ name: "impl",
+ kind: Impl,
},
],
),
@@ -555,6 +537,25 @@ fn main() {
),
},
},
+ Annotation {
+ range: 69..73,
+ kind: Runnable(
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 66..100,
+ focus_range: 69..73,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ ),
+ },
]
"#]],
);
@@ -623,27 +624,8 @@ fn main() {
expect![[r#"
[
Annotation {
- range: 61..65,
- kind: Runnable(
- Runnable {
- use_name_in_title: false,
- nav: NavigationTarget {
- file_id: FileId(
- 0,
- ),
- full_range: 58..95,
- focus_range: 61..65,
- name: "main",
- kind: Function,
- },
- kind: Bin,
- cfg: None,
- },
- ),
- },
- Annotation {
range: 7..11,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePosition {
file_id: FileId(
0,
@@ -652,14 +634,17 @@ fn main() {
},
data: Some(
[
- NavigationTarget {
+ FileRange {
file_id: FileId(
0,
),
- full_range: 14..56,
- focus_range: 19..23,
- name: "impl",
- kind: Impl,
+ range: 19..23,
+ },
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 74..78,
},
],
),
@@ -667,7 +652,7 @@ fn main() {
},
Annotation {
range: 7..11,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePosition {
file_id: FileId(
0,
@@ -676,17 +661,14 @@ fn main() {
},
data: Some(
[
- FileRange {
- file_id: FileId(
- 0,
- ),
- range: 19..23,
- },
- FileRange {
+ NavigationTarget {
file_id: FileId(
0,
),
- range: 74..78,
+ full_range: 14..56,
+ focus_range: 19..23,
+ name: "impl",
+ kind: Impl,
},
],
),
@@ -727,6 +709,25 @@ fn main() {
),
},
},
+ Annotation {
+ range: 61..65,
+ kind: Runnable(
+ Runnable {
+ use_name_in_title: false,
+ nav: NavigationTarget {
+ file_id: FileId(
+ 0,
+ ),
+ full_range: 58..95,
+ focus_range: 61..65,
+ name: "main",
+ kind: Function,
+ },
+ kind: Bin,
+ cfg: None,
+ },
+ ),
+ },
]
"#]],
);
@@ -747,6 +748,20 @@ mod tests {
[
Annotation {
range: 3..7,
+ kind: HasReferences {
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 3,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
+ range: 3..7,
kind: Runnable(
Runnable {
use_name_in_title: false,
@@ -812,20 +827,6 @@ mod tests {
},
),
},
- Annotation {
- range: 3..7,
- kind: HasReferences {
- pos: FilePosition {
- file_id: FileId(
- 0,
- ),
- offset: 3,
- },
- data: Some(
- [],
- ),
- },
- },
]
"#]],
);
@@ -877,7 +878,7 @@ struct Foo;
[
Annotation {
range: 0..71,
- kind: HasImpls {
+ kind: HasReferences {
pos: FilePosition {
file_id: FileId(
0,
@@ -891,7 +892,7 @@ struct Foo;
},
Annotation {
range: 0..71,
- kind: HasReferences {
+ kind: HasImpls {
pos: FilePosition {
file_id: FileId(
0,
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 6384db39d7..c1a4a7b1fc 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -4,7 +4,6 @@ use ide_db::{
helpers::pick_best_token,
RootDatabase,
};
-use itertools::Itertools;
use syntax::{ast, AstNode, SyntaxKind::*, T};
use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
@@ -34,10 +33,10 @@ pub(crate) fn goto_implementation(
})?;
let range = original_token.text_range();
let navs =
- sema.descend_into_macros(DescendPreference::None, original_token)
- .into_iter()
- .filter_map(|token| token.parent().and_then(ast::NameLike::cast))
- .filter_map(|node| match &node {
+ sema.descend_into_macros_single(DescendPreference::SameText, original_token)
+ .parent()
+ .and_then(ast::NameLike::cast)
+ .and_then(|node| match &node {
ast::NameLike::Name(name) => {
NameClass::classify(&sema, name).and_then(|class| match class {
NameClass::Definition(it) | NameClass::ConstReference(it) => Some(it),
@@ -52,8 +51,7 @@ pub(crate) fn goto_implementation(
}),
ast::NameLike::Lifetime(_) => None,
})
- .unique()
- .filter_map(|def| {
+ .and_then(|def| {
let navs = match def {
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
@@ -75,8 +73,7 @@ pub(crate) fn goto_implementation(
};
Some(navs)
})
- .flatten()
- .collect();
+ .unwrap_or_default();
Some(RangeInfo { range, info: navs })
}
diff --git a/crates/span/src/lib.rs b/crates/span/src/lib.rs
index d9f20e18c4..09af34ce7e 100644
--- a/crates/span/src/lib.rs
+++ b/crates/span/src/lib.rs
@@ -12,7 +12,7 @@ pub use crate::map::{RealSpanMap, SpanMap};
pub use syntax::{TextRange, TextSize};
pub use vfs::FileId;
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct FilePosition {
pub file_id: FileId,
pub offset: TextSize,