mod args;
mod callable;
mod function;
pub(crate) mod method;
mod static_call;
pub(crate) use args::substitute_static_in_return;
pub use args::{
check_constructor_args, distinct_spans_for_expansion, expand_sole_spread_arg,
spread_element_type, CheckArgsParams,
};
pub(crate) use function::extract_class_docblock;
pub struct CallAnalyzer;
pub(crate) fn consume_arg_assignment(
expr: &php_ast::owned::Expr,
ctx: &mut crate::flow_state::FlowState,
) {
if let php_ast::owned::ExprKind::Assign(a) = &expr.kind {
if let php_ast::owned::ExprKind::Variable(name) = &a.target.kind {
let n = name.trim_start_matches('$');
ctx.read_vars.insert(mir_types::Name::from(n));
ctx.mark_consumed(n);
}
}
}
pub(crate) fn premark_byref_arg_vars(
params: &[mir_codebase::storage::FnParam],
args: &[php_ast::owned::Arg],
ctx: &mut crate::flow_state::FlowState,
) {
use php_ast::owned::ExprKind;
fn premark_one(
param: &mir_codebase::storage::FnParam,
arg: &php_ast::owned::Arg,
ctx: &mut crate::flow_state::FlowState,
) {
if !param.is_byref {
return;
}
if let ExprKind::Variable(name) = &arg.value.kind {
let var_name = name.trim_start_matches('$');
if !ctx.var_is_defined(var_name) {
let ty = param
.out_ty
.as_ref()
.or(param.ty.as_ref())
.map(|t| (**t).clone())
.unwrap_or_else(mir_types::Type::mixed);
ctx.set_var(var_name, ty);
}
}
}
let variadic_index = params.iter().position(|p| p.is_variadic);
let max_positional = variadic_index.unwrap_or(params.len());
let mut positional = 0usize;
for arg in args {
if arg.unpack {
break;
}
if let Some(name) = &arg.name {
let name = crate::parser::name_to_string_owned(name);
if let Some(param) = params.iter().find(|p| p.name.as_ref() == name.as_str()) {
premark_one(param, arg, ctx);
} else if let Some(vi) = variadic_index {
premark_one(¶ms[vi], arg, ctx);
}
continue;
}
let param = if positional < max_positional {
params.get(positional)
} else {
variadic_index.map(|vi| ¶ms[vi])
};
if let Some(param) = param {
premark_one(param, arg, ctx);
}
positional += 1;
}
}
thread_local! {
pub(crate) static ARG_TYPES_BUF: std::cell::RefCell<Option<Vec<mir_types::Type>>> =
const { std::cell::RefCell::new(Some(Vec::new())) };
}