Make call info to use real name resolution

This commit is contained in:
Aleksey Kladov 2019-04-11 15:34:13 +03:00
parent 10d66d63d7
commit 505acc973b
4 changed files with 34 additions and 27 deletions

View File

@ -60,7 +60,7 @@ pub use self::{
source_id::{AstIdMap, ErasedFileAstId},
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc},
nameres::{PerNs, Namespace, ImportId},
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay, CallableDef},
impl_block::{ImplBlock, ImplItem},
docs::{Docs, Documentation},
adt::AdtDef,

View File

@ -15,11 +15,12 @@ use std::sync::Arc;
use std::{fmt, mem};
use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait};
pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig};
pub(crate) use infer::{infer, InferenceResult, InferTy};
use display::{HirDisplay, HirFormatter};
pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig};
pub(crate) use infer::{infer, InferenceResult, InferTy};
pub use lower::CallableDef;
/// A type constructor or type name: this might be something like the primitive
/// type `bool`, a struct like `Vec`, or things like function pointers or
/// tuples.
@ -288,6 +289,15 @@ impl Ty {
}
}
pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> {
match self {
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
Some((*callable_def, parameters))
}
_ => None,
}
}
fn builtin_deref(&self) -> Option<Ty> {
match self {
Ty::Apply(a_ty) => match a_ty.ctor {

View File

@ -2,7 +2,6 @@ use test_utils::tested_by;
use ra_db::SourceDatabase;
use ra_syntax::{
AstNode, SyntaxNode, TextUnit,
SyntaxKind::FN_DEF,
ast::{self, ArgListOwner},
algo::find_node_at_offset,
};
@ -18,19 +17,26 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
let calling_node = FnCallNode::with_node(syntax, position.offset)?;
let name_ref = calling_node.name_ref()?;
// Resolve the function's NameRef (NOTE: this isn't entirely accurate).
let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
let symbol = file_symbols.into_iter().find(|it| it.ptr.kind() == FN_DEF)?;
let fn_file = db.parse(symbol.file_id);
let fn_def = symbol.ptr.to_node(&fn_file);
let fn_def = ast::FnDef::cast(fn_def).unwrap();
let function = hir::source_binder::function_from_source(db, symbol.file_id, fn_def)?;
let analyser = hir::SourceAnalyser::new(db, position.file_id, name_ref.syntax());
let function = match calling_node {
FnCallNode::CallExpr(expr) => {
//FIXME: apply subst
let (callable_def, _subst) =
analyser.type_of(db, expr.expr()?.into())?.as_callable()?;
match callable_def {
hir::CallableDef::Function(it) => it,
//FIXME: handle other callables
_ => return None,
}
}
FnCallNode::MethodCallExpr(expr) => analyser.resolve_method_call(expr)?,
};
let mut call_info = CallInfo::new(db, function);
// If we have a calling expression let's find which argument we are on
let num_params = call_info.parameters().len();
let has_self = fn_def.param_list().and_then(|l| l.self_param()).is_some();
let has_self = function.signature(db).has_self_param();
if num_params == 1 {
if !has_self {
@ -142,7 +148,7 @@ mod tests {
}
#[test]
fn test_fn_signature_two_args_first() {
fn test_fn_signature_two_args_firstx() {
let info = call_info(
r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>3, ); }"#,
@ -382,11 +388,9 @@ assert_eq!(6, my_crate::add_one(5));
fn test_fn_signature_with_docs_from_actix() {
let info = call_info(
r#"
pub trait WriteHandler<E>
where
Self: Actor,
Self::Context: ActorContext,
{
struct WriteHandler<E>;
impl<E> WriteHandler<E> {
/// Method is called when writer emits error.
///
/// If this method returns `ErrorAction::Continue` writer processing
@ -403,8 +407,7 @@ where
}
}
pub fn foo() {
WriteHandler r;
pub fn foo(mut r: WriteHandler<()>) {
r.finished(<|>);
}

View File

@ -19,7 +19,6 @@ pub(crate) struct CompletionContext<'a> {
pub(super) token: SyntaxToken<'a>,
pub(super) resolver: Resolver,
pub(super) module: Option<hir::Module>,
pub(super) function: Option<hir::Function>,
pub(super) function_syntax: Option<&'a ast::FnDef>,
pub(super) use_item_syntax: Option<&'a ast::UseItem>,
pub(super) struct_lit_syntax: Option<&'a ast::StructLit>,
@ -59,7 +58,6 @@ impl<'a> CompletionContext<'a> {
offset: position.offset,
resolver,
module,
function: None,
function_syntax: None,
use_item_syntax: None,
struct_lit_syntax: None,
@ -150,10 +148,6 @@ impl<'a> CompletionContext<'a> {
.ancestors()
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
.find_map(ast::FnDef::cast);
if let (Some(module), Some(fn_def)) = (self.module, self.function_syntax) {
let function = source_binder::function_from_module(self.db, module, fn_def);
self.function = Some(function);
}
let parent = match name_ref.syntax().parent() {
Some(it) => it,