@param  string           $method_id
@param  Context          $context
@param  StatementsSource $source
@param  CodeLocation     $code_location
@param  array            $suppressed_issues

@return false|null
496116
public static function checkMethodVisibility(
        $method_id,
        Context $context,
        StatementsSource $source,
        CodeLocation $code_location,
        array $suppressed_issues
    ) {
        $codebase = $source->getCodebase();
        $codebase_methods = $codebase->methods;
        $codebase_classlikes = $codebase->classlikes;

        list($fq_classlike_name, $method_name) = explode('::', $method_id);

        if ($codebase_methods->visibility_provider->has($fq_classlike_name)) {
            $method_visible = $codebase_methods->visibility_provider->isMethodVisible(
                $source,
                $fq_classlike_name,
                $method_name,
                $context,
                $code_location
            );

            if ($method_visible === false) {
                if (IssueBuffer::accepts(
                    new InaccessibleMethod(
                        'Cannot access method ' . $codebase_methods->getCasedMethodId($method_id) .
                            ' from context ' . $context->self,
                        $code_location
                    ),
                    $suppressed_issues
                )) {
                    return false;
                }
            } elseif ($method_visible === true) {
                return false;
            }
        }

        $declaring_method_id = $codebase_methods->getDeclaringMethodId($method_id);

        if (!$declaring_method_id) {
            $method_name = explode('::', $method_id)[1];

            if ($method_name === '__construct'
                || $method_id === 'Closure::__invoke'
                || $method_id === 'Closure::fromcallable'
            ) {
                return null;
            }

            throw new \UnexpectedValueException('$declaring_method_id not expected to be null here');
        }

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

        $appearing_method_class = null;
        $appearing_class_storage = null;
        $appearing_method_name = null;

        if ($appearing_method_id) {
            list($appearing_method_class, $appearing_method_name) = explode('::', $appearing_method_id);

            // if the calling class is the same, we know the method exists, so it must be visible
            if ($appearing_method_class === $context->self) {
                return null;
            }

            $appearing_class_storage = $codebase->classlike_storage_provider->get($appearing_method_class);
        }

        list($declaring_method_class) = explode('::', $declaring_method_id);

        if ($source->getSource() instanceof TraitAnalyzer && $declaring_method_class === $source->getFQCLN()) {
            return null;
        }

        $storage = $codebase->methods->getStorage($declaring_method_id);
        $visibility = $storage->visibility;

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

        switch ($visibility) {
            case ClassLikeAnalyzer::VISIBILITY_PUBLIC:
                return null;

            case ClassLikeAnalyzer::VISIBILITY_PRIVATE:
                if (!$context->self || $appearing_method_class !== $context->self) {
                    if (IssueBuffer::accepts(
                        new InaccessibleMethod(
                            'Cannot access private method ' . $codebase_methods->getCasedMethodId($method_id) .
                                ' from context ' . $context->self,
                            $code_location
                        ),
                        $suppressed_issues
                    )) {
                        return false;
                    }
                }

                return null;

            case ClassLikeAnalyzer::VISIBILITY_PROTECTED:
                if (!$context->self) {
                    if (IssueBuffer::accepts(
                        new InaccessibleMethod(
                            'Cannot access protected method ' . $method_id,
                            $code_location
                        ),
                        $suppressed_issues
                    )) {
                        return false;
                    }

                    return null;
                }

                if ($appearing_method_class
                    && $codebase_classlikes->classExtends($appearing_method_class, $context->self)
                ) {
                    return null;
                }

                if ($appearing_method_class
                    && !$codebase_classlikes->classExtends($context->self, $appearing_method_class)
                ) {
                    if (IssueBuffer::accepts(
                        new InaccessibleMethod(
                            'Cannot access protected method ' . $codebase_methods->getCasedMethodId($method_id) .
                                ' from context ' . $context->self,
                            $code_location
                        ),
                        $suppressed_issues
                    )) {
                        return false;
                    }
                }
        }

        return null;
    }
529438
public function getAppearingMethodId($method_id)
    {
        $method_id = strtolower($method_id);

        list($fq_class_name, $method_name) = explode('::', $method_id);

        $fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);

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

        if (isset($class_storage->appearing_method_ids[$method_name])) {
            return $class_storage->appearing_method_ids[$method_name];
        }
    }
701004
public static function isMethodAllowed($methodName = NULL, $methodsList = NULL)
	{
		NULL !== $methodName or $methodName = static::method(FALSE);
		is_array($methodsList) or $methodsList = static::getMethodsAllowed();

		return Kohana_Helpers_Arr::inArray($methodName, $methodsList);
	}
488251
public function getMethodMutations(
        $original_method_id,
        Context $this_context,
        string $root_file_path,
        string $root_file_name
    ) {
        list($fq_class_name) = explode('::', $original_method_id);

        $appearing_method_id = $this->codebase->methods->getAppearingMethodId($original_method_id);

        if (!$appearing_method_id) {
            // this can happen for some abstract classes implementing (but not fully) interfaces
            return;
        }

        list($appearing_fq_class_name) = explode('::', $appearing_method_id);

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

        if (!$appearing_class_storage->user_defined) {
            return;
        }

        $file_analyzer = $this->getFileAnalyzerForClassLike($fq_class_name);

        $file_analyzer->setRootFilePath($root_file_path, $root_file_name);

        if (strtolower($appearing_fq_class_name) !== strtolower($fq_class_name)) {
            $file_analyzer = $this->getFileAnalyzerForClassLike($appearing_fq_class_name);
        }

        $stmts = $this->codebase->getStatementsForFile(
            $file_analyzer->getFilePath()
        );

        $file_analyzer->populateCheckers($stmts);

        if (!$this_context->self) {
            $this_context->self = $fq_class_name;
            $this_context->vars_in_scope['$this'] = Type::parseString($fq_class_name);
        }

        $file_analyzer->getMethodMutations($appearing_method_id, $this_context, true);

        $file_analyzer->class_analyzers_to_analyze = [];
        $file_analyzer->interface_analyzers_to_analyze = [];
    }
812021
public function allowsMethod($method_id)
    {
        if (!$this->method_ids) {
            return false;
        }

        if (preg_match('/^[^:]+::[^:]+$/', $method_id)) {
            $method_stub = '*::' . explode('::', $method_id)[1];

            foreach ($this->method_ids as $config_method_id) {
                if ($config_method_id === $method_id) {
                    return true;
                }

                if ($config_method_id === $method_stub) {
                    return true;
                }

                if ($config_method_id[0] === '/' && preg_match($config_method_id, $method_id)) {
                    return true;
                }
            }

            return false;
        }

        return in_array($method_id, $this->method_ids);
    }
965551
@Ensures({
    "contextLocal >= 0",
    "checkInvariantsLocal >= 0"
  })
  protected void enterContractedMethod() {
    contextLocal = newLocal(CONTRACT_CONTEXT_TYPE);
    checkInvariantsLocal = newLocal(Type.BOOLEAN_TYPE);
    invokeStatic(CONTRACT_RUNTIME_TYPE, GET_CONTEXT_METHOD);
    dup();
    storeLocal(contextLocal);
    if (statik) {
      loadThisClass();
    } else {
      loadThis();
    }
    invokeVirtual(CONTRACT_CONTEXT_TYPE, TRY_ENTER_METHOD);
    storeLocal(checkInvariantsLocal);
  }
61086
private void generateJavaDoc(final SQLiteModelMethod method, MethodSpec.Builder methodBuilder, boolean updateMode, String whereCondition, Pair<String, List<Pair<String, TypeName>>> where,
			List<Pair<String, TypeName>> methodParams) {

		final List<SQLProperty> updatedProperties = new ArrayList<>();
		final One<Boolean> onWhereStatement = new One<Boolean>(false);

		String sqlModify = JQLChecker.getInstance().replace(method, method.jql, new JQLReplacerListenerImpl(method) {

			@Override
			public void onWhereStatementBegin(Where_stmtContext ctx) {
				onWhereStatement.value0 = true;
			}

			@Override
			public void onWhereStatementEnd(Where_stmtContext ctx) {
				onWhereStatement.value0 = false;
			}

			@Override
			public String onColumnNameToUpdate(String columnName) {
				SQLProperty tempProperty = currentEntity.get(columnName);

				AssertKripton.assertTrueOrUnknownPropertyInJQLException(tempProperty != null, method, columnName);

				updatedProperties.add(tempProperty);

				return tempProperty.columnName;
			}

			@Override
			public String onColumnName(String columnName) {
				SQLProperty tempProperty = currentEntity.get(columnName);

				AssertKripton.assertTrueOrUnknownPropertyInJQLException(tempProperty != null, method, columnName);

				return tempProperty.columnName;
			}

			@Override
			public String onBindParameter(String bindParameterName, boolean inStatement) {
				String resolvedParamName = method.findParameterNameByAlias(bindParameterName);
				AssertKripton.assertTrueOrUnknownParamInJQLException(resolvedParamName != null, method, bindParameterName);

				if (onWhereStatement.value0) {
					return SqlAnalyzer.PARAM_PREFIX + bindParameterName + SqlAnalyzer.PARAM_SUFFIX;
				} else {
					return SqlAnalyzer.PARAM_PREFIX + bindParameterName + SqlAnalyzer.PARAM_SUFFIX;
				}

			}

		});

		if (updateMode) {
			methodBuilder.addJavadoc("<h2>SQL update</h2>\n");
			methodBuilder.addJavadoc("<pre>$L</pre>\n", sqlModify);
			methodBuilder.addJavadoc("\n");

			// list of updated fields
			methodBuilder.addJavadoc("<h2>Updated columns:</h2>\n");
			methodBuilder.addJavadoc("<ul>\n");
			for (SQLProperty property : updatedProperties) {
				methodBuilder.addJavadoc("\t<li>$L</li>\n", property.columnName);
			}
			methodBuilder.addJavadoc("</ul>");
			methodBuilder.addJavadoc("\n\n");

		} else {
			methodBuilder.addJavadoc("<h2>SQL delete</h2>\n");
			methodBuilder.addJavadoc("<pre>$L</pre>", sqlModify);
			methodBuilder.addJavadoc("\n\n");
		}

		// list of where parameter
		if (where.value1.size() > 0) {
			methodBuilder.addJavadoc("<h2>Where parameters:</h2>\n");
			methodBuilder.addJavadoc("<dl>\n");
			for (Pair<String, TypeName> property : where.value1) {
				String rawName = method.findParameterNameByAlias(property.value0);
				methodBuilder.addJavadoc("\t<dt>$L</dt>", SqlAnalyzer.PARAM_PREFIX + property.value0 + SqlAnalyzer.PARAM_SUFFIX);
				methodBuilder.addJavadoc("<dd>is mapped to method's parameter <strong>$L</strong></dd>\n", rawName);
			}
			methodBuilder.addJavadoc("</dl>");
		} else {
			methodBuilder.addJavadoc("<p>No where parameters were found.</p>");
		}
		methodBuilder.addJavadoc("\n\n");

		if (method.hasDynamicWhereConditions()) {
			methodBuilder.addJavadoc("<dl>\n");
			methodBuilder.addJavadoc("<dt>$L</dt><dd>is part of where conditions resolved at runtime. In above SQL it is displayed as #{$L}</dd>", method.dynamicWhereParameterName,
					JQLDynamicStatementType.DYNAMIC_WHERE);
			methodBuilder.addJavadoc("\n</dl>");
			methodBuilder.addJavadoc("\n\n");
		}

		// dynamic conditions
		if (method.hasDynamicWhereConditions()) {
			methodBuilder.addJavadoc("<h2>Method's parameters and associated dynamic parts:</h2>\n");
			methodBuilder.addJavadoc("<dl>\n");

			if (method.hasDynamicWhereConditions()) {
				methodBuilder.addJavadoc("<dt>$L</dt><dd>is part of where conditions resolved at runtime. In above SQL it is displayed as #{$L}</dd>", method.dynamicWhereParameterName,
						JQLDynamicStatementType.DYNAMIC_WHERE);
			}

			methodBuilder.addJavadoc("</dl>");
			methodBuilder.addJavadoc("\n\n");
		}

		// method parameters
		if (methodParams.size() > 0) {
			for (Pair<String, TypeName> param : methodParams) {
				String resolvedName = method.findParameterAliasByName(param.value0);
				methodBuilder.addJavadoc("@param $L", param.value0);
				if (method.isThisDynamicWhereConditionsName(param.value0)) {
					methodBuilder.addJavadoc("\n\tis used as dynamic where conditions\n");
				} else if (where.value1.contains(new Pair<>(resolvedName, param.value1))) {
					methodBuilder.addJavadoc("\n\tis used as where parameter <strong>$L</strong>\n", SqlAnalyzer.PARAM_PREFIX + resolvedName + SqlAnalyzer.PARAM_SUFFIX);
				} else {
					methodBuilder.addJavadoc("\n\tis used as updated field <strong>$L</strong>\n", resolvedName);
				}
			}
		}

		// if true, field must be associate to ben attributes
		TypeName returnType = method.getReturnClass();
		// define return value
		if (returnType == TypeName.VOID) {

		} else {
			methodBuilder.addJavadoc("\n");
			if (isIn(returnType, Boolean.TYPE, Boolean.class)) {
				if (updateMode) {
					methodBuilder.addJavadoc("@return <code>true</code> if record is updated, <code>false</code> otherwise");
				} else {
					methodBuilder.addJavadoc("@return <code>true</code> if record is deleted, <code>false</code> otherwise");
				}
				// methodBuilder.addCode("return result!=0;\n");
			} else if (isIn(returnType, Long.TYPE, Long.class, Integer.TYPE, Integer.class, Short.TYPE, Short.class)) {
				if (updateMode) {
					methodBuilder.addJavadoc("@return number of updated records");
				} else {
					methodBuilder.addJavadoc("@return number of deleted records");
				}

				// methodBuilder.addCode("return result;\n");
			} else {
				// more than one listener found
				throw (new InvalidMethodSignException(method, "invalid return type"));
			}
			methodBuilder.addJavadoc("\n");
		}

	}
1359556
public static function analyzeStatic(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\StaticPropertyFetch $stmt,
        Context $context
    ) {
        if ($stmt->class instanceof PhpParser\Node\Expr\Variable ||
            $stmt->class instanceof PhpParser\Node\Expr\ArrayDimFetch
        ) {
            // @todo check this
            return null;
        }

        $fq_class_name = null;

        $codebase = $statements_analyzer->getCodebase();

        if ($stmt->class instanceof PhpParser\Node\Name) {
            if (count($stmt->class->parts) === 1
                && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)
            ) {
                if ($stmt->class->parts[0] === '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 = (string)$context->self;
                }

                if ($context->isPhantomClass($fq_class_name)) {
                    return null;
                }
            } else {
                $aliases = $statements_analyzer->getAliases();

                if ($context->calling_method_id
                    && !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
                ) {
                    $codebase->file_reference_provider->addMethodReferenceToClassMember(
                        $context->calling_method_id,
                        'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
                    );
                }

                $fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
                    $stmt->class,
                    $aliases
                );

                if ($context->isPhantomClass($fq_class_name)) {
                    return null;
                }

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

            $stmt->class->inferredType = $fq_class_name ? new Type\Union([new TNamedObject($fq_class_name)]) : null;
        }

        if ($stmt->name instanceof PhpParser\Node\VarLikeIdentifier) {
            $prop_name = $stmt->name->name;
        } elseif (isset($stmt->name->inferredType)
            && $stmt->name->inferredType->isSingleStringLiteral()
        ) {
            $prop_name = $stmt->name->inferredType->getSingleStringLiteral()->value;
        } else {
            $prop_name = null;
        }

        if (!$prop_name) {
            if ($fq_class_name) {
                $codebase->analyzer->addMixedMemberName(
                    strtolower($fq_class_name) . '::$',
                    $context->calling_method_id ?: $statements_analyzer->getFileName()
                );
            }

            return null;
        }

        if (!$fq_class_name
            || !$context->check_classes
            || !$context->check_variables
            || ExpressionAnalyzer::isMock($fq_class_name)
        ) {
            return null;
        }

        $var_id = ExpressionAnalyzer::getVarId(
            $stmt,
            $context->self ?: $statements_analyzer->getFQCLN(),
            $statements_analyzer
        );

        $property_id = $fq_class_name . '::$' . $prop_name;

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

        if ($var_id && $context->hasVariable($var_id, $statements_analyzer)) {
            // we don't need to check anything
            $stmt->inferredType = $context->vars_in_scope[$var_id];

            if ($context->collect_references) {
                // log the appearance
                $codebase->properties->propertyExists(
                    $property_id,
                    false,
                    $statements_analyzer,
                    $context,
                    new CodeLocation($statements_analyzer->getSource(), $stmt)
                );
            }

            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
                );
            }

            return null;
        }

        if (!$codebase->properties->propertyExists(
            $property_id,
            false,
            $statements_analyzer,
            $context,
            $context->collect_references ? new CodeLocation($statements_analyzer->getSource(), $stmt) : null
        )
        ) {
            if (IssueBuffer::accepts(
                new UndefinedPropertyFetch(
                    'Static property ' . $property_id . ' is not defined',
                    new CodeLocation($statements_analyzer->getSource(), $stmt),
                    $property_id
                ),
                $statements_analyzer->getSuppressedIssues()
            )) {
                // fall through
            }

            return;
        }

        if (ClassLikeAnalyzer::checkPropertyVisibility(
            $property_id,
            $context,
            $statements_analyzer,
            new CodeLocation($statements_analyzer->getSource(), $stmt),
            $statements_analyzer->getSuppressedIssues()
        ) === false) {
            return false;
        }

        $declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
            $fq_class_name . '::$' . $prop_name,
            true
        );

        $class_storage = $codebase->classlike_storage_provider->get((string)$declaring_property_class);
        $property = $class_storage->properties[$prop_name];

        if ($var_id) {
            if ($property->type) {
                $context->vars_in_scope[$var_id] = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    clone $property->type,
                    $declaring_property_class,
                    $declaring_property_class
                );
            } else {
                $context->vars_in_scope[$var_id] = Type::getMixed();
            }

            $stmt->inferredType = clone $context->vars_in_scope[$var_id];

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

        return null;
    }
659974
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Expr\StaticCall $stmt,
        Context $context
    ) {
        $method_id = null;

        $lhs_type = null;

        $file_analyzer = $statements_analyzer->getFileAnalyzer();
        $codebase = $statements_analyzer->getCodebase();
        $source = $statements_analyzer->getSource();

        $stmt->inferredType = null;

        $config = $codebase->config;

        if ($stmt->class instanceof PhpParser\Node\Name) {
            $fq_class_name = null;

            if (count($stmt->class->parts) === 1
                && in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)
            ) {
                if ($stmt->class->parts[0] === 'parent') {
                    $child_fq_class_name = $context->self;

                    $class_storage = $child_fq_class_name
                        ? $codebase->classlike_storage_provider->get($child_fq_class_name)
                        : null;

                    if (!$class_storage || !$class_storage->parent_classes) {
                        if (IssueBuffer::accepts(
                            new ParentNotFound(
                                'Cannot call method on parent as this class does not extend another',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }

                        return;
                    }

                    $fq_class_name = reset($class_storage->parent_classes);

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

                    $fq_class_name = $class_storage->name;
                } elseif ($context->self) {
                    if ($stmt->class->parts[0] === 'static' && isset($context->vars_in_scope['$this'])) {
                        $fq_class_name = (string) $context->vars_in_scope['$this'];
                        $lhs_type = clone $context->vars_in_scope['$this'];
                    } else {
                        $fq_class_name = $context->self;
                    }
                } else {
                    $namespace = $statements_analyzer->getNamespace()
                        ? $statements_analyzer->getNamespace() . '\\'
                        : '';

                    $fq_class_name = $namespace . $statements_analyzer->getClassName();
                }

                if ($context->isPhantomClass($fq_class_name)) {
                    return null;
                }
            } elseif ($context->check_classes) {
                $aliases = $statements_analyzer->getAliases();

                if ($context->calling_method_id
                    && !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
                ) {
                    $codebase->file_reference_provider->addMethodReferenceToClassMember(
                        $context->calling_method_id,
                        'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
                    );
                }

                $fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
                    $stmt->class,
                    $aliases
                );

                if ($context->isPhantomClass($fq_class_name)) {
                    return null;
                }

                $does_class_exist = false;

                if ($context->self) {
                    $self_storage = $codebase->classlike_storage_provider->get($context->self);

                    if (isset($self_storage->used_traits[strtolower($fq_class_name)])) {
                        $fq_class_name = $context->self;
                        $does_class_exist = true;
                    }
                }

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

                if (!$does_class_exist) {
                    return $does_class_exist;
                }
            }

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

            if ($fq_class_name && !$lhs_type) {
                $lhs_type = new Type\Union([new TNamedObject($fq_class_name)]);
            }
        } else {
            ExpressionAnalyzer::analyze($statements_analyzer, $stmt->class, $context);
            $lhs_type = $stmt->class->inferredType;
        }

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

            return null;
        }

        $has_mock = false;

        foreach ($lhs_type->getTypes() as $lhs_type_part) {
            $intersection_types = [];

            if ($lhs_type_part instanceof TNamedObject) {
                $fq_class_name = $lhs_type_part->value;

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

                $intersection_types = $lhs_type_part->extra_types;
            } elseif ($lhs_type_part instanceof Type\Atomic\TClassString
                && $lhs_type_part->as_type
            ) {
                $fq_class_name = $lhs_type_part->as_type->value;

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

                $intersection_types = $lhs_type_part->as_type->extra_types;
            } elseif ($lhs_type_part instanceof Type\Atomic\TLiteralClassString) {
                $fq_class_name = $lhs_type_part->value;

                if (!ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                    $statements_analyzer,
                    $fq_class_name,
                    new CodeLocation($source, $stmt->class),
                    $statements_analyzer->getSuppressedIssues(),
                    false
                )) {
                    return false;
                }
            } elseif ($lhs_type_part instanceof Type\Atomic\TTemplateParam
                && !$lhs_type_part->as->isMixed()
                && !$lhs_type_part->as->hasObject()
            ) {
                $fq_class_name = null;

                foreach ($lhs_type_part->as->getTypes() as $generic_param_type) {
                    if (!$generic_param_type instanceof TNamedObject) {
                        continue 2;
                    }

                    $fq_class_name = $generic_param_type->value;
                    break;
                }

                if (!$fq_class_name) {
                    if (IssueBuffer::accepts(
                        new UndefinedClass(
                            'Type ' . $lhs_type_part->as . ' cannot be called as a class',
                            new CodeLocation($statements_analyzer->getSource(), $stmt),
                            (string) $lhs_type_part
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }

                    continue;
                }
            } else {
                if ($lhs_type_part instanceof Type\Atomic\TMixed
                    || $lhs_type_part instanceof Type\Atomic\TTemplateParam
                    || $lhs_type_part instanceof Type\Atomic\TClassString
                ) {
                    if ($stmt->name instanceof PhpParser\Node\Identifier) {
                        $codebase->analyzer->addMixedMemberName(
                            strtolower($stmt->name->name),
                            $context->calling_method_id ?: $statements_analyzer->getFileName()
                        );
                    }

                    if (IssueBuffer::accepts(
                        new MixedMethodCall(
                            'Cannot call method on an unknown class',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }

                    continue;
                }

                if ($lhs_type_part instanceof Type\Atomic\TString) {
                    if ($config->allow_string_standin_for_class
                        && !$lhs_type_part instanceof Type\Atomic\TNumericString
                    ) {
                        continue;
                    }

                    if (IssueBuffer::accepts(
                        new InvalidStringClass(
                            'String cannot be used as a class',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }

                    continue;
                }

                if ($lhs_type_part instanceof Type\Atomic\TNull
                    && $lhs_type->ignore_nullable_issues
                ) {
                    continue;
                }

                if (IssueBuffer::accepts(
                    new UndefinedClass(
                        'Type ' . $lhs_type_part . ' cannot be called as a class',
                        new CodeLocation($statements_analyzer->getSource(), $stmt),
                        (string) $lhs_type_part
                    ),
                    $statements_analyzer->getSuppressedIssues()
                )) {
                    // fall through
                }

                continue;
            }

            $fq_class_name = $codebase->classlikes->getUnAliasedName($fq_class_name);

            $is_mock = ExpressionAnalyzer::isMock($fq_class_name);

            $has_mock = $has_mock || $is_mock;

            if ($stmt->name instanceof PhpParser\Node\Identifier && !$is_mock) {
                $method_name_lc = strtolower($stmt->name->name);
                $method_id = $fq_class_name . '::' . $method_name_lc;
                $cased_method_id = $fq_class_name . '::' . $stmt->name->name;

                $args = $stmt->args;

                if ($intersection_types
                    && !$codebase->methods->methodExists($method_id)
                ) {
                    foreach ($intersection_types as $intersection_type) {
                        if (!$intersection_type instanceof TNamedObject) {
                            continue;
                        }

                        $intersection_method_id = $intersection_type->value . '::' . $method_name_lc;

                        if ($codebase->methods->methodExists($intersection_method_id)) {
                            $method_id = $intersection_method_id;
                            $fq_class_name = $intersection_type->value;
                            $cased_method_id = $fq_class_name . '::' . $stmt->name->name;
                            break;
                        }
                    }
                }

                if (!$codebase->methods->methodExists(
                    $method_id,
                    $context->calling_method_id,
                    $codebase->collect_references ? new CodeLocation($source, $stmt->name) : null,
                    null,
                    $statements_analyzer->getFilePath()
                )
                    || !MethodAnalyzer::isMethodVisible(
                        $method_id,
                        $context,
                        $statements_analyzer->getSource()
                    )
                ) {
                    if ($codebase->methods->methodExists(
                        $fq_class_name . '::__callStatic',
                        $context->calling_method_id,
                        $codebase->collect_references ? new CodeLocation($source, $stmt->name) : null,
                        null,
                        $statements_analyzer->getFilePath()
                    )) {
                        $class_storage = $codebase->classlike_storage_provider->get($fq_class_name);

                        if (isset($class_storage->pseudo_static_methods[$method_name_lc])) {
                            $pseudo_method_storage = $class_storage->pseudo_static_methods[$method_name_lc];

                            if (self::checkFunctionArguments(
                                $statements_analyzer,
                                $args,
                                $pseudo_method_storage->params,
                                $method_id,
                                $context
                            ) === false) {
                                return false;
                            }

                            $generic_params = [];

                            if (self::checkFunctionLikeArgumentsMatch(
                                $statements_analyzer,
                                $args,
                                null,
                                $pseudo_method_storage->params,
                                $pseudo_method_storage,
                                null,
                                $generic_params,
                                new CodeLocation($source, $stmt),
                                $context
                            ) === false) {
                                return false;
                            }

                            if ($pseudo_method_storage->return_type) {
                                $return_type_candidate = clone $pseudo_method_storage->return_type;

                                $return_type_candidate = ExpressionAnalyzer::fleshOutType(
                                    $codebase,
                                    $return_type_candidate,
                                    $fq_class_name,
                                    $fq_class_name
                                );

                                if (!isset($stmt->inferredType)) {
                                    $stmt->inferredType = $return_type_candidate;
                                } else {
                                    $stmt->inferredType = Type::combineUnionTypes(
                                        $return_type_candidate,
                                        $stmt->inferredType
                                    );
                                }

                                return;
                            }
                        } else {
                            if (self::checkFunctionArguments(
                                $statements_analyzer,
                                $args,
                                null,
                                null,
                                $context
                            ) === false) {
                                return false;
                            }
                        }

                        $array_values = array_map(
                            /**
                             * @return PhpParser\Node\Expr\ArrayItem
                             */
                            function (PhpParser\Node\Arg $arg) {
                                return new PhpParser\Node\Expr\ArrayItem($arg->value);
                            },
                            $args
                        );

                        $args = [
                            new PhpParser\Node\Arg(new PhpParser\Node\Scalar\String_($method_id)),
                            new PhpParser\Node\Arg(new PhpParser\Node\Expr\Array_($array_values)),
                        ];

                        $method_id = $fq_class_name . '::__callstatic';
                    }

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

                        return null;
                    }
                }

                $does_method_exist = MethodAnalyzer::checkMethodExists(
                    $codebase,
                    $method_id,
                    new CodeLocation($source, $stmt),
                    $statements_analyzer->getSuppressedIssues(),
                    $context->calling_method_id
                );

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

                    return;
                }

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

                if ($class_storage->user_defined
                    && $context->self
                    && ($context->collect_mutations || $context->collect_initializations)
                ) {
                    $appearing_method_id = $codebase->getAppearingMethodId($method_id);

                    if (!$appearing_method_id) {
                        if (IssueBuffer::accepts(
                            new UndefinedMethod(
                                'Method ' . $method_id . ' does not exist',
                                new CodeLocation($statements_analyzer->getSource(), $stmt),
                                $method_id
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            //
                        }

                        return;
                    }

                    list($appearing_method_class_name) = explode('::', $appearing_method_id);

                    if ($codebase->classExtends($context->self, $appearing_method_class_name)) {
                        $old_context_include_location = $context->include_location;
                        $old_self = $context->self;
                        $context->include_location = new CodeLocation($statements_analyzer->getSource(), $stmt);
                        $context->self = $appearing_method_class_name;

                        if ($context->collect_mutations) {
                            $file_analyzer->getMethodMutations($method_id, $context);
                        } else {
                            // collecting initializations
                            $local_vars_in_scope = [];
                            $local_vars_possibly_in_scope = [];

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

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

                            if (!isset($context->initialized_methods[$method_id])) {
                                if ($context->initialized_methods === null) {
                                    $context->initialized_methods = [];
                                }

                                $context->initialized_methods[$method_id] = true;

                                $file_analyzer->getMethodMutations($method_id, $context);

                                foreach ($local_vars_in_scope as $var => $type) {
                                    $context->vars_in_scope[$var] = $type;
                                }

                                foreach ($local_vars_possibly_in_scope as $var => $type) {
                                    $context->vars_possibly_in_scope[$var] = $type;
                                }
                            }
                        }

                        $context->include_location = $old_context_include_location;
                        $context->self = $old_self;

                        if (isset($context->vars_in_scope['$this']) && $old_self) {
                            $context->vars_in_scope['$this'] = Type::parseString($old_self);
                        }
                    }
                }

                if ($class_storage->deprecated) {
                    if (IssueBuffer::accepts(
                        new DeprecatedClass(
                            $fq_class_name . ' is marked deprecated',
                            new CodeLocation($statements_analyzer->getSource(), $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }
                }

                if ($class_storage->internal
                    && $context->self
                    && !$context->collect_initializations
                    && !$context->collect_mutations
                ) {
                    $self_root = preg_replace('/^([^\\\]+).*/', '$1', $context->self);
                    $declaring_root = preg_replace('/^([^\\\]+).*/', '$1', $fq_class_name);

                    if (strtolower($self_root) !== strtolower($declaring_root)) {
                        if (IssueBuffer::accepts(
                            new InternalClass(
                                $fq_class_name . ' is marked internal',
                                new CodeLocation($statements_analyzer->getSource(), $stmt)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            // fall through
                        }
                    }
                }

                if (MethodAnalyzer::checkMethodVisibility(
                    $method_id,
                    $context,
                    $statements_analyzer->getSource(),
                    new CodeLocation($source, $stmt),
                    $statements_analyzer->getSuppressedIssues()
                ) === false) {
                    return false;
                }

                if ((!$stmt->class instanceof PhpParser\Node\Name
                        || $stmt->class->parts[0] !== 'parent'
                        || $statements_analyzer->isStatic())
                    && (
                        !$context->self
                        || $statements_analyzer->isStatic()
                        || !$codebase->classExtends($context->self, $fq_class_name)
                    )
                ) {
                    if (MethodAnalyzer::checkStatic(
                        $method_id,
                        ($stmt->class instanceof PhpParser\Node\Name
                            && strtolower($stmt->class->parts[0]) === 'self')
                            || $context->self === $fq_class_name,
                        !$statements_analyzer->isStatic(),
                        $codebase,
                        new CodeLocation($source, $stmt),
                        $statements_analyzer->getSuppressedIssues(),
                        $is_dynamic_this_method
                    ) === false) {
                        // fall through
                    }

                    if ($is_dynamic_this_method) {
                        $fake_method_call_expr = new PhpParser\Node\Expr\MethodCall(
                            new PhpParser\Node\Expr\Variable(
                                'this',
                                $stmt->class->getAttributes()
                            ),
                            $stmt->name,
                            $stmt->args,
                            $stmt->getAttributes()
                        );

                        if (MethodCallAnalyzer::analyze(
                            $statements_analyzer,
                            $fake_method_call_expr,
                            $context
                        ) === false) {
                            return false;
                        }

                        if (isset($fake_method_call_expr->inferredType)) {
                            $stmt->inferredType = $fake_method_call_expr->inferredType;
                        }

                        return null;
                    }
                }

                if (MethodAnalyzer::checkMethodNotDeprecatedOrInternal(
                    $codebase,
                    $context,
                    $method_id,
                    new CodeLocation($statements_analyzer->getSource(), $stmt),
                    $statements_analyzer->getSuppressedIssues()
                ) === false) {
                    // fall through
                }

                $found_generic_params = MethodCallAnalyzer::getClassTemplateParams(
                    $codebase,
                    $class_storage,
                    $fq_class_name,
                    $method_name_lc,
                    $lhs_type_part,
                    null
                );

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

                $fq_class_name = $stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts === ['parent']
                    ? (string) $statements_analyzer->getFQCLN()
                    : $fq_class_name;

                $self_fq_class_name = $fq_class_name;

                $return_type_candidate = null;

                if ($codebase->methods->return_type_provider->has($fq_class_name)) {
                    $return_type_candidate = $codebase->methods->return_type_provider->getReturnType(
                        $statements_analyzer,
                        $fq_class_name,
                        $stmt->name->name,
                        $stmt->args,
                        $context,
                        new CodeLocation($statements_analyzer->getSource(), $stmt->name)
                    );
                }

                $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);

                if (!$return_type_candidate && $declaring_method_id && $declaring_method_id !== $method_id) {
                    list($declaring_fq_class_name, $declaring_method_name) = explode('::', $declaring_method_id);

                    if ($codebase->methods->return_type_provider->has($declaring_fq_class_name)) {
                        $return_type_candidate = $codebase->methods->return_type_provider->getReturnType(
                            $statements_analyzer,
                            $declaring_fq_class_name,
                            $declaring_method_name,
                            $stmt->args,
                            $context,
                            new CodeLocation($statements_analyzer->getSource(), $stmt->name),
                            null,
                            $fq_class_name,
                            $stmt->name->name
                        );
                    }
                }

                if (!$return_type_candidate) {
                    $return_type_candidate = $codebase->methods->getMethodReturnType(
                        $method_id,
                        $self_fq_class_name,
                        $args
                    );

                    if ($return_type_candidate) {
                        $return_type_candidate = clone $return_type_candidate;

                        if ($found_generic_params) {
                            $return_type_candidate->replaceTemplateTypesWithArgTypes(
                                $found_generic_params
                            );
                        }

                        $return_type_candidate = ExpressionAnalyzer::fleshOutType(
                            $codebase,
                            $return_type_candidate,
                            $self_fq_class_name,
                            $fq_class_name
                        );

                        $return_type_location = $codebase->methods->getMethodReturnTypeLocation(
                            $method_id,
                            $secondary_return_type_location
                        );

                        if ($secondary_return_type_location) {
                            $return_type_location = $secondary_return_type_location;
                        }

                        // only check the type locally if it's defined externally
                        if ($return_type_location && !$config->isInProjectDirs($return_type_location->file_path)) {
                            $return_type_candidate->check(
                                $statements_analyzer,
                                new CodeLocation($source, $stmt),
                                $statements_analyzer->getSuppressedIssues(),
                                $context->phantom_classes
                            );
                        }
                    }
                }

                $method_storage = $codebase->methods->getUserMethodStorage($method_id);

                if ($method_storage) {
                    if ($method_storage->assertions) {
                        self::applyAssertionsToContext(
                            $stmt->name,
                            $method_storage->assertions,
                            $stmt->args,
                            $found_generic_params ?: [],
                            $context,
                            $statements_analyzer
                        );
                    }

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

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

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

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

                    if ($appearing_method_id && $declaring_method_id) {
                        foreach ($config->after_method_checks as $plugin_fq_class_name) {
                            $plugin_fq_class_name::afterMethodCallAnalysis(
                                $stmt,
                                $method_id,
                                $appearing_method_id,
                                $declaring_method_id,
                                $context,
                                $source,
                                $codebase,
                                $file_manipulations,
                                $return_type_candidate
                            );
                        }
                    }

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

                if ($return_type_candidate) {
                    if (isset($stmt->inferredType)) {
                        $stmt->inferredType = Type::combineUnionTypes($stmt->inferredType, $return_type_candidate);
                    } else {
                        $stmt->inferredType = $return_type_candidate;
                    }
                }
            } else {
                if (!$context->ignore_variable_method) {
                    $codebase->analyzer->addMixedMemberName(
                        strtolower($fq_class_name) . '::',
                        $context->calling_method_id ?: $statements_analyzer->getFileName()
                    );
                }

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

            if ($codebase->store_node_types && $method_id) {
                /** @psalm-suppress PossiblyInvalidArgument never a string, PHP Parser bug */
                $codebase->analyzer->addNodeReference(
                    $statements_analyzer->getFilePath(),
                    $stmt->name,
                    $method_id . '()'
                );
            }

            if ($codebase->store_node_types
                && (!$context->collect_initializations
                    && !$context->collect_mutations)
                && isset($stmt->inferredType)
            ) {
                /** @psalm-suppress PossiblyInvalidArgument never a string, PHP Parser bug */
                $codebase->analyzer->addNodeType(
                    $statements_analyzer->getFilePath(),
                    $stmt->name,
                    (string) $stmt->inferredType
                );
            }
        }

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

        if (!$config->remember_property_assignments_after_call && !$context->collect_initializations) {
            $context->removeAllObjectVars();
        }
    }
1205513
private void updateMethodMap(Map<RequestMethod, List<Integer>> methodMap, Integer roleId, String methodMask) {
        for (int i = 0; i < RoleResourceConstant.METHOD_NUM; ++i) {
            if (methodMask.charAt(i) == RoleResourceConstant.METHOD_IS_ACCESSIBLE) {
                RequestMethod curMethod = RoleResourceConstant.IND_METHOD_MAP.get(i);

                // update List<roleId>
                List<Integer> roleIdList = methodMap.get(curMethod);
                if (roleIdList == null) {
                    roleIdList = new ArrayList<Integer>();
                    methodMap.put(curMethod, roleIdList);
                }
                roleIdList.add(roleId);
            }
        }
    }
195354
public function getMethodParams(
        $method_id,
        StatementsSource $source = null,
        array $args = null,
        Context $context = null
    ) : array {
        list($fq_class_name, $method_name) = explode('::', $method_id);

        if ($this->params_provider->has($fq_class_name)) {
            $method_params = $this->params_provider->getMethodParams(
                $fq_class_name,
                $method_name,
                $args,
                $source,
                $context
            );

            if ($method_params !== null) {
                return $method_params;
            }
        }

        $declaring_method_id = $this->getDeclaringMethodId($method_id);

        // functions
        if (CallMap::inCallMap($declaring_method_id ?: $method_id)) {
            $declaring_fq_class_name = explode('::', $declaring_method_id ?: $method_id)[0];

            $class_storage = $this->classlike_storage_provider->get($declaring_fq_class_name);

            if (!$class_storage->stubbed) {
                $function_param_options = CallMap::getParamsFromCallMap($declaring_method_id ?: $method_id);

                if ($function_param_options === null) {
                    throw new \UnexpectedValueException(
                        'Not expecting $function_param_options to be null for ' . $declaring_method_id
                    );
                }

                if (!$source || $args === null || count($function_param_options) === 1) {
                    return $function_param_options[0];
                }

                if ($context && $source instanceof \Psalm\Internal\Analyzer\StatementsAnalyzer) {
                    foreach ($args as $arg) {
                        \Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(
                            $source,
                            $arg->value,
                            $context
                        );
                    }
                }

                return FunctionLikeAnalyzer::getMatchingParamsFromCallMapOptions(
                    $source->getCodebase(),
                    $function_param_options,
                    $args
                );
            }
        }

        if ($declaring_method_id) {
            $storage = $this->getStorage($declaring_method_id);

            $params = $storage->params;

            if ($storage->has_docblock_param_types) {
                return $params;
            }

            $appearing_method_id = $this->getAppearingMethodId($declaring_method_id);

            if (!$appearing_method_id) {
                return $params;
            }

            list($appearing_fq_class_name, $appearing_method_name) = explode('::', $appearing_method_id);

            $class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name);

            if (!isset($class_storage->overridden_method_ids[$appearing_method_name])) {
                return $params;
            }

            if (!isset($class_storage->documenting_method_ids[$appearing_method_name])) {
                return $params;
            }

            $overridden_method_id = $class_storage->documenting_method_ids[$appearing_method_name];
            $overridden_storage = $this->getStorage($overridden_method_id);

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

            foreach ($params as $i => $param) {
                if (isset($overridden_storage->params[$i]->type)
                    && $overridden_storage->params[$i]->has_docblock_type
                    && $overridden_storage->params[$i]->name === $param->name
                ) {
                    $params[$i] = clone $param;
                    /** @var Type\Union $params[$i]->type */
                    $params[$i]->type = clone $overridden_storage->params[$i]->type;

                    if ($source) {
                        $params[$i]->type = self::localizeParamType(
                            $source->getCodebase(),
                            $params[$i]->type,
                            $appearing_fq_class_name,
                            $overriding_fq_class_name
                        );
                    }

                    if ($params[$i]->signature_type
                        && $params[$i]->signature_type->isNullable()
                    ) {
                        $params[$i]->type->addType(new Type\Atomic\TNull);
                    }

                    $params[$i]->type_location = $overridden_storage->params[$i]->type_location;
                }
            }

            return $params;
        }

        throw new \UnexpectedValueException('Cannot get method params for ' . $method_id);
    }
904976
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Stmt\Return_ $stmt,
        Context $context
    ) {
        $doc_comment_text = (string)$stmt->getDocComment();

        $var_comments = [];
        $var_comment_type = null;

        $source = $statements_analyzer->getSource();

        $codebase = $statements_analyzer->getCodebase();

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

            foreach ($var_comments as $var_comment) {
                $comment_type = ExpressionAnalyzer::fleshOutType(
                    $codebase,
                    $var_comment->type,
                    $context->self,
                    $context->self
                );

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

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

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

            if ($var_comment_type) {
                $stmt->inferredType = $var_comment_type;
            } elseif (isset($stmt->expr->inferredType)) {
                $stmt->inferredType = $stmt->expr->inferredType;

                if ($stmt->inferredType->isNever()) {
                    if (IssueBuffer::accepts(
                        new NoValue(
                            'This function or method call never returns output',
                            new CodeLocation($source, $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        // fall through
                    }

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

                if ($stmt->inferredType->isVoid()) {
                    $stmt->inferredType = Type::getNull();
                }
            } else {
                $stmt->inferredType = Type::getMixed();
            }
        } else {
            $stmt->inferredType = Type::getVoid();
        }

        if ($source instanceof FunctionLikeAnalyzer
            && !($source->getSource() instanceof TraitAnalyzer)
        ) {
            $source->addReturnTypes($context);

            $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt);

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

            $cased_method_id = $source->getCorrectlyCasedMethodId();

            if ($stmt->expr) {
                if ($storage->return_type && !$storage->return_type->hasMixed()) {
                    $inferred_type = ExpressionAnalyzer::fleshOutType(
                        $codebase,
                        $stmt->inferredType,
                        $source->getFQCLN(),
                        $source->getFQCLN()
                    );

                    $local_return_type = $source->getLocalReturnType($storage->return_type);

                    if ($local_return_type->isGenerator() && $storage->has_yield) {
                        return null;
                    }

                    if ($stmt->inferredType->hasMixed()) {
                        if ($local_return_type->isVoid() || $local_return_type->isNever()) {
                            if (IssueBuffer::accepts(
                                new InvalidReturnStatement(
                                    'No return values are expected for ' . $cased_method_id,
                                    new CodeLocation($source, $stmt->expr)
                                ),
                                $statements_analyzer->getSuppressedIssues()
                            )) {
                                return false;
                            }
                        }

                        if (!$context->collect_initializations
                            && !$context->collect_mutations
                            && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
                            && !($source->getSource() instanceof TraitAnalyzer)
                        ) {
                            $codebase->analyzer->incrementMixedCount($statements_analyzer->getFilePath());
                        }

                        if (IssueBuffer::accepts(
                            new MixedReturnStatement(
                                'Could not infer a return type',
                                new CodeLocation($source, $stmt->expr)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }

                        return null;
                    }

                    if (!$context->collect_initializations
                        && !$context->collect_mutations
                        && $statements_analyzer->getFilePath() === $statements_analyzer->getRootFilePath()
                        && !($source->getSource() instanceof TraitAnalyzer)
                    ) {
                        $codebase->analyzer->incrementNonMixedCount($statements_analyzer->getFilePath());
                    }

                    if ($local_return_type->isVoid()) {
                        if (IssueBuffer::accepts(
                            new InvalidReturnStatement(
                                'No return values are expected for ' . $cased_method_id,
                                new CodeLocation($source, $stmt->expr)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }

                        return null;
                    }

                    if (!TypeAnalyzer::isContainedBy(
                        $codebase,
                        $inferred_type,
                        $local_return_type,
                        true,
                        true,
                        $has_scalar_match,
                        $type_coerced,
                        $type_coerced_from_mixed,
                        $to_string_cast,
                        $type_coerced_from_scalar
                    )
                    ) {
                        // is the declared return type more specific than the inferred one?
                        if ($type_coerced) {
                            if ($type_coerced_from_mixed) {
                                if (IssueBuffer::accepts(
                                    new MixedReturnTypeCoercion(
                                        'The type \'' . $stmt->inferredType->getId() . '\' is more general than the'
                                            . ' declared return type \'' . $local_return_type->getId() . '\''
                                            . ' for ' . $cased_method_id,
                                        new CodeLocation($source, $stmt->expr)
                                    ),
                                    $statements_analyzer->getSuppressedIssues()
                                )) {
                                    return false;
                                }
                            } else {
                                if (IssueBuffer::accepts(
                                    new LessSpecificReturnStatement(
                                        'The type \'' . $stmt->inferredType->getId() . '\' is more general than the'
                                            . ' declared return type \'' . $local_return_type->getId() . '\''
                                            . ' for ' . $cased_method_id,
                                        new CodeLocation($source, $stmt->expr)
                                    ),
                                    $statements_analyzer->getSuppressedIssues()
                                )) {
                                    return false;
                                }
                            }

                            foreach ($local_return_type->getTypes() as $local_type_part) {
                                if ($local_type_part instanceof Type\Atomic\TClassString
                                    && $stmt->expr instanceof PhpParser\Node\Scalar\String_
                                ) {
                                    if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                                        $statements_analyzer,
                                        $stmt->expr->value,
                                        new CodeLocation($source, $stmt->expr),
                                        $statements_analyzer->getSuppressedIssues()
                                    ) === false
                                    ) {
                                        return false;
                                    }
                                } elseif ($local_type_part instanceof Type\Atomic\TArray
                                    && $stmt->expr instanceof PhpParser\Node\Expr\Array_
                                ) {
                                    foreach ($local_type_part->type_params[1]->getTypes() as $local_array_type_part) {
                                        if ($local_array_type_part instanceof Type\Atomic\TClassString) {
                                            foreach ($stmt->expr->items as $item) {
                                                if ($item && $item->value instanceof PhpParser\Node\Scalar\String_) {
                                                    if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                                                        $statements_analyzer,
                                                        $item->value->value,
                                                        new CodeLocation($source, $item->value),
                                                        $statements_analyzer->getSuppressedIssues()
                                                    ) === false
                                                    ) {
                                                        return false;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } else {
                            if (IssueBuffer::accepts(
                                new InvalidReturnStatement(
                                    'The type \'' . $stmt->inferredType->getId()
                                        . '\' does not match the declared return '
                                        . 'type \'' . $local_return_type->getId() . '\' for ' . $cased_method_id,
                                    new CodeLocation($source, $stmt->expr)
                                ),
                                $statements_analyzer->getSuppressedIssues()
                            )) {
                                return false;
                            }
                        }
                    }

                    if (!$stmt->inferredType->ignore_nullable_issues
                        && $inferred_type->isNullable()
                        && !$local_return_type->isNullable()
                    ) {
                        if (IssueBuffer::accepts(
                            new NullableReturnStatement(
                                'The declared return type \'' . $local_return_type . '\' for '
                                    . $cased_method_id . ' is not nullable, but the function returns \''
                                        . $inferred_type . '\'',
                                new CodeLocation($source, $stmt->expr)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }
                    }

                    if (!$stmt->inferredType->ignore_falsable_issues
                        && $inferred_type->isFalsable()
                        && !$local_return_type->isFalsable()
                        && !$local_return_type->hasBool()
                        && !$local_return_type->hasScalar()
                    ) {
                        if (IssueBuffer::accepts(
                            new FalsableReturnStatement(
                                'The declared return type \'' . $local_return_type . '\' for '
                                    . $cased_method_id . ' does not allow false, but the function returns \''
                                        . $inferred_type . '\'',
                                new CodeLocation($source, $stmt->expr)
                            ),
                            $statements_analyzer->getSuppressedIssues()
                        )) {
                            return false;
                        }
                    }
                }
            } else {
                if ($storage->signature_return_type
                    && !$storage->signature_return_type->isVoid()
                    && !$storage->has_yield
                ) {
                    if (IssueBuffer::accepts(
                        new InvalidReturnStatement(
                            'Empty return statement is not expected in ' . $cased_method_id,
                            new CodeLocation($source, $stmt)
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        return false;
                    }

                    return null;
                }
            }
        }

        return null;
    }
622246
public static function isMethodVisible(
        $method_id,
        Context $context,
        StatementsSource $source
    ) {
        $codebase = $source->getCodebase();

        list($fq_classlike_name, $method_name) = explode('::', $method_id);

        if ($codebase->methods->visibility_provider->has($fq_classlike_name)) {
            $method_visible = $codebase->methods->visibility_provider->isMethodVisible(
                $source,
                $fq_classlike_name,
                $method_name,
                $context,
                null
            );

            if ($method_visible !== null) {
                return $method_visible;
            }
        }

        $declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);

        if (!$declaring_method_id) {
            // this can happen for methods in the callmap that were not reflected
            return true;
        }

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

        $appearing_method_class = null;

        if ($appearing_method_id) {
            list($appearing_method_class) = explode('::', $appearing_method_id);

            // if the calling class is the same, we know the method exists, so it must be visible
            if ($appearing_method_class === $context->self) {
                return true;
            }
        }

        list($declaring_method_class) = explode('::', $declaring_method_id);

        if ($source->getSource() instanceof TraitAnalyzer && $declaring_method_class === $source->getFQCLN()) {
            return true;
        }

        $storage = $codebase->methods->getStorage($declaring_method_id);

        switch ($storage->visibility) {
            case ClassLikeAnalyzer::VISIBILITY_PUBLIC:
                return true;

            case ClassLikeAnalyzer::VISIBILITY_PRIVATE:
                return $context->self && $appearing_method_class === $context->self;

            case ClassLikeAnalyzer::VISIBILITY_PROTECTED:
                if (!$context->self) {
                    return false;
                }

                if ($appearing_method_class
                    && $codebase->classExtends($appearing_method_class, $context->self)
                ) {
                    return true;
                }

                if ($appearing_method_class
                    && !$codebase->classExtends($context->self, $appearing_method_class)
                ) {
                    return false;
                }
        }

        return true;
    }
5708
private void defineJavadocForContentUri(MethodSpec.Builder builder, SQLiteModelMethod method) {
		String contentUri = method.contentProviderUri().replace("*", "[*]");

		classBuilder.addJavadoc("<tr><td><pre>$L</pre></td><td>{@link $LImpl#$L}</td></tr>\n", contentUri, method.getParent().getName(), method.contentProviderMethodName);
		builder.addJavadoc("<tr><td><pre>$L</pre></td><td>{@link $LImpl#$L}</td></tr>\n", contentUri, method.getParent().getName(), method.contentProviderMethodName);

	}
176370
public function getMethodReturnsByRef($method_id)
    {
        $method_id = $this->getDeclaringMethodId($method_id);

        if (!$method_id) {
            return false;
        }

        list($fq_class_name) = explode('::', $method_id);

        $fq_class_storage = $this->classlike_storage_provider->get($fq_class_name);

        if (!$fq_class_storage->user_defined && CallMap::inCallMap($method_id)) {
            return false;
        }

        $storage = $this->getStorage($method_id);

        return $storage->returns_by_ref;
    }
1233801
public static function analyze(
        StatementsAnalyzer $statements_analyzer,
        PhpParser\Node\Stmt\TryCatch $stmt,
        Context $context
    ) {
        $catch_actions = [];
        $all_catches_leave = true;

        $codebase = $statements_analyzer->getCodebase();

        /** @var int $i */
        foreach ($stmt->catches as $i => $catch) {
            $catch_actions[$i] = ScopeAnalyzer::getFinalControlActions(
                $catch->stmts,
                $codebase->config->exit_functions
            );
            $all_catches_leave = $all_catches_leave && !in_array(ScopeAnalyzer::ACTION_NONE, $catch_actions[$i], true);
        }

        $existing_thrown_exceptions = $context->possibly_thrown_exceptions;

        /**
         * @var array<string, array<array-key, CodeLocation>>
         */
        $context->possibly_thrown_exceptions = [];

        if ($all_catches_leave) {
            $try_context = $context;
        } else {
            $try_context = clone $context;

            if ($codebase->alter_code) {
                $try_context->branch_point = $try_context->branch_point ?: (int) $stmt->getAttribute('startFilePos');
            }
        }

        $assigned_var_ids = $try_context->assigned_var_ids;
        $context->assigned_var_ids = [];

        $old_unreferenced_vars = $try_context->unreferenced_vars;
        $newly_unreferenced_vars = [];
        $reassigned_vars = [];

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

        /** @var array<string, bool> */
        $newly_assigned_var_ids = $context->assigned_var_ids;

        $context->assigned_var_ids = array_merge(
            $assigned_var_ids,
            $newly_assigned_var_ids
        );

        if ($try_context !== $context) {
            foreach ($context->vars_in_scope as $var_id => $type) {
                if (!isset($try_context->vars_in_scope[$var_id])) {
                    $try_context->vars_in_scope[$var_id] = clone $type;
                    $try_context->vars_in_scope[$var_id]->from_docblock = true;
                    $type->possibly_undefined_from_try = true;
                } else {
                    $try_context->vars_in_scope[$var_id] = Type::combineUnionTypes(
                        $try_context->vars_in_scope[$var_id],
                        $type
                    );
                }
            }

            $try_context->vars_possibly_in_scope = $context->vars_possibly_in_scope;

            $context->referenced_var_ids = array_merge(
                $try_context->referenced_var_ids,
                $context->referenced_var_ids
            );

            if ($context->collect_references) {
                $newly_unreferenced_vars = array_merge(
                    $newly_unreferenced_vars,
                    array_diff_key(
                        $context->unreferenced_vars,
                        $old_unreferenced_vars
                    )
                );

                foreach ($context->unreferenced_vars as $var_id => $locations) {
                    if (isset($old_unreferenced_vars[$var_id])
                        && $old_unreferenced_vars[$var_id] !== $locations
                    ) {
                        $reassigned_vars[$var_id] = $locations;
                    }
                }
            }
        }

        $try_leaves_loop = $context->loop_scope
            && $context->loop_scope->final_actions
            && !in_array(ScopeAnalyzer::ACTION_NONE, $context->loop_scope->final_actions, true);

        if (!$all_catches_leave) {
            foreach ($newly_assigned_var_ids as $assigned_var_id => $_) {
                $context->removeVarFromConflictingClauses($assigned_var_id);
            }
        } else {
            foreach ($newly_assigned_var_ids as $assigned_var_id => $_) {
                $try_context->removeVarFromConflictingClauses($assigned_var_id);
            }
        }

        // at this point we have two contexts – $context, in which it is assumed that everything was fine,
        // and $try_context - which allows all variables to have the union of the values before and after
        // the try was applied
        $original_context = clone $try_context;

        $issues_to_suppress = [
            'RedundantCondition',
            'RedundantConditionGivenDocblockType',
            'TypeDoesNotContainNull',
            'TypeDoesNotContainType',
        ];

        /** @var int $i */
        foreach ($stmt->catches as $i => $catch) {
            $catch_context = clone $original_context;

            $fq_catch_classes = [];

            $catch_var_name = $catch->var->name;

            if (!is_string($catch_var_name)) {
                throw new \UnexpectedValueException('Catch var name must be a string');
            }

            foreach ($catch->types as $catch_type) {
                $fq_catch_class = ClassLikeAnalyzer::getFQCLNFromNameObject(
                    $catch_type,
                    $statements_analyzer->getAliases()
                );

                if ($original_context->check_classes) {
                    if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
                        $statements_analyzer,
                        $fq_catch_class,
                        new CodeLocation($statements_analyzer->getSource(), $catch_type, $context->include_location),
                        $statements_analyzer->getSuppressedIssues(),
                        false
                    ) === false) {
                        return false;
                    }
                }

                if (($codebase->classExists($fq_catch_class)
                        && strtolower($fq_catch_class) !== 'exception'
                        && !($codebase->classExtends($fq_catch_class, 'Exception')
                            || $codebase->classImplements($fq_catch_class, 'Throwable')))
                    || ($codebase->interfaceExists($fq_catch_class)
                        && strtolower($fq_catch_class) !== 'throwable'
                        && !$codebase->interfaceExtends($fq_catch_class, 'Throwable'))
                ) {
                    if (IssueBuffer::accepts(
                        new InvalidCatch(
                            'Class/interface ' . $fq_catch_class . ' cannot be caught',
                            new CodeLocation($statements_analyzer->getSource(), $stmt),
                            $fq_catch_class
                        ),
                        $statements_analyzer->getSuppressedIssues()
                    )) {
                        return false;
                    }
                }

                $fq_catch_classes[] = $fq_catch_class;
            }

            $potentially_caught_classes = array_flip($fq_catch_classes);

            if ($catch_context->collect_exceptions) {
                foreach ($fq_catch_classes as $fq_catch_class) {
                    $fq_catch_class_lower = strtolower($fq_catch_class);

                    foreach ($context->possibly_thrown_exceptions as $exception_fqcln => $_) {
                        $exception_fqcln_lower = strtolower($exception_fqcln);

                        if ($exception_fqcln_lower === $fq_catch_class_lower) {
                            unset($context->possibly_thrown_exceptions[$exception_fqcln]);
                            continue;
                        }

                        if ($codebase->classExists($exception_fqcln)
                            && $codebase->classExtendsOrImplements(
                                $exception_fqcln,
                                $fq_catch_class
                            )
                        ) {
                            unset($context->possibly_thrown_exceptions[$exception_fqcln]);
                            continue;
                        }

                        if ($codebase->interfaceExists($exception_fqcln)
                            && $codebase->interfaceExtends(
                                $exception_fqcln,
                                $fq_catch_class
                            )
                        ) {
                            unset($context->possibly_thrown_exceptions[$exception_fqcln]);
                            continue;
                        }
                    }
                }
            }

            $catch_var_id = '$' . $catch_var_name;

            $catch_context->vars_in_scope[$catch_var_id] = new Union(
                array_map(
                    /**
                     * @param string $fq_catch_class
                     *
                     * @return Type\Atomic
                     */
                    function ($fq_catch_class) use ($codebase) {
                        $catch_class_type = new TNamedObject($fq_catch_class);

                        if (version_compare(PHP_VERSION, '7.0.0dev', '>=')
                            && $codebase->interfaceExists($fq_catch_class)
                            && !$codebase->interfaceExtends($fq_catch_class, 'Throwable')
                        ) {
                            $catch_class_type->addIntersectionType(new TNamedObject('Throwable'));
                        }

                        return $catch_class_type;
                    },
                    $fq_catch_classes
                )
            );

            // discard all clauses because crazy stuff may have happened in try block
            $catch_context->clauses = [];

            $catch_context->vars_possibly_in_scope[$catch_var_id] = true;

            if (!$statements_analyzer->hasVariable($catch_var_id)) {
                $location = new CodeLocation(
                    $statements_analyzer,
                    $catch->var,
                    $context->include_location
                );
                $statements_analyzer->registerVariable(
                    $catch_var_id,
                    $location,
                    $try_context->branch_point
                );
                $catch_context->unreferenced_vars[$catch_var_id] = [$location->getHash() => $location];
            }

            // this registers the variable to avoid unfair deadcode issues
            $catch_context->hasVariable($catch_var_id, $statements_analyzer);

            $suppressed_issues = $statements_analyzer->getSuppressedIssues();

            foreach ($issues_to_suppress as $issue_to_suppress) {
                if (!in_array($issue_to_suppress, $suppressed_issues, true)) {
                    $statements_analyzer->addSuppressedIssues([$issue_to_suppress]);
                }
            }

            $statements_analyzer->analyze($catch->stmts, $catch_context);

            foreach ($issues_to_suppress as $issue_to_suppress) {
                if (!in_array($issue_to_suppress, $suppressed_issues, true)) {
                    $statements_analyzer->removeSuppressedIssues([$issue_to_suppress]);
                }
            }

            $context->referenced_var_ids = array_merge(
                $catch_context->referenced_var_ids,
                $context->referenced_var_ids
            );

            if ($context->collect_references && $catch_actions[$i] !== [ScopeAnalyzer::ACTION_END]) {
                foreach ($context->unreferenced_vars as $var_id => $_) {
                    if (!isset($catch_context->unreferenced_vars[$var_id])) {
                        unset($context->unreferenced_vars[$var_id]);
                    }
                }

                $newly_unreferenced_vars = array_merge(
                    $newly_unreferenced_vars,
                    array_diff_key(
                        $catch_context->unreferenced_vars,
                        $old_unreferenced_vars
                    )
                );

                foreach ($catch_context->unreferenced_vars as $var_id => $locations) {
                    if (!isset($old_unreferenced_vars[$var_id])
                        && (isset($context->unreferenced_vars[$var_id])
                            || isset($newly_assigned_var_ids[$var_id]))
                    ) {
                        $statements_analyzer->registerVariableUses($locations);
                    } elseif (isset($old_unreferenced_vars[$var_id])
                        && $old_unreferenced_vars[$var_id] !== $locations
                    ) {
                        $statements_analyzer->registerVariableUses($locations);
                    }
                }
            }

            if ($context->collect_exceptions) {
                $potentially_caught_classes = array_diff_key(
                    $potentially_caught_classes,
                    $context->possibly_thrown_exceptions
                );
            }

            if ($catch_actions[$i] !== [ScopeAnalyzer::ACTION_END]) {
                foreach ($catch_context->vars_in_scope as $var_id => $type) {
                    if (isset($context->vars_in_scope[$var_id])
                        && $context->vars_in_scope[$var_id]->getId() !== $type->getId()
                    ) {
                        $context->vars_in_scope[$var_id] = Type::combineUnionTypes(
                            $context->vars_in_scope[$var_id],
                            $type
                        );
                    }
                }

                $context->vars_possibly_in_scope = array_merge(
                    $catch_context->vars_possibly_in_scope,
                    $context->vars_possibly_in_scope
                );
            } elseif ($stmt->finally) {
                $context->vars_possibly_in_scope = array_merge(
                    $catch_context->vars_possibly_in_scope,
                    $context->vars_possibly_in_scope
                );
            }
        }

        if ($context->loop_scope
            && !$try_leaves_loop
            && !in_array(ScopeAnalyzer::ACTION_NONE, $context->loop_scope->final_actions, true)
        ) {
            $context->loop_scope->final_actions[] = ScopeAnalyzer::ACTION_NONE;
        }

        if ($stmt->finally) {
            $suppressed_issues = $statements_analyzer->getSuppressedIssues();

            foreach ($issues_to_suppress as $issue_to_suppress) {
                if (!in_array($issue_to_suppress, $suppressed_issues, true)) {
                    $statements_analyzer->addSuppressedIssues([$issue_to_suppress]);
                }
            }

            $statements_analyzer->analyze($stmt->finally->stmts, $context);

            foreach ($issues_to_suppress as $issue_to_suppress) {
                if (!in_array($issue_to_suppress, $suppressed_issues, true)) {
                    $statements_analyzer->removeSuppressedIssues([$issue_to_suppress]);
                }
            }
        }

        if ($context->collect_references) {
            foreach ($old_unreferenced_vars as $var_id => $locations) {
                if (isset($context->unreferenced_vars[$var_id])
                    && $context->unreferenced_vars[$var_id] !== $locations
                ) {
                    $statements_analyzer->registerVariableUses($locations);
                }
            }
        }

        foreach ($existing_thrown_exceptions as $possibly_thrown_exception => $codelocations) {
            foreach ($codelocations as $hash => $codelocation) {
                $context->possibly_thrown_exceptions[$possibly_thrown_exception][$hash] = $codelocation;
            }
        }

        return null;
    }
663815
private void checkSQL(MethodDeclaration method, AnnotationProcessorEnvironment env) {

        final JdbcControl.SQL methodSQL = method.getAnnotation(JdbcControl.SQL.class);
        if (methodSQL == null) {
            return;
        }

        //
        // check for empty SQL statement member
        //
        if (methodSQL.statement() == null || methodSQL.statement().length() == 0) {
            env.getMessager().printError(method.getPosition(),
                                         getResourceString("jdbccontrol.empty.statement", method.getSimpleName()));
            return;
        }

        //
        // Make sure maxrows is not set to some negative number other than -1
        //
        int maxRows = methodSQL.maxRows();
        if (maxRows < JdbcControl.MAXROWS_ALL) {
            env.getMessager().printError(method.getPosition(),
                                         getResourceString("jdbccontrol.bad.maxrows", method.getSimpleName(),maxRows));
            return;
        }

        //
        //
        // parse the SQL
        //
        //
        SqlParser _p = new SqlParser();
        SqlStatement _statement;
        try {
            _statement = _p.parse(methodSQL.statement());
        } catch (ControlException ce) {
            env.getMessager().printError(method.getPosition(),  getResourceString("jdbccontrol.bad.parse",
                                                                                  method.getSimpleName(),
                                                                                  ce.toString()));
            return;
        }

        //
        // Check that the any statement element params (delimited by '{' and '}' can be
        // matched to method parameter names. NOTE: This check is only valid on non-compiled files,
        // once compiled to a class file method parameter names are replaced with 'arg0', 'arg1', etc.
        // and cannot be used for this check.
        //
        try {
            ParameterChecker.checkReflectionParameters(_statement, method);
        } catch (ControlException e) {
            env.getMessager().printError(method.getPosition(), e.getMessage());
            return;
        }

        //
        // check for case of generatedKeyColumns being set, when getGeneratedKeys is not set to true
        //
        final boolean getGeneratedKeys = methodSQL.getGeneratedKeys();
        final String[] generatedKeyColumnNames = methodSQL.generatedKeyColumnNames();
        final int[] generatedKeyIndexes = methodSQL.generatedKeyColumnIndexes();
        if (!getGeneratedKeys && (generatedKeyColumnNames.length != 0 || generatedKeyIndexes.length != 0)) {
            env.getMessager().printError(method.getPosition(),
                                         getResourceString("jdbccontrol.genkeys", method.getSimpleName()));
            return;
        }

        //
        // check that both generatedKeyColumnNames and generatedKeyColumnIndexes are not set
        //
        if (generatedKeyColumnNames.length > 0 && generatedKeyIndexes.length > 0) {
            env.getMessager().printError(method.getPosition(),
                                         getResourceString("jdbccontrol.genkeycolumns", method.getSimpleName()));

            return;
        }

        //
        // batch update methods must return int[]
        //
        final boolean batchUpdate = methodSQL.batchUpdate();
        final TypeMirror returnType = method.getReturnType();
        if (batchUpdate) {
            if (returnType instanceof ArrayType) {
                final TypeMirror aType = ((ArrayType) returnType).getComponentType();
                if (aType instanceof PrimitiveType == false
                        || ((PrimitiveType) aType).getKind() != PrimitiveType.Kind.INT) {
                    env.getMessager().printError(method.getPosition(),
                                                 getResourceString("jdbccontrol.batchupdate", method.getSimpleName()));
                    return;
                }
            } else if (returnType instanceof VoidType == false) {
                env.getMessager().printError(method.getPosition(),
                                             getResourceString("jdbccontrol.batchupdate", method.getSimpleName()));
                return;
            }

        }

        //
        // iterator type check match
        //
        if (returnType instanceof InterfaceType) {
            String iName = ((InterfaceType) returnType).getDeclaration().getQualifiedName();
            if ("java.util.Iterator".equals(iName)) {
                String iteratorClassName = null;
                try {
                    // this should always except
                    methodSQL.iteratorElementType();
                } catch (MirroredTypeException mte) {
                    iteratorClassName = mte.getQualifiedName();
                }

                if ("org.apache.beehive.controls.system.jdbc.JdbcControl.UndefinedIteratorType".equals(iteratorClassName)) {
                    env.getMessager().printError(method.getPosition(),
                                                 getResourceString("jdbccontrol.iterator.returntype",
                                                                   method.getSimpleName()));
                    return;
                }
            }
        }

        //
        // scrollable result set check
        //
        final JdbcControl.ScrollType scrollable = methodSQL.scrollableResultSet();
        switch (scrollable) {
            case SCROLL_INSENSITIVE:
            case SCROLL_SENSITIVE:
            case SCROLL_INSENSITIVE_UPDATABLE:
            case SCROLL_SENSITIVE_UPDATABLE:
            case FORWARD_ONLY_UPDATABLE:
                String typeName = null;
                if (returnType instanceof DeclaredType) {
                    typeName = ((DeclaredType) returnType).getDeclaration().getQualifiedName();
                }

                if (typeName == null || !"java.sql.ResultSet".equals(typeName)) {
                    env.getMessager().printError(method.getPosition(),
                                                 getResourceString("jdbccontrol.scrollresultset",
                                                                   method.getSimpleName()));
                    return;
                }
            case FORWARD_ONLY:
            default:
                break;
        }

        return;
    }