Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/semantics.rs16
-rw-r--r--crates/ide/src/annotations.rs11
-rw-r--r--crates/ide/src/goto_implementation.rs53
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs1
-rw-r--r--crates/rust-analyzer/src/config.rs20
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs14
-rw-r--r--docs/book/src/configuration_generated.md7
-rw-r--r--editors/code/package.json10
9 files changed, 122 insertions, 14 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 62ce3daab7..ec43442c9b 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -2105,6 +2105,22 @@ impl<'db> SemanticsImpl<'db> {
parent = parent_;
}
}
+
+ pub fn impl_generated_from_derive(&self, impl_: Impl) -> Option<Adt> {
+ let source = hir_def::src::HasSource::ast_ptr(&impl_.id.loc(self.db), self.db);
+ let mut file_id = source.file_id;
+ let adt_ast_id = loop {
+ let macro_call = file_id.macro_file()?;
+ match macro_call.loc(self.db).kind {
+ hir_expand::MacroCallKind::Derive { ast_id, .. } => break ast_id,
+ hir_expand::MacroCallKind::FnLike { ast_id, .. } => file_id = ast_id.file_id,
+ hir_expand::MacroCallKind::Attr { ast_id, .. } => file_id = ast_id.file_id,
+ }
+ };
+ let adt_source = adt_ast_id.to_in_file_node(self.db);
+ self.cache(adt_source.value.syntax().ancestors().last().unwrap(), adt_source.file_id);
+ ToDef::to_def(self, adt_source.as_ref())
+ }
}
// FIXME This can't be the best way to do this
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 36c44044bb..6fb8dedea4 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -9,7 +9,7 @@ use syntax::{AstNode, TextRange, ast::HasName};
use crate::{
NavigationTarget, RunnableKind,
annotations::fn_references::find_all_methods,
- goto_implementation::goto_implementation,
+ goto_implementation::{GotoImplementationConfig, goto_implementation},
navigation_target,
references::{FindAllRefsConfig, find_all_refs},
runnables::{Runnable, runnables},
@@ -44,6 +44,7 @@ pub struct AnnotationConfig<'a> {
pub annotate_method_references: bool,
pub annotate_enum_variant_references: bool,
pub location: AnnotationLocation,
+ pub filter_adjacent_derive_implementations: bool,
pub minicore: MiniCore<'a>,
}
@@ -204,7 +205,12 @@ pub(crate) fn resolve_annotation(
) -> Annotation {
match annotation.kind {
AnnotationKind::HasImpls { pos, ref mut data } => {
- *data = goto_implementation(db, pos).map(|range| range.info);
+ let goto_implementation_config = GotoImplementationConfig {
+ filter_adjacent_derive_implementations: config
+ .filter_adjacent_derive_implementations,
+ };
+ *data =
+ goto_implementation(db, &goto_implementation_config, pos).map(|range| range.info);
}
AnnotationKind::HasReferences { pos, ref mut data } => {
*data = find_all_refs(
@@ -253,6 +259,7 @@ mod tests {
annotate_enum_variant_references: true,
location: AnnotationLocation::AboveName,
minicore: MiniCore::default(),
+ filter_adjacent_derive_implementations: false,
};
fn check_with_config(
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 875403c4e3..0572bca445 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -8,6 +8,10 @@ use syntax::{AstNode, SyntaxKind::*, T, ast};
use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
+pub struct GotoImplementationConfig {
+ pub filter_adjacent_derive_implementations: bool,
+}
+
// Feature: Go to Implementation
//
// Navigates to the impl items of types.
@@ -19,6 +23,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
// ![Go to Implementation](https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif)
pub(crate) fn goto_implementation(
db: &RootDatabase,
+ config: &GotoImplementationConfig,
FilePosition { file_id, offset }: FilePosition,
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
let sema = Semantics::new(db);
@@ -55,7 +60,19 @@ pub(crate) fn goto_implementation(
.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)),
+ Definition::Adt(adt) => {
+ let mut impls = Impl::all_for_type(db, adt.ty(sema.db));
+ if config.filter_adjacent_derive_implementations {
+ impls.retain(|impl_| {
+ sema.impl_generated_from_derive(*impl_) != Some(adt)
+ });
+ }
+ impls
+ .into_iter()
+ .filter_map(|imp| imp.try_to_nav(&sema))
+ .flatten()
+ .collect()
+ }
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
Definition::BuiltinType(builtin) => {
impls_for_ty(&sema, builtin.ty(sema.db))
@@ -125,12 +142,24 @@ mod tests {
use ide_db::FileRange;
use itertools::Itertools;
- use crate::fixture;
+ use crate::{GotoImplementationConfig, fixture};
+ const TEST_CONFIG: &GotoImplementationConfig =
+ &GotoImplementationConfig { filter_adjacent_derive_implementations: false };
+
+ #[track_caller]
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
+ check_with_config(TEST_CONFIG, ra_fixture);
+ }
+
+ #[track_caller]
+ fn check_with_config(
+ config: &GotoImplementationConfig,
+ #[rust_analyzer::rust_fixture] ra_fixture: &str,
+ ) {
let (analysis, position, expected) = fixture::annotations(ra_fixture);
- let navs = analysis.goto_implementation(position).unwrap().unwrap().info;
+ let navs = analysis.goto_implementation(config, position).unwrap().unwrap().info;
let cmp = |frange: &FileRange| (frange.file_id, frange.range.start());
@@ -416,4 +445,22 @@ fn test() {
"#,
);
}
+
+ #[test]
+ fn filter_adjacent_derives() {
+ check_with_config(
+ &GotoImplementationConfig { filter_adjacent_derive_implementations: true },
+ r#"
+//- minicore: clone, copy, derive
+
+#[derive(Clone, Copy)]
+struct Foo$0;
+
+trait Bar {}
+
+impl Bar for Foo {}
+ // ^^^
+ "#,
+ );
+ }
}
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index ece5bac6df..2609457573 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -86,6 +86,7 @@ pub use crate::{
file_structure::{FileStructureConfig, StructureNode, StructureNodeKind},
folding_ranges::{Fold, FoldKind},
goto_definition::GotoDefinitionConfig,
+ goto_implementation::GotoImplementationConfig,
highlight_related::{HighlightRelatedConfig, HighlightedRange},
hover::{
HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult,
@@ -537,9 +538,10 @@ impl Analysis {
/// Returns the impls from the symbol at `position`.
pub fn goto_implementation(
&self,
+ config: &GotoImplementationConfig,
position: FilePosition,
) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> {
- self.with_db(|db| goto_implementation::goto_implementation(db, position))
+ self.with_db(|db| goto_implementation::goto_implementation(db, config, position))
}
/// Returns the type definitions for the symbol at `position`.
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index de24bc09ff..5e4a277f38 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -1214,6 +1214,7 @@ impl flags::AnalysisStats {
annotate_method_references: false,
annotate_enum_variant_references: false,
location: ide::AnnotationLocation::AboveName,
+ filter_adjacent_derive_implementations: false,
minicore: MiniCore::default(),
};
for &file_id in file_ids {
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 6d2907ee56..185df4dd73 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -10,9 +10,9 @@ use hir::Symbol;
use ide::{
AnnotationConfig, AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig,
CompletionFieldsToResolve, DiagnosticsConfig, GenericParameterHints, GotoDefinitionConfig,
- HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
- InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
- RenameConfig, Snippet, SnippetScope, SourceRootId,
+ GotoImplementationConfig, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat,
+ InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig,
+ MemoryLayoutHoverRenderKind, RenameConfig, Snippet, SnippetScope, SourceRootId,
};
use ide_db::{
MiniCore, SnippetCap,
@@ -98,6 +98,9 @@ config_data! {
/// Code's `files.watcherExclude`.
files_exclude | files_excludeDirs: Vec<Utf8PathBuf> = vec![],
+ /// 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.
+ gotoImplementations_filterAdjacentDerives: bool = false,
+
/// Highlight related return values while the cursor is on any `match`, `if`, or match arm
/// arrow (`=>`).
highlightRelated_branchExitPoints_enable: bool = true,
@@ -1413,6 +1416,7 @@ pub struct LensConfig {
// annotations
pub location: AnnotationLocation,
+ pub filter_adjacent_derive_implementations: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -1469,6 +1473,7 @@ impl LensConfig {
annotate_enum_variant_references: self.enum_variant_refs,
location: self.location.into(),
minicore,
+ filter_adjacent_derive_implementations: self.filter_adjacent_derive_implementations,
}
}
}
@@ -2503,6 +2508,15 @@ impl Config {
refs_trait: *self.lens_enable() && *self.lens_references_trait_enable(),
enum_variant_refs: *self.lens_enable() && *self.lens_references_enumVariant_enable(),
location: *self.lens_location(),
+ filter_adjacent_derive_implementations: *self
+ .gotoImplementations_filterAdjacentDerives(),
+ }
+ }
+
+ pub fn goto_implementation(&self) -> GotoImplementationConfig {
+ GotoImplementationConfig {
+ filter_adjacent_derive_implementations: *self
+ .gotoImplementations_filterAdjacentDerives(),
}
}
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 66a7a0b825..ab463533d7 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -849,10 +849,11 @@ pub(crate) fn handle_goto_implementation(
let _p = tracing::info_span!("handle_goto_implementation").entered();
let position =
try_default!(from_proto::file_position(&snap, params.text_document_position_params)?);
- let nav_info = match snap.analysis.goto_implementation(position)? {
- None => return Ok(None),
- Some(it) => it,
- };
+ let nav_info =
+ match snap.analysis.goto_implementation(&snap.config.goto_implementation(), position)? {
+ None => return Ok(None),
+ Some(it) => it,
+ };
let src = FileRange { file_id: position.file_id, range: nav_info.range };
let res = to_proto::goto_definition_response(&snap, Some(src), nav_info.info)?;
Ok(Some(res))
@@ -2142,7 +2143,10 @@ fn show_impl_command_link(
) -> Option<lsp_ext::CommandLinkGroup> {
if implementations
&& show_references
- && let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None)
+ && let Some(nav_data) = snap
+ .analysis
+ .goto_implementation(&snap.config.goto_implementation(), *position)
+ .unwrap_or(None)
{
let uri = to_proto::url(snap, position.file_id);
let line_index = snap.file_line_index(position.file_id).ok()?;
diff --git a/docs/book/src/configuration_generated.md b/docs/book/src/configuration_generated.md
index d768993f50..7ec7c379c6 100644
--- a/docs/book/src/configuration_generated.md
+++ b/docs/book/src/configuration_generated.md
@@ -635,6 +635,13 @@ Default: `"client"`
Controls file watching implementation.
+## rust-analyzer.gotoImplementations.filterAdjacentDerives {#gotoImplementations.filterAdjacentDerives}
+
+Default: `false`
+
+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.
+
+
## rust-analyzer.highlightRelated.branchExitPoints.enable {#highlightRelated.branchExitPoints.enable}
Default: `true`
diff --git a/editors/code/package.json b/editors/code/package.json
index d659421a02..0269494da9 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1628,6 +1628,16 @@
}
},
{
+ "title": "Goto Implementations",
+ "properties": {
+ "rust-analyzer.gotoImplementations.filterAdjacentDerives": {
+ "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.",
+ "default": false,
+ "type": "boolean"
+ }
+ }
+ },
+ {
"title": "Highlight Related",
"properties": {
"rust-analyzer.highlightRelated.branchExitPoints.enable": {