@param   StatementsAnalyzer           $statements_analyzer
@param   PhpParser\Node\Expr\Yield_  $stmt
@param   Context                     $context

@return  false|null
187103
protected static function analyzeYield(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\Yield_ $stmt,
        Context $context
    ) {
        $doc_comment_text = (string)$stmt->getDocComment();

        $var_comments = [];
        $var_comment_type = null;

        $codebase = $statements_analyzer->getCodebase();

        if ($doc_comment_text) {
            try {
                $var_comments = CommentAnalyzer::getTypeFromComment(
                    $doc_comment_text,
                    $statements_analyzer,
                    $statements_analyzer->getAliases()
                );
            } catch (DocblockParseException $e) {
                if (IssueBuffer::accepts(
                    new InvalidDocblock(
                        (string)$e->getMessage(),
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    )
                )) {
                    // fall through
                }
            }

            foreach ($var_comments as $var_comment) {
                $comment_type = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    $var_comment->type,
                    $context->self,
                    $context->self ? new Type\Atomic\TNamedObject($context->self) : null
                );

                if (!$var_comment->var_id) {
                    $var_comment_type = $comment_type;
                    continue;
                }

                $context->vars_in_scope[$var_comment->var_id] = $comment_type;
            }
        }

        if ($stmt->key) {
            if (self::analyze($statements_analyzer, $stmt->key, $context) === false) {
                return false;
            }
        }

        if ($stmt->value) {
            if (self::analyze($statements_analyzer, $stmt->value, $context) === false) {
                return false;
            }

            if ($var_comment_type) {
                $stmt->inferredType = $var_comment_type;
            } elseif (isset($stmt->value->inferredType)) {
                $stmt->inferredType = $stmt->value->inferredType;
            } else {
                $stmt->inferredType = Type::getMixed();
            }
        } else {
            $stmt->inferredType = Type::getNull();
        }

        $source = $statements_analyzer->getSource();

        if ($source instanceof FunctionLikeAnalyzer
            && !($source->getSource() instanceof TraitAnalyzer)
        ) {
            $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt);

            $storage = $source->getFunctionLikeStorage($statements_analyzer);

            if ($storage->return_type) {
                foreach ($storage->return_type->getTypes() as $atomic_return_type) {
                    if ($atomic_return_type instanceof Type\Atomic\TGenericObject
                        && $atomic_return_type->value === 'Generator'
                    ) {
                        if (!$atomic_return_type->type_params[2]->isMixed()
                            && !$atomic_return_type->type_params[2]->isVoid()
                        ) {
                            $stmt->inferredType = clone $atomic_return_type->type_params[2];
                        }
                    }
                }
            }
        }

        return null;
    }
926316
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\FuncCall $stmt,
        Context $context
    ) {
        $function = $stmt->name;

        $function_id = null;
        $function_params = null;
        $in_call_map = false;

        $is_stubbed = false;

        $function_storage = null;

        $codebase = $statements_analyzer->getCodebase();

        $code_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
        $codebase_functions = $codebase->functions;
        $config = $codebase->config;
        $defined_constants = [];
        $global_variables = [];

        $function_exists = false;

        if ($stmt->name instanceof PhpParser\Node\Expr) {
            if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context) === false) {
                return false;
            }

            if (isset($stmt->name->inferredType)) {
                if ($stmt->name->inferredType->isNull()) {
                    if (IssueBuffer::accepts(
                        new NullFunctionCall(
                            'Cannot call function on null value',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        return false;
                    }

                    return;
                }

                if ($stmt->name->inferredType->isNullable()) {
                    if (IssueBuffer::accepts(
                        new PossiblyNullFunctionCall(
                            'Cannot call function on possibly null value',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }
                }

                $invalid_function_call_types = [];
                $has_valid_function_call_type = false;

                foreach ($stmt->name->inferredType->getTypes() as $var_type_part) {
                    if ($var_type_part instanceof Type\Atomic\Fn || $var_type_part instanceof Type\Atomic\TCallable) {
                        $function_params = $var_type_part->params;

                        if (isset($stmt->inferredType) && $var_type_part->return_type) {
                            $stmt->inferredType = Type::combineUnionTypes(
                                $stmt->inferredType,
                                $var_type_part->return_type
                            );
                        } else {
                            $stmt->inferredType = $var_type_part->return_type ?: Type::getMixed();
                        }

                        $function_exists = true;
                        $has_valid_function_call_type = true;
                    } elseif ($var_type_part instanceof TMixed || $var_type_part instanceof TTemplateParam) {
                        $has_valid_function_call_type = true;

                        if (IssueBuffer::accepts(
                            new MixedFunctionCall(
                                'Cannot call function on mixed',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    } elseif ($var_type_part instanceof TCallableObject
                        || $var_type_part instanceof TCallableString
                    ) {
                        // this is fine
                        $has_valid_function_call_type = true;
                    } elseif (($var_type_part instanceof TNamedObject && $var_type_part->value === 'Closure')) {
                        // this is fine
                        $has_valid_function_call_type = true;
                    } elseif ($var_type_part instanceof TString
                        || $var_type_part instanceof Type\Atomic\TArray
                        || ($var_type_part instanceof Type\Atomic\ObjectLike
                            && count($var_type_part->properties) === 2)
                    ) {
                        // this is also kind of fine
                        $has_valid_function_call_type = true;
                    } elseif ($var_type_part instanceof TNull) {
                        // handled above
                    } elseif (!$var_type_part instanceof TNamedObject
                        || !$codebase->classlikes->classOrInterfaceExists($var_type_part->value)
                        || !$codebase->methods->methodExists($var_type_part->value . '::__invoke')
                    ) {
                        $invalid_function_call_types[] = (string)$var_type_part;
                    } else {
                        if (self::checkMethodArgs(
                            $var_type_part->value . '::__invoke',
                            $stmt->args,
                            $class_template_params,
                            $context,
                            new CodeLocation($statements_analyzer->getSource(), $stmt),
                            $statements_analyzer
                        ) === false) {
                            return false;
                        }

                        $invokable_return_type = $codebase->methods->getMethodReturnType(
                            $var_type_part->value . '::__invoke',
                            $var_type_part->value
                        );

                        if (isset($stmt->inferredType)) {
                            $stmt->inferredType = Type::combineUnionTypes(
                                $invokable_return_type ?: Type::getMixed(),
                                $stmt->inferredType
                            );
                        } else {
                            $stmt->inferredType = $invokable_return_type ?: Type::getMixed();
                        }
                    }
                }

                if ($invalid_function_call_types) {
                    $var_type_part = reset($invalid_function_call_types);

                    if ($has_valid_function_call_type) {
                        if (IssueBuffer::accepts(
                            new PossiblyInvalidFunctionCall(
                                'Cannot treat type ' . $var_type_part . ' as callable',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }
                    } else {
                        if (IssueBuffer::accepts(
                            new InvalidFunctionCall(
                                'Cannot treat type ' . $var_type_part . ' as callable',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }
                    }
                }
            }

            if (!isset($stmt->inferredType)) {
                $stmt->inferredType = Type::getMixed();
            }
        } else {
            $original_function_id = implode('\\', $stmt->name->parts);

            if (!$stmt->name instanceof PhpParser\Node\Name\FullyQualified) {
                $function_id = $codebase_functions->getFullyQualifiedFunctionNameFromString(
                    $original_function_id,
                    $statements_analyzer
                );
            } else {
                $function_id = $original_function_id;
            }

            $namespaced_function_exists = $codebase_functions->functionExists(
                $statements_analyzer,
                strtolower($function_id)
            );

            if (!$namespaced_function_exists
                && !$stmt->name instanceof PhpParser\Node\Name\FullyQualified
            ) {
                $in_call_map = CallMap::inCallMap($original_function_id);
                $is_stubbed = $codebase_functions->hasStubbedFunction($original_function_id);

                if ($is_stubbed || $in_call_map) {
                    $function_id = $original_function_id;
                }
            } else {
                $in_call_map = CallMap::inCallMap($function_id);
                $is_stubbed = $codebase_functions->hasStubbedFunction($function_id);
            }

            if ($is_stubbed || $in_call_map || $namespaced_function_exists) {
                $function_exists = true;
            }

            $is_predefined = true;

            $is_maybe_root_function = !$stmt->name instanceof PhpParser\Node\Name\FullyQualified
                && count($stmt->name->parts) === 1;

            if (!$in_call_map) {
                $predefined_functions = $config->getPredefinedFunctions();
                $is_predefined = isset($predefined_functions[strtolower($original_function_id)])
                    || isset($predefined_functions[strtolower($function_id)]);

                if ($context->check_functions) {
                    if (self::checkFunctionExists(
                        $statements_analyzer,
                        $function_id,
                        $code_location,
                        $is_maybe_root_function
                    ) === false
                    ) {
                        return false;
                    }
                }
            } else {
                $function_exists = true;
            }

            if ($function_exists) {
                $function_params = null;

                if ($codebase->functions->params_provider->has($function_id)) {
                    $function_params = $codebase->functions->params_provider->getFunctionParams(
                        $statements_analyzer,
                        $function_id,
                        $stmt->args
                    );
                }

                if ($function_params === null) {
                    if (!$in_call_map || $is_stubbed) {
                        $function_storage = $codebase_functions->getStorage(
                            $statements_analyzer,
                            strtolower($function_id)
                        );

                        $function_params = $function_storage->params;

                        if (!$is_predefined) {
                            $defined_constants = $function_storage->defined_constants;
                            $global_variables = $function_storage->global_variables;
                        }
                    }

                    if ($in_call_map && !$is_stubbed) {
                        $function_params = FunctionLikeAnalyzer::getFunctionParamsFromCallMapById(
                            $codebase,
                            $function_id,
                            $stmt->args
                        );
                    }
                }

                if ($codebase->store_node_types) {
                    $codebase->analyzer->addNodeReference(
                        $statements_analyzer->getFilePath(),
                        $stmt->name,
                        $function_id . '()'
                    );
                }
            }
        }

        $set_inside_conditional = false;

        if ($function instanceof PhpParser\Node\Name
            && $function->parts === ['assert']
            && !$context->inside_conditional
        ) {
            $context->inside_conditional = true;
            $set_inside_conditional = true;
        }

        if (self::checkFunctionArguments(
            $statements_analyzer,
            $stmt->args,
            $function_params,
            $function_id,
            $context
        ) === false) {
            // fall through
        }

        if ($set_inside_conditional) {
            $context->inside_conditional = false;
        }

        $generic_params = null;

        if ($function_exists) {
            if ($stmt->name instanceof PhpParser\Node\Name && $function_id) {
                if (!$is_stubbed && $in_call_map) {
                    $function_params = FunctionLikeAnalyzer::getFunctionParamsFromCallMapById(
                        $codebase,
                        $function_id,
                        $stmt->args
                    );
                }
            }

            // do this here to allow closure param checks
            if ($function_params !== null
                && self::checkFunctionLikeArgumentsMatch(
                    $statements_analyzer,
                    $stmt->args,
                    $function_id,
                    $function_params,
                    $function_storage,
                    null,
                    $generic_params,
                    $code_location,
                    $context
                ) === false) {
                // fall through
            }

            if ($stmt->name instanceof PhpParser\Node\Name && $function_id) {
                $stmt->inferredType = null;

                if ($codebase->functions->return_type_provider->has($function_id)) {
                    $stmt->inferredType = $codebase->functions->return_type_provider->getReturnType(
                        $statements_analyzer,
                        $function_id,
                        $stmt->args,
                        $context,
                        new CodeLocation($statements_analyzer->getSource(), $stmt->name)
                    );
                }

                if (!$stmt->inferredType) {
                    if (!$in_call_map || $is_stubbed) {
                        if ($function_storage && $function_storage->template_types) {
                            foreach ($function_storage->template_types as $template_name => $_) {
                                if (!isset($generic_params[$template_name])) {
                                    $generic_params[$template_name] = ['' => [Type::getMixed(), 0]];
                                }
                            }
                        }

                        if ($function_storage && !$context->isSuppressingExceptions($statements_analyzer)) {
                            $context->mergeFunctionExceptions(
                                $function_storage,
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            );
                        }

                        try {
                            if ($function_storage && $function_storage->return_type) {
                                $return_type = clone $function_storage->return_type;

                                if ($generic_params && $function_storage->template_types) {
                                    $return_type->replaceTemplateTypesWithArgTypes(
                                        $generic_params
                                    );
                                }

                                $return_type_location = $function_storage->return_type_location;

                                if ($config->after_function_checks) {
                                    $file_manipulations = [];

                                    foreach ($config->after_function_checks as $plugin_fq_class_name) {
                                        $plugin_fq_class_name::afterFunctionCallAnalysis(
                                            $stmt,
                                            $function_id,
                                            $context,
                                            $statements_analyzer->getSource(),
                                            $codebase,
                                            $file_manipulations,
                                            $return_type
                                        );
                                    }

                                    if ($file_manipulations) {
                                        FileManipulationBuffer::add(
                                            $statements_analyzer->getFilePath(),
                                            $file_manipulations
                                        );
                                    }
                                }

                                /** @var Type\Union $return_type */
                                $stmt->inferredType = $return_type;
                                $return_type->by_ref = $function_storage->returns_by_ref;

                                // only check the type locally if it's defined externally
                                if ($return_type_location &&
                                    !$is_stubbed && // makes lookups or array_* functions quicker
                                    !$config->isInProjectDirs($return_type_location->file_path)
                                ) {
                                    $return_type->check(
                                        $statements_analyzer,
                                        new CodeLocation($statements_analyzer->getSource(), $stmt),
                                        $statements_analyzer->getSuppressedIssues(),
                                        $context->phantom_classes
                                    );
                                }
                            }
                        } catch (\InvalidArgumentException $e) {
                            // this can happen when the function was defined in the Config startup script
                            $stmt->inferredType = Type::getMixed();
                        }
                    } else {
                        $stmt->inferredType = FunctionAnalyzer::getReturnTypeFromCallMapWithArgs(
                            $statements_analyzer,
                            $function_id,
                            $stmt->args,
                            $context
                        );
                    }
                }
            }

            foreach ($defined_constants as $const_name => $const_type) {
                $context->constants[$const_name] = clone $const_type;
                $context->vars_in_scope[$const_name] = clone $const_type;
            }

            foreach ($global_variables as $var_id => $_) {
                $context->vars_in_scope[$var_id] = Type::getMixed();
                $context->vars_possibly_in_scope[$var_id] = true;
            }

            if ($config->use_assert_for_type &&
                $function instanceof PhpParser\Node\Name &&
                $function->parts === ['assert'] &&
                isset($stmt->args[0])
            ) {
                $assert_clauses = \Psalm\Type\Algebra::getFormula(
                    $stmt->args[0]->value,
                    $statements_analyzer->getFQCLN(),
                    $statements_analyzer,
                    $codebase
                );

                $simplified_clauses = Algebra::simplifyCNF(array_merge($context->clauses, $assert_clauses));

                $assert_type_assertions = Algebra::getTruthsFromFormula($simplified_clauses);

                if ($assert_type_assertions) {
                    $changed_vars = [];

                    // while in an and, we allow scope to boil over to support
                    // statements of the form if ($x && $x->foo())
                    $op_vars_in_scope = Reconciler::reconcileKeyedTypes(
                        $assert_type_assertions,
                        $context->vars_in_scope,
                        $changed_vars,
                        [],
                        $statements_analyzer,
                        [],
                        $context->inside_loop,
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    );

                    foreach ($changed_vars as $changed_var) {
                        if (isset($op_vars_in_scope[$changed_var])) {
                            $op_vars_in_scope[$changed_var]->from_docblock = true;
                        }
                    }

                    $context->vars_in_scope = $op_vars_in_scope;
                }
            }
        }

        if (!$config->remember_property_assignments_after_call
            && !$in_call_map
            && !$context->collect_initializations
        ) {
            $context->removeAllObjectVars();
        }

        if ($stmt->name instanceof PhpParser\Node\Name &&
            ($stmt->name->parts === ['get_class'] || $stmt->name->parts === ['gettype']) &&
            $stmt->args
        ) {
            $var = $stmt->args[0]->value;

            if ($var instanceof PhpParser\Node\Expr\Variable
                && is_string($var->name)
            ) {
                $var_id = '$' . $var->name;

                if (isset($context->vars_in_scope[$var_id])) {
                    $atomic_type = $stmt->name->parts === ['get_class']
                        ? new Type\Atomic\GetClassT($var_id, $context->vars_in_scope[$var_id])
                        : new Type\Atomic\GetTypeT($var_id);

                    $stmt->inferredType = new Type\Union([$atomic_type]);
                }
            } elseif (isset($var->inferredType)) {
                $class_string_types = [];

                foreach ($var->inferredType->getTypes() as $class_type) {
                    if ($class_type instanceof Type\Atomic\TNamedObject) {
                        $class_string_types[] = new Type\Atomic\TClassString($class_type->value, clone $class_type);
                    }
                }

                if ($class_string_types) {
                    $stmt->inferredType = new Type\Union($class_string_types);
                }
            }
        }

        if ($codebase->store_node_types
            && (!$context->collect_initializations
                && !$context->collect_mutations)
            && isset($stmt->inferredType)
        ) {
            $codebase->analyzer->addNodeType(
                $statements_analyzer->getFilePath(),
                $stmt,
                (string) $stmt->inferredType
            );
        }

        if ($function_storage) {
            if ($function_storage->assertions && $stmt->name instanceof PhpParser\Node\Name) {
                self::applyAssertionsToContext(
                    $stmt->name,
                    $function_storage->assertions,
                    $stmt->args,
                    $generic_params ?: [],
                    $context,
                    $statements_analyzer
                );
            }

            if ($function_storage->if_true_assertions) {
                $stmt->ifTrueAssertions = array_map(
                    function (Assertion $assertion) use ($generic_params) : Assertion {
                        return $assertion->getUntemplatedCopy($generic_params ?: []);
                    },
                    $function_storage->if_true_assertions
                );
            }

            if ($function_storage->if_false_assertions) {
                $stmt->ifFalseAssertions = array_map(
                    function (Assertion $assertion) use ($generic_params) : Assertion {
                        return $assertion->getUntemplatedCopy($generic_params ?: []);
                    },
                    $function_storage->if_false_assertions
                );
            }
        }

        if ($function instanceof PhpParser\Node\Name) {
            $first_arg = isset($stmt->args[0]) ? $stmt->args[0] : null;

            if ($function->parts === ['method_exists']) {
                $context->check_methods = false;
            } elseif ($function->parts === ['class_exists']) {
                if ($first_arg && $first_arg->value instanceof PhpParser\Node\Scalar\String_) {
                    $context->phantom_classes[strtolower($first_arg->value->value)] = true;
                }
            } elseif ($function->parts === ['file_exists'] && $first_arg) {
                $var_id = ExpressionAnalyzer::getArrayVarId($first_arg->value, null);

                if ($var_id) {
                    $context->phantom_files[$var_id] = true;
                }
            } elseif ($function->parts === ['extension_loaded']) {
                if ($first_arg
                    && $first_arg->value instanceof PhpParser\Node\Scalar\String_
                ) {
                    if (@extension_loaded($first_arg->value->value)) {
                        // do nothing
                    } else {
                        $context->check_classes = false;
                    }
                }
            } elseif ($function->parts === ['function_exists']) {
                $context->check_functions = false;
            } elseif ($function->parts === ['is_callable']) {
                $context->check_methods = false;
                $context->check_functions = false;
            } elseif ($function->parts === ['defined']) {
                $context->check_consts = false;
            } elseif ($function->parts === ['extract']) {
                $context->check_variables = false;
            } elseif (strtolower($function->parts[0]) === 'var_dump'
                || strtolower($function->parts[0]) === 'shell_exec') {
                if (IssueBuffer::accepts(
                    new ForbiddenCode(
                        'Unsafe ' . implode('', $function->parts),
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    // continue
                }
            } elseif (isset($codebase->config->forbidden_functions[strtolower((string) $function)])) {
                if (IssueBuffer::accepts(
                    new ForbiddenCode(
                        'You have forbidden the use of ' . $function,
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    // continue
                }
            } elseif ($function->parts === ['define']) {
                if ($first_arg) {
                    $fq_const_name = StatementsAnalyzer::getConstName(
                        $first_arg->value,
                        $codebase,
                        $statements_analyzer->getAliases()
                    );

                    if ($fq_const_name !== null) {
                        $second_arg = $stmt->args[1];
                        ExpressionAnalyzer::analyze($statements_analyzer, $second_arg->value, $context);

                        $statements_analyzer->setConstType(
                            $fq_const_name,
                            isset($second_arg->value->inferredType) ?
                                $second_arg->value->inferredType :
                                Type::getMixed(),
                            $context
                        );
                    }
                } else {
                    $context->check_consts = false;
                }
            } elseif ($first_arg
                && $function_id
                && strpos($function_id, 'is_') === 0
                && $function_id !== 'is_a'
            ) {
                if (isset($stmt->assertions)) {
                    $assertions = $stmt->assertions;
                } else {
                    $assertions = AssertionFinder::processFunctionCall(
                        $stmt,
                        $context->self,
                        $statements_analyzer,
                        $context->inside_negation
                    );
                }

                $changed_vars = [];

                $referenced_var_ids = array_map(
                    function (array $_) : bool {
                        return true;
                    },
                    $assertions
                );

                if ($assertions) {
                    Reconciler::reconcileKeyedTypes(
                        $assertions,
                        $context->vars_in_scope,
                        $changed_vars,
                        $referenced_var_ids,
                        $statements_analyzer,
                        [],
                        $context->inside_loop,
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    );
                }
            }
        }

        return null;
    }
921906
public function analyze(
        Context $context,
        Context $global_context = null,
        $add_mutations = false,
        array $byref_uses = null
    ) {
        $storage = $this->storage;

        $function_stmts = $this->function->getStmts() ?: [];

        $hash = null;
        $real_method_id = null;

        $cased_method_id = null;

        $class_storage = null;

        if ($global_context) {
            foreach ($global_context->constants as $const_name => $var_type) {
                if (!$context->hasVariable($const_name)) {
                    $context->vars_in_scope[$const_name] = clone $var_type;
                }
            }
        }

        $codebase = $this->codebase;
        $project_analyzer = $this->getProjectAnalyzer();

        $implemented_docblock_param_types = [];

        $classlike_storage_provider = $codebase->classlike_storage_provider;

        $overridden_method_ids = [];

        if ($this->function instanceof ClassMethod) {
            if (!$storage instanceof MethodStorage) {
                throw new \UnexpectedValueException('$storage must be MethodStorage');
            }

            $real_method_id = (string)$this->getMethodId();

            $method_id = (string)$this->getMethodId($context->self);

            if ($add_mutations) {
                $hash = md5($real_method_id . '::' . $context->getScopeSummary());

                // if we know that the function has no effects on vars, we don't bother rechecking
                if (isset(self::$no_effects_hashes[$hash])) {
                    return null;
                }
            } elseif ($context->self) {
                $context->vars_in_scope['$this'] = new Type\Union([new TNamedObject($context->self)]);
                $context->vars_possibly_in_scope['$this'] = true;
            }

            $fq_class_name = (string)$context->self;

            $class_storage = $classlike_storage_provider->get($fq_class_name);

            if ($class_storage->has_visitor_issues) {
                return null;
            }

            $cased_method_id = $fq_class_name . '::' . $storage->cased_name;

            $overridden_method_ids = $codebase->methods->getOverriddenMethodIds($method_id);

            if ($this->function->name->name === '__construct') {
                $context->inside_constructor = true;
            }

            $codeLocation = new CodeLocation(
                $this,
                $this->function,
                null,
                true
            );

            if ($overridden_method_ids
                && $this->function->name->name !== '__construct'
                && !$context->collect_initializations
                && !$context->collect_mutations
            ) {
                foreach ($overridden_method_ids as $overridden_method_id) {
                    $parent_method_storage = $codebase->methods->getStorage($overridden_method_id);

                    list($overridden_fq_class_name) = explode('::', $overridden_method_id);

                    $parent_storage = $classlike_storage_provider->get($overridden_fq_class_name);

                    $implementer_visibility = $storage->visibility;

                    $implementer_appearing_method_id = $codebase->methods->getAppearingMethodId($cased_method_id);
                    $implementer_declaring_method_id = $real_method_id;

                    if ($implementer_appearing_method_id
                        && $implementer_appearing_method_id !== $implementer_declaring_method_id
                    ) {
                        list($appearing_fq_class_name, $appearing_method_name) = explode(
                            '::',
                            $implementer_appearing_method_id
                        );

                        $appearing_class_storage = $classlike_storage_provider->get(
                            $appearing_fq_class_name
                        );

                        if (isset($appearing_class_storage->trait_visibility_map[$appearing_method_name])) {
                            $implementer_visibility
                                = $appearing_class_storage->trait_visibility_map[$appearing_method_name];
                        }
                    }

                    // we've already checked this in the class checker
                    if (!isset($class_storage->class_implements[strtolower($overridden_fq_class_name)])) {
                        MethodAnalyzer::compareMethods(
                            $codebase,
                            $class_storage,
                            $parent_storage,
                            $storage,
                            $parent_method_storage,
                            $fq_class_name,
                            $implementer_visibility,
                            $codeLocation,
                            $storage->suppressed_issues
                        );
                    }

                    foreach ($parent_method_storage->params as $i => $guide_param) {
                        if ($guide_param->type
                            && (!$guide_param->signature_type
                                || ($guide_param->signature_type !== $guide_param->type
                                    && $storage->inheritdoc)
                                || !$parent_storage->user_defined
                            )
                        ) {
                            if (!isset($implemented_docblock_param_types[$i])) {
                                $implemented_docblock_param_types[$i] = $guide_param->type;
                            }
                        }
                    }
                }
            }

            MethodAnalyzer::checkMethodSignatureMustOmitReturnType($storage, $codeLocation);

            $context->calling_method_id = strtolower($method_id);
        } elseif ($this->function instanceof Function_) {
            $cased_method_id = $this->function->name;
        } else { // Closure
            if ($storage->return_type) {
                $closure_return_type = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    $storage->return_type,
                    $context->self,
                    $context->self
                );
            } else {
                $closure_return_type = Type::getMixed();
            }

            /** @var PhpParser\Node\Expr\Closure $this->function */
            $this->function->inferredType = new Type\Union([
                new Type\Atomic\Fn(
                    'Closure',
                    $storage->params,
                    $closure_return_type
                ),
            ]);
        }

        $this->suppressed_issues = array_merge(
            $this->getSource()->getSuppressedIssues(),
            $storage->suppressed_issues
        );

        if ($storage instanceof MethodStorage && $storage->is_static) {
            $this->is_static = true;
        }

        $statements_analyzer = new StatementsAnalyzer($this);

        if ($byref_uses) {
            $statements_analyzer->setByRefUses($byref_uses);
        }

        if ($storage->template_types) {
            foreach ($storage->template_types as $param_name => $_) {
                $fq_classlike_name = Type::getFQCLNFromString(
                    $param_name,
                    $this->getAliases()
                );

                if ($codebase->classOrInterfaceExists($fq_classlike_name)) {
                    if (IssueBuffer::accepts(
                        new ReservedWord(
                            'Cannot use ' . $param_name . ' as template name since the class already exists',
                            new CodeLocation($this, $this->function),
                            'resource'
                        ),
                        $this->getSuppressedIssues()
                    )) {
                        // fall through
                    }
                }
            }
        }

        $template_types = $storage->template_types;

        if ($class_storage && $class_storage->template_types) {
            $template_types = array_merge($template_types ?: [], $class_storage->template_types);
        }

        $params = $storage->params;

        if ($storage instanceof MethodStorage) {
            $non_null_param_types = array_filter(
                $storage->params,
                /** @return bool */
                function (FunctionLikeParameter $p) {
                    return $p->type !== null && $p->has_docblock_type;
                }
            );
        } else {
            $non_null_param_types = array_filter(
                $storage->params,
                /** @return bool */
                function (FunctionLikeParameter $p) {
                    return $p->type !== null;
                }
            );
        }

        if ($storage instanceof MethodStorage
            && is_string($cased_method_id)
            && $overridden_method_ids
        ) {
            $types_without_docblocks = array_filter(
                $storage->params,
                /** @return bool */
                function (FunctionLikeParameter $p) {
                    return !$p->type || !$p->has_docblock_type;
                }
            );

            if ($types_without_docblocks) {
                $params = $codebase->methods->getMethodParams($cased_method_id, $this);
            }
        }

        $check_stmts = true;

        foreach ($params as $offset => $function_param) {
            $signature_type = $function_param->signature_type;
            $signature_type_location = $function_param->signature_type_location;

            if ($signature_type && $signature_type_location && $signature_type->hasObjectType()) {
                list($start, $end) = $signature_type_location->getSelectionBounds();

                $codebase->analyzer->addOffsetReference(
                    $this->getFilePath(),
                    $start,
                    $end,
                    (string) $signature_type
                );
            }

            if ($signature_type) {
                $signature_type = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    $signature_type,
                    $context->self,
                    $context->self
                );
            }

            if ($function_param->type) {
                $is_signature_type = $function_param->type === $function_param->signature_type;

                if ($is_signature_type
                    && $storage instanceof MethodStorage
                    && $storage->inheritdoc
                    && isset($implemented_docblock_param_types[$offset])
                ) {
                    $param_type = clone $implemented_docblock_param_types[$offset];
                } else {
                    $param_type = clone $function_param->type;
                }

                $param_type = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    $param_type,
                    $context->self,
                    $context->self
                );

                if ($function_param->type_location) {
                    if ($param_type->check(
                        $this,
                        $function_param->type_location,
                        $storage->suppressed_issues,
                        [],
                        false
                    ) === false) {
                        $check_stmts = false;
                    }
                }
            } else {
                if (!$non_null_param_types && isset($implemented_docblock_param_types[$offset])) {
                    $param_type = clone $implemented_docblock_param_types[$offset];

                    $param_type = ExpressionAnalyzer::fleshOutType(
                        $codebase,
                        $param_type,
                        $context->self,
                        $context->self
                    );
                } else {
                    $param_type = Type::getMixed();
                }
            }

            $var_type = $param_type;

            if ($function_param->is_variadic) {
                $var_type = new Type\Union([
                    new Type\Atomic\TArray([
                        Type::getInt(),
                        $param_type,
                    ]),
                ]);
            }

            $context->vars_in_scope['$' . $function_param->name] = $var_type;
            $context->vars_possibly_in_scope['$' . $function_param->name] = true;

            if ($context->collect_references && $function_param->location) {
                $context->unreferenced_vars['$' . $function_param->name] = [
                    $function_param->location->getHash() => $function_param->location
                ];
            }

            if (!$function_param->type_location || !$function_param->location) {
                continue;
            }

            /**
             * @psalm-suppress MixedArrayAccess
             *
             * @var PhpParser\Node\Param
             */
            $parser_param = $this->function->getParams()[$offset];

            if ($signature_type) {
                if (!TypeAnalyzer::isContainedBy(
                    $codebase,
                    $param_type,
                    $signature_type,
                    false,
                    false,
                    $has_scalar_match,
                    $type_coerced,
                    $type_coerced_from_mixed
                ) && !$type_coerced_from_mixed
                ) {
                    if ($codebase->alter_code
                        && isset($project_analyzer->getIssuesToFix()['MismatchingDocblockParamType'])
                    ) {
                        $this->addOrUpdateParamType($project_analyzer, $function_param->name, $signature_type, true);

                        continue;
                    }

                    if (IssueBuffer::accepts(
                        new MismatchingDocblockParamType(
                            'Parameter $' . $function_param->name . ' has wrong type \'' . $param_type .
                                '\', should be \'' . $signature_type . '\'',
                            $function_param->type_location
                        ),
                        $storage->suppressed_issues
                    )) {
                        return false;
                    }

                    if ($signature_type->check(
                        $this,
                        $function_param->type_location,
                        $storage->suppressed_issues,
                        [],
                        false
                    ) === false) {
                        $check_stmts = false;
                    }

                    continue;
                }
            }

            if ($parser_param->default) {
                ExpressionAnalyzer::analyze($statements_analyzer, $parser_param->default, $context);

                $default_type = isset($parser_param->default->inferredType)
                    ? $parser_param->default->inferredType
                    : null;

                if ($default_type
                    && !$default_type->hasMixed()
                    && !TypeAnalyzer::isContainedBy(
                        $codebase,
                        $default_type,
                        $param_type
                    )
                ) {
                    if (IssueBuffer::accepts(
                        new InvalidParamDefault(
                            'Default value type ' . $default_type . ' for argument ' . ($offset + 1)
                                . ' of method ' . $cased_method_id
                                . ' does not match the given type ' . $param_type,
                            $function_param->type_location
                        )
                    )) {
                        // fall through
                    }
                }
            }

            if ($template_types) {
                $substituted_type = clone $param_type;
                if ($substituted_type->check(
                    $this->source,
                    $function_param->type_location,
                    $this->suppressed_issues,
                    [],
                    false
                ) === false) {
                    $check_stmts = false;
                }
            } else {
                if ($param_type->isVoid()) {
                    if (IssueBuffer::accepts(
                        new ReservedWord(
                            'Parameter cannot be void',
                            $function_param->type_location,
                            'void'
                        ),
                        $this->suppressed_issues
                    )) {
                        // fall through
                    }
                }

                if ($param_type->check(
                    $this->source,
                    $function_param->type_location,
                    $this->suppressed_issues,
                    [],
                    false
                ) === false) {
                    $check_stmts = false;
                }
            }

            if ($codebase->collect_references) {
                if ($function_param->type_location !== $function_param->signature_type_location &&
                    $function_param->signature_type_location &&
                    $function_param->signature_type
                ) {
                    if ($function_param->signature_type->check(
                        $this->source,
                        $function_param->signature_type_location,
                        $this->suppressed_issues,
                        [],
                        false
                    ) === false) {
                        $check_stmts = false;
                    }
                }
            }

            if ($function_param->by_ref) {
                // register by ref params as having been used, to avoid false positives
                // @todo change the assignment analysis *just* for byref params
                // so that we don't have to do this
                $context->hasVariable('$' . $function_param->name);
            }

            $statements_analyzer->registerVariable(
                '$' . $function_param->name,
                $function_param->location,
                null
            );
        }

        if ($storage->unused_docblock_params) {
            foreach ($storage->unused_docblock_params as $param_name => $param_location) {
                if (IssueBuffer::accepts(
                    new InvalidDocblockParamName(
                        'Incorrect param name $' . $param_name . ' in docblock for ' . $cased_method_id,
                        $param_location
                    )
                )) {
                }
            }
        }

        if (ReturnTypeAnalyzer::checkReturnType(
            $this->function,
            $project_analyzer,
            $this,
            $storage,
            $context
        ) === false) {
            $check_stmts = false;
        }

        if (!$check_stmts) {
            return false;
        }

        if ($context->collect_initializations || $context->collect_mutations) {
            $statements_analyzer->addSuppressedIssues([
                'DocblockTypeContradiction',
                'InvalidReturnStatement',
                'RedundantCondition',
                'RedundantConditionGivenDocblockType',
                'TypeDoesNotContainNull',
                'TypeDoesNotContainType',
                'LoopInvalidation',
            ]);
        }

        $statements_analyzer->analyze($function_stmts, $context, $global_context, true);

        $this->examineParamTypes($statements_analyzer, $context, $codebase);

        foreach ($storage->params as $offset => $function_param) {
            // only complain if there's no type defined by a parent type
            if (!$function_param->type
                && $function_param->location
                && !isset($implemented_docblock_param_types[$offset])
            ) {
                if ($codebase->alter_code
                    && isset($project_analyzer->getIssuesToFix()['MissingParamType'])
                ) {
                    $possible_type = $this->possible_param_types[$function_param->name] ?? null;

                    if (!$possible_type || $possible_type->hasMixed() || $possible_type->isNull()) {
                        continue;
                    }

                    self::addOrUpdateParamType(
                        $project_analyzer,
                        $function_param->name,
                        $possible_type
                    );

                    continue;
                }

                if ($this->function instanceof Closure) {
                    IssueBuffer::accepts(
                        new MissingClosureParamType(
                            'Parameter $' . $function_param->name . ' has no provided type',
                            $function_param->location
                        ),
                        array_merge($this->suppressed_issues, $storage->suppressed_issues)
                    );
                } else {
                    IssueBuffer::accepts(
                        new MissingParamType(
                            'Parameter $' . $function_param->name . ' has no provided type',
                            $function_param->location
                        ),
                        array_merge($this->suppressed_issues, $storage->suppressed_issues)
                    );
                }
            }
        }

        if ($storage->signature_return_type && $storage->signature_return_type_location) {
            list($start, $end) = $storage->signature_return_type_location->getSelectionBounds();

            $codebase->analyzer->addOffsetReference(
                $this->getFilePath(),
                $start,
                $end,
                (string) $storage->signature_return_type
            );
        }

        if ($this->function instanceof Closure) {
            $this->verifyReturnType(
                $statements_analyzer,
                $storage->return_type,
                $this->source->getFQCLN(),
                $storage->return_type_location
            );

            $closure_yield_types = [];

            $ignore_nullable_issues = false;
            $ignore_falsable_issues = false;

            $closure_return_types = ReturnTypeCollector::getReturnTypes(
                $this->function->stmts,
                $closure_yield_types,
                $ignore_nullable_issues,
                $ignore_falsable_issues,
                true
            );

            if ($closure_return_types) {
                $closure_return_type = new Type\Union($closure_return_types);

                if (!$storage->return_type
                    || $storage->return_type->hasMixed()
                    || TypeAnalyzer::isContainedBy(
                        $codebase,
                        $closure_return_type,
                        $storage->return_type
                    )
                ) {
                    if ($this->function->inferredType) {
                        /** @var Type\Atomic\Fn */
                        $closure_atomic = $this->function->inferredType->getTypes()['Closure'];
                        $closure_atomic->return_type = $closure_return_type;
                    }
                }
            }
        }

        if ($context->collect_references
            && !$context->collect_initializations
            && $codebase->find_unused_variables
            && $context->check_variables
        ) {
            foreach ($statements_analyzer->getUnusedVarLocations() as list($var_name, $original_location)) {
                if (!array_key_exists(substr($var_name, 1), $storage->param_types)) {
                    continue;
                }

                if (strpos($var_name, '$_') === 0 || (strpos($var_name, '$unused') === 0 && $var_name !== '$unused')) {
                    continue;
                }

                $position = array_search(substr($var_name, 1), array_keys($storage->param_types), true);

                if ($position === false) {
                    throw new \UnexpectedValueException('$position should not be false here');
                }

                if ($storage->params[$position]->by_ref) {
                    continue;
                }

                if (!($storage instanceof MethodStorage)
                    || $storage->visibility === ClassLikeAnalyzer::VISIBILITY_PRIVATE
                ) {
                    if ($this->function instanceof Closure) {
                        if (IssueBuffer::accepts(
                            new UnusedClosureParam(
                                'Param ' . $var_name . ' is never referenced in this method',
                                $original_location
                            ),
                            $this->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    } else {
                        if (IssueBuffer::accepts(
                            new UnusedParam(
                                'Param ' . $var_name . ' is never referenced in this method',
                                $original_location
                            ),
                            $this->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    }
                } else {
                    $fq_class_name = (string)$context->self;

                    $class_storage = $codebase->classlike_storage_provider->get($fq_class_name);

                    $method_name_lc = strtolower($storage->cased_name);

                    if ($storage->abstract || !isset($class_storage->overridden_method_ids[$method_name_lc])) {
                        continue;
                    }

                    $parent_method_id = end($class_storage->overridden_method_ids[$method_name_lc]);

                    if ($parent_method_id) {
                        $parent_method_storage = $codebase->methods->getStorage($parent_method_id);

                        // if the parent method has a param at that position and isn't abstract
                        if (!$parent_method_storage->abstract
                            && isset($parent_method_storage->params[$position])
                        ) {
                            continue;
                        }
                    }

                    $storage->unused_params[$position] = $original_location;
                }
            }

            if ($storage instanceof MethodStorage
                && $class_storage
                && $storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PRIVATE
            ) {
                $method_id_lc = strtolower($this->getMethodId());

                foreach ($storage->params as $i => $_) {
                    if (!isset($storage->unused_params[$i])) {
                        $codebase->file_reference_provider->addMethodParamUse(
                            $method_id_lc,
                            $i,
                            $method_id_lc
                        );

                        /** @var ClassMethod $this->function */
                        $method_name_lc = strtolower($storage->cased_name);

                        if (!isset($class_storage->overridden_method_ids[$method_name_lc])) {
                            continue;
                        }

                        foreach ($class_storage->overridden_method_ids[$method_name_lc] as $parent_method_id) {
                            $codebase->file_reference_provider->addMethodParamUse(
                                strtolower($parent_method_id),
                                $i,
                                $method_id_lc
                            );
                        }
                    }
                }
            }
        }

        foreach ($statements_analyzer->getUncaughtThrows($context) as $possibly_thrown_exception => $codelocations) {
            $is_expected = false;

            foreach ($storage->throws as $expected_exception => $_) {
                if ($expected_exception === $possibly_thrown_exception
                    || $codebase->classExtends($possibly_thrown_exception, $expected_exception)
                ) {
                    $is_expected = true;
                    break;
                }
            }

            if (!$is_expected) {
                foreach ($codelocations as $codelocation) {
                    // issues are suppressed in ThrowAnalyzer, CallAnalyzer, etc.
                    if (IssueBuffer::accepts(
                        new MissingThrowsDocblock(
                            $possibly_thrown_exception . ' is thrown but not caught - please either catch'
                                . ' or add a @throws annotation',
                            $codelocation
                        )
                    )) {
                        // fall through
                    }
                }
            }
        }

        if ($add_mutations) {
            if ($this->return_vars_in_scope !== null) {
                $context->vars_in_scope = TypeAnalyzer::combineKeyedTypes(
                    $context->vars_in_scope,
                    $this->return_vars_in_scope
                );
            }

            if ($this->return_vars_possibly_in_scope !== null) {
                $context->vars_possibly_in_scope = array_merge(
                    $context->vars_possibly_in_scope,
                    $this->return_vars_possibly_in_scope
                );
            }

            foreach ($context->vars_in_scope as $var => $_) {
                if (strpos($var, '$this->') !== 0 && $var !== '$this') {
                    unset($context->vars_in_scope[$var]);
                }
            }

            foreach ($context->vars_possibly_in_scope as $var => $_) {
                if (strpos($var, '$this->') !== 0 && $var !== '$this') {
                    unset($context->vars_possibly_in_scope[$var]);
                }
            }

            if ($hash && $real_method_id && $this instanceof MethodAnalyzer) {
                $new_hash = md5($real_method_id . '::' . $context->getScopeSummary());

                if ($new_hash === $hash) {
                    self::$no_effects_hashes[$hash] = true;
                }
            }
        }

        return null;
    }
157491
public function checkContext(ContextInterface $context)
    {
        try {
            $checkedCode = $this->preprocessor->preprocess($context->getCheckedCode());
            $parsedStatements = $this->parser->parse($checkedCode);
            $this->traverser->traverse($parsedStatements, $context, $this->lexer->getTokens());
        } catch (\Exception $e) {
            $context->addError(new CheckError($e->getMessage()));
        } catch (\ParseException $e) {
            $context->addError(new CheckError($e->getMessage(), $e->getLine()));
        }
    }
523087
public static function analyzeClassConst(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\ClassConstFetch $stmt,
        Context $context
    ) {
        $codebase = $statements_analyzer->getCodebase();

        if ($stmt->class instanceof PhpParser\Node\Name) {
            if ($context->check_consts
                || ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class')
            ) {
                $first_part_lc = strtolower($stmt->class->parts[0]);

                if ($first_part_lc === 'self' || $first_part_lc === 'static') {
                    if (!$context->self) {
                        throw new \UnexpectedValueException('$context->self cannot be null');
                    }

                    $fq_class_name = (string)$context->self;
                } elseif ($first_part_lc === 'parent') {
                    $fq_class_name = $statements_analyzer->getParentFQCLN();

                    if ($fq_class_name === null) {
                        if (IssueBuffer::accepts(
                            new ParentNotFound(
                                'Cannot check property fetch on parent as this class does not extend another',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }

                        return;
                    }
                } else {
                    $fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
                        $stmt->class,
                        $statements_analyzer->getAliases()
                    );

                    if ($stmt->name instanceof PhpParser\Node\Identifier) {
                        if (!$context->inside_class_exists || $stmt->name->name !== 'class') {
                            if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                                $statements_analyzer,
                                $fq_class_name,
                                new CodeLocation($statements_analyzer->getSource(), $stmt->class),
                                $statements_analyzer->getSuppressedIssues(),
                                false,
                                true
                            ) === false) {
                                return false;
                            }
                        }
                    }
                }

                if ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class') {
                    $stmt->inferredType = Type::getLiteralClassString($fq_class_name);

                    if ($codebase->store_node_types) {
                        $codebase->analyzer->addNodeReference(
                            $statements_analyzer->getFilePath(),
                            $stmt->class,
                            $fq_class_name
                        );
                    }

                    return null;
                }

                // if we're ignoring that the class doesn't exist, exit anyway
                if (!$codebase->classOrInterfaceExists($fq_class_name)) {
                    $stmt->inferredType = Type::getMixed();

                    return null;
                }

                if ($codebase->store_node_types) {
                    $codebase->analyzer->addNodeReference(
                        $statements_analyzer->getFilePath(),
                        $stmt->class,
                        $fq_class_name
                    );
                }

                if (!$stmt->name instanceof PhpParser\Node\Identifier) {
                    return null;
                }

                $const_id = $fq_class_name . '::' . $stmt->name;

                if ($codebase->store_node_types) {
                    $codebase->analyzer->addNodeReference(
                        $statements_analyzer->getFilePath(),
                        $stmt->name,
                        $const_id
                    );
                }

                if ($fq_class_name === $context->self
                    || (
                        $statements_analyzer->getSource()->getSource() instanceof TraitAnalyzer &&
                        $fq_class_name === $statements_analyzer->getSource()->getFQCLN()
                    )
                ) {
                    $class_visibility = \ReflectionProperty::IS_PRIVATE;
                } elseif ($context->self &&
                    $codebase->classExtends($context->self, $fq_class_name)
                ) {
                    $class_visibility = \ReflectionProperty::IS_PROTECTED;
                } else {
                    $class_visibility = \ReflectionProperty::IS_PUBLIC;
                }

                $class_constants = $codebase->classlikes->getConstantsForClass(
                    $fq_class_name,
                    $class_visibility
                );

                if (!isset($class_constants[$stmt->name->name]) && $first_part_lc !== 'static') {
                    $all_class_constants = [];

                    if ($fq_class_name !== $context->self) {
                        $all_class_constants = $codebase->classlikes->getConstantsForClass(
                            $fq_class_name,
                            \ReflectionProperty::IS_PRIVATE
                        );
                    }

                    if ($all_class_constants && isset($all_class_constants[$stmt->name->name])) {
                        if (IssueBuffer::accepts(
                            new InaccessibleClassConstant(
                                'Constant ' . $const_id . ' is not visible in this context',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    } else {
                        if (IssueBuffer::accepts(
                            new UndefinedConstant(
                                'Constant ' . $const_id . ' is not defined',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    }

                    return false;
                }

                if ($context->calling_method_id) {
                    $codebase->file_reference_provider->addMethodReferenceToClassMember(
                        $context->calling_method_id,
                        strtolower($fq_class_name) . '::' . $stmt->name->name
                    );
                }

                $class_const_storage = $codebase->classlike_storage_provider->get($fq_class_name);

                if (isset($class_const_storage->deprecated_constants[$stmt->name->name])) {
                    if (IssueBuffer::accepts(
                        new DeprecatedConstant(
                            'Constant ' . $const_id . ' is deprecated',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }
                }

                if (isset($class_constants[$stmt->name->name]) && $first_part_lc !== 'static') {
                    $stmt->inferredType = clone $class_constants[$stmt->name->name];
                    $context->vars_in_scope[$const_id] = $stmt->inferredType;
                } else {
                    $stmt->inferredType = Type::getMixed();
                }

                return null;
            }
        } elseif ($stmt->name instanceof PhpParser\Node\Identifier && $stmt->name->name === 'class') {
            ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context);
            $lhs_type = $stmt->class->inferredType;

            $class_string_types = [];

            $has_mixed_or_object = false;

            if ($lhs_type) {
                foreach ($lhs_type->getTypes() as $lhs_atomic_type) {
                    if ($lhs_atomic_type instanceof Type\Atomic\TNamedObject) {
                        $class_string_types[] = new Type\Atomic\TClassString(
                            $lhs_atomic_type->value,
                            clone $lhs_atomic_type
                        );
                    } elseif ($lhs_atomic_type instanceof Type\Atomic\TObject
                        || $lhs_atomic_type instanceof Type\Atomic\TMixed
                    ) {
                        $has_mixed_or_object = true;
                    }
                }
            }

            if ($has_mixed_or_object) {
                $stmt->inferredType = new Type\Union([new Type\Atomic\TClassString()]);
            } elseif ($class_string_types) {
                $stmt->inferredType = new Type\Union($class_string_types);
            } else {
                $stmt->inferredType = Type::getMixed();
            }

            return;
        }

        $stmt->inferredType = Type::getMixed();

        if ($stmt->class instanceof PhpParser\Node\Expr) {
            if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context) === false) {
                return false;
            }
        }

        return null;
    }
416203
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\Array_ $stmt,
        Context $context
    ) {
        // if the array is empty, this special type allows us to match any other array type against it
        if (empty($stmt->items)) {
            $stmt->inferredType = Type::getEmptyArray();

            return null;
        }

        $item_key_atomic_types = [];
        $item_value_atomic_types = [];

        $property_types = [];
        $class_strings = [];

        $can_create_objectlike = true;

        $array_keys = [];

        $int_offset_diff = 0;

        $codebase = $statements_analyzer->getCodebase();

        /** @var int $int_offset */
        foreach ($stmt->items as $int_offset => $item) {
            if ($item === null) {
                continue;
            }

            $item_key_value = null;

            if ($item->key) {
                if (ExpressionAnalyzer::analyze($statements_analyzer, $item->key, $context) === false) {
                    return false;
                }

                if (isset($item->key->inferredType)) {
                    $key_type = $item->key->inferredType;

                    if ($key_type->isNull()) {
                        $key_type = Type::getString('');
                    }

                    if ($item->key instanceof PhpParser\Node\Scalar\String_
                        && preg_match('/^(0|[1-9][0-9]*)$/', $item->key->value)
                    ) {
                        $key_type = Type::getInt(false, (int) $item->key->value);
                    }

                    $item_key_atomic_types = array_merge($item_key_atomic_types, array_values($key_type->getTypes()));

                    if ($key_type->isSingleStringLiteral()) {
                        $item_key_literal_type = $key_type->getSingleStringLiteral();
                        $item_key_value = $item_key_literal_type->value;

                        if ($item_key_literal_type instanceof Type\Atomic\TLiteralClassString) {
                            $class_strings[$item_key_value] = true;
                        }
                    } elseif ($key_type->isSingleIntLiteral()) {
                        $item_key_value = $key_type->getSingleIntLiteral()->value;

                        if ($item_key_value > $int_offset + $int_offset_diff) {
                            $int_offset_diff = $item_key_value - $int_offset;
                        }
                    }
                }
            } else {
                $item_key_value = $int_offset + $int_offset_diff;
                $item_key_atomic_types[] = new Type\Atomic\TInt();
            }

            if ($item_key_value !== null) {
                if (isset($array_keys[$item_key_value])) {
                    if (IssueBuffer::accepts(
                        new DuplicateArrayKey(
                            'Key \'' . $item_key_value . '\' already exists on array',
                            new CodeLocation($statements_analyzer->getSource(), $item)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }
                }

                $array_keys[$item_key_value] = true;
            }

            if (ExpressionAnalyzer::analyze($statements_analyzer, $item->value, $context) === false) {
                return false;
            }

            if ($item_value_atomic_types && !$can_create_objectlike) {
                continue;
            }

            if (isset($item->value->inferredType)) {
                if ($item_key_value !== null && count($property_types) <= 50) {
                    $property_types[$item_key_value] = $item->value->inferredType;
                } else {
                    $can_create_objectlike = false;
                }

                $item_value_atomic_types = array_merge(
                    $item_value_atomic_types,
                    array_values($item->value->inferredType->getTypes())
                );
            } else {
                $item_value_atomic_types[] = new Type\Atomic\TMixed();

                if ($item_key_value !== null && count($property_types) <= 50) {
                    $property_types[$item_key_value] = Type::getMixed();
                } else {
                    $can_create_objectlike = false;
                }
            }
        }

        if ($item_key_atomic_types) {
            $item_key_type = TypeCombination::combineTypes(
                $item_key_atomic_types,
                $codebase,
                false,
                true,
                30
            );
        } else {
            $item_key_type = null;
        }

        if ($item_value_atomic_types) {
            $item_value_type = TypeCombination::combineTypes(
                $item_value_atomic_types,
                $codebase,
                false,
                true,
                30
            );
        } else {
            $item_value_type = null;
        }
        // if this array looks like an object-like array, let's return that instead
        if ($item_value_type
            && $item_key_type
            && ($item_key_type->hasString() || $item_key_type->hasInt())
            && $can_create_objectlike
        ) {
            $object_like = new Type\Atomic\ObjectLike($property_types, $class_strings);
            $object_like->sealed = true;

            $stmt->inferredType = new Type\Union([$object_like]);

            return null;
        }

        $array_type = new Type\Atomic\TNonEmptyArray([
            $item_key_type ?: new Type\Union([new TInt, new TString]),
            $item_value_type ?: Type::getMixed(),
        ]);

        $array_type->count = count($stmt->items);

        $stmt->inferredType = new Type\Union([
            $array_type,
        ]);

        return null;
    }
464156
public function read(\PDOStatement $stmt)
    {

        $this->unfoundPrecedence=array();

        $preparedReader = new PreparedOperations($this->FQuery);


        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
            // loop over joined faces
            foreach ($preparedReader->getPreparedFaces() as $basePath => $preparedFace) {

                $identity = $preparedFace->rowIdentity($row, $basePath);

                if ($identity) {
                    // if already instantiated then get it from ikeeper and try the forwards
                    if ($this->instancesKeeper->hasInstance($preparedFace->getFace()->getClass(), $identity)) {
                        $instance = $this->instancesKeeper->getInstance($preparedFace->getFace()->getClass(), $identity);

                        $preparedFace->runOperations($instance,$row,$this->instancesKeeper, $this->unfoundPrecedence);

                        if (!$this->resultSet->pathHasIdentity($basePath, $identity)) {
                            $this->resultSet->addInstanceByPath($basePath, $instance, $identity);
                        }

                        // else create the instance and hydrate it
                    } else {
                        $instance = $this->createInstance($preparedFace->getFace());
                        $this->instancesKeeper->addInstance($instance, $identity);
                        $this->resultSet->addInstanceByPath($basePath, $instance, $identity);

                        $preparedFace->runOperations($instance,$row,$this->instancesKeeper, $this->unfoundPrecedence);

                    }
                }

            }


        }

        // set unset instances. To be improved ?
        foreach ($this->unfoundPrecedence as $unfound) {

            if(!$this->instancesKeeper->hasInstance($unfound['elementToSet']->getClass(), $unfound['identityOfElement'])){

                var_dump($unfound['elementToSet']->getClass());
                var_dump($unfound['identityOfElement']);
                var_dump(get_class($instance));

            }

            $unfoundInstance = $this->instancesKeeper->getInstance($unfound['elementToSet']->getClass(), $unfound['identityOfElement']);
            $unfound['instance']->faceSetter($unfound['elementToSet'], $unfoundInstance);
        }


        return $this->resultSet;

    }
1250110
protected void executeStatements(TestContext context) {
        for (String stmt : statements)  {
            try {
                final String toExecute;

                if (stmt.trim().endsWith(";")) {
                    toExecute = context.replaceDynamicContentInString(stmt.trim().substring(0, stmt.trim().length()-1));
                } else {
                    toExecute = context.replaceDynamicContentInString(stmt.trim());
                }

                if (log.isDebugEnabled()) {
                    log.debug("Executing SQL statement: " + toExecute);
                }

                getJdbcTemplate().execute(toExecute);

                log.info("SQL statement execution successful");
            } catch (Exception e) {
                if (ignoreErrors) {
                    log.error("Ignoring error while executing SQL statement: " + e.getLocalizedMessage());
                    continue;
                } else {
                    throw new CitrusRuntimeException(e);
                }
            }
        }
    }
995758
def get_statement_by_name(stmt_name):
    """"""
    stmt_classes = get_all_descendants(Statement)
    for stmt_class in stmt_classes:
        if stmt_class.__name__.lower() == stmt_name.lower():
            return stmt_class
    raise NotAStatementName('\"%s\" is not recognized as a statement type!'
                            % stmt_name)
744699
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr $stmt,
        Context $context,
        $array_assignment = false,
        Context $global_context = null
    ) {
        $codebase = $statements_analyzer->getCodebase();

        if ($stmt instanceof PhpParser\Node\Expr\Variable) {
            if (VariableFetchAnalyzer::analyze(
                $statements_analyzer,
                $stmt,
                $context,
                false,
                null,
                $array_assignment
            ) === false
            ) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Assign) {
            $assignment_type = AssignmentAnalyzer::analyze(
                $statements_analyzer,
                $stmt->var,
                $stmt->expr,
                null,
                $context,
                (string)$stmt->getDocComment(),
                $stmt->getLine()
            );

            if ($assignment_type === false) {
                return false;
            }

            $stmt->inferredType = $assignment_type;
        } elseif ($stmt instanceof PhpParser\Node\Expr\AssignOp) {
            if (AssignmentAnalyzer::analyzeAssignmentOperation($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\MethodCall) {
            if (MethodCallAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\StaticCall) {
            if (StaticCallAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\ConstFetch) {
            ConstFetchAnalyzer::analyze($statements_analyzer, $stmt, $context);
        } elseif ($stmt instanceof PhpParser\Node\Scalar\String_) {
            $stmt->inferredType = Type::getString($stmt->value);
        } elseif ($stmt instanceof PhpParser\Node\Scalar\EncapsedStringPart) {
            // do nothing
        } elseif ($stmt instanceof PhpParser\Node\Scalar\MagicConst) {
            switch (strtolower($stmt->getName())) {
                case '__line__':
                    $stmt->inferredType = Type::getInt();
                    break;

                case '__class__':
                    if (!$context->self) {
                        if (IssueBuffer::accepts(
                            new UndefinedConstant(
                                'Cannot get __class__ outside a class',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }

                        $stmt->inferredType = Type::getClassString();
                        break;
                    }

                    $stmt->inferredType = Type::getLiteralClassString($context->self);
                    break;

                case '__namespace__':
                    $namespace = $statements_analyzer->getNamespace();
                    if ($namespace === null &&
                    IssueBuffer::accepts(
                        new UndefinedConstant(
                            'Cannot get __namespace__ outside a namespace',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }

                    $stmt->inferredType = Type::getString($namespace);
                    break;

                case '__file__':
                case '__dir__':
                case '__function__':
                case '__trait__':
                case '__method__':
                    $stmt->inferredType = Type::getString();
                    break;
            }
        } elseif ($stmt instanceof PhpParser\Node\Scalar\LNumber) {
            $stmt->inferredType = Type::getInt(false, $stmt->value);
        } elseif ($stmt instanceof PhpParser\Node\Scalar\DNumber) {
            $stmt->inferredType = Type::getFloat($stmt->value);
        } elseif ($stmt instanceof PhpParser\Node\Expr\UnaryMinus ||
            $stmt instanceof PhpParser\Node\Expr\UnaryPlus
        ) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            if (!isset($stmt->expr->inferredType)) {
                $stmt->inferredType = new Type\Union([new TInt, new TFloat]);
            } elseif ($stmt->expr->inferredType->isMixed()) {
                $stmt->inferredType = Type::getMixed();
            } else {
                $acceptable_types = [];

                foreach ($stmt->expr->inferredType->getTypes() as $type_part) {
                    if ($type_part instanceof TInt || $type_part instanceof TFloat) {
                        if ($type_part instanceof Type\Atomic\TLiteralInt
                            && $stmt instanceof PhpParser\Node\Expr\UnaryMinus
                        ) {
                            $type_part->value = -$type_part->value;
                        } elseif ($type_part instanceof Type\Atomic\TLiteralFloat
                            && $stmt instanceof PhpParser\Node\Expr\UnaryMinus
                        ) {
                            $type_part->value = -$type_part->value;
                        }

                        $acceptable_types[] = $type_part;
                    } elseif ($type_part instanceof TString) {
                        $acceptable_types[] = new TInt;
                        $acceptable_types[] = new TFloat;
                    } else {
                        $acceptable_types[] = new TInt;
                    }
                }

                $stmt->inferredType = new Type\Union($acceptable_types);
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Isset_) {
            self::analyzeIsset($statements_analyzer, $stmt, $context);
            $stmt->inferredType = Type::getBool();
        } elseif ($stmt instanceof PhpParser\Node\Expr\ClassConstFetch) {
            if (ConstFetchAnalyzer::analyzeClassConst($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\PropertyFetch) {
            if (PropertyFetchAnalyzer::analyzeInstance($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\StaticPropertyFetch) {
            if (PropertyFetchAnalyzer::analyzeStatic($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\BitwiseNot) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            if (!isset($stmt->expr->inferredType)) {
                $stmt->inferredType = new Type\Union([new TInt(), new TString()]);
            } elseif ($stmt->expr->inferredType->isMixed()) {
                $stmt->inferredType = Type::getMixed();
            } else {
                $acceptable_types = [];
                $unacceptable_type = null;
                $has_valid_operand = false;

                foreach ($stmt->expr->inferredType->getTypes() as $type_string => $type_part) {
                    if ($type_part instanceof TInt || $type_part instanceof TString) {
                        if ($type_part instanceof Type\Atomic\TLiteralInt) {
                            $type_part->value = ~$type_part->value;
                        } elseif ($type_part instanceof Type\Atomic\TLiteralString) {
                            $type_part->value = ~$type_part->value;
                        }

                        $acceptable_types[] = $type_part;
                        $has_valid_operand = true;
                    } elseif ($type_part instanceof TFloat) {
                        $type_part = ($type_part instanceof Type\Atomic\TLiteralFloat) ?
                            new Type\Atomic\TLiteralInt(~$type_part->value) :
                            new TInt;

                        $stmt->expr->inferredType->removeType($type_string);
                        $stmt->expr->inferredType->addType($type_part);

                        $acceptable_types[] = $type_part;
                        $has_valid_operand = true;
                    } elseif (!$unacceptable_type) {
                        $unacceptable_type = $type_part;
                    }
                }

                if ($unacceptable_type) {
                    $message = 'Cannot negate a non-numeric non-string type ' . $unacceptable_type;
                    if ($has_valid_operand) {
                        if (IssueBuffer::accepts(
                            new PossiblyInvalidOperand(
                                $message,
                                new CodeLocation($statements_analyzer, $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    } else {
                        if (IssueBuffer::accepts(
                            new InvalidOperand(
                                $message,
                                new CodeLocation($statements_analyzer, $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    }

                    $stmt->inferredType = Type::getMixed();
                } else {
                    $stmt->inferredType = new Type\Union($acceptable_types);
                }
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\BinaryOp) {
            if (BinaryOpAnalyzer::analyze(
                $statements_analyzer,
                $stmt,
                $context
            ) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\PostInc ||
            $stmt instanceof PhpParser\Node\Expr\PostDec ||
            $stmt instanceof PhpParser\Node\Expr\PreInc ||
            $stmt instanceof PhpParser\Node\Expr\PreDec
        ) {
            if (self::analyze($statements_analyzer, $stmt->var, $context) === false) {
                return false;
            }

            if (isset($stmt->var->inferredType)) {
                $return_type = null;

                $fake_right_expr = new PhpParser\Node\Scalar\LNumber(1, $stmt->getAttributes());
                $fake_right_expr->inferredType = Type::getInt();

                BinaryOpAnalyzer::analyzeNonDivArithmeticOp(
                    $statements_analyzer,
                    $stmt->var,
                    $fake_right_expr,
                    $stmt,
                    $return_type,
                    $context
                );

                $stmt->inferredType = clone $stmt->var->inferredType;
                $stmt->inferredType->from_calculation = true;

                foreach ($stmt->inferredType->getTypes() as $atomic_type) {
                    if ($atomic_type instanceof Type\Atomic\TLiteralInt) {
                        $stmt->inferredType->addType(new Type\Atomic\TInt);
                    } elseif ($atomic_type instanceof Type\Atomic\TLiteralFloat) {
                        $stmt->inferredType->addType(new Type\Atomic\TFloat);
                    }
                }

                $var_id = self::getArrayVarId($stmt->var, null);

                if ($var_id && isset($context->vars_in_scope[$var_id])) {
                    $context->vars_in_scope[$var_id] = $stmt->inferredType;

                    if ($context->collect_references && $stmt->var instanceof PhpParser\Node\Expr\Variable) {
                        $location = new CodeLocation($statements_analyzer, $stmt->var);
                        $context->assigned_var_ids[$var_id] = true;
                        $context->possibly_assigned_var_ids[$var_id] = true;
                        $statements_analyzer->registerVariableAssignment(
                            $var_id,
                            $location
                        );
                        $context->unreferenced_vars[$var_id] = [$location->getHash() => $location];
                    }
                }
            } else {
                $stmt->inferredType = Type::getMixed();
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\New_) {
            if (NewAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Array_) {
            if (ArrayAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Scalar\Encapsed) {
            if (self::analyzeEncapsulatedString($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\FuncCall) {
            if (FunctionCallAnalyzer::analyze(
                $statements_analyzer,
                $stmt,
                $context
            ) === false
            ) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Ternary) {
            if (TernaryAnalyzer::analyze($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\BooleanNot) {
            if (self::analyzeBooleanNot($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Empty_) {
            self::analyzeEmpty($statements_analyzer, $stmt, $context);
        } elseif ($stmt instanceof PhpParser\Node\Expr\Closure) {
            $closure_analyzer = new ClosureAnalyzer($stmt, $statements_analyzer);

            if (self::analyzeClosureUses($statements_analyzer, $stmt, $context) === false) {
                return false;
            }

            $use_context = new Context($context->self);
            $use_context->collect_references = $codebase->collect_references;

            if (!$statements_analyzer->isStatic()) {
                if ($context->collect_mutations &&
                    $context->self &&
                    $codebase->classExtends(
                        $context->self,
                        (string)$statements_analyzer->getFQCLN()
                    )
                ) {
                    $use_context->vars_in_scope['$this'] = clone $context->vars_in_scope['$this'];
                } elseif ($context->self) {
                    $use_context->vars_in_scope['$this'] = new Type\Union([new TNamedObject($context->self)]);
                }
            }

            foreach ($context->vars_in_scope as $var => $type) {
                if (strpos($var, '$this->') === 0) {
                    $use_context->vars_in_scope[$var] = clone $type;
                }
            }

            foreach ($context->vars_possibly_in_scope as $var => $_) {
                if (strpos($var, '$this->') === 0) {
                    $use_context->vars_possibly_in_scope[$var] = true;
                }
            }

            $byref_uses = [];

            foreach ($stmt->uses as $use) {
                if (!is_string($use->var->name)) {
                    continue;
                }

                $use_var_id = '$' . $use->var->name;

                if ($use->byRef) {
                    $byref_uses[$use_var_id] = true;
                }

                // insert the ref into the current context if passed by ref, as whatever we're passing
                // the closure to could execute it straight away.
                if (!$context->hasVariable($use_var_id, $statements_analyzer) && $use->byRef) {
                    $context->vars_in_scope[$use_var_id] = Type::getMixed();
                }

                $use_context->vars_in_scope[$use_var_id] =
                    $context->hasVariable($use_var_id, $statements_analyzer) && !$use->byRef
                    ? clone $context->vars_in_scope[$use_var_id]
                    : Type::getMixed();

                $use_context->vars_possibly_in_scope[$use_var_id] = true;
            }

            $use_context->calling_method_id = $context->calling_method_id;

            $closure_analyzer->analyze($use_context, $context, false, $byref_uses);

            if (!isset($stmt->inferredType)) {
                $stmt->inferredType = Type::getClosure();
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\ArrayDimFetch) {
            if (ArrayFetchAnalyzer::analyze(
                $statements_analyzer,
                $stmt,
                $context
            ) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Int_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $stmt->inferredType = Type::getInt();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Double) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $stmt->inferredType = Type::getFloat();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Bool_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $stmt->inferredType = Type::getBool();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\String_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            if (isset($stmt->expr->inferredType)) {
                self::castStringAttempt($statements_analyzer, $stmt->expr);
            }

            $stmt->inferredType = Type::getString();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Object_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $stmt->inferredType = new Type\Union([new TNamedObject('stdClass')]);
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Array_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $permissible_atomic_types = [];
            $all_permissible = false;

            if (isset($stmt->expr->inferredType)) {
                $all_permissible = true;

                foreach ($stmt->expr->inferredType->getTypes() as $type) {
                    if ($type instanceof Scalar) {
                        $permissible_atomic_types[] = new ObjectLike([new Type\Union([$type])]);
                    } elseif ($type instanceof TNull) {
                        $permissible_atomic_types[] = new TArray([Type::getEmpty(), Type::getEmpty()]);
                    } elseif ($type instanceof TArray) {
                        $permissible_atomic_types[] = clone $type;
                    } elseif ($type instanceof ObjectLike) {
                        $permissible_atomic_types[] = clone $type;
                    } else {
                        $all_permissible = false;
                        break;
                    }
                }
            }

            if ($all_permissible) {
                $stmt->inferredType = TypeCombination::combineTypes($permissible_atomic_types);
            } else {
                $stmt->inferredType = Type::getArray();
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Cast\Unset_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            $stmt->inferredType = Type::getNull();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Clone_) {
            self::analyzeClone($statements_analyzer, $stmt, $context);
        } elseif ($stmt instanceof PhpParser\Node\Expr\Instanceof_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }

            if ($stmt->class instanceof PhpParser\Node\Expr) {
                if (self::analyze($statements_analyzer, $stmt->class, $context) === false) {
                    return false;
                }
            } elseif (!in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)
            ) {
                if ($context->check_classes) {
                    $fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
                        $stmt->class,
                        $statements_analyzer->getAliases()
                    );

                    if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                        $statements_analyzer,
                        $fq_class_name,
                        new CodeLocation($statements_analyzer->getSource(), $stmt->class),
                        $statements_analyzer->getSuppressedIssues(),
                        false
                    ) === false) {
                        return false;
                    }

                    if ($codebase->store_node_types
                        && $fq_class_name
                        && $codebase->classOrInterfaceExists($fq_class_name)
                    ) {
                        $codebase->analyzer->addNodeReference(
                            $statements_analyzer->getFilePath(),
                            $stmt->class,
                            $fq_class_name
                        );
                    }
                }
            }

            $stmt->inferredType = Type::getBool();
        } elseif ($stmt instanceof PhpParser\Node\Expr\Exit_) {
            if ($stmt->expr) {
                if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                    return false;
                }
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Include_) {
            IncludeAnalyzer::analyze($statements_analyzer, $stmt, $context, $global_context);
        } elseif ($stmt instanceof PhpParser\Node\Expr\Eval_) {
            $context->check_classes = false;
            $context->check_variables = false;

            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\AssignRef) {
            if (AssignmentAnalyzer::analyzeAssignmentRef($statements_analyzer, $stmt, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\ErrorSuppress) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }
            $stmt->inferredType = isset($stmt->expr->inferredType) ? $stmt->expr->inferredType : null;
        } elseif ($stmt instanceof PhpParser\Node\Expr\ShellExec) {
            if (IssueBuffer::accepts(
                new ForbiddenCode(
                    'Use of shell_exec',
                    new CodeLocation($statements_analyzer->getSource(), $stmt)
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                // continue
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Print_) {
            if (self::analyze($statements_analyzer, $stmt->expr, $context) === false) {
                return false;
            }
        } elseif ($stmt instanceof PhpParser\Node\Expr\Yield_) {
            self::analyzeYield($statements_analyzer, $stmt, $context);
        } elseif ($stmt instanceof PhpParser\Node\Expr\YieldFrom) {
            self::analyzeYieldFrom($statements_analyzer, $stmt, $context);
        } elseif ($stmt instanceof PhpParser\Node\Expr\Error) {
            // do nothing
        } else {
            if (IssueBuffer::accepts(
                new UnrecognizedExpression(
                    'Psalm does not understand ' . get_class($stmt),
                    new CodeLocation($statements_analyzer->getSource(), $stmt)
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                return false;
            }
        }

        if (!$context->inside_conditional
            && ($stmt instanceof PhpParser\Node\Expr\BinaryOp
                || $stmt instanceof PhpParser\Node\Expr\Instanceof_
                || $stmt instanceof PhpParser\Node\Expr\Assign
                || $stmt instanceof PhpParser\Node\Expr\BooleanNot
                || $stmt instanceof PhpParser\Node\Expr\Empty_
                || $stmt instanceof PhpParser\Node\Expr\Isset_
                || $stmt instanceof PhpParser\Node\Expr\FuncCall)
        ) {
            AssertionFinder::scrapeAssertions(
                $stmt,
                $context->self,
                $statements_analyzer,
                $codebase
            );
        }

        $plugin_classes = $codebase->config->after_expression_checks;

        if ($plugin_classes) {
            $file_manipulations = [];

            foreach ($plugin_classes as $plugin_fq_class_name) {
                if ($plugin_fq_class_name::afterExpressionAnalysis(
                    $stmt,
                    $context,
                    $statements_analyzer->getSource(),
                    $codebase,
                    $file_manipulations
                ) === false) {
                    return false;
                }
            }

            if ($file_manipulations) {
                /** @psalm-suppress MixedTypeCoercion */
                FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
            }
        }

        return null;
    }
369918
private static function handleArrayAddition(
        StatementsAnalyzer $statements_analyzer,
        array $args,
        Context $context
    ) {
        $array_arg = $args[0]->value;

        if (ExpressionAnalyzer::analyze(
            $statements_analyzer,
            $array_arg,
            $context
        ) === false) {
            return false;
        }

        if (isset($array_arg->inferredType) && $array_arg->inferredType->hasArray()) {
            /** @var TArray|ObjectLike */
            $array_type = $array_arg->inferredType->getTypes()['array'];

            if ($array_type instanceof ObjectLike) {
                $array_type = $array_type->getGenericArrayType();
            }

            $by_ref_type = new Type\Union([clone $array_type]);

            foreach ($args as $argument_offset => $arg) {
                if ($argument_offset === 0) {
                    continue;
                }

                if (ExpressionAnalyzer::analyze(
                    $statements_analyzer,
                    $arg->value,
                    $context
                ) === false) {
                    return false;
                }

                if (!isset($arg->value->inferredType) || $arg->value->inferredType->hasMixed()) {
                    $by_ref_type = Type::combineUnionTypes(
                        $by_ref_type,
                        new Type\Union([new TArray([Type::getInt(), Type::getMixed()])])
                    );
                } elseif ($arg->unpack) {
                    $by_ref_type = Type::combineUnionTypes(
                        $by_ref_type,
                        clone $arg->value->inferredType
                    );
                } else {
                    $by_ref_type = Type::combineUnionTypes(
                        $by_ref_type,
                        new Type\Union(
                            [
                                new TArray(
                                    [
                                        Type::getInt(),
                                        clone $arg->value->inferredType
                                    ]
                                ),
                            ]
                        )
                    );
                }
            }

            ExpressionAnalyzer::assignByRefParam(
                $statements_analyzer,
                $array_arg,
                $by_ref_type,
                $by_ref_type,
                $context,
                false
            );
        }

        return;
    }
1243107
protected static function analyzeIsset(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\Isset_ $stmt,
        Context $context
    ) {
        foreach ($stmt->vars as $isset_var) {
            if ($isset_var instanceof PhpParser\Node\Expr\PropertyFetch
                && $isset_var->var instanceof PhpParser\Node\Expr\Variable
                && $isset_var->var->name === 'this'
                && $isset_var->name instanceof PhpParser\Node\Identifier
            ) {
                $var_id = '$this->' . $isset_var->name->name;

                if (!isset($context->vars_in_scope[$var_id])) {
                    $context->vars_in_scope[$var_id] = Type::getMixed();
                    $context->vars_possibly_in_scope[$var_id] = true;
                }
            }

            self::analyzeIssetVar($statements_analyzer, $isset_var, $context);
        }

        $stmt->inferredType = Type::getBool();
    }
835689
public static function afterExpressionAnalysis(
        PhpParser\Node\Expr $expr,
        Context $context,
        StatementsSource $statements_source,
        Codebase $codebase,
        array &$file_replacements = []
    ) {
        if ($expr instanceof PhpParser\Node\Scalar\String_) {
            $class_or_class_method = '/^\\\?Psalm(\\\[A-Z][A-Za-z0-9]+)+(::[A-Za-z0-9]+)?$/';

            if (strpos($statements_source->getFileName(), 'base/DefinitionManager.php') === false
                && strpos($expr->value, 'TestController') === false
                && preg_match($class_or_class_method, $expr->value)
            ) {
                $absolute_class = preg_split('/[:]/', $expr->value)[0];

                if (\Psalm\IssueBuffer::accepts(
                    new \Psalm\Issue\InvalidClass(
                        'Use ::class constants when representing class names',
                        new CodeLocation($statements_source, $expr),
                        $absolute_class
                    ),
                    $statements_source->getSuppressedIssues()
                )) {
                    // fall through
                }
            }
        } elseif ($expr instanceof PhpParser\Node\Expr\BinaryOp\Concat
            && $expr->left instanceof PhpParser\Node\Expr\ClassConstFetch
            && $expr->left->class instanceof PhpParser\Node\Name
            && $expr->left->name instanceof PhpParser\Node\Identifier
            && strtolower($expr->left->name->name) === 'class'
            && !in_array(strtolower($expr->left->class->parts[0]), ['self', 'static', 'parent'])
            && $expr->right instanceof PhpParser\Node\Scalar\String_
            && preg_match('/^::[A-Za-z0-9]+$/', $expr->right->value)
        ) {
            $method_id = ((string) $expr->left->class->getAttribute('resolvedName')) . $expr->right->value;

            $appearing_method_id = $codebase->getAppearingMethodId($method_id);

            if (!$appearing_method_id) {
                if (\Psalm\IssueBuffer::accepts(
                    new \Psalm\Issue\UndefinedMethod(
                        'Method ' . $method_id . ' does not exist',
                        new CodeLocation($statements_source, $expr),
                        $method_id
                    ),
                    $statements_source->getSuppressedIssues()
                )) {
                    return false;
                }

                return;
            }
        }
    }
536296
protected void executeStatements(TestContext context) {
        for (String stmt : statements) {
            try {
                final String toExecute = context.replaceDynamicContentInString(stmt.trim());

                if (log.isDebugEnabled()) {
                    log.debug("Executing PLSQL statement: " + toExecute);
                }

                getJdbcTemplate().execute(toExecute);

                log.info("PLSQL statement execution successful");
            } catch (DataAccessException e) {
                if (ignoreErrors) {
                    log.warn("Ignoring error while executing PLSQL statement: " + e.getMessage());
                    continue;
                } else {
                    throw new CitrusRuntimeException("Failed to execute PLSQL statement", e);
                }
            }
        }
    }
39702
private function extractMethod($stmt, array &$methods)
    {
        if (!($stmt instanceof ClassMethod)) {
            return;
        }

        $skip = $this->isPublicOnly && $stmt->isPublic() === false;

        if (!$skip) {
            $methods[] = new Method(
                new MethodContext($this->context->namespace, $this->context->class),
                $stmt->name,
                $this->printer->prettyPrint([$stmt])
            );
        }
    }
35795
function interpretStatements(statements, resultVars) {
    var /** @type {?} */ stmtsWithReturn = statements.concat([new ReturnStatement(literalArr(resultVars.map(function (resultVar) { return variable(resultVar); })))]);
    var /** @type {?} */ ctx = new _ExecutionContext(null, null, null, new Map());
    var /** @type {?} */ visitor = new StatementInterpreter();
    var /** @type {?} */ result = visitor.visitAllStatements(stmtsWithReturn, ctx);
    return result != null ? result.value : null;
}
53388
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\MethodCall $stmt,
        Context $context
    ) {
        $stmt->inferredType = null;

        if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->var, $context) === false) {
            return false;
        }

        if (!$stmt->name instanceof PhpParser\Node\Identifier) {
            if (ExpressionAnalyzer::analyze($statements_analyzer, $stmt->name, $context) === false) {
                return false;
            }
        }

        if ($stmt->var instanceof PhpParser\Node\Expr\Variable) {
            if (is_string($stmt->var->name) && $stmt->var->name === 'this' && !$statements_analyzer->getFQCLN()) {
                if (IssueBuffer::accepts(
                    new InvalidScope(
                        'Use of $this in non-class context',
                        new CodeLocation($statements_analyzer->getSource(), $stmt)
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    return false;
                }
            }
        }

        $lhs_var_id = ExpressionAnalyzer::getArrayVarId(
            $stmt->var,
            $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        $class_type = $lhs_var_id && $context->hasVariable($lhs_var_id, $statements_analyzer)
            ? $context->vars_in_scope[$lhs_var_id]
            : null;

        if (isset($stmt->var->inferredType)) {
            $class_type = $stmt->var->inferredType;
        } elseif (!$class_type) {
            $stmt->inferredType = Type::getMixed();
        }

        if (!$context->check_classes) {
            if (self::checkFunctionArguments(
                $statements_analyzer,
                $stmt->args,
                null,
                null,
                $context
            ) === false) {
                return false;
            }

            return null;
        }

        $has_mock = false;

        if ($class_type && $stmt->name instanceof PhpParser\Node\Identifier && $class_type->isNull()) {
            if (IssueBuffer::accepts(
                new NullReference(
                    'Cannot call method ' . $stmt->name->name . ' on null value',
                    new CodeLocation($statements_analyzer->getSource(), $stmt->name)
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                return false;
            }

            return null;
        }

        if ($class_type
            && $stmt->name instanceof PhpParser\Node\Identifier
            && $class_type->isNullable()
            && !$class_type->ignore_nullable_issues
        ) {
            if (IssueBuffer::accepts(
                new PossiblyNullReference(
                    'Cannot call method ' . $stmt->name->name . ' on possibly null value',
                    new CodeLocation($statements_analyzer->getSource(), $stmt->name)
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                // fall through
            }
        }

        if ($class_type
            && $stmt->name instanceof PhpParser\Node\Identifier
            && $class_type->isFalsable()
            && !$class_type->ignore_falsable_issues
        ) {
            if (IssueBuffer::accepts(
                new PossiblyFalseReference(
                    'Cannot call method ' . $stmt->name->name . ' on possibly false value',
                    new CodeLocation($statements_analyzer->getSource(), $stmt->name)
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                // fall through
            }
        }

        $codebase = $statements_analyzer->getCodebase();
        $config = $codebase->config;

        $non_existent_class_method_ids = [];
        $non_existent_interface_method_ids = [];
        $existent_method_ids = [];
        $has_mixed_method_call = false;

        $invalid_method_call_types = [];
        $has_valid_method_call_type = false;

        $source = $statements_analyzer->getSource();

        $returns_by_ref = false;

        $no_method_id = false;

        if (!$class_type) {
            $class_type = Type::getMixed();
        }

        $return_type = null;

        $lhs_types = $class_type->getTypes();

        foreach ($lhs_types as $lhs_type_part) {
            $result = self::analyzeAtomicCall(
                $statements_analyzer,
                $stmt,
                $codebase,
                $context,
                $lhs_type_part,
                $lhs_var_id,
                $return_type,
                $returns_by_ref,
                $has_mock,
                $has_valid_method_call_type,
                $has_mixed_method_call,
                $invalid_method_call_types,
                $existent_method_ids,
                $non_existent_class_method_ids,
                $non_existent_interface_method_ids
            );

            if ($result === false) {
                return false;
            }

            if ($result === true) {
                $no_method_id = true;
            }
        }

        if ($invalid_method_call_types) {
            $invalid_class_type = $invalid_method_call_types[0];

            if ($has_valid_method_call_type || $has_mixed_method_call) {
                if (IssueBuffer::accepts(
                    new PossiblyInvalidMethodCall(
                        'Cannot call method on possible ' . $invalid_class_type . ' variable ' . $lhs_var_id,
                        new CodeLocation($source, $stmt->name)
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    // keep going
                }
            } else {
                if (IssueBuffer::accepts(
                    new InvalidMethodCall(
                        'Cannot call method on ' . $invalid_class_type . ' variable ' . $lhs_var_id,
                        new CodeLocation($source, $stmt->name)
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    // keep going
                }
            }
        }

        if ($non_existent_class_method_ids) {
            if ($context->check_methods) {
                if ($existent_method_ids || $has_mixed_method_call) {
                    if (IssueBuffer::accepts(
                        new PossiblyUndefinedMethod(
                            'Method ' . $non_existent_class_method_ids[0] . ' does not exist',
                            new CodeLocation($source, $stmt->name),
                            $non_existent_class_method_ids[0]
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // keep going
                    }
                } else {
                    if (IssueBuffer::accepts(
                        new UndefinedMethod(
                            'Method ' . $non_existent_class_method_ids[0] . ' does not exist',
                            new CodeLocation($source, $stmt->name),
                            $non_existent_class_method_ids[0]
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // keep going
                    }
                }
            }

            return null;
        }

        if ($non_existent_interface_method_ids) {
            if ($context->check_methods) {
                if ($existent_method_ids || $has_mixed_method_call) {
                    if (IssueBuffer::accepts(
                        new PossiblyUndefinedMethod(
                            'Method ' . $non_existent_interface_method_ids[0] . ' does not exist',
                            new CodeLocation($source, $stmt->name),
                            $non_existent_interface_method_ids[0]
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // keep going
                    }
                } else {
                    if (IssueBuffer::accepts(
                        new UndefinedInterfaceMethod(
                            'Method ' . $non_existent_interface_method_ids[0] . ' does not exist',
                            new CodeLocation($source, $stmt->name),
                            $non_existent_interface_method_ids[0]
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // keep going
                    }
                }
            }

            return null;
        }

        $stmt->inferredType = $return_type;

        if ($returns_by_ref) {
            if (!$stmt->inferredType) {
                $stmt->inferredType = Type::getMixed();
            }

            $stmt->inferredType->by_ref = $returns_by_ref;
        }

        if ($no_method_id) {
            return self::checkMethodArgs(
                null,
                $stmt->args,
                $found_generic_params,
                $context,
                new CodeLocation($statements_analyzer->getSource(), $stmt),
                $statements_analyzer
            );
        }

        if ($codebase->store_node_types
            && (!$context->collect_initializations
                && !$context->collect_mutations)
            && isset($stmt->inferredType)
        ) {
            $codebase->analyzer->addNodeType(
                $statements_analyzer->getFilePath(),
                $stmt->name,
                (string) $stmt->inferredType
            );
        }

        if (!$config->remember_property_assignments_after_call && !$context->collect_initializations) {
            $context->removeAllObjectVars();
        }

        // if we called a method on this nullable variable, remove the nullable status here
        // because any further calls must have worked
        if ($lhs_var_id
            && !$class_type->isMixed()
            && $has_valid_method_call_type
            && !$has_mixed_method_call
            && !$invalid_method_call_types
            && $existent_method_ids
            && ($class_type->from_docblock || $class_type->isNullable())
        ) {
            $keys_to_remove = [];

            foreach ($class_type->getTypes() as $key => $type) {
                if (!$type instanceof TNamedObject) {
                    $keys_to_remove[] = $key;
                } else {
                    $type->from_docblock = false;
                }
            }

            foreach ($keys_to_remove as $key) {
                $class_type->removeType($key);
            }

            $class_type->from_docblock = false;

            $context->removeVarFromConflictingClauses($lhs_var_id, null, $statements_analyzer);

            $context->vars_in_scope[$lhs_var_id] = $class_type;
        }
    }