Skip to content

Commit 33a6f33

Browse files
Merge pull request #20186 from ChayimFriedman2/goto-impl-no-derive
feat: Provide an option to not show derives near the ADT for "Goto Implementations" or "Implementations" codelens
2 parents 7c810e9 + 4fddcc6 commit 33a6f33

File tree

9 files changed

+122
-14
lines changed

9 files changed

+122
-14
lines changed

crates/hir/src/semantics.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,6 +2105,22 @@ impl<'db> SemanticsImpl<'db> {
21052105
parent = parent_;
21062106
}
21072107
}
2108+
2109+
pub fn impl_generated_from_derive(&self, impl_: Impl) -> Option<Adt> {
2110+
let source = hir_def::src::HasSource::ast_ptr(&impl_.id.loc(self.db), self.db);
2111+
let mut file_id = source.file_id;
2112+
let adt_ast_id = loop {
2113+
let macro_call = file_id.macro_file()?;
2114+
match macro_call.loc(self.db).kind {
2115+
hir_expand::MacroCallKind::Derive { ast_id, .. } => break ast_id,
2116+
hir_expand::MacroCallKind::FnLike { ast_id, .. } => file_id = ast_id.file_id,
2117+
hir_expand::MacroCallKind::Attr { ast_id, .. } => file_id = ast_id.file_id,
2118+
}
2119+
};
2120+
let adt_source = adt_ast_id.to_in_file_node(self.db);
2121+
self.cache(adt_source.value.syntax().ancestors().last().unwrap(), adt_source.file_id);
2122+
ToDef::to_def(self, adt_source.as_ref())
2123+
}
21082124
}
21092125

21102126
// FIXME This can't be the best way to do this

crates/ide/src/annotations.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use syntax::{AstNode, TextRange, ast::HasName};
99
use crate::{
1010
NavigationTarget, RunnableKind,
1111
annotations::fn_references::find_all_methods,
12-
goto_implementation::goto_implementation,
12+
goto_implementation::{GotoImplementationConfig, goto_implementation},
1313
navigation_target,
1414
references::{FindAllRefsConfig, find_all_refs},
1515
runnables::{Runnable, runnables},
@@ -44,6 +44,7 @@ pub struct AnnotationConfig<'a> {
4444
pub annotate_method_references: bool,
4545
pub annotate_enum_variant_references: bool,
4646
pub location: AnnotationLocation,
47+
pub filter_adjacent_derive_implementations: bool,
4748
pub minicore: MiniCore<'a>,
4849
}
4950

@@ -204,7 +205,12 @@ pub(crate) fn resolve_annotation(
204205
) -> Annotation {
205206
match annotation.kind {
206207
AnnotationKind::HasImpls { pos, ref mut data } => {
207-
*data = goto_implementation(db, pos).map(|range| range.info);
208+
let goto_implementation_config = GotoImplementationConfig {
209+
filter_adjacent_derive_implementations: config
210+
.filter_adjacent_derive_implementations,
211+
};
212+
*data =
213+
goto_implementation(db, &goto_implementation_config, pos).map(|range| range.info);
208214
}
209215
AnnotationKind::HasReferences { pos, ref mut data } => {
210216
*data = find_all_refs(
@@ -253,6 +259,7 @@ mod tests {
253259
annotate_enum_variant_references: true,
254260
location: AnnotationLocation::AboveName,
255261
minicore: MiniCore::default(),
262+
filter_adjacent_derive_implementations: false,
256263
};
257264

258265
fn check_with_config(

crates/ide/src/goto_implementation.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use syntax::{AstNode, SyntaxKind::*, T, ast};
88

99
use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
1010

11+
pub struct GotoImplementationConfig {
12+
pub filter_adjacent_derive_implementations: bool,
13+
}
14+
1115
// Feature: Go to Implementation
1216
//
1317
// Navigates to the impl items of types.
@@ -19,6 +23,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
1923
// ![Go to Implementation](https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif)
2024
pub(crate) fn goto_implementation(
2125
db: &RootDatabase,
26+
config: &GotoImplementationConfig,
2227
FilePosition { file_id, offset }: FilePosition,
2328
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
2429
let sema = Semantics::new(db);
@@ -55,7 +60,19 @@ pub(crate) fn goto_implementation(
5560
.and_then(|def| {
5661
let navs = match def {
5762
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
58-
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
63+
Definition::Adt(adt) => {
64+
let mut impls = Impl::all_for_type(db, adt.ty(sema.db));
65+
if config.filter_adjacent_derive_implementations {
66+
impls.retain(|impl_| {
67+
sema.impl_generated_from_derive(*impl_) != Some(adt)
68+
});
69+
}
70+
impls
71+
.into_iter()
72+
.filter_map(|imp| imp.try_to_nav(&sema))
73+
.flatten()
74+
.collect()
75+
}
5976
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
6077
Definition::BuiltinType(builtin) => {
6178
impls_for_ty(&sema, builtin.ty(sema.db))
@@ -125,12 +142,24 @@ mod tests {
125142
use ide_db::FileRange;
126143
use itertools::Itertools;
127144

128-
use crate::fixture;
145+
use crate::{GotoImplementationConfig, fixture};
129146

147+
const TEST_CONFIG: &GotoImplementationConfig =
148+
&GotoImplementationConfig { filter_adjacent_derive_implementations: false };
149+
150+
#[track_caller]
130151
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
152+
check_with_config(TEST_CONFIG, ra_fixture);
153+
}
154+
155+
#[track_caller]
156+
fn check_with_config(
157+
config: &GotoImplementationConfig,
158+
#[rust_analyzer::rust_fixture] ra_fixture: &str,
159+
) {
131160
let (analysis, position, expected) = fixture::annotations(ra_fixture);
132161

133-
let navs = analysis.goto_implementation(position).unwrap().unwrap().info;
162+
let navs = analysis.goto_implementation(config, position).unwrap().unwrap().info;
134163

135164
let cmp = |frange: &FileRange| (frange.file_id, frange.range.start());
136165

@@ -416,4 +445,22 @@ fn test() {
416445
"#,
417446
);
418447
}
448+
449+
#[test]
450+
fn filter_adjacent_derives() {
451+
check_with_config(
452+
&GotoImplementationConfig { filter_adjacent_derive_implementations: true },
453+
r#"
454+
//- minicore: clone, copy, derive
455+
456+
#[derive(Clone, Copy)]
457+
struct Foo$0;
458+
459+
trait Bar {}
460+
461+
impl Bar for Foo {}
462+
// ^^^
463+
"#,
464+
);
465+
}
419466
}

crates/ide/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ pub use crate::{
8686
file_structure::{FileStructureConfig, StructureNode, StructureNodeKind},
8787
folding_ranges::{Fold, FoldKind},
8888
goto_definition::GotoDefinitionConfig,
89+
goto_implementation::GotoImplementationConfig,
8990
highlight_related::{HighlightRelatedConfig, HighlightedRange},
9091
hover::{
9192
HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult,
@@ -537,9 +538,10 @@ impl Analysis {
537538
/// Returns the impls from the symbol at `position`.
538539
pub fn goto_implementation(
539540
&self,
541+
config: &GotoImplementationConfig,
540542
position: FilePosition,
541543
) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> {
542-
self.with_db(|db| goto_implementation::goto_implementation(db, position))
544+
self.with_db(|db| goto_implementation::goto_implementation(db, config, position))
543545
}
544546

545547
/// Returns the type definitions for the symbol at `position`.

crates/rust-analyzer/src/cli/analysis_stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ impl flags::AnalysisStats {
12141214
annotate_method_references: false,
12151215
annotate_enum_variant_references: false,
12161216
location: ide::AnnotationLocation::AboveName,
1217+
filter_adjacent_derive_implementations: false,
12171218
minicore: MiniCore::default(),
12181219
};
12191220
for &file_id in file_ids {

crates/rust-analyzer/src/config.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use hir::Symbol;
1010
use ide::{
1111
AnnotationConfig, AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig,
1212
CompletionFieldsToResolve, DiagnosticsConfig, GenericParameterHints, GotoDefinitionConfig,
13-
HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
14-
InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
15-
RenameConfig, Snippet, SnippetScope, SourceRootId,
13+
GotoImplementationConfig, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat,
14+
InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig,
15+
MemoryLayoutHoverRenderKind, RenameConfig, Snippet, SnippetScope, SourceRootId,
1616
};
1717
use ide_db::{
1818
MiniCore, SnippetCap,
@@ -98,6 +98,9 @@ config_data! {
9898
/// Code's `files.watcherExclude`.
9999
files_exclude | files_excludeDirs: Vec<Utf8PathBuf> = vec![],
100100

101+
/// If this is `true`, when "Goto Implementations" and in "Implementations" lens, are triggered on a `struct` or `enum` or `union`, we filter out trait implementations that originate from `derive`s above the type.
102+
gotoImplementations_filterAdjacentDerives: bool = false,
103+
101104
/// Highlight related return values while the cursor is on any `match`, `if`, or match arm
102105
/// arrow (`=>`).
103106
highlightRelated_branchExitPoints_enable: bool = true,
@@ -1413,6 +1416,7 @@ pub struct LensConfig {
14131416

14141417
// annotations
14151418
pub location: AnnotationLocation,
1419+
pub filter_adjacent_derive_implementations: bool,
14161420
}
14171421

14181422
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -1469,6 +1473,7 @@ impl LensConfig {
14691473
annotate_enum_variant_references: self.enum_variant_refs,
14701474
location: self.location.into(),
14711475
minicore,
1476+
filter_adjacent_derive_implementations: self.filter_adjacent_derive_implementations,
14721477
}
14731478
}
14741479
}
@@ -2503,6 +2508,15 @@ impl Config {
25032508
refs_trait: *self.lens_enable() && *self.lens_references_trait_enable(),
25042509
enum_variant_refs: *self.lens_enable() && *self.lens_references_enumVariant_enable(),
25052510
location: *self.lens_location(),
2511+
filter_adjacent_derive_implementations: *self
2512+
.gotoImplementations_filterAdjacentDerives(),
2513+
}
2514+
}
2515+
2516+
pub fn goto_implementation(&self) -> GotoImplementationConfig {
2517+
GotoImplementationConfig {
2518+
filter_adjacent_derive_implementations: *self
2519+
.gotoImplementations_filterAdjacentDerives(),
25062520
}
25072521
}
25082522

crates/rust-analyzer/src/handlers/request.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -849,10 +849,11 @@ pub(crate) fn handle_goto_implementation(
849849
let _p = tracing::info_span!("handle_goto_implementation").entered();
850850
let position =
851851
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
852-
let nav_info = match snap.analysis.goto_implementation(position)? {
853-
None => return Ok(None),
854-
Some(it) => it,
855-
};
852+
let nav_info =
853+
match snap.analysis.goto_implementation(&snap.config.goto_implementation(), position)? {
854+
None => return Ok(None),
855+
Some(it) => it,
856+
};
856857
let src = FileRange { file_id: position.file_id, range: nav_info.range };
857858
let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
858859
Ok(Some(res))
@@ -2142,7 +2143,10 @@ fn show_impl_command_link(
21422143
) -> Option<lsp_ext::CommandLinkGroup> {
21432144
if implementations
21442145
&& show_references
2145-
&& let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None)
2146+
&& let Some(nav_data) = snap
2147+
.analysis
2148+
.goto_implementation(&snap.config.goto_implementation(), *position)
2149+
.unwrap_or(None)
21462150
{
21472151
let uri = to_proto::url(snap, position.file_id);
21482152
let line_index = snap.file_line_index(position.file_id).ok()?;

docs/book/src/configuration_generated.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,13 @@ Default: `"client"`
635635
Controls file watching implementation.
636636

637637

638+
## rust-analyzer.gotoImplementations.filterAdjacentDerives {#gotoImplementations.filterAdjacentDerives}
639+
640+
Default: `false`
641+
642+
If this is `true`, when "Goto Implementations" and in "Implementations" lens, are triggered on a `struct` or `enum` or `union`, we filter out trait implementations that originate from `derive`s above the type.
643+
644+
638645
## rust-analyzer.highlightRelated.branchExitPoints.enable {#highlightRelated.branchExitPoints.enable}
639646

640647
Default: `true`

editors/code/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,16 @@
16271627
}
16281628
}
16291629
},
1630+
{
1631+
"title": "Goto Implementations",
1632+
"properties": {
1633+
"rust-analyzer.gotoImplementations.filterAdjacentDerives": {
1634+
"markdownDescription": "If this is `true`, when \"Goto Implementations\" and in \"Implementations\" lens, are triggered on a `struct` or `enum` or `union`, we filter out trait implementations that originate from `derive`s above the type.",
1635+
"default": false,
1636+
"type": "boolean"
1637+
}
1638+
}
1639+
},
16301640
{
16311641
"title": "Highlight Related",
16321642
"properties": {

0 commit comments

Comments
 (0)