PhpDocConformanceService
final class PhpDocConformanceService (View source)
Whether a PhpDoc type and a signature type describe the same thing.
Used by FunctionPhpDocConformsSignatureCheck, ClassMethodsPhpDocConformsSignatureCheck, and their Enum/Interface variants.
Three concerns that used to live here have moved out, leaving this class to hold the compatibility relation and nothing else:
- phpstan/psalm annotation narrowing → {\StubTests\Framework\Validator\Services\PhpStanTypeNormalizer}, which is pure string rewriting and whose leaf table grows on a different schedule than the algorithm below;
- "which type names are primitives" → {\StubTests\Framework\Validator\Services\TypeResolver::PRIMITIVES}, general type vocabulary that ReturnTypeComparator also needs and was reaching across for;
@templatename extraction → {\StubTests\Framework\PhpDoc\TemplateTypeNormalizer}, which the stub parsers already had a better implementation of.
Methods
Check if a PhpDoc type is compatible with a signature type.
Extract @template variable names from a raw PhpDoc comment.
Normalise a PhpDoc type string: strip phpstan/psalm annotations, then apply the shared normalizeType() (union ordering, FQN backslash, T[] → array).
Split a union type string into individual components.
Get the signature type string for a parameter.
Get the signature type string for a property.
Details
bool
isPhpDocCompatibleWithSignature(string $sig, string $doc, array $templateNames = [])
Check if a PhpDoc type is compatible with a signature type.
Permissive algorithm — avoids false positives from intentional patterns:
- Typed-array narrowing: sig
array, docstring[]→ pass (string[] normalises to array) - phpstan generics: sig
array, docarray<K,V>→ pass (generics stripped) - resource widening: sig
GMP, docresource|GMP→ pass (intersection non-empty) - bool/false split: sig
bool, docfalse→ pass (bool expands to {false, true}) - union reordering: sig
string|false, docfalse|string→ pass (normalised) - mixed sig or doc: sig
mixed, docstring→ pass (mixed encompasses all) - object sig with class doc: sig
object, docSomeClass→ pass - class sig with object doc: sig
SomeClass, docobject→ pass - resource→class migration: sig
SomeClass, docresource→ pass (PHP8 object migration) - @template variable in doc: sig
\SplFileInfo, doc\T(T declared via @template) → pass - static ↔ class name: sig
\DateTime, docstatic→ pass - class-to-class narrowing: sig
\Iterator, doc\ArrayIterator→ pass
Catches: sig string, doc int → fail (no shared component)
array
extractTemplateNames(string|null $rawPhpDoc)
Extract @template variable names from a raw PhpDoc comment.
Delegates to the one implementation the stub parsers also use. This class used to carry a
second, DocBlockFactory-based one that silently dropped @template-contravariant.
string
normalizeDocType(string $type)
Normalise a PhpDoc type string: strip phpstan/psalm annotations, then apply the shared normalizeType() (union ordering, FQN backslash, T[] → array).
array
splitUnionComponents(string $type)
Split a union type string into individual components.
string|null
getParamSigTypeForPhpDoc(PHPParameter $param, string $phpVersion)
Get the signature type string for a parameter.
Priority:
- Declared type from getDeclaredType() — if non-empty (not NoType)
- LanguageLevelTypeAware — highest version <= $phpVersion, or defaultType
string|null
getPropertySigTypeForPhpDoc(PHPProperty $property, string $phpVersion)
Get the signature type string for a property.
Priority:
- Signature type from getType() — if non-empty (not NoType)
- LanguageLevelTypeAware — highest version <= $phpVersion, or defaultType