addFile( 'somefile.php', ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'foo(); } }', ], 'missingParentWithFunction' => [ 'code' => ' [], 'ignored_issues' => [ 'UndefinedClass', 'MissingReturnType', ], ], 'subclassWithSimplerArg' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ '$object' => 'Bar|Foo', ], ], 'instantiateClassAndIsA' => [ 'code' => 'bar(); }', ], 'returnStringAfterIsACheckWithClassConst' => [ 'code' => ' [ 'code' => ' [ 'code' => ' $array */ function foo(array $array, string $key) : void { foreach ($array as $i => $item) { $array[$key] = new class() {}; if ($array[$i] === $array[$key]) {} } }', ], 'getClassSelfClass' => [ 'code' => 'baz(); } return ""; } public function baz(): string { return "baz"; } }', ], 'staticClassComparison' => [ 'code' => 'baz(); } return ""; } public static function foo2(): string { if (static::class === D::class) { return static::bat(); } return ""; } } class D extends C { public function baz(): string { return "baz"; } public static function bat(): string { return "baz"; } }', ], 'isAStaticClass' => [ 'code' => 'baz(); } return ""; } public static function foo2(): string { if (is_a(static::class, D::class, true)) { return static::bat(); } return ""; } } class D extends C { public function baz(): string { return "baz"; } public static function bat(): string { return "baz"; } }', ], 'typedMagicCall' => [ 'code' => 'zugzug(); $b = (new A)->bar()->baz();', 'assertions' => [ '$a' => 'B', '$b' => 'string', ], ], 'abstractCallToInterfaceMethod' => [ 'code' => 'fooBar(); } }', ], 'noCrashWhenIgnoringUndefinedClass' => [ 'code' => ' [], 'ignored_issues' => [ 'UndefinedClass', ], ], 'noCrashWhenIgnoringUndefinedParam' => [ 'code' => ' [], 'ignored_issues' => [ 'UndefinedClass', 'InvalidArgument', ], ], 'noCrashWhenIgnoringUndefinedReturnIterableArg' => [ 'code' => ' [], 'ignored_issues' => [ 'UndefinedClass', 'MixedInferredReturnType', 'InvalidArgument', ], ], 'noCrashWhenIgnoringUndefinedReturnClassArg' => [ 'code' => ' [], 'ignored_issues' => [ 'UndefinedClass', 'MixedInferredReturnType', 'InvalidArgument', ], ], 'allowAbstractInstantiationOnPossibleChild' => [ 'code' => ' [ 'code' => 'renderer = $r; } } class ConcreteClass extends AbstractClass { public function __construct(A $r) { parent::__construct($r); } } ', ], 'interfaceExistsCreatesClassString' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [], 'ignored_issues' => ['PropertyNotSetInConstructor'], ], 'classAliasNoException' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => 'mock(); return $b; }', ], 'preventDoubleStaticResolution1' => [ 'code' => ' */ class iter extends ArrayObject { /** * @return self */ public function stabilize(): self { return $this; } } class a { /** * @return iter */ public function ret(): iter { return new iter([$this]); } } class b extends a { } $a = new b; $a = $a->ret(); $a = $a->stabilize();', 'assertions' => [ '$a===' => 'iter', ], ], 'preventDoubleStaticResolution2' => [ 'code' => ' */ class iter extends ArrayObject { /** * @return self */ public function stabilize(): self { return $this; } } interface a { /** * @return iter */ public function ret(): iter; } class b implements a { public function ret(): iter { return new iter([$this]); } } /** @var a */ $a = new b; $a = $a->ret(); $a = $a->stabilize();', 'assertions' => [ '$a===' => 'iter', ], ], 'preventDoubleStaticResolution3' => [ 'code' => ' */ class iter extends ArrayObject { /** * @return self */ public function stabilize(): self { return $this; } } interface a { /** * @return iter */ public function ret(): iter; } class b implements a { public function ret(): iter { return new iter([$this]); } } /** @var a */ $a = new b; $a = $a->ret(); $a = $a->stabilize();', 'assertions' => [ '$a===' => 'iter', ], ], 'allowTraversableImplementationAlongWithIteratorAggregate' => [ 'code' => ' * @implements IteratorAggregate */ final class C implements Traversable, IteratorAggregate { public function getIterator() { yield 1; } } ', ], 'allowTraversableImplementationAlongWithIterator' => [ 'code' => ' * @implements Iterator<1, 1> */ final class C implements Traversable, Iterator { public function current() { return 1; } public function key() { return 1; } public function next() { } public function rewind() { } public function valid() { return false; } } ', ], 'allowTraversableImplementationOnAbstractClass' => [ 'code' => ' */ abstract class C implements Traversable {} ', ], 'allowIndirectTraversableImplementationOnAbstractClass' => [ 'code' => ' */ interface I extends Traversable {} abstract class C implements I {} ', ], 'newOnNamedObject' => [ 'code' => ' [ '$o2===' => 'stdClass', ], ], 'newOnObjectOfAnonymousClass' => [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => ' 'UndefinedClass', ], 'wrongCaseClass' => [ 'code' => ' 'InvalidClass', ], 'wrongCaseClassWithCall' => [ 'code' => ' 'InvalidClass', ], 'invalidThisFetch' => [ 'code' => ' 'InvalidScope', ], 'invalidThisArgument' => [ 'code' => ' 'InvalidScope', ], 'undefinedConstant' => [ 'code' => ' 'UndefinedConstant', ], 'undefinedClassConstant' => [ 'code' => ' 'UndefinedConstant', ], 'overridePublicAccessLevelToPrivate' => [ 'code' => ' 'OverriddenMethodAccess', ], 'overridePublicAccessLevelToProtected' => [ 'code' => ' 'OverriddenMethodAccess', ], 'overrideProtectedAccessLevelToPrivate' => [ 'code' => ' 'OverriddenMethodAccess', ], 'overridePublicPropertyAccessLevelToPrivate' => [ 'code' => ' 'OverriddenPropertyAccess - src' . DIRECTORY_SEPARATOR . 'somefile.php:9:33 - Property B::$foo has different access level than A::$foo', ], 'overridePublicPropertyAccessLevelToProtected' => [ 'code' => ' 'OverriddenPropertyAccess', ], 'overrideProtectedPropertyAccessLevelToPrivate' => [ 'code' => ' 'OverriddenPropertyAccess', ], 'classRedefinition' => [ 'code' => ' 'DuplicateClass', ], 'classRedefinitionInNamespace' => [ 'code' => ' 'DuplicateClass', ], 'classRedefinitionInSeparateNamespace' => [ 'code' => ' 'DuplicateClass', ], 'abstractClassInstantiation' => [ 'code' => ' 'AbstractInstantiation', ], 'abstractClassMethod' => [ 'code' => ' 'UnimplementedAbstractMethod', ], 'abstractReflectedClassMethod' => [ 'code' => '> */ class DedupeIterator extends FilterIterator { /** * @param Iterator $i */ public function __construct(Iterator $i) { parent::__construct($i); } }', 'error_message' => 'UnimplementedAbstractMethod', ], 'missingParent' => [ 'code' => ' 'UndefinedClass', ], 'lessSpecificReturnStatement' => [ 'code' => ' 'LessSpecificReturnStatement', ], 'circularReference' => [ 'code' => ' 'CircularReference', ], 'preventAbstractInstantiationDefiniteClasss' => [ 'code' => ' 'AbstractInstantiation', ], 'preventExtendingInterface' => [ 'code' => ' 'UndefinedClass', ], 'preventImplementingClass' => [ 'code' => ' 'UndefinedInterface', ], 'classAliasAlreadyDefinedClass' => [ 'code' => ' 'TypeDoesNotContainType', ], 'cannotOverrideFinalType' => [ 'code' => ' 'MethodSignatureMismatch', ], 'preventFinalOverriding' => [ 'code' => 'foo();', 'error_message' => 'LessSpecificReturnStatement', ], 'preventTraversableImplementation' => [ 'code' => ' */ final class C implements Traversable {} ', 'error_message' => 'InvalidTraversableImplementation', ], 'preventIndirectTraversableImplementation' => [ 'code' => ' */ interface I extends Traversable {} final class C implements I {} ', 'error_message' => 'InvalidTraversableImplementation', ], 'detectMissingTemplateExtends' => [ 'code' => ' 'MissingTemplateParam', ], 'detectMissingTemplateImplements' => [ 'code' => ' 'MissingTemplateParam', ], 'detectMissingTemplateUse' => [ 'code' => ' 'MissingTemplateParam', ], 'detectMissingTemplateExtendsNative' => [ 'code' => ' 'MissingTemplateParam', ], 'detectMissingTemplateImplementsNative' => [ 'code' => ' 'MissingTemplateParam', ], 'cannotNameClassConstantClass' => [ 'code' => ' */ protected const CLASS = Bar::class; } class Bar {} ', 'error_message' => 'ReservedWord', ], 'newOnObject' => [ 'code' => ' 'MixedMethodCall', ], 'forbiddenThrowableImplementation' => [ 'code' => ' 'InvalidInterfaceImplementation', 'ignored_issues' => [], 'php_version' => '7.0', ], 'directConstructorCall' => [ 'code' => '__construct(); ', 'error_message' => 'DirectConstructorCall', ], 'directConstructorCallOnThis' => [ 'code' => '__construct(); } } $a = new A; $a->f(); ', 'error_message' => 'DirectConstructorCall', ], 'privateFinalMethodsAreForbidden' => [ 'code' => <<<'PHP' 'PrivateFinalMethod', ], 'readonlyClass' => [ 'code' => <<<'PHP' a = 33; PHP, 'error_message' => 'InaccessibleProperty', 'ignored_issues' => [], 'php_version' => '8.2', ], 'readonlyClassRequiresTypedProperties' => [ 'code' => <<<'PHP' 'MissingPropertyType', 'ignored_issues' => [], 'php_version' => '8.2', ], 'readonlyClassCannotHaveDynamicProperties' => [ 'code' => <<<'PHP' 'InvalidAttribute', 'ignored_issues' => [], 'php_version' => '8.2', ], 'readonlyClassesCannotBeExtendedByNonReadonlyOnes' => [ 'code' => <<<'PHP' 'InvalidExtendClass', 'ignored_issues' => [], 'php_version' => '8.2', ], 'classCannotExtendIfNotInInheritors' => [ 'code' => <<<'PHP' 'InheritorViolation', 'ignored_issues' => [], ], 'classCannotImplementIfNotInInheritors' => [ 'code' => <<<'PHP' 'InheritorViolation', 'ignored_issues' => [], ], 'interfaceCannotImplementIfNotInInheritors' => [ 'code' => <<<'PHP' 'InheritorViolation', 'ignored_issues' => [], ], 'UnfulfilledInterfaceInheritors' => [ 'code' => <<<'PHP' 'InheritorViolation', 'ignored_issues' => [], ], ]; } }