Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions crates/ide/src/call_hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use indexmap::IndexMap;

use hir::Semantics;
use ide_db::{
call_info::FnCallNode,
defs::{Definition, NameClass, NameRefClass},
helpers::pick_best_token,
search::FileReference,
Expand Down Expand Up @@ -101,23 +100,27 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio
_ => None,
})
.flatten()
.filter_map(|node| FnCallNode::with_node_exact(&node))
.filter_map(ast::CallableExpr::cast)
.filter_map(|call_node| {
let name_ref = call_node.name_ref()?;
let func_target = match call_node {
FnCallNode::CallExpr(expr) => {
let callable = sema.type_of_expr(&expr.expr()?)?.original.as_callable(db)?;
let (nav_target, range) = match call_node {
ast::CallableExpr::Call(call) => {
let expr = call.expr()?;
let callable = sema.type_of_expr(&expr)?.original.as_callable(db)?;
match callable.kind() {
hir::CallableKind::Function(it) => it.try_to_nav(db),
hir::CallableKind::Function(it) => {
let range = expr.syntax().text_range();
it.try_to_nav(db).zip(Some(range))
}
_ => None,
}
}
FnCallNode::MethodCallExpr(expr) => {
ast::CallableExpr::MethodCall(expr) => {
let range = expr.name_ref()?.syntax().text_range();
let function = sema.resolve_method_call(&expr)?;
function.try_to_nav(db)
function.try_to_nav(db).zip(Some(range))
}
}?;
Some((func_target, name_ref.syntax().text_range()))
Some((nav_target, range))
})
.for_each(|(nav, range)| calls.add(nav, range));

Expand Down
37 changes: 9 additions & 28 deletions crates/ide_assists/src/handlers/generate_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,6 @@ pub(crate) fn generate_function(acc: &mut Assists, ctx: &AssistContext) -> Optio
gen_fn(acc, ctx).or_else(|| gen_method(acc, ctx))
}

enum FuncExpr {
Func(ast::CallExpr),
Method(ast::MethodCallExpr),
}

impl FuncExpr {
fn arg_list(&self) -> Option<ast::ArgList> {
match self {
FuncExpr::Func(fn_call) => fn_call.arg_list(),
FuncExpr::Method(m_call) => m_call.arg_list(),
}
}

fn syntax(&self) -> &SyntaxNode {
match self {
FuncExpr::Func(fn_call) => fn_call.syntax(),
FuncExpr::Method(m_call) => m_call.syntax(),
}
}
}

fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
Expand Down Expand Up @@ -254,7 +233,8 @@ impl FunctionBuilder {
let needs_pub = target_module.is_some();
let target_module = target_module.or_else(|| current_module(target.syntax(), ctx))?;
let fn_name = make::name(fn_name);
let (type_params, params) = fn_args(ctx, target_module, FuncExpr::Func(call.clone()))?;
let (type_params, params) =
fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?;

let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
let is_async = await_expr.is_some();
Expand Down Expand Up @@ -284,7 +264,8 @@ impl FunctionBuilder {
let needs_pub =
!module_is_descendant(&current_module(call.syntax(), ctx)?, &target_module, ctx);
let fn_name = make::name(&name.text());
let (type_params, params) = fn_args(ctx, target_module, FuncExpr::Method(call.clone()))?;
let (type_params, params) =
fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?;

let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
let is_async = await_expr.is_some();
Expand Down Expand Up @@ -392,7 +373,7 @@ fn get_fn_target(
file = in_file;
target
}
None => next_space_for_fn_after_call_site(FuncExpr::Func(call))?,
None => next_space_for_fn_after_call_site(ast::CallableExpr::Call(call))?,
};
Some((target.clone(), file, get_insert_offset(&target)))
}
Expand Down Expand Up @@ -438,7 +419,7 @@ impl GeneratedFunctionTarget {
fn fn_args(
ctx: &AssistContext,
target_module: hir::Module,
call: FuncExpr,
call: ast::CallableExpr,
) -> Option<(Option<ast::GenericParamList>, ast::ParamList)> {
let mut arg_names = Vec::new();
let mut arg_types = Vec::new();
Expand Down Expand Up @@ -468,8 +449,8 @@ fn fn_args(
None,
make::param_list(
match call {
FuncExpr::Func(_) => None,
FuncExpr::Method(_) => Some(make::self_param()),
ast::CallableExpr::Call(_) => None,
ast::CallableExpr::MethodCall(_) => Some(make::self_param()),
},
params,
),
Expand Down Expand Up @@ -553,7 +534,7 @@ fn fn_arg_type(
/// directly after the current block
/// We want to write the generated function directly after
/// fns, impls or macro calls, but inside mods
fn next_space_for_fn_after_call_site(expr: FuncExpr) -> Option<GeneratedFunctionTarget> {
fn next_space_for_fn_after_call_site(expr: ast::CallableExpr) -> Option<GeneratedFunctionTarget> {
let mut ancestors = expr.syntax().ancestors().peekable();
let mut last_ancestor: Option<SyntaxNode> = None;
while let Some(next_ancestor) = ancestors.next() {
Expand Down
37 changes: 12 additions & 25 deletions crates/ide_assists/src/handlers/inline_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ide_db::{
use itertools::{izip, Itertools};
use syntax::{
ast::{self, edit_in_place::Indent, HasArgList, PathExpr},
ted, AstNode, SyntaxNode,
ted, AstNode,
};

use crate::{
Expand Down Expand Up @@ -178,7 +178,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
let name_ref: ast::NameRef = ctx.find_node_at_offset()?;
let call_info = CallInfo::from_name_ref(name_ref.clone())?;
let (function, label) = match &call_info.node {
CallExprNode::Call(call) => {
ast::CallableExpr::Call(call) => {
let path = match call.expr()? {
ast::Expr::PathExpr(path) => path.path(),
_ => None,
Expand All @@ -190,7 +190,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
};
(function, format!("Inline `{}`", path))
}
CallExprNode::MethodCallExpr(call) => {
ast::CallableExpr::MethodCall(call) => {
(ctx.sema.resolve_method_call(call)?, format!("Inline `{}`", name_ref))
}
};
Expand Down Expand Up @@ -223,31 +223,17 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>

builder.replace_ast(
match call_info.node {
CallExprNode::Call(it) => ast::Expr::CallExpr(it),
CallExprNode::MethodCallExpr(it) => ast::Expr::MethodCallExpr(it),
ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it),
ast::CallableExpr::MethodCall(it) => ast::Expr::MethodCallExpr(it),
},
replacement,
);
},
)
}

enum CallExprNode {
Call(ast::CallExpr),
MethodCallExpr(ast::MethodCallExpr),
}

impl CallExprNode {
fn syntax(&self) -> &SyntaxNode {
match self {
CallExprNode::Call(it) => it.syntax(),
CallExprNode::MethodCallExpr(it) => it.syntax(),
}
}
}

struct CallInfo {
node: CallExprNode,
node: ast::CallableExpr,
arguments: Vec<ast::Expr>,
generic_arg_list: Option<ast::GenericArgList>,
}
Expand All @@ -261,7 +247,7 @@ impl CallInfo {
arguments.extend(call.arg_list()?.args());
Some(CallInfo {
generic_arg_list: call.generic_arg_list(),
node: CallExprNode::MethodCallExpr(call),
node: ast::CallableExpr::MethodCall(call),
arguments,
})
} else if let Some(segment) = ast::PathSegment::cast(parent) {
Expand All @@ -271,7 +257,7 @@ impl CallInfo {

Some(CallInfo {
arguments: call.arg_list()?.args().collect(),
node: CallExprNode::Call(call),
node: ast::CallableExpr::Call(call),
generic_arg_list: segment.generic_arg_list(),
})
} else {
Expand Down Expand Up @@ -367,8 +353,9 @@ fn inline(
ted::replace(usage.syntax(), &replacement.syntax().clone_for_update());
}
};
// izip confuses RA due to our lack of hygiene info currently losing us typeinfo
// izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors
let usages: &[ast::PathExpr] = &*usages;
let expr: &ast::Expr = expr;
match usages {
// inline single use closure arguments
[usage]
Expand Down Expand Up @@ -414,8 +401,8 @@ fn inline(
}

let original_indentation = match node {
CallExprNode::Call(it) => it.indent_level(),
CallExprNode::MethodCallExpr(it) => it.indent_level(),
ast::CallableExpr::Call(it) => it.indent_level(),
ast::CallableExpr::MethodCall(it) => it.indent_level(),
};
body.reindent_to(original_indentation);

Expand Down
94 changes: 17 additions & 77 deletions crates/ide_db/src/call_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use stdx::format_to;
use syntax::{
algo,
ast::{self, HasArgList, HasName},
match_ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
AstNode, Direction, SyntaxToken, TextRange, TextSize,
};

use crate::RootDatabase;
Expand All @@ -25,9 +25,11 @@ impl CallInfo {
pub fn parameter_labels(&self) -> impl Iterator<Item = &str> + '_ {
self.parameters.iter().map(move |&it| &self.signature[it])
}

pub fn parameter_ranges(&self) -> &[TextRange] {
&self.parameters
}

fn push_param(&mut self, param: &str) {
if !self.signature.ends_with('(') {
self.signature.push_str(", ");
Expand Down Expand Up @@ -115,31 +117,24 @@ fn call_info_impl(
token: SyntaxToken,
) -> Option<(hir::Callable, Option<usize>)> {
// Find the calling expression and it's NameRef
let calling_node = FnCallNode::with_node(&token.parent()?)?;
let parent = token.parent()?;
let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| {
it.arg_list()
.map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
})?;

let callable = match &calling_node {
FnCallNode::CallExpr(call) => {
sema.type_of_expr(&call.expr()?)?.adjusted().as_callable(sema.db)?
ast::CallableExpr::Call(call) => {
let expr = call.expr()?;
sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
}
FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?,
};
ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
}?;
let active_param = if let Some(arg_list) = calling_node.arg_list() {
// Number of arguments specified at the call site
let num_args_at_callsite = arg_list.args().count();

let arg_list_range = arg_list.syntax().text_range();
if !arg_list_range.contains_inclusive(token.text_range().start()) {
cov_mark::hit!(call_info_bad_offset);
return None;
}
let param = std::cmp::min(
num_args_at_callsite,
arg_list
.args()
.take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
.count(),
);

let param = arg_list
.args()
.take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
.count();
Some(param)
} else {
None
Expand Down Expand Up @@ -175,60 +170,5 @@ impl ActiveParameter {
}
}

#[derive(Debug)]
pub enum FnCallNode {
CallExpr(ast::CallExpr),
MethodCallExpr(ast::MethodCallExpr),
}

impl FnCallNode {
fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> {
syntax.ancestors().find_map(|node| {
match_ast! {
match node {
ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)),
ast::MethodCallExpr(it) => {
let arg_list = it.arg_list()?;
if !arg_list.syntax().text_range().contains_range(syntax.text_range()) {
return None;
}
Some(FnCallNode::MethodCallExpr(it))
},
_ => None,
}
}
})
}

pub fn with_node_exact(node: &SyntaxNode) -> Option<FnCallNode> {
match_ast! {
match node {
ast::CallExpr(it) => Some(FnCallNode::CallExpr(it)),
ast::MethodCallExpr(it) => Some(FnCallNode::MethodCallExpr(it)),
_ => None,
}
}
}

pub fn name_ref(&self) -> Option<ast::NameRef> {
match self {
FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? {
ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
_ => return None,
}),
FnCallNode::MethodCallExpr(call_expr) => {
call_expr.syntax().children().find_map(ast::NameRef::cast)
}
}
}

fn arg_list(&self) -> Option<ast::ArgList> {
match self {
FnCallNode::CallExpr(expr) => expr.arg_list(),
FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
}
}
}

#[cfg(test)]
mod tests;
1 change: 0 additions & 1 deletion crates/ide_db/src/call_info/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,6 @@ pub fn foo(mut r: WriteHandler<()>) {

#[test]
fn call_info_bad_offset() {
cov_mark::check!(call_info_bad_offset);
check(
r#"
fn foo(x: u32, y: u32) -> u32 {x + y}
Expand Down
2 changes: 1 addition & 1 deletion crates/syntax/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
};

pub use self::{
expr_ext::{ArrayExprKind, BlockModifier, ElseBranch, LiteralKind},
expr_ext::{ArrayExprKind, BlockModifier, CallableExpr, ElseBranch, LiteralKind},
generated::{nodes::*, tokens::*},
node_ext::{
AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind,
Expand Down
Loading