Show more parameter name hints

This commit is contained in:
Kirill Bulatov 2020-02-23 01:09:48 +03:00
parent 4ca22f3a88
commit 6670868d09

View file

@ -1,12 +1,12 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use hir::{HirDisplay, SourceAnalyzer, SourceBinder}; use hir::{Function, HirDisplay, SourceAnalyzer, SourceBinder};
use once_cell::unsync::Lazy; use once_cell::unsync::Lazy;
use ra_ide_db::RootDatabase; use ra_ide_db::RootDatabase;
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{ use ra_syntax::{
ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, match_ast, SmolStr, SourceFile, SyntaxNode, TextRange,
}; };
use crate::{FileId, FunctionSignature}; use crate::{FileId, FunctionSignature};
@ -107,18 +107,23 @@ fn get_param_name_hints(
ast::Expr::CallExpr(expr) => expr.arg_list()?.args(), ast::Expr::CallExpr(expr) => expr.arg_list()?.args(),
ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(), ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(),
_ => return None, _ => return None,
}
.into_iter()
// we need args len to determine whether to skip or not the &self parameter
.collect::<Vec<_>>();
let (has_self_param, fn_signature) = get_fn_signature(db, analyzer, &expr)?;
let parameters = if has_self_param && fn_signature.parameter_names.len() > args.len() {
fn_signature.parameter_names.into_iter().skip(1)
} else {
fn_signature.parameter_names.into_iter().skip(0)
}; };
let mut parameters = get_fn_signature(db, analyzer, &expr)?.parameter_names.into_iter(); let hints =
parameters
if let ast::Expr::MethodCallExpr(_) = &expr {
parameters.next();
};
let hints = parameters
.zip(args) .zip(args)
.filter_map(|(param, arg)| { .filter_map(|(param, arg)| {
if arg.syntax().kind() == SyntaxKind::LITERAL && !param.is_empty() { if !param.is_empty() {
Some((arg.syntax().text_range(), param)) Some((arg.syntax().text_range(), param))
} else { } else {
None None
@ -138,25 +143,27 @@ fn get_fn_signature(
db: &RootDatabase, db: &RootDatabase,
analyzer: &SourceAnalyzer, analyzer: &SourceAnalyzer,
expr: &ast::Expr, expr: &ast::Expr,
) -> Option<FunctionSignature> { ) -> Option<(bool, FunctionSignature)> {
match expr { match expr {
ast::Expr::CallExpr(expr) => { ast::Expr::CallExpr(expr) => {
// FIXME: Type::as_callable is broken for closures // FIXME: Type::as_callable is broken for closures
let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
match callable_def { match callable_def {
hir::CallableDef::FunctionId(it) => { hir::CallableDef::FunctionId(it) => {
let fn_def = it.into(); let fn_def: Function = it.into();
Some(FunctionSignature::from_hir(db, fn_def)) Some((fn_def.has_self_param(db), FunctionSignature::from_hir(db, fn_def)))
} }
hir::CallableDef::StructId(it) => FunctionSignature::from_struct(db, it.into()), hir::CallableDef::StructId(it) => FunctionSignature::from_struct(db, it.into())
.map(|signature| (false, signature)),
hir::CallableDef::EnumVariantId(it) => { hir::CallableDef::EnumVariantId(it) => {
FunctionSignature::from_enum_variant(db, it.into()) FunctionSignature::from_enum_variant(db, it.into())
.map(|signature| (false, signature))
} }
} }
} }
ast::Expr::MethodCallExpr(expr) => { ast::Expr::MethodCallExpr(expr) => {
let fn_def = analyzer.resolve_method_call(&expr)?; let fn_def = analyzer.resolve_method_call(&expr)?;
Some(FunctionSignature::from_hir(db, fn_def)) Some((fn_def.has_self_param(db), FunctionSignature::from_hir(db, fn_def)))
} }
_ => None, _ => None,
} }