mago-semantics 1.20.1

PHP Semantics Checker.
Documentation
use mago_span::HasSpan;
use mago_syntax::ast::Access;
use mago_syntax::ast::AnonymousClass;
use mago_syntax::ast::ArgumentList;
use mago_syntax::ast::ArrowFunction;
use mago_syntax::ast::Assignment;
use mago_syntax::ast::AttributeList;
use mago_syntax::ast::Call;
use mago_syntax::ast::Class;
use mago_syntax::ast::Closure;
use mago_syntax::ast::Constant;
use mago_syntax::ast::Declare;
use mago_syntax::ast::Enum;
use mago_syntax::ast::Expression;
use mago_syntax::ast::Function;
use mago_syntax::ast::FunctionLikeParameterList;
use mago_syntax::ast::FunctionLikeReturnTypeHint;
use mago_syntax::ast::Goto;
use mago_syntax::ast::Hint;
use mago_syntax::ast::Interface;
use mago_syntax::ast::List;
use mago_syntax::ast::Literal;
use mago_syntax::ast::Match;
use mago_syntax::ast::Namespace;
use mago_syntax::ast::PartialApplication;
use mago_syntax::ast::Pipe;
use mago_syntax::ast::Program;
use mago_syntax::ast::Statement;
use mago_syntax::ast::Switch;
use mago_syntax::ast::Trait;
use mago_syntax::ast::Try;
use mago_syntax::ast::UnaryPrefixOperator;
use mago_syntax::walker::Walker;

use crate::internal::context::Context;

pub mod checker;
pub mod consts;
pub mod context;

#[derive(Clone, Debug)]
pub struct CheckingWalker;

impl<'ast, 'arena> Walker<'ast, 'arena, Context<'_, 'ast, 'arena>> for CheckingWalker {
    #[inline]
    fn walk_in_statement(&self, statement: &'ast Statement<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        context.ancestors.push(statement.span());
    }

    #[inline]
    fn walk_in_expression(&self, expression: &'ast Expression<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        context.ancestors.push(expression.span());

        checker::expression::check_for_clone_with(expression, context);
    }

    #[inline]
    fn walk_out_statement(&self, _statement: &'ast Statement<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        context.ancestors.pop();
    }

    #[inline]
    fn walk_out_expression(&self, _expression: &'ast Expression<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        context.ancestors.pop();
    }

    #[inline]
    fn walk_in_program(&self, program: &'ast Program<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::statement::check_top_level_statements(program, context);
    }

    #[inline]
    fn walk_in_declare(&self, declare: &Declare<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::statement::check_declare(declare, context);
    }

    #[inline]
    fn walk_in_namespace(&self, namespace: &Namespace<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::statement::check_namespace(namespace, context);
    }

    #[inline]
    fn walk_in_hint(&self, hint: &Hint<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        context.hint_depth += 1;
        checker::hint::check_hint(hint, context);
    }

    #[inline]
    fn walk_out_hint(&self, _hint: &Hint, context: &mut Context<'_, 'ast, 'arena>) {
        context.hint_depth -= 1;
    }

    #[inline]
    fn walk_in_try(&self, r#try: &Try<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::r#try::check_try(r#try, context);
    }

    #[inline]
    fn walk_in_class(&self, class: &'ast Class<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::class_like::check_class(class, context);
    }

    #[inline]
    fn walk_in_interface(&self, interface: &'ast Interface<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::class_like::check_interface(interface, context);
    }

    #[inline]
    fn walk_in_trait(&self, r#trait: &'ast Trait<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::class_like::check_trait(r#trait, context);
    }

    #[inline]
    fn walk_in_enum(&self, r#enum: &'ast Enum<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::class_like::check_enum(r#enum, context);
    }

    #[inline]
    fn walk_in_anonymous_class(
        &self,
        anonymous_class: &'ast AnonymousClass<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::class_like::check_anonymous_class(anonymous_class, context);
    }

    #[inline]
    fn walk_in_function(&self, function: &'ast Function<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::function_like::check_function(function, context);
    }

    #[inline]
    fn walk_in_attribute_list(
        &self,
        attribute_list: &'ast AttributeList<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::attribute::check_attribute_list(attribute_list, context);
    }

    #[inline]
    fn walk_in_goto(&self, goto: &'ast Goto<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::statement::check_goto(goto, context);
    }

    #[inline]
    fn walk_in_argument_list(
        &self,
        argument_list: &'ast ArgumentList<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::argument::check_argument_list(argument_list, context);
    }

    #[inline]
    fn walk_in_closure(&self, closure: &'ast Closure<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::function_like::check_closure(closure, context);
    }

    #[inline]
    fn walk_in_arrow_function(
        &self,
        arrow_function: &'ast ArrowFunction<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::function_like::check_arrow_function(arrow_function, context);
    }

    #[inline]
    fn walk_in_function_like_parameter_list(
        &self,
        function_like_parameter_list: &'ast FunctionLikeParameterList<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::function_like::check_parameter_list(function_like_parameter_list, context);
    }

    #[inline]
    fn walk_in_match(&self, r#match: &'ast Match<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::control_flow::check_match(r#match, context);
    }

    #[inline]
    fn walk_in_switch(&self, switch: &'ast Switch<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::control_flow::check_switch(switch, context);
    }

    #[inline]
    fn walk_in_assignment(&self, assignment: &'ast Assignment<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::assignment::check_assignment(assignment, context);
    }

    #[inline]
    fn walk_in_function_like_return_type_hint(
        &self,
        function_like_return_type_hint: &'ast FunctionLikeReturnTypeHint<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::function_like::check_return_type_hint(function_like_return_type_hint, context);
    }

    #[inline]
    fn walk_in_partial_application(
        &self,
        partial_application: &'ast PartialApplication<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::partial_application::check_partial_application(partial_application, context);
    }

    #[inline]
    fn walk_in_list(&self, list: &'ast List<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::array::check_list(list, context);
    }

    fn walk_in_call(&self, call: &'ast Call<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::call::check_call(call, context);
    }

    #[inline]
    fn walk_in_access(&self, access: &'ast Access<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::access::check_access(access, context);
    }

    #[inline]
    fn walk_in_unary_prefix_operator(
        &self,
        unary_prefix_operator: &'ast UnaryPrefixOperator<'arena>,
        context: &mut Context<'_, 'ast, 'arena>,
    ) {
        checker::expression::check_unary_prefix_operator(unary_prefix_operator, context);
    }

    #[inline]
    fn walk_literal_expression(&self, literal_expression: &'ast Literal, context: &mut Context<'_, 'ast, 'arena>) {
        checker::literal::check_literal(literal_expression, context);
    }

    #[inline]
    fn walk_in_constant(&self, constant: &'ast Constant<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::constant::check_constant(constant, context);
    }

    fn walk_in_pipe(&self, pipe: &'ast Pipe<'arena>, context: &mut Context<'_, 'ast, 'arena>) {
        checker::pipe::check_pipe(pipe, context);
    }
}