作者:mgonya
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeDuplicateClass(CodeBase $code_base, Clazz $clazz)
{
// Determine if its a duplicate by looking to see if
// the FQSEN is suffixed with an alternate ID.
if (!$clazz->getFQSEN()->isAlternate()) {
return;
}
$original_fqsen = $clazz->getFQSEN()->getCanonicalFQSEN();
if (!$code_base->hasClassWithFQSEN($original_fqsen)) {
// If there's a missing class we'll catch that
// elsewhere
return;
}
// Get the original class
$original_class = $code_base->getClassByFQSEN($original_fqsen);
// Check to see if the original definition was from
// an internal class
if ($original_class->isInternal()) {
Log::err(Log::EREDEF, "{$clazz} defined at " . "{$clazz->getContext()->getFile()}:{$clazz->getContext()->getLineNumberStart()} " . "was previously defined as {$original_class} internally", $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart());
// Otherwise, print the coordinates of the original
// definition
} else {
Log::err(Log::EREDEF, "{$clazz} defined at " . "{$clazz->getContext()->getFile()}:{$clazz->getContext()->getLineNumberStart()} " . "was previously defined as {$original_class} at " . "{$original_class->getContext()->getFile()}:{$original_class->getContext()->getLineNumberStart()}", $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart());
}
return;
}
作者:actan
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeDuplicateClass(CodeBase $code_base, Clazz $clazz)
{
// Determine if its a duplicate by looking to see if
// the FQSEN is suffixed with an alternate ID.
if (!$clazz->getFQSEN()->isAlternate()) {
return;
}
$original_fqsen = $clazz->getFQSEN()->getCanonicalFQSEN();
if (!$code_base->hasClassWithFQSEN($original_fqsen)) {
// If there's a missing class we'll catch that
// elsewhere
return;
}
// Get the original class
$original_class = $code_base->getClassByFQSEN($original_fqsen);
// Check to see if the original definition was from
// an internal class
if ($original_class->isInternal()) {
Issue::emit(Issue::RedefineClassInternal, $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart(), (string) $clazz, $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart(), (string) $original_class);
// Otherwise, print the coordinates of the original
// definition
} else {
Issue::emit(Issue::RedefineClass, $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart(), (string) $clazz, $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart(), (string) $original_class, $original_class->getContext()->getFile(), $original_class->getContext()->getLineNumberStart());
}
return;
}
作者:actan
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeParentConstructorCalled(CodeBase $code_base, Clazz $clazz)
{
// Only look at classes configured to require a call
// to its parent constructor
if (!in_array($clazz->getName(), Config::get()->parent_constructor_required)) {
return;
}
// Don't worry about internal classes
if ($clazz->isInternal()) {
return;
}
// Don't worry if there's no parent class
if (!$clazz->hasParentClassFQSEN()) {
return;
}
if (!$code_base->hasClassWithFQSEN($clazz->getParentClassFQSEN())) {
// This is an error, but its caught elsewhere. We'll
// just roll through looking for other errors
return;
}
$parent_clazz = $code_base->getClassByFQSEN($clazz->getParentClassFQSEN());
if (!$parent_clazz->isAbstract() && !$clazz->getIsParentConstructorCalled()) {
Issue::emit(Issue::TypeParentConstructorCalled, $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart(), (string) $clazz->getFQSEN(), (string) $parent_clazz->getFQSEN());
}
}
作者:akraba
项目:pha
/**
* @return bool
* True if the FQSEN exists. If not, a log line is emitted
*/
private static function fqsenExistsForClass(FQSEN $fqsen, CodeBase $code_base, Clazz $clazz) : bool
{
if (!$code_base->hasClassWithFQSEN($fqsen)) {
Log::err(Log::EUNDEF, "Trying to inherit from unknown class {$fqsen}", $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart());
return false;
}
return true;
}
作者:mgonya
项目:pha
/**
* @return bool
* True if the FQSEN exists. If not, a log line is emitted
*/
private static function fqsenExistsForClass(FQSEN $fqsen, CodeBase $code_base, Clazz $clazz, string $message_template) : bool
{
if (!$code_base->hasClassWithFQSEN($fqsen)) {
Log::err(Log::EUNDEF, sprintf($message_template, $fqsen), $clazz->getContext()->getFile(), $clazz->getContext()->getLineNumberStart());
return false;
}
return true;
}
作者:tpun
项目:pha
/**
* @return bool
* True if the FQSEN exists. If not, a log line is emitted
*/
private static function fqsenExistsForClass(FQSEN $fqsen, CodeBase $code_base, Clazz $clazz, string $issue_type) : bool
{
if (!$code_base->hasClassWithFQSEN($fqsen)) {
Issue::maybeEmit($code_base, $clazz->getContext(), $issue_type, $clazz->getFileRef()->getLineNumberStart(), (string) $fqsen);
return false;
}
return true;
}
作者:black-silenc
项目:pha
/**
* @return Clazz
* The class that defined this element
*
* @throws CodeBaseException
* An exception may be thrown if we can't find the
* class
*/
public function getDefiningClass(CodeBase $code_base) : Clazz
{
$class_fqsen = $this->getDefiningClassFQSEN();
if (!$code_base->hasClassWithFQSEN($class_fqsen)) {
throw new CodeBaseException($class_fqsen, "Defining class {$class_fqsen} for {$this->getFQSEN()} not found");
}
return $code_base->getClassByFQSEN($class_fqsen);
}
作者:Jvbzephi
项目:pha
public function testMethodInCodeBase()
{
$context = $this->contextForCode("\n namespace A;\n Class B {\n public function c() {\n return 42;\n }\n }\n ");
$class_fqsen = FullyQualifiedClassName::fromFullyQualifiedString('\\A\\b');
self::assertTrue($this->code_base->hasClassWithFQSEN($class_fqsen), "Class with FQSEN {$class_fqsen} not found");
$clazz = $this->code_base->getClassByFQSEN($class_fqsen);
self::assertTrue($clazz->hasMethodWithName($this->code_base, 'c'), "Method with FQSEN not found");
}
作者:ablyle
项目:pha
/**
* @return Method
*/
public function getClosure() : Func
{
$closure_fqsen = FullyQualifiedFunctionName::fromClosureInContext($this->context);
if (!$this->code_base->hasFunctionWithFQSEN($closure_fqsen)) {
throw new CodeBaseException($closure_fqsen, "Could not find closure {$closure_fqsen}");
}
return $this->code_base->getFunctionByFQSEN($closure_fqsen);
}
作者:black-silenc
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeDuplicateFunction(CodeBase $code_base, FunctionInterface $method)
{
$fqsen = $method->getFQSEN();
if (!$fqsen->isAlternate()) {
return;
}
$original_fqsen = $fqsen->getCanonicalFQSEN();
if (!$code_base->hasMethod($original_fqsen)) {
return;
}
$original_method = $code_base->getMethod($original_fqsen);
$method_name = $method->getName();
if ($original_method->isInternal()) {
Issue::emit(Issue::RedefineFunctionInternal, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart(), $method_name, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart());
} else {
Issue::emit(Issue::RedefineFunction, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart(), $method_name, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart(), $original_method->getFileRef()->getFile(), $original_method->getFileRef()->getLineNumberStart());
}
}
作者:black-silenc
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeParameterTypes(CodeBase $code_base, FunctionInterface $method)
{
// Look at each method parameter
foreach ($method->getParameterList() as $parameter) {
$union_type = $parameter->getUnionType();
// Look at each type in the parameter's Union Type
foreach ($union_type->getTypeSet() as $type) {
// If its a native type or a reference to
// self, its OK
if ($type->isNativeType() || $type->isSelfType()) {
continue;
}
// Otherwise, make sure the class exists
$type_fqsen = $type->asFQSEN();
if (!$code_base->hasClassWithFQSEN($type_fqsen)) {
Issue::emit(Issue::UndeclaredTypeParameter, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart(), (string) $type_fqsen);
}
}
}
}
作者:misdreavus7
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeParameterTypes(CodeBase $code_base, Method $method)
{
// Look at each method parameter
foreach ($method->getParameterList() as $parameter) {
$union_type = $parameter->getUnionType();
// Look at each type in the parameter's Union Type
foreach ($union_type->getTypeList() as $type) {
// If its a native type or a reference to
// self, its OK
if ($type->isNativeType() || $type->isSelfType()) {
continue;
}
// Otherwise, make sure the class exists
$type_fqsen = $type->asFQSEN();
if (!$code_base->hasClassWithFQSEN($type_fqsen)) {
Log::err(Log::EUNDEF, "parameter of undeclared type {$type_fqsen}", $method->getContext()->getFile(), $method->getContext()->getLineNumberStart());
}
}
}
}
作者:tpun
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeDuplicateFunction(CodeBase $code_base, FunctionInterface $method)
{
$fqsen = $method->getFQSEN();
if (!$fqsen->isAlternate()) {
return;
}
$original_fqsen = $fqsen->getCanonicalFQSEN();
if ($original_fqsen instanceof FullyQualifiedFunctionName) {
if (!$code_base->hasFunctionWithFQSEN($original_fqsen)) {
return;
}
$original_method = $code_base->getFunctionByFQSEN($original_fqsen);
} else {
if (!$code_base->hasMethodWithFQSEN($original_fqsen)) {
return;
}
$original_method = $code_base->getMethodByFQSEN($original_fqsen);
}
$method_name = $method->getName();
if (!$method->hasSuppressIssue(Issue::RedefineFunction)) {
if ($original_method->isInternal()) {
Issue::maybeEmit($code_base, $method->getContext(), Issue::RedefineFunctionInternal, $method->getFileRef()->getLineNumberStart(), $method_name, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart());
} else {
Issue::maybeEmit($code_base, $method->getContext(), Issue::RedefineFunction, $method->getFileRef()->getLineNumberStart(), $method_name, $method->getFileRef()->getFile(), $method->getFileRef()->getLineNumberStart(), $original_method->getFileRef()->getFile(), $original_method->getFileRef()->getLineNumberStart());
}
}
}
作者:kangko
项目:pha
/**
* @return Constant
* Get the (non-class) constant associated with this node
* in this context
*
* @throws NodeException
* An exception is thrown if we can't understand the node
*
* @throws CodeBaseExtension
* An exception is thrown if we can't find the given
* class
*/
public function getConst() : Constant
{
assert($this->node->kind === \ast\AST_CONST, "Node must be of type \\ast\\AST_CONST");
if ($this->node->children['name']->kind !== \ast\AST_NAME) {
throw new NodeException($this->node, "Can't determine constant name");
}
// Get an FQSEN for the root namespace
$fqsen = null;
$constant_name = $this->node->children['name']->children['name'];
if (!$this->code_base->hasConstant($fqsen, $constant_name)) {
throw new CodeBaseException($fqsen, "Cannot find constant with name {$constant_name}");
}
return $this->code_base->getConstant($fqsen, $constant_name);
}
作者:tpun
项目:pha
/**
* Take a look at all globally accessible elements and see if
* we can find any dead code that is never referenced
*
* @return void
*/
public static function analyzeReferenceCounts(CodeBase $code_base)
{
// Check to see if dead code detection is enabled. Keep
// in mind that the results here are just a guess and
// we can't tell with certainty that anything is
// definitely unreferenced.
if (!Config::get()->dead_code_detection) {
return;
}
// Get the count of all known elements
$total_count = $code_base->totalElementCount();
$i = 0;
// Functions
self::analyzeElementListReferenceCounts($code_base, $code_base->getFunctionMap(), Issue::UnreferencedMethod, $total_count, $i);
// Constants
self::analyzeElementListReferenceCounts($code_base, $code_base->getGlobalConstantMap(), Issue::UnreferencedConstant, $total_count, $i);
// Classes
self::analyzeElementListReferenceCounts($code_base, $code_base->getClassMap(), Issue::UnreferencedClass, $total_count, $i);
// Class Maps
foreach ($code_base->getClassMapMap() as $class_map) {
self::analyzeClassMapReferenceCounts($code_base, $class_map, $total_count, $i);
}
}
作者:hslatma
项目:pha
/**
* Check to see if the given Clazz is a duplicate
*
* @return null
*/
public static function analyzeDuplicateFunction(CodeBase $code_base, Method $method)
{
$fqsen = $method->getFQSEN();
if (!$fqsen->isAlternate()) {
return;
}
$original_fqsen = $fqsen->getCanonicalFQSEN();
if (!$code_base->hasMethod($original_fqsen)) {
return;
}
$original_method = $code_base->getMethod($original_fqsen);
$method_name = $method->getName();
if ('internal' === $original_method->getContext()->getFile()) {
// If its in an conditional and the original is an
// internal method, presume its all OK.
if ($method->getContext()->getIsConditional()) {
return;
}
Log::err(Log::EREDEF, "Function {$method_name} defined at {$method->getContext()->getFile()}:{$method->getContext()->getLineNumberStart()} was previously defined internally", $method->getContext()->getFile(), $method->getContext()->getLineNumberStart());
} else {
Log::err(Log::EREDEF, "Function {$method_name} defined at {$method->getContext()->getFile()}:{$method->getContext()->getLineNumberStart()} was previously defined at {$original_method->getContext()->getFile()}:{$original_method->getContext()->getLineNumberStart()}", $method->getContext()->getFile(), $method->getContext()->getLineNumberStart());
}
}
作者:jazzda
项目:pha
/**
* @param Node $node
* A node to parse
*
* @return Context
* A new or an unchanged context resulting from
* parsing the node
*/
public function visitCall(Node $node) : Context
{
$expression = $node->children['expr'];
if (Config::get()->backward_compatibility_checks) {
AST::backwardCompatibilityCheck($this->context, $node);
foreach ($node->children['args']->children as $arg_node) {
if ($arg_node instanceof Node) {
AST::backwardCompatibilityCheck($this->context, $arg_node);
}
}
}
if ($expression->kind == \ast\AST_NAME) {
try {
$method = AST::functionFromNameInContext($expression->children['name'], $this->context, $this->code_base);
} catch (CodeBaseException $exception) {
Log::err(Log::EUNDEF, $exception->getMessage(), $this->context->getFile(), $node->lineno);
return $this->context;
}
// Check the call for paraemter and argument types
$this->analyzeCallToMethod($this->code_base, $method, $node);
} else {
if ($expression->kind == \ast\AST_VAR) {
$variable_name = AST::variableName($expression);
if (empty($variable_name)) {
return $this->context;
}
// $var() - hopefully a closure, otherwise we don't know
if ($this->context->getScope()->hasVariableWithName($variable_name)) {
$variable = $this->context->getScope()->getVariableWithName($variable_name);
$union_type = $variable->getUnionType();
if ($union_type->isEmpty()) {
return $this->context;
}
$type = $union_type->head();
if (!$type instanceof CallableType) {
return $this->context;
}
$closure_fqsen = FullyQualifiedFunctionName::fromFullyQualifiedString((string) $type->asFQSEN());
if ($this->code_base->hasMethod($closure_fqsen)) {
// Get the closure
$method = $this->code_base->getMethod($closure_fqsen);
// Check the call for paraemter and argument types
$this->analyzeCallToMethod($this->code_base, $method, $node);
}
}
}
}
return $this->context;
}
作者:gitter-badge
项目:pha
/**
* @return Clazz[]
* A list of classes associated with the given node
*
* @throws CodeBaseException
* An exception is thrown if we can't find a class for
* the given type
*/
private function classListFromNode(Node $node)
{
// Get the types associated with the node
$union_type = self::unionTypeFromNode($this->code_base, $this->context, $node);
// Iterate over each viable class type to see if any
// have the constant we're looking for
foreach ($union_type->nonNativeTypes()->getTypeList() as $class_type) {
// Get the class FQSEN
$class_fqsen = $class_type->asFQSEN();
// See if the class exists
if (!$this->code_base->hasClassWithFQSEN($class_fqsen)) {
throw new CodeBaseException($class_fqsen, "reference to undeclared class {$class_fqsen}");
}
(yield $this->code_base->getClassByFQSEN($class_fqsen));
}
}
作者:kangko
项目:pha
/**
* Take a look at all globally accessible elements and see if
* we can find any dead code that is never referenced
*
* @return void
*/
public static function analyzeReferenceCounts(CodeBase $code_base)
{
// Check to see if dead code detection is enabled. Keep
// in mind that the results here are just a guess and
// we can't tell with certainty that anything is
// definitely unreferenced.
if (!Config::get()->dead_code_detection) {
return;
}
// Get the count of all known elements
$total_count = count($code_base->getMethodMap(), COUNT_RECURSIVE) + count($code_base->getPropertyMap(), COUNT_RECURSIVE) + count($code_base->getConstantMap(), COUNT_RECURSIVE) + count($code_base->getClassMap(), COUNT_RECURSIVE);
$i = 0;
$analyze_list = function ($list) use($code_base, &$i, $total_count) {
foreach ($list as $name => $element) {
CLI::progress('dead code', ++$i / $total_count);
self::analyzeElementReferenceCounts($code_base, $element);
}
};
$analyze_map = function ($map) use($code_base, &$i, $total_count) {
foreach ($map as $fqsen_string => $list) {
foreach ($list as $name => $element) {
CLI::progress('dead code', ++$i / $total_count);
// Don't worry about internal elements
if ($element->getContext()->isInternal()) {
continue;
}
$element_fqsen = $element->getFQSEN();
if ($element_fqsen instanceof FullyQualifiedClassElement) {
$class_fqsen = $element->getDefiningClassFQSEN();
// Don't analyze elements defined in a parent
// class
if ((string) $class_fqsen !== $fqsen_string) {
continue;
}
$defining_class = $element->getDefiningClass($code_base);
// Don't analyze elements on interfaces or on
// abstract classes, as they're uncallable.
if ($defining_class->isInterface() || $defining_class->isAbstract() || $defining_class->isTrait()) {
continue;
}
// Ignore magic methods
if ($element instanceof Method && $element->getIsMagic()) {
continue;
}
}
self::analyzeElementReferenceCounts($code_base, $element);
}
}
};
$analyze_map($code_base->getMethodMap());
$analyze_map($code_base->getPropertyMap());
$analyze_map($code_base->getConstantMap());
$analyze_list($code_base->getClassMap());
}
作者:ets
项目:pha
public function isSubclassOf(CodeBase $code_base, Type $parent)
{
$fqsen = $this->asFQSEN();
assert($fqsen instanceof FullyQualifiedClassName);
$this_clazz = $code_base->getClassByFQSEN($fqsen);
$parent_fqsen = $parent->asFQSEN();
assert($parent_fqsen instanceof FullyQualifiedClassName);
$parent_clazz = $code_base->getClassByFQSEN($parent_fqsen);
return $this_clazz->isSubclassOf($code_base, $parent_clazz);
}