use super::{
AnalysisContext, Scope, ScopeAnalyzer, ScopeIssue, builtin_declaration_arg_positions,
is_topic_defaulting_builtin, is_topic_modifying_builtin,
};
use crate::ast::Node;
use std::rc::Rc;
#[allow(clippy::too_many_arguments)]
pub(super) fn handle_function_call<'a>(
analyzer: &ScopeAnalyzer,
node: &'a Node,
name: &str,
args: &'a [Node],
scope: &Rc<Scope>,
ancestors: &mut Vec<&'a Node>,
issues: &mut Vec<ScopeIssue>,
context: &AnalysisContext<'a>,
strict_vars_mode: bool,
) {
if let Some((sigil, var_name)) = analyzer.extract_name_like_variable(name) {
analyzer.record_variable_use(
scope,
strict_vars_mode,
context,
issues,
node,
sigil,
var_name,
);
}
if args.is_empty() && is_topic_defaulting_builtin(name) {
if is_topic_modifying_builtin(name) {
let _ = scope.initialize_and_use_variable_parts("$", "_");
} else {
let _ = scope.use_variable_parts("$", "_");
}
}
ancestors.push(node);
let declaration_arg_positions = builtin_declaration_arg_positions(name);
for (arg_index, arg) in args.iter().enumerate() {
analyzer.analyze_node(arg, scope, ancestors, issues, context);
if declaration_arg_positions.contains(&arg_index) {
analyzer.mark_builtin_declaration_arg_consumed(arg, scope, context);
}
}
ancestors.pop();
}
#[allow(clippy::too_many_arguments)]
pub(super) fn handle_method_call<'a>(
analyzer: &ScopeAnalyzer,
node: &'a Node,
object: &'a Node,
method: &str,
args: &'a [Node],
scope: &Rc<Scope>,
ancestors: &mut Vec<&'a Node>,
issues: &mut Vec<ScopeIssue>,
context: &AnalysisContext<'a>,
strict_vars_mode: bool,
) {
ancestors.push(node);
analyzer.analyze_node(object, scope, ancestors, issues, context);
if let Some((sigil, var_name)) = analyzer.extract_method_name_variable(method) {
analyzer.record_variable_use(
scope,
strict_vars_mode,
context,
issues,
node,
sigil,
var_name,
);
}
for arg in args {
analyzer.analyze_node(arg, scope, ancestors, issues, context);
}
ancestors.pop();
}
pub(super) fn handle_unary<'a>(
analyzer: &ScopeAnalyzer,
node: &'a Node,
operand: &'a Node,
scope: &Rc<Scope>,
ancestors: &mut Vec<&'a Node>,
issues: &mut Vec<ScopeIssue>,
context: &AnalysisContext<'a>,
) {
ancestors.push(node);
analyzer.analyze_node(operand, scope, ancestors, issues, context);
ancestors.pop();
}
pub(super) fn handle_binary<'a>(
analyzer: &ScopeAnalyzer,
node: &'a Node,
left: &'a Node,
right: &'a Node,
scope: &Rc<Scope>,
ancestors: &mut Vec<&'a Node>,
issues: &mut Vec<ScopeIssue>,
context: &AnalysisContext<'a>,
) {
ancestors.push(node);
analyzer.analyze_node(left, scope, ancestors, issues, context);
analyzer.analyze_node(right, scope, ancestors, issues, context);
ancestors.pop();
}
pub(super) fn handle_array_literal<'a>(
analyzer: &ScopeAnalyzer,
node: &'a Node,
elements: &'a [Node],
scope: &Rc<Scope>,
ancestors: &mut Vec<&'a Node>,
issues: &mut Vec<ScopeIssue>,
context: &AnalysisContext<'a>,
) {
ancestors.push(node);
for element in elements {
analyzer.analyze_node(element, scope, ancestors, issues, context);
}
ancestors.pop();
}