diff --git a/src/Psalm/Checker/ClassLikeChecker.php b/src/Psalm/Checker/ClassLikeChecker.php index 67a087125..329615449 100644 --- a/src/Psalm/Checker/ClassLikeChecker.php +++ b/src/Psalm/Checker/ClassLikeChecker.php @@ -75,7 +75,7 @@ abstract class ClassLikeChecker implements StatementsSource protected $suppressed_issues; /** - * @var array + * @var array */ protected static $method_checkers = []; @@ -85,80 +85,86 @@ abstract class ClassLikeChecker implements StatementsSource /** * A lookup table of all methods on a given class * - * @var array + * @var array */ protected static $class_methods = []; /** * A lookup table of cached ClassLikeCheckers * - * @var array + * @var array */ protected static $class_checkers = []; /** * A lookup table for public class properties * - * @var array + * @var array */ protected static $public_class_properties = []; /** * A lookup table for protected class properties * - * @var array + * @var array */ protected static $protected_class_properties = []; /** * A lookup table for protected class properties * - * @var array + * @var array */ protected static $private_class_properties = []; /** * A lookup table for public static class properties * - * @var array + * @var array */ protected static $public_static_class_properties = []; /** * A lookup table for protected static class properties * - * @var array + * @var array */ protected static $protected_static_class_properties = []; /** * A lookup table for private static class properties * - * @var array + * @var array */ protected static $private_static_class_properties = []; /** * A lookup table for public class constants * - * @var array + * @var array */ protected static $public_class_constants = []; /** * A lookup table to record which classes have been scanned * - * @var array + * @var array */ protected static $registered_classes = []; /** * A lookup table used for storing the results of ClassChecker::classImplements * - * @var array + * @var array */ protected static $class_implements = []; + /** @var array */ + protected static $class_files = []; + + /** @var array> */ + protected static $file_classes = []; + public function __construct(PhpParser\Node\Stmt\ClassLike $class, StatementsSource $source, $absolute_class) { $this->class = $class; @@ -170,6 +176,9 @@ abstract class ClassLikeChecker implements StatementsSource $this->suppressed_issues = $source->getSuppressedIssues(); + self::$class_files[$absolute_class] = $this->file_name; + self::$file_classes[$this->file_name][] = $absolute_class; + if (self::$this_class) { self::$class_checkers[$absolute_class] = $this; } @@ -552,6 +561,8 @@ abstract class ClassLikeChecker implements StatementsSource } } + FileChecker::addFileReferenceToClass($file_name, $absolute_class); + return true; } @@ -667,8 +678,15 @@ abstract class ClassLikeChecker implements StatementsSource if ($reflected_class->isUserDefined()) { $class_file_name = $reflected_class->getFileName(); + $file_checker = new FileChecker($class_file_name); + + $short_file_name = $file_checker->getFileName(); + + self::$class_files[$class_name] = $short_file_name; + self::$file_classes[$short_file_name][] = $class_name; + // this doesn't work on traits - (new FileChecker($class_file_name))->check(true, false); + $file_checker->check(true, false); } else { $class_properties = $reflected_class->getProperties(); @@ -890,6 +908,11 @@ abstract class ClassLikeChecker implements StatementsSource return $method_name; } + public static function getClassesForFile($file_name) + { + return array_unique(self::$file_classes[$file_name]); + } + public static function clearCache() { self::$method_checkers = []; @@ -909,6 +932,8 @@ abstract class ClassLikeChecker implements StatementsSource self::$protected_static_class_properties = []; self::$private_static_class_properties = []; + self::$class_references = []; + ClassChecker::clearCache(); InterfaceChecker::clearCache(); } diff --git a/src/Psalm/Checker/FileChecker.php b/src/Psalm/Checker/FileChecker.php index ca4c3455f..ad84f63dd 100644 --- a/src/Psalm/Checker/FileChecker.php +++ b/src/Psalm/Checker/FileChecker.php @@ -40,6 +40,13 @@ class FileChecker implements StatementsSource public static $show_notices = true; + /** + * A lookup table used for getting all the files that reference a class + * + * @var array> + */ + protected static $file_references_to_class = []; + public function __construct($file_name, array $preloaded_statements = []) { $this->real_file_name = $file_name; @@ -370,6 +377,26 @@ class FileChecker implements StatementsSource return ClassLikeChecker::getClassLikeCheckerFromClass($class_name); } + public static function addFileReferenceToClass($source_file, $absolute_class) + { + self::$file_references_to_class[$absolute_class][$source_file] = true; + } + + public static function getFilesReferencingFile($file) + { + $referenced_files = []; + + $file_classes = ClassLikeChecker::getClassesForFile($file); + + foreach ($file_classes as $file_class) { + if (isset(self::$file_references_to_class[$file_class])) { + $referenced_files = array_merge($referenced_files, array_keys(self::$file_references_to_class[$file_class])); + } + } + + return array_unique($referenced_files); + } + public static function clearCache() { self::$file_checkers = [];