ClassStaleMethodsCheck
class ClassStaleMethodsCheck extends AbstractClassCheck (View source)
Validates that a method declared in stubs actually exists in reflection for the version under test.
This is the only check in the suite that runs stubs → reflection. Every other one iterates the
reflection side and skips members absent from stubs — ClassMethodsExistCheck reduces to
array_diff(reflectionMethods, stubMethods), and the attribute checks continue on any reflection
member missing from the stub map. A stub declaring a method the runtime does not have was therefore
visited by nothing: five SplFixedArray iterator methods, DOMDocument::renameNode,
DOMText::replaceWholeText and ReflectionZendExtension::export stayed unbounded past their
removal in PHP 8.0 while the full 412k-test suite passed. Reverting one of those annotations and
re-running the suite reproduced that: still green.
Why the scope is narrow
A general stubs → reflection check is not viable — measured, not assumed. Unscoped it reports 9,391
absent entities (63% of all stubs), dominated by 58 PECL extensions the container never loads; and
91 of 93 stale constants are driver-contributed PDO::{MYSQL_ATTR,SQLSRV,OCI,FB_ATTR}_* that
reflection cannot judge. Three restrictions make the signal usable:
- Methods only. Constants and properties are dominated by driver-contributed and dynamic members respectively.
- {\StubTests\Framework\DataProvider\StubCategory::CORE} and {\StubTests\Framework\DataProvider\StubCategory::BUNDLED} only — the same definition PhpDocValidatorTest uses for "core stubs". EXTERNAL and PECL extensions are frequently absent from the reflecting container, so their stub-only members say nothing about the stub.
- *Skip magic methods and `PS_UNRESERVEPREFIX
.** Both are intentional stub-only declarations: PHP does not reportwakeup/sleep/__constructon many internal classes even where they work, and the prefix is this project's workaround for methods whose real name is a reserved keyword (Generator::throw`). These two account for 25 of the 57 otherwise-stale members.
Own methods only, not the hierarchy
This deliberately reads $stubEntity->getMethods() rather than
collectEntityMethodsByConfig(), which the other checks use. That helper walks parent classes and
interfaces, so an interface's own (correctly unbounded) Iterator::rewind would be attributed to
every implementor — reporting SplFixedArray::rewind again even after its class-level declaration
was bounded, and adding SplObjectStorage::seek from SeekableIterator. The question here is
specifically "does the stub file that declares this method on this class over-declare it", so only
own declarations are considered.
A class the reflecting runtime does not have at all is skipped: that is {\StubTests\Framework\Validator\EntityExistsCheck}'s subject, and judging its members here would report every one of them.
Remaining legitimate exceptions are carried as known problems rather than as more code — chiefly
PDO's driver-conditional methods and SimpleXMLElement's ArrayAccess members, which PHP implements
through internal handlers rather than declared methods.
Constants
| private FUNCTION_LOOKUP_UNSUPPORTED |
|
| private JUDGEABLE_CATEGORIES |
The stub categories that ship with PHP itself, and so can be judged against reflection. |
Properties
| protected ReflectionProviderInterface | $reflectionProvider | from AbstractReflectionCheck | |
| protected KnownProblemsRegistry | $knownProblemsRegistry | from AbstractReflectionCheck | |
| protected EntityLookupService | $entityLookup | from AbstractClassCheck | |
| protected MethodCollectionService | $methodCollection | from AbstractClassCheck | |
| protected EntityTypeConfig|null | $entityTypeConfig | from AbstractClassCheck |
Methods
No description
Records a skipped-success result if a known problem covers this entity, and returns true.
Look up an entity by ID, dispatching to the right lookup method based on config.
Collect version-filtered methods, dispatching based on config.
Collect version-filtered properties, dispatching based on config.
No description
No description
Details
__construct(ReflectionProviderInterface|null $reflectionProvider = null, KnownProblemsRegistry|null $knownProblemsRegistry = null, EntityLookupService|null $entityLookup = null, MethodCollectionService|null $methodCollection = null, EntityTypeConfig|null $entityTypeConfig = null)
No description
protected bool
skipWithKnownProblem(CheckResultSet $results, string $entityType, string $entityId, CheckType $checkType, string $phpVersion)
Records a skipped-success result if a known problem covers this entity, and returns true.
Returns false if validation should proceed normally.
protected PHPClassLikeObject|null
lookupEntityById(StubDataQueryInterface $storage, string $entityId)
Look up an entity by ID, dispatching to the right lookup method based on config.
Defaults to class lookup when no config is set.
protected array
collectEntityMethodsByConfig(PHPClassLikeObject $entity, string $phpVersion)
Collect version-filtered methods, dispatching based on config.
Defaults to class hierarchy traversal when no config is set.
protected array
collectEntityPropertiesByConfig(PHPClassLikeObject $entity, string $phpVersion)
Collect version-filtered properties, dispatching based on config.
Only classes have properties; returns empty array for enum/interface.
protected string
getEntityLabel()
No description
protected string
getEntityType()
No description
protected string
getConstantEntityType()
No description
protected PHPClass|null
findClassById(StubDataQueryInterface $storage, string $entityId)
No description
protected PHPEnum|null
findEnumById(StubDataQueryInterface $storage, string $entityId)
No description
protected PHPInterface|null
findInterfaceById(StubDataQueryInterface $storage, string $entityId)
No description
protected CheckType
getCheckName()
No description
bool
supports(string $phpVersion)
No description
CheckResultSet
run(StubDataQueryInterface $stubs, string $entityId, string $phpVersion)
No description