From 002e611d090ae8531afc80caf4f8d699f81f7595 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 19 Dec 2023 08:30:48 +0100 Subject: [PATCH] fix: Deduplicate annotations --- crates/hir-expand/src/files.rs | 2 +- crates/hir/src/semantics.rs | 5 +- .../src/handlers/generate_enum_variant.rs | 2 +- crates/ide-db/src/rename.rs | 4 +- crates/ide/src/annotations.rs | 331 +++++++++--------- crates/ide/src/goto_implementation.rs | 15 +- crates/span/src/lib.rs | 2 +- 7 files changed, 179 insertions(+), 182 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 { } impl InFile { - pub fn original_ast_node(self, db: &dyn db::ExpandDatabase) -> Option> { + pub fn original_ast_node_rooted(self, db: &dyn db::ExpandDatabase) -> Option> { // 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(&self, node: N) -> Option { - 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> }, @@ -56,7 +57,7 @@ pub(crate) fn annotations( config: &AnnotationConfig, file_id: FileId, ) -> Vec { - 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, source_file_id: FileId, ) -> Option<(TextRange, Option)> { - 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 { @@ -252,25 +253,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 { @@ -306,6 +288,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 { @@ -337,39 +338,6 @@ 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 { - pos: FilePosition { - file_id: FileId( - 0, - ), - offset: 7, - }, - data: Some( - [], - ), - }, - }, Annotation { range: 7..11, kind: HasReferences { @@ -391,6 +359,39 @@ fn main() { ), }, }, + Annotation { + range: 7..11, + kind: HasImpls { + pos: FilePosition { + file_id: FileId( + 0, + ), + offset: 7, + }, + data: Some( + [], + ), + }, + }, + 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 { @@ -426,49 +427,6 @@ 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 { - pos: FilePosition { - file_id: FileId( - 0, - ), - offset: 7, - }, - data: Some( - [ - NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 36..64, - focus_range: 57..61, - name: "impl", - kind: Impl, - }, - ], - ), - }, - }, Annotation { range: 7..11, kind: HasReferences { @@ -496,6 +454,30 @@ fn main() { ), }, }, + Annotation { + range: 7..11, + kind: HasImpls { + pos: FilePosition { + file_id: FileId( + 0, + ), + offset: 7, + }, + data: Some( + [ + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 36..64, + focus_range: 57..61, + name: "impl", + kind: Impl, + }, + ], + ), + }, + }, Annotation { range: 20..31, kind: HasImpls { @@ -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, + }, + ), + }, ] "#]], ); @@ -622,49 +623,6 @@ 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 { - pos: FilePosition { - file_id: FileId( - 0, - ), - offset: 7, - }, - data: Some( - [ - NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 14..56, - focus_range: 19..23, - name: "impl", - kind: Impl, - }, - ], - ), - }, - }, Annotation { range: 7..11, kind: HasReferences { @@ -692,6 +650,30 @@ fn main() { ), }, }, + Annotation { + range: 7..11, + kind: HasImpls { + pos: FilePosition { + file_id: FileId( + 0, + ), + offset: 7, + }, + data: Some( + [ + NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 14..56, + focus_range: 19..23, + name: "impl", + kind: Impl, + }, + ], + ), + }, + }, Annotation { range: 33..44, kind: HasReferences { @@ -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, + }, + ), + }, ] "#]], ); @@ -745,6 +746,20 @@ mod tests { "#, expect![[r#" [ + Annotation { + range: 3..7, + kind: HasReferences { + pos: FilePosition { + file_id: FileId( + 0, + ), + offset: 3, + }, + data: Some( + [], + ), + }, + }, Annotation { range: 3..7, kind: Runnable( @@ -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,