mod collect_overloads;
mod filter_overloads;
mod resolve_signature_by_args;
use std::sync::Arc;
use emmylua_parser::{LuaAstNode, LuaCallExpr};
use crate::db_index::{DbIndex, LuaFunctionType, LuaType};
use super::{
LuaInferCache,
generic::infer_call_generic,
infer::{InferCallFuncResult, InferFailReason, infer_expr_list_types, try_infer_expr_no_flow},
};
pub(crate) use collect_overloads::call_operator_self_type;
pub use collect_overloads::collect_callable_overload_groups;
pub(crate) use filter_overloads::match_callable_by_arg_types;
pub use filter_overloads::{filter_callable_overloads, find_callable_overload};
pub(crate) use resolve_signature_by_args::{
callable_accepts_args, get_func_param_type, is_func_last_param_variadic,
resolve_signature_by_args,
};
pub fn resolve_signature(
db: &DbIndex,
cache: &mut LuaInferCache,
overloads: Vec<Arc<LuaFunctionType>>,
call_expr: LuaCallExpr,
is_generic: bool,
arg_count: Option<usize>,
) -> InferCallFuncResult {
let args = call_expr.get_args_list().ok_or(InferFailReason::None)?;
let mut declined_no_flow_arg_ranges = Vec::new();
let expr_types_with_ranges = infer_expr_list_types(
db,
cache,
args.get_args().collect::<Vec<_>>().as_slice(),
arg_count,
|db, cache, expr| {
if cache.is_no_flow() {
let expr_range = expr.get_range();
let Some(expr_type) = try_infer_expr_no_flow(db, cache, expr)? else {
if !is_generic {
declined_no_flow_arg_ranges.push(expr_range);
return Ok(LuaType::Unknown);
}
return Err(InferFailReason::None);
};
Ok(expr_type)
} else {
Ok(crate::infer_expr(db, cache, expr).unwrap_or(LuaType::Unknown))
}
},
)?;
let declined_no_flow_args = expr_types_with_ranges
.iter()
.map(|(_, range)| declined_no_flow_arg_ranges.contains(range))
.collect::<Vec<_>>();
let expr_types: Vec<_> = expr_types_with_ranges
.into_iter()
.map(|(ty, _)| ty)
.collect();
if is_generic {
resolve_signature_by_generic(db, cache, overloads, call_expr, expr_types, arg_count)
} else {
resolve_signature_by_args(
db,
&overloads,
&expr_types,
call_expr.is_colon_call(),
arg_count,
&declined_no_flow_args,
)
}
}
fn resolve_signature_by_generic(
db: &DbIndex,
cache: &mut LuaInferCache,
overloads: Vec<Arc<LuaFunctionType>>,
call_expr: LuaCallExpr,
expr_types: Vec<LuaType>,
arg_count: Option<usize>,
) -> InferCallFuncResult {
let mut instantiate_funcs = Vec::new();
for func in overloads {
let instantiate_func = infer_call_generic(db, cache, &func, call_expr.clone())?;
instantiate_funcs.push(Arc::new(instantiate_func));
}
resolve_signature_by_args(
db,
&instantiate_funcs,
&expr_types,
call_expr.is_colon_call(),
arg_count,
&[],
)
}