mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 05:13:35 +00:00
Allow crate authors to control completion of their things
Via the new `#[rust_analyzer::completions(...)]` attribute. Also fix a bug with existing settings for that where the paths wouldn't resolve correctly.
This commit is contained in:
parent
62e7d9f0fc
commit
7b584ef9bf
30 changed files with 770 additions and 293 deletions
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{HasContainer, ItemContainer, MethodCandidateCallback, Name};
|
||||
use hir::{Complete, HasContainer, ItemContainer, MethodCandidateCallback, Name};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::SmolStr;
|
||||
|
||||
|
|
@ -259,7 +259,9 @@ fn complete_methods(
|
|||
// This needs to come before the `seen_methods` test, so that if we see the same method twice,
|
||||
// once as inherent and once not, we will include it.
|
||||
if let ItemContainer::Trait(trait_) = func.container(self.ctx.db) {
|
||||
if self.ctx.exclude_traits.contains(&trait_) {
|
||||
if self.ctx.exclude_traits.contains(&trait_)
|
||||
|| trait_.complete(self.ctx.db) == Complete::IgnoreMethods
|
||||
{
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use hir::{Name, PathCandidateCallback, ScopeDef, sym};
|
||||
use hir::{Complete, Name, PathCandidateCallback, ScopeDef, sym};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::ast;
|
||||
|
||||
|
|
@ -33,10 +33,10 @@ where
|
|||
fn on_trait_item(&mut self, item: hir::AssocItem) -> ControlFlow<()> {
|
||||
// The excluded check needs to come before the `seen` test, so that if we see the same method twice,
|
||||
// once as inherent and once not, we will include it.
|
||||
if item
|
||||
.container_trait(self.ctx.db)
|
||||
.is_none_or(|trait_| !self.ctx.exclude_traits.contains(&trait_))
|
||||
&& self.seen.insert(item)
|
||||
if item.container_trait(self.ctx.db).is_none_or(|trait_| {
|
||||
!self.ctx.exclude_traits.contains(&trait_)
|
||||
&& trait_.complete(self.ctx.db) != Complete::IgnoreMethods
|
||||
}) && self.seen.insert(item)
|
||||
{
|
||||
(self.add_assoc_item)(self.acc, item);
|
||||
}
|
||||
|
|
@ -104,7 +104,9 @@ pub(crate) fn complete_expr_path(
|
|||
.iter()
|
||||
.copied()
|
||||
.map(hir::Trait::from)
|
||||
.filter(|it| !ctx.exclude_traits.contains(it))
|
||||
.filter(|it| {
|
||||
!ctx.exclude_traits.contains(it) && it.complete(ctx.db) != Complete::IgnoreMethods
|
||||
})
|
||||
.flat_map(|it| it.items(ctx.sema.db))
|
||||
.for_each(|item| add_assoc_item(acc, item)),
|
||||
Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
|
||||
|
|
|
|||
|
|
@ -268,19 +268,7 @@ fn import_on_the_fly(
|
|||
&& !ctx.is_item_hidden(original_item)
|
||||
&& ctx.check_stability(original_item.attrs(ctx.db).as_deref())
|
||||
})
|
||||
.filter(|import| {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
|
||||
if kind == AutoImportExclusionType::Always {
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.filter(|import| filter_excluded_flyimport(ctx, import))
|
||||
.sorted_by(|a, b| {
|
||||
let key = |import_path| {
|
||||
(
|
||||
|
|
@ -366,24 +354,7 @@ fn import_on_the_fly_method(
|
|||
!ctx.is_item_hidden(&import.item_to_import)
|
||||
&& !ctx.is_item_hidden(&import.original_item)
|
||||
})
|
||||
.filter(|import| {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
|
||||
if kind == AutoImportExclusionType::Always {
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let ModuleDef::Trait(_) = import.item_to_import.into_module_def() {
|
||||
!ctx.exclude_flyimport.contains_key(&def)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.filter(|import| filter_excluded_flyimport(ctx, import))
|
||||
.sorted_by(|a, b| {
|
||||
let key = |import_path| {
|
||||
(
|
||||
|
|
@ -401,6 +372,28 @@ fn import_on_the_fly_method(
|
|||
Some(())
|
||||
}
|
||||
|
||||
fn filter_excluded_flyimport(ctx: &CompletionContext<'_>, import: &LocatedImport) -> bool {
|
||||
let def = import.item_to_import.into_module_def();
|
||||
let is_exclude_flyimport = ctx.exclude_flyimport.get(&def).copied();
|
||||
|
||||
if matches!(is_exclude_flyimport, Some(AutoImportExclusionType::Always))
|
||||
|| !import.complete_in_flyimport.0
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let method_imported = import.item_to_import != import.original_item;
|
||||
if method_imported
|
||||
&& (is_exclude_flyimport.is_some()
|
||||
|| ctx.exclude_flyimport.contains_key(&import.original_item.into_module_def()))
|
||||
{
|
||||
// If this is a method, exclude it either if it was excluded itself (which may not be caught above,
|
||||
// because `item_to_import` is the trait), or if its trait was excluded. We don't need to check
|
||||
// the attributes here, since they pass from trait to methods on import map construction.
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn import_name(ctx: &CompletionContext<'_>) -> String {
|
||||
let token_kind = ctx.token.kind();
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use std::{iter, ops::ControlFlow};
|
|||
|
||||
use base_db::{RootQueryDb as _, salsa::AsDynDatabase};
|
||||
use hir::{
|
||||
DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution,
|
||||
ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo,
|
||||
DisplayTarget, HasAttrs, Local, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef,
|
||||
Semantics, SemanticsScope, Symbol, Type, TypeInfo,
|
||||
};
|
||||
use ide_db::{
|
||||
FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs,
|
||||
|
|
@ -796,15 +796,12 @@ impl<'a> CompletionContext<'a> {
|
|||
.exclude_traits
|
||||
.iter()
|
||||
.filter_map(|path| {
|
||||
scope
|
||||
.resolve_mod_path(&ModPath::from_segments(
|
||||
hir::PathKind::Plain,
|
||||
path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
|
||||
))
|
||||
.find_map(|it| match it {
|
||||
hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern)).find_map(
|
||||
|it| match it {
|
||||
hir::ItemInNs::Types(ModuleDef::Trait(t)) => Some(t),
|
||||
_ => None,
|
||||
})
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -812,11 +809,7 @@ impl<'a> CompletionContext<'a> {
|
|||
.exclude_flyimport
|
||||
.iter()
|
||||
.flat_map(|(path, kind)| {
|
||||
scope
|
||||
.resolve_mod_path(&ModPath::from_segments(
|
||||
hir::PathKind::Plain,
|
||||
path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
|
||||
))
|
||||
hir::resolve_absolute_path(db, path.split("::").map(Symbol::intern))
|
||||
.map(|it| (it.into_module_def(), *kind))
|
||||
})
|
||||
.collect();
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ pub(crate) fn render_expr(
|
|||
continue;
|
||||
};
|
||||
|
||||
item.add_import(LocatedImport::new(path, trait_item, trait_item));
|
||||
item.add_import(LocatedImport::new_no_completion(path, trait_item, trait_item));
|
||||
}
|
||||
|
||||
Some(item)
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec
|
|||
ctx.config.insert_use.prefix_kind,
|
||||
import_cfg,
|
||||
)?;
|
||||
Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item)))
|
||||
Some((path.len() > 1).then(|| LocatedImport::new_no_completion(path.clone(), item, item)))
|
||||
};
|
||||
let mut res = Vec::with_capacity(requires.len());
|
||||
for import in requires {
|
||||
|
|
|
|||
|
|
@ -1555,7 +1555,10 @@ fn main() {
|
|||
#[test]
|
||||
fn excluded_trait_method_is_excluded() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1575,23 +1578,20 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (as ExcludedTrait) fn(&self)
|
||||
me baz() (as ExcludedTrait) fn(&self)
|
||||
me foo() (as ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1599,7 +1599,10 @@ fn foo() {
|
|||
#[test]
|
||||
fn excluded_trait_not_excluded_when_inherent() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1633,7 +1636,10 @@ fn foo(v: &dyn ExcludedTrait) {
|
|||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1667,7 +1673,10 @@ fn foo(v: impl ExcludedTrait) {
|
|||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1706,7 +1715,7 @@ fn foo<T: ExcludedTrait>(v: T) {
|
|||
fn excluded_trait_method_is_excluded_from_flyimport() {
|
||||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
|
||||
exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
|
|
@ -1730,23 +1739,20 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (use module2::ExcludedTrait) fn(&self)
|
||||
me baz() (use module2::ExcludedTrait) fn(&self)
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1756,7 +1762,7 @@ fn flyimport_excluded_trait_method_is_excluded_from_flyimport() {
|
|||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_flyimport: vec![(
|
||||
"test::module2::ExcludedTrait".to_owned(),
|
||||
"ra_test_fixture::module2::ExcludedTrait".to_owned(),
|
||||
AutoImportExclusionType::Methods,
|
||||
)],
|
||||
..TEST_CONFIG
|
||||
|
|
@ -1782,23 +1788,20 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar() (use module2::ExcludedTrait) fn(&self)
|
||||
me baz() (use module2::ExcludedTrait) fn(&self)
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
me inherent() fn(&self)
|
||||
sn box Box::new(expr)
|
||||
sn call function(expr)
|
||||
sn const const {}
|
||||
sn dbg dbg!(expr)
|
||||
sn dbgr dbg!(&expr)
|
||||
sn deref *expr
|
||||
sn let let
|
||||
sn letm let mut
|
||||
sn match match expr {}
|
||||
sn ref &expr
|
||||
sn refm &mut expr
|
||||
sn return return expr
|
||||
sn unsafe unsafe {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1806,7 +1809,10 @@ fn foo() {
|
|||
#[test]
|
||||
fn excluded_trait_method_is_excluded_from_path_completion() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1826,10 +1832,7 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me bar(…) (as ExcludedTrait) fn(&self)
|
||||
me baz(…) (as ExcludedTrait) fn(&self)
|
||||
me foo(…) (as ExcludedTrait) fn(&self)
|
||||
me inherent(…) fn(&self)
|
||||
me inherent(…) fn(&self)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
@ -1837,7 +1840,10 @@ fn foo() {
|
|||
#[test]
|
||||
fn excluded_trait_method_is_not_excluded_when_trait_is_specified() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1863,7 +1869,10 @@ fn foo() {
|
|||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1893,7 +1902,10 @@ fn foo() {
|
|||
#[test]
|
||||
fn excluded_trait_not_excluded_when_inherent_path() {
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
@ -1914,7 +1926,10 @@ fn foo() {
|
|||
"#]],
|
||||
);
|
||||
check_with_config(
|
||||
CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
|
||||
CompletionConfig {
|
||||
exclude_traits: &["ra_test_fixture::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
|
|
|
|||
|
|
@ -1810,9 +1810,10 @@ fn function() {
|
|||
|
||||
#[test]
|
||||
fn excluded_trait_item_included_when_exact_match() {
|
||||
// FIXME: This does not work, we need to change the code.
|
||||
check_with_config(
|
||||
CompletionConfig {
|
||||
exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
|
||||
exclude_traits: &["ra_test_fixture::module2::ExcludedTrait".to_owned()],
|
||||
..TEST_CONFIG
|
||||
},
|
||||
r#"
|
||||
|
|
@ -1830,8 +1831,120 @@ fn foo() {
|
|||
true.foo$0
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
me foo() (use module2::ExcludedTrait) fn(&self)
|
||||
"#]],
|
||||
expect![""],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn excluded_via_attr() {
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
true.$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
ExcludedTrait$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_methods)]
|
||||
pub trait ExcludedTrait {
|
||||
fn foo(&self) {}
|
||||
fn bar(&self) {}
|
||||
fn baz(&self) {}
|
||||
}
|
||||
|
||||
impl<T> ExcludedTrait for T {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
ExcludedTrait$0
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
tt ExcludedTrait (use module2::ExcludedTrait)
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
mod module2 {
|
||||
#[rust_analyzer::completions(ignore_flyimport)]
|
||||
pub struct Foo {}
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
Foo$0
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue