Specify desirable namespace when calling resolve

That way, we are able to get rid of a number of unreachable statements
This commit is contained in:
Aleksey Kladov 2019-09-12 23:35:53 +03:00
parent 1adf0519bc
commit 51e2d76b98
13 changed files with 542 additions and 472 deletions

View file

@ -3,11 +3,11 @@ use crate::completion::{CompletionContext, Completions};
pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
// Show only macros in top level.
if ctx.is_new_item {
for (name, res) in ctx.analyzer.all_names(ctx.db) {
if res.get_macros().is_some() {
acc.add_resolution(ctx, name.to_string(), &res.only_macros());
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
if let hir::ScopeDef::MacroDef(mac) = res {
acc.add_macro(ctx, Some(name.to_string()), mac);
}
}
})
}
}

View file

@ -1,4 +1,4 @@
use hir::{Adt, Either, Resolution};
use hir::{Adt, Either, PathResolution};
use ra_syntax::AstNode;
use test_utils::tested_by;
@ -9,15 +9,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
Some(path) => path.clone(),
_ => return,
};
let def = match ctx.analyzer.resolve_hir_path(ctx.db, &path).take_types() {
Some(Resolution::Def(def)) => def,
let def = match dbg!(ctx.analyzer.resolve_hir_path(ctx.db, &path)) {
Some(PathResolution::Def(def)) => def,
_ => return,
};
match def {
hir::ModuleDef::Module(module) => {
let module_scope = module.scope(ctx.db);
for (name, res) in module_scope.entries() {
if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.as_ref().take_types() {
if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() {
if ctx.use_item_syntax.is_some() {
tested_by!(dont_complete_primitive_in_use);
continue;
@ -34,7 +34,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
}
}
}
acc.add_resolution(ctx, name.to_string(), &res.def.map(hir::Resolution::Def));
acc.add_resolution(ctx, name.to_string(), &res.def.into());
}
}
hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {

View file

@ -7,22 +7,20 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
}
// FIXME: ideally, we should look at the type we are matching against and
// suggest variants + auto-imports
let names = ctx.analyzer.all_names(ctx.db);
for (name, res) in names.into_iter() {
let r = res.as_ref();
let def = match r.take_types().or_else(|| r.take_values()) {
Some(hir::Resolution::Def(def)) => def,
_ => continue,
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
let def = match &res {
hir::ScopeDef::ModuleDef(def) => def,
_ => return,
};
match def {
hir::ModuleDef::Adt(hir::Adt::Enum(..))
| hir::ModuleDef::EnumVariant(..)
| hir::ModuleDef::Const(..)
| hir::ModuleDef::Module(..) => (),
_ => continue,
_ => return,
}
acc.add_resolution(ctx, name.to_string(), &res)
}
});
}
#[cfg(test)]

View file

@ -10,8 +10,9 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
return;
}
let names = ctx.analyzer.all_names(ctx.db);
names.into_iter().for_each(|(name, res)| acc.add_resolution(ctx, name.to_string(), &res));
ctx.analyzer.process_all_names(ctx.db, &mut |name, res| {
acc.add_resolution(ctx, name.to_string(), &res)
});
// auto-import
// We fetch ident from the original file, because we need to pre-filter auto-imports

View file

@ -1,5 +1,5 @@
//! This modules takes care of rendering various defenitions as completion items.
use hir::{Docs, HasSource, HirDisplay, PerNs, Resolution, Ty, TypeWalk};
//! This modules takes care of rendering various definitions as completion items.
use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
use join_to_string::join;
use ra_syntax::ast::NameOwner;
use test_utils::tested_by;
@ -39,19 +39,65 @@ impl Completions {
&mut self,
ctx: &CompletionContext,
local_name: String,
resolution: &PerNs<Resolution>,
resolution: &ScopeDef,
) {
use hir::ModuleDef::*;
if let Some(macro_) = resolution.get_macros() {
self.add_macro(ctx, Some(local_name.clone()), macro_);
}
// if let Some(macro_) = resolution.get_macros() {
// self.add_macro(ctx, Some(local_name.clone()), macro_);
// }
let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
let def = match def {
// Only insert once if it is just a macro name
None if resolution.get_macros().is_some() => return,
None => {
// let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values());
// let def = match def {
// // Only insert once if it is just a macro name
// None if resolution.get_macros().is_some() => return,
// None => {
// self.add(CompletionItem::new(
// CompletionKind::Reference,
// ctx.source_range(),
// local_name,
// ));
// return;
// }
// Some(it) => it,
// };
let mut completion_kind = CompletionKind::Reference;
let (kind, docs) = match resolution {
ScopeDef::ModuleDef(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)),
ScopeDef::ModuleDef(Function(func)) => {
return self.add_function_with_name(ctx, Some(local_name), *func);
}
ScopeDef::ModuleDef(Adt(hir::Adt::Struct(it))) => {
(CompletionItemKind::Struct, it.docs(ctx.db))
}
ScopeDef::ModuleDef(Adt(hir::Adt::Union(it))) => {
(CompletionItemKind::Struct, it.docs(ctx.db))
}
ScopeDef::ModuleDef(Adt(hir::Adt::Enum(it))) => {
(CompletionItemKind::Enum, it.docs(ctx.db))
}
ScopeDef::ModuleDef(EnumVariant(it)) => {
(CompletionItemKind::EnumVariant, it.docs(ctx.db))
}
ScopeDef::ModuleDef(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)),
ScopeDef::ModuleDef(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)),
ScopeDef::ModuleDef(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)),
ScopeDef::ModuleDef(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)),
ScopeDef::ModuleDef(BuiltinType(..)) => {
completion_kind = CompletionKind::BuiltinType;
(CompletionItemKind::BuiltinType, None)
}
ScopeDef::GenericParam(..) => (CompletionItemKind::TypeParam, None),
ScopeDef::LocalBinding(..) => (CompletionItemKind::Binding, None),
ScopeDef::SelfType(..) => (
CompletionItemKind::TypeParam, // (does this need its own kind?)
None,
),
ScopeDef::MacroDef(mac) => {
self.add_macro(ctx, Some(local_name.clone()), *mac);
return;
}
ScopeDef::Unknown => {
self.add(CompletionItem::new(
CompletionKind::Reference,
ctx.source_range(),
@ -59,41 +105,11 @@ impl Completions {
));
return;
}
Some(it) => it,
};
let mut completion_kind = CompletionKind::Reference;
let (kind, docs) = match def {
Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)),
Resolution::Def(Function(func)) => {
return self.add_function_with_name(ctx, Some(local_name), *func);
}
Resolution::Def(Adt(hir::Adt::Struct(it))) => {
(CompletionItemKind::Struct, it.docs(ctx.db))
}
Resolution::Def(Adt(hir::Adt::Union(it))) => {
(CompletionItemKind::Struct, it.docs(ctx.db))
}
Resolution::Def(Adt(hir::Adt::Enum(it))) => (CompletionItemKind::Enum, it.docs(ctx.db)),
Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)),
Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)),
Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)),
Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)),
Resolution::Def(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)),
Resolution::Def(BuiltinType(..)) => {
completion_kind = CompletionKind::BuiltinType;
(CompletionItemKind::BuiltinType, None)
}
Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None),
Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None),
Resolution::SelfType(..) => (
CompletionItemKind::TypeParam, // (does this need its own kind?)
None,
),
};
let mut completion_item =
CompletionItem::new(completion_kind, ctx.source_range(), local_name);
if let Resolution::LocalBinding(pat_id) = def {
if let ScopeDef::LocalBinding(pat_id) = resolution {
let ty = ctx
.analyzer
.type_of_pat_by_id(ctx.db, pat_id.clone())
@ -108,7 +124,12 @@ impl Completions {
self.add_function_with_name(ctx, None, func)
}
fn add_macro(&mut self, ctx: &CompletionContext, name: Option<String>, macro_: hir::MacroDef) {
pub(crate) fn add_macro(
&mut self,
ctx: &CompletionContext,
name: Option<String>,
macro_: hir::MacroDef,
) {
let ast_node = macro_.source(ctx.db).ast;
if let Some(name) = name {
let detail = macro_label(&ast_node);