src/Phan/Analysis/DuplicateClassAnalyzer.php
<?php
declare(strict_types=1);
namespace Phan\Analysis;
use Phan\CodeBase;
use Phan\Issue;
use Phan\Language\Element\Clazz;
/**
* Analyzer that checks for duplicate classes/traits/interfaces.
*/
class DuplicateClassAnalyzer
{
/**
* Check to see if the given Clazz is a duplicate
*/
public static function analyzeDuplicateClass(
CodeBase $code_base,
Clazz $clazz
): void {
// Determine if it's 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();
// @phan-suppress-next-line PhanPartialTypeMismatchArgument static method has ambiguity
if (!$code_base->hasClassWithFQSEN($original_fqsen)) {
// If there's a missing class we'll catch that
// elsewhere
return;
}
// Get the original class
// @phan-suppress-next-line PhanPartialTypeMismatchArgument static method has ambiguity
$original_class = $code_base->getClassByFQSEN($original_fqsen);
// Check to see if the original definition was from
// an internal class
if ($original_class->isPHPInternal()) {
if (!$clazz->checkHasSuppressIssueAndIncrementCount(Issue::RedefineClassInternal)) {
Issue::maybeEmit(
$code_base,
$clazz->getContext(),
Issue::RedefineClassInternal,
$clazz->getFileRef()->getLineNumberStart(),
(string)$clazz,
$clazz->getFileRef()->getFile(),
$clazz->getFileRef()->getLineNumberStart(),
(string)$original_class
);
}
// Otherwise, print the coordinates of the original
// definition
} else {
if (!$clazz->checkHasSuppressIssueAndIncrementCount(Issue::RedefineClass)) {
Issue::maybeEmit(
$code_base,
$clazz->getContext(),
Issue::RedefineClass,
$clazz->getFileRef()->getLineNumberStart(),
(string)$clazz,
$clazz->getFileRef()->getFile(),
$clazz->getFileRef()->getLineNumberStart(),
(string)$original_class,
$original_class->getFileRef()->getFile(),
$original_class->getFileRef()->getLineNumberStart()
);
}
// If there are 3 classes with the same namespace and name,
// warn *once* about the first (user-defined) class being a duplicate.
// NOTE: This won't work very well in language server mode.
if ($clazz->getFQSEN()->getAlternateId() === 1) {
if (!$original_class->checkHasSuppressIssueAndIncrementCount(Issue::RedefineClass)) {
Issue::maybeEmit(
$code_base,
$original_class->getContext(),
Issue::RedefineClass,
$original_class->getFileRef()->getLineNumberStart(),
(string)$original_class,
$original_class->getFileRef()->getFile(),
$original_class->getFileRef()->getLineNumberStart(),
(string)$clazz,
$clazz->getFileRef()->getFile(),
$clazz->getFileRef()->getLineNumberStart()
);
}
}
}
return;
}
}