Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/display.rs2
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/ide_completion/src/completions.rs3
-rw-r--r--crates/ide_completion/src/completions/attribute.rs58
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs60
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs18
-rw-r--r--crates/ide_completion/src/completions/use_.rs109
-rw-r--r--crates/ide_completion/src/lib.rs1
-rw-r--r--crates/ide_completion/src/tests/attribute.rs143
-rw-r--r--crates/ide_completion/src/tests/use_tree.rs19
-rw-r--r--crates/ide_completion/src/tests/visibility.rs9
-rw-r--r--crates/ide_db/src/search.rs6
12 files changed, 269 insertions, 164 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index d94f55e326..1e949771ea 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -481,7 +481,7 @@ impl HirDisplay for Module {
// FIXME: Module doesn't have visibility saved in data.
match self.name(f.db) {
Some(name) => write!(f, "mod {}", name),
- None if self.crate_root(f.db) == *self => match self.krate().display_name(f.db) {
+ None if self.is_crate_root(f.db) => match self.krate().display_name(f.db) {
Some(name) => write!(f, "extern crate {}", name),
None => write!(f, "extern crate {{unknown}}"),
},
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 918cadc869..032da5f50a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -452,6 +452,11 @@ impl Module {
Module { id: def_map.module_id(def_map.root()) }
}
+ pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool {
+ let def_map = db.crate_def_map(self.id.krate());
+ def_map.root() == self.id.local_id
+ }
+
/// Iterates over all child modules.
pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
let def_map = self.id.def_map(db.upcast());
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index 92074b3e10..715bd28e21 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -4,9 +4,11 @@ pub(crate) mod attribute;
pub(crate) mod dot;
pub(crate) mod flyimport;
pub(crate) mod fn_param;
+pub(crate) mod format_string;
pub(crate) mod keyword;
pub(crate) mod lifetime;
pub(crate) mod mod_;
+pub(crate) mod use_;
pub(crate) mod pattern;
pub(crate) mod postfix;
pub(crate) mod qualified_path;
@@ -14,7 +16,6 @@ pub(crate) mod record;
pub(crate) mod snippet;
pub(crate) mod trait_impl;
pub(crate) mod unqualified_path;
-pub(crate) mod format_string;
use std::iter;
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 8950b13d6f..1a1fa533c1 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -1,9 +1,10 @@
-//! Completion for attributes
+//! Completion for (built-in) attributes, derives and lints.
//!
-//! This module uses a bit of static metadata to provide completions
-//! for built-in attributes.
-//! Non-built-in attribute (excluding derives attributes) completions are done in [`super::unqualified_path`].
+//! This module uses a bit of static metadata to provide completions for builtin-in attributes and lints.
+use std::iter;
+
+use hir::ScopeDef;
use ide_db::{
helpers::{
generated_lints::{
@@ -85,24 +86,45 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
_ => return,
};
- if !is_trivial_path {
- return;
- }
+ match qualifier {
+ Some((path, qualifier)) => {
+ let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier())
+ .all(|p| p.segment().and_then(|s| s.super_token()).is_some());
+ if is_super_chain {
+ acc.add_keyword(ctx, "super::");
+ }
- if let Some((_, Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))))) = qualifier {
- for (name, def) in module.scope(ctx.db, ctx.module) {
- if let Some(def) = module_or_attr(def) {
- acc.add_resolution(ctx, name, def);
+ let module = match qualifier {
+ Some(hir::PathResolution::Def(hir::ModuleDef::Module(it))) => it,
+ _ => return,
+ };
+
+ for (name, def) in module.scope(ctx.db, ctx.module) {
+ if let Some(def) = module_or_attr(def) {
+ acc.add_resolution(ctx, name, def);
+ }
}
+ return;
}
- return;
- }
-
- ctx.process_all_names(&mut |name, def| {
- if let Some(def) = module_or_attr(def) {
- acc.add_resolution(ctx, name, def);
+ // fresh use tree with leading colon2, only show crate roots
+ None if !is_trivial_path => {
+ ctx.process_all_names(&mut |name, res| match res {
+ ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
+ acc.add_resolution(ctx, name, res);
+ }
+ _ => (),
+ });
}
- });
+ // only show modules in a fresh UseTree
+ None => {
+ ctx.process_all_names(&mut |name, def| {
+ if let Some(def) = module_or_attr(def) {
+ acc.add_resolution(ctx, name, def);
+ }
+ });
+ ["self::", "super::", "crate::"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
+ }
+ }
let attributes = annotated_item_kind.and_then(|kind| {
if ast::Expr::can_cast(kind) {
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index b15ec38b0a..14195e8149 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -1,10 +1,8 @@
//! Completion of paths, i.e. `some::prefix::$0`.
-use std::iter;
-
use hir::{ScopeDef, Trait};
use rustc_hash::FxHashSet;
-use syntax::{ast, AstNode};
+use syntax::ast;
use crate::{
completions::module_or_fn_macro,
@@ -17,14 +15,11 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
return;
}
- let ((path, resolution), use_tree_parent, kind) = match ctx.path_context {
+ let ((path, resolution), kind) = match ctx.path_context {
// let ... else, syntax would come in really handy here right now
- Some(PathCompletionContext {
- qualifier: Some(ref qualifier),
- use_tree_parent,
- kind,
- ..
- }) => (qualifier, use_tree_parent, kind),
+ Some(PathCompletionContext { qualifier: Some(ref qualifier), kind, .. }) => {
+ (qualifier, kind)
+ }
_ => return,
};
@@ -86,52 +81,23 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
}
return;
}
- Some(PathKind::Attr { .. }) => {
+ Some(PathKind::Attr { .. } | PathKind::Use) => {
return;
}
- Some(PathKind::Use) => {
- if iter::successors(Some(path.clone()), |p| p.qualifier())
- .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
- {
- acc.add_keyword(ctx, "super::");
- }
- // only show `self` in a new use-tree when the qualifier doesn't end in self
- if use_tree_parent
- && !matches!(
- path.segment().and_then(|it| it.kind()),
- Some(ast::PathSegmentKind::SelfKw)
- )
- {
- acc.add_keyword(ctx, "self");
- }
+ Some(PathKind::Pat) => (),
+ _ => {
+ // Add associated types on type parameters and `Self`.
+ ctx.scope.assoc_type_shorthand_candidates(&resolution, |_, alias| {
+ acc.add_type_alias(ctx, alias);
+ None::<()>
+ });
}
- _ => (),
- }
-
- if !matches!(kind, Some(PathKind::Pat)) {
- // Add associated types on type parameters and `Self`.
- ctx.scope.assoc_type_shorthand_candidates(&resolution, |_, alias| {
- acc.add_type_alias(ctx, alias);
- None::<()>
- });
}
match resolution {
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, ctx.module);
for (name, def) in module_scope {
- if let Some(PathKind::Use) = kind {
- if let ScopeDef::Unknown = def {
- if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
- if name_ref.syntax().text() == name.to_smol_str().as_str() {
- // for `use self::foo$0`, don't suggest `foo` as a completion
- cov_mark::hit!(dont_complete_current_use);
- continue;
- }
- }
- }
- }
-
let add_resolution = match def {
// Don't suggest attribute macros and derives.
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 01f3f777a1..1f78cfdf75 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -20,25 +20,11 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
_ => return,
};
- if let Some(PathKind::Use) = kind {
- // only show modules in a fresh UseTree
- cov_mark::hit!(unqualified_path_only_modules_in_import);
- ctx.process_all_names(&mut |name, res| {
- if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
- acc.add_resolution(ctx, name, res);
- }
- });
-
- ["self::", "super::", "crate::"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
- return;
- }
- ["self", "super", "crate"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
-
match kind {
- Some(PathKind::Vis { .. }) => return,
- Some(PathKind::Attr { .. }) => return,
+ Some(PathKind::Vis { .. } | PathKind::Attr { .. } | PathKind::Use { .. }) => return,
_ => (),
}
+ ["self", "super", "crate"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
match &ctx.completion_location {
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
diff --git a/crates/ide_completion/src/completions/use_.rs b/crates/ide_completion/src/completions/use_.rs
new file mode 100644
index 0000000000..b536095862
--- /dev/null
+++ b/crates/ide_completion/src/completions/use_.rs
@@ -0,0 +1,109 @@
+//! Completion for use trees
+//!
+//! This module uses a bit of static metadata to provide completions
+//! for built-in attributes.
+//! Non-built-in attribute (excluding derives attributes) completions are done in [`super::unqualified_path`].
+
+use std::iter;
+
+use hir::ScopeDef;
+use syntax::{ast, AstNode};
+
+use crate::{
+ context::{CompletionContext, PathCompletionContext, PathKind},
+ Completions,
+};
+
+pub(crate) fn complete_use_tree(acc: &mut Completions, ctx: &CompletionContext) {
+ let (is_trivial_path, qualifier, use_tree_parent) = match ctx.path_context {
+ Some(PathCompletionContext {
+ kind: Some(PathKind::Use),
+ is_trivial_path,
+ use_tree_parent,
+ ref qualifier,
+ ..
+ }) => (is_trivial_path, qualifier, use_tree_parent),
+ _ => return,
+ };
+
+ match qualifier {
+ Some((path, qualifier)) => {
+ let is_super_chain = iter::successors(Some(path.clone()), |p| p.qualifier())
+ .all(|p| p.segment().and_then(|s| s.super_token()).is_some());
+ if is_super_chain {
+ acc.add_keyword(ctx, "super::");
+ }
+ // only show `self` in a new use-tree when the qualifier doesn't end in self
+ let not_preceded_by_self = use_tree_parent
+ && !matches!(
+ path.segment().and_then(|it| it.kind()),
+ Some(ast::PathSegmentKind::SelfKw)
+ );
+ if not_preceded_by_self {
+ acc.add_keyword(ctx, "self");
+ }
+
+ let qualifier = match qualifier {
+ Some(it) => it,
+ None => return,
+ };
+
+ match qualifier {
+ hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
+ let module_scope = module.scope(ctx.db, ctx.module);
+ let unknown_is_current = |name: &hir::Name| {
+ matches!(
+ ctx.name_syntax.as_ref(),
+ Some(ast::NameLike::NameRef(name_ref))
+ if name_ref.syntax().text() == name.to_smol_str().as_str()
+ )
+ };
+ for (name, def) in module_scope {
+ let add_resolution = match def {
+ ScopeDef::Unknown if unknown_is_current(&name) => {
+ // for `use self::foo$0`, don't suggest `foo` as a completion
+ cov_mark::hit!(dont_complete_current_use);
+ continue;
+ }
+ ScopeDef::ModuleDef(_) | ScopeDef::MacroDef(_) | ScopeDef::Unknown => {
+ true
+ }
+ _ => false,
+ };
+
+ if add_resolution {
+ acc.add_resolution(ctx, name, def);
+ }
+ }
+ }
+ hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
+ cov_mark::hit!(enum_plain_qualified_use_tree);
+ e.variants(ctx.db)
+ .into_iter()
+ .for_each(|variant| acc.add_enum_variant(ctx, variant, None));
+ }
+ _ => {}
+ }
+ }
+ // fresh use tree with leading colon2, only show crate roots
+ None if !is_trivial_path => {
+ cov_mark::hit!(use_tree_crate_roots_only);
+ ctx.process_all_names(&mut |name, res| match res {
+ ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
+ acc.add_resolution(ctx, name, res);
+ }
+ _ => (),
+ });
+ }
+ // only show modules in a fresh UseTree
+ None => {
+ cov_mark::hit!(unqualified_path_only_modules_in_import);
+ ctx.process_all_names(&mut |name, res| {
+ if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
+ acc.add_resolution(ctx, name, res);
+ }
+ });
+ ["self::", "super::", "crate::"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
+ }
+ }
+}
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 5b49a49911..2f7ca13ee8 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -153,6 +153,7 @@ pub fn completions(
let mut acc = Completions::default();
completions::attribute::complete_known_attribute_input(&mut acc, &ctx);
completions::attribute::complete_attribute(&mut acc, &ctx);
+ completions::use_::complete_use_tree(&mut acc, &ctx);
completions::fn_param::complete_fn_param(&mut acc, &ctx);
completions::keyword::complete_expr_keyword(&mut acc, &ctx);
completions::snippet::complete_expr_snippet(&mut acc, &ctx);
diff --git a/crates/ide_completion/src/tests/attribute.rs b/crates/ide_completion/src/tests/attribute.rs
index ac43a67bdc..5a9c48a327 100644
--- a/crates/ide_completion/src/tests/attribute.rs
+++ b/crates/ide_completion/src/tests/attribute.rs
@@ -18,6 +18,9 @@ struct Foo;
"#,
expect![[r#"
md proc_macros
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -33,9 +36,6 @@ struct Foo;
at derive(…)
at repr(…)
at non_exhaustive
- kw self
- kw super
- kw crate
"#]],
)
}
@@ -61,7 +61,10 @@ fn proc_macros_qualified() {
#[proc_macros::$0]
struct Foo;
"#,
- expect![[r#""#]],
+ expect![[r#"
+ at input_replace pub macro input_replace
+ at identity pub macro identity
+ "#]],
)
}
@@ -75,15 +78,15 @@ fn with_existing_attr() {
check(
r#"#[no_mangle] #[$0] mcall!();"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
at deny(…)
at forbid(…)
at warn(…)
- kw self
- kw super
- kw crate
"#]],
)
}
@@ -93,6 +96,9 @@ fn attr_on_source_file() {
check(
r#"#![$0]"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -113,9 +119,6 @@ fn attr_on_source_file() {
at recursion_limit = "…"
at type_length_limit = …
at windows_subsystem = "…"
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -125,6 +128,9 @@ fn attr_on_module() {
check(
r#"#[$0] mod foo;"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -139,14 +145,14 @@ fn attr_on_module() {
at no_mangle
at macro_use
at path = "…"
- kw self
- kw super
- kw crate
"#]],
);
check(
r#"mod foo {#![$0]}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -160,9 +166,6 @@ fn attr_on_module() {
at must_use
at no_mangle
at no_implicit_prelude
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -172,6 +175,9 @@ fn attr_on_macro_rules() {
check(
r#"#[$0] macro_rules! foo {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -186,9 +192,6 @@ fn attr_on_macro_rules() {
at no_mangle
at macro_export
at macro_use
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -198,6 +201,9 @@ fn attr_on_macro_def() {
check(
r#"#[$0] macro foo {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -210,9 +216,6 @@ fn attr_on_macro_def() {
at doc(alias = "…")
at must_use
at no_mangle
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -222,6 +225,9 @@ fn attr_on_extern_crate() {
check(
r#"#[$0] extern crate foo;"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -235,9 +241,6 @@ fn attr_on_extern_crate() {
at must_use
at no_mangle
at macro_use
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -247,6 +250,9 @@ fn attr_on_use() {
check(
r#"#[$0] use foo;"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -259,9 +265,6 @@ fn attr_on_use() {
at doc(alias = "…")
at must_use
at no_mangle
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -271,6 +274,9 @@ fn attr_on_type_alias() {
check(
r#"#[$0] type foo = ();"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -283,9 +289,6 @@ fn attr_on_type_alias() {
at doc(alias = "…")
at must_use
at no_mangle
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -301,6 +304,9 @@ struct Foo;
expect![[r#"
md core
at derive pub macro derive
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -316,9 +322,6 @@ struct Foo;
at derive(…)
at repr(…)
at non_exhaustive
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -328,6 +331,9 @@ fn attr_on_enum() {
check(
r#"#[$0] enum Foo {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -343,9 +349,6 @@ fn attr_on_enum() {
at derive(…)
at repr(…)
at non_exhaustive
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -355,6 +358,9 @@ fn attr_on_const() {
check(
r#"#[$0] const FOO: () = ();"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -367,9 +373,6 @@ fn attr_on_const() {
at doc(alias = "…")
at must_use
at no_mangle
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -379,6 +382,9 @@ fn attr_on_static() {
check(
r#"#[$0] static FOO: () = ()"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -396,9 +402,6 @@ fn attr_on_static() {
at link_section = "…"
at global_allocator
at used
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -408,6 +411,9 @@ fn attr_on_trait() {
check(
r#"#[$0] trait Foo {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -421,9 +427,6 @@ fn attr_on_trait() {
at must_use
at no_mangle
at must_use
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -433,6 +436,9 @@ fn attr_on_impl() {
check(
r#"#[$0] impl () {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -446,14 +452,14 @@ fn attr_on_impl() {
at must_use
at no_mangle
at automatically_derived
- kw self
- kw super
- kw crate
"#]],
);
check(
r#"impl () {#![$0]}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -466,9 +472,6 @@ fn attr_on_impl() {
at doc(alias = "…")
at must_use
at no_mangle
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -478,6 +481,9 @@ fn attr_on_extern_block() {
check(
r#"#[$0] extern {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -491,14 +497,14 @@ fn attr_on_extern_block() {
at must_use
at no_mangle
at link
- kw self
- kw super
- kw crate
"#]],
);
check(
r#"extern {#![$0]}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -512,9 +518,6 @@ fn attr_on_extern_block() {
at must_use
at no_mangle
at link
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -524,6 +527,9 @@ fn attr_on_variant() {
check(
r#"enum Foo { #[$0] Bar }"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -531,9 +537,6 @@ fn attr_on_variant() {
at forbid(…)
at warn(…)
at non_exhaustive
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -543,6 +546,9 @@ fn attr_on_fn() {
check(
r#"#[$0] fn main() {}"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
@@ -570,9 +576,6 @@ fn attr_on_fn() {
at target_feature = "…"
at test
at track_caller
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -583,15 +586,15 @@ fn attr_on_expr() {
check(
r#"fn main() { #[$0] foo() }"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at cfg(…)
at cfg_attr(…)
at deny(…)
at forbid(…)
at warn(…)
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -601,6 +604,9 @@ fn attr_in_source_file_end() {
check(
r#"#[$0]"#,
expect![[r#"
+ kw self::
+ kw super::
+ kw crate::
at allow(…)
at automatically_derived
at cfg(…)
@@ -637,9 +643,6 @@ fn attr_in_source_file_end() {
at track_caller
at used
at warn(…)
- kw self
- kw super
- kw crate
"#]],
);
}
diff --git a/crates/ide_completion/src/tests/use_tree.rs b/crates/ide_completion/src/tests/use_tree.rs
index 5f20e342e0..ac7e75bd38 100644
--- a/crates/ide_completion/src/tests/use_tree.rs
+++ b/crates/ide_completion/src/tests/use_tree.rs
@@ -135,6 +135,25 @@ struct Bar;
}
#[test]
+fn enum_plain_qualified_use_tree() {
+ cov_mark::check!(enum_plain_qualified_use_tree);
+ check(
+ r#"
+use Foo::$0
+
+enum Foo { Variant }
+impl Foo {
+ const CONST: () = ()
+ fn func() {}
+}
+"#,
+ expect![[r#"
+ ev Variant ()
+ "#]],
+ );
+}
+
+#[test]
fn self_qualified_use_tree() {
check(
r#"
diff --git a/crates/ide_completion/src/tests/visibility.rs b/crates/ide_completion/src/tests/visibility.rs
index 2fd16235dc..8fdfeccb9a 100644
--- a/crates/ide_completion/src/tests/visibility.rs
+++ b/crates/ide_completion/src/tests/visibility.rs
@@ -17,9 +17,6 @@ pub($0)
"#,
expect![[r#"
kw in
- kw self
- kw super
- kw crate
"#]],
);
}
@@ -30,11 +27,7 @@ fn after_in_kw() {
r#"
pub(in $0)
"#,
- expect![[r#"
- kw self
- kw super
- kw crate
- "#]],
+ expect![[r#""#]],
);
}
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index dcfc2b7bfc..7ea2bc63f2 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -223,7 +223,7 @@ impl Definition {
// def is crate root
// FIXME: We don't do searches for crates currently, as a crate does not actually have a single name
if let &Definition::Module(module) = self {
- if module.crate_root(db) == module {
+ if module.is_crate_root(db) {
return SearchScope::reverse_dependencies(db, module.krate());
}
}
@@ -378,7 +378,7 @@ impl<'a> FindUsages<'a> {
let name = match self.def {
// special case crate modules as these do not have a proper name
- Definition::Module(module) if module.crate_root(self.sema.db) == module => {
+ Definition::Module(module) if module.is_crate_root(self.sema.db) => {
// FIXME: This assumes the crate name is always equal to its display name when it really isn't
module
.krate()
@@ -460,7 +460,7 @@ impl<'a> FindUsages<'a> {
Definition::Module(module) => {
let scope = search_scope.intersection(&SearchScope::module(self.sema.db, module));
- let is_crate_root = module.crate_root(self.sema.db) == module;
+ let is_crate_root = module.is_crate_root(self.sema.db);
for (text, file_id, search_range) in scope_files(sema, &scope) {
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());