[ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' [ 'code' => ' */ class Bar { public function foo() : void { $bar = /** @return TA */ function() { return ["hello"]; }; /** @var array */ $bat = [$bar(), $bar()]; foreach ($bat as $b) { echo $b[0]; } } } /** * @psalm-type _A=array{elt:int} * @param _A $p * @return _A */ function f($p) { /** @var _A */ $r = $p; return $r; }', ], 'classTypeAliasSimple' => [ 'code' => ' "Nokia"]; } } /** @psalm-type NameType = array{name: string} */ class Name { /** @psalm-return NameType */ function toArray(): array { return ["name" => "Matt"]; } } /** * @psalm-import-type PhoneType from Phone as PhoneType2 * @psalm-import-type NameType from Name as NameType2 * * @psalm-type UserType = PhoneType2&NameType2 */ class User { /** @psalm-return UserType */ function toArray(): array { return array_merge( (new Name)->toArray(), (new Phone)->toArray() ); } }', ], 'classTypeAliasImportWithAlias' => [ 'code' => ' "Nokia"]; } } /** * @psalm-import-type PhoneType from Phone as TPhone */ class User { /** @psalm-return TPhone */ function toArray(): array { return array_merge([], (new Phone)->toArray()); } }', ], 'classTypeAliasDirectUsage' => [ 'code' => ' "Nokia"]; } } /** * @psalm-import-type PhoneType from Phone */ class User { /** @psalm-return PhoneType */ function toArray(): array { return array_merge([], (new Phone)->toArray()); } }', ], 'classTypeAliasFromExternalNamespace' => [ 'code' => ' "Nokia"]; } } } namespace Bar { /** * @psalm-import-type PhoneType from \Foo\Phone */ class User { /** @psalm-return PhoneType */ function toArray(): array { return (new \Foo\Phone)->toArray(); } } }', ], 'importTypeForParam' => [ 'code' => 'b($type); } /** * @psalm-param Type2 $type */ private function b(int $type): void { } }', ], 'usedInVarForForeach' => [ 'code' => ' [ 'code' => ' [ 'code' => ' */ class C implements A { public function output() { return "hello"; } } $instance = new C(); $output = $instance->output();', 'assertions' => [ '$output' => 'string', ], ], 'sameDocBlockTypeAliasAsTypeParameterForExtendedRegularClass' => [ 'code' => 'value = $value; } } /** * @psalm-type Foo=string * @extends A */ class C extends A {} $instance = new C("hello"); $output = $instance->value;', 'assertions' => [ '$output' => 'string', ], ], 'sameDocBlockTypeAliasAsTypeParameterForExtendedAbstractClass' => [ 'code' => 'value = $value; } } /** * @psalm-type Foo=string * @extends A */ class C extends A {} $instance = new C("hello"); $output = $instance->value;', 'assertions' => [ '$output' => 'string', ], ], 'importedTypeAliasAsTypeParameterForImplementation' => [ 'code' => ' */ class C implements A {}', ], 'importedTypeAliasAsConstrainedTypeParameterForImplementation' => [ 'code' => ' */ class C implements A {} ', ], 'importedTypeAliasAsTypeParameterForExtendedClass' => [ 'code' => ' */ class C extends A {}', ], 'importedTypeAliasAsTypeParameterForExtendedAbstractClass' => [ 'code' => ' */ class C extends A {}', ], 'importedTypeAliasRenamedAsTypeParameterForImplementation' => [ 'code' => ' */ class C implements A {}', ], 'importedTypeAliasRenamedAsTypeParameterForExtendedClass' => [ 'code' => ' */ class C extends A {}', ], 'importedTypeAliasRenamedAsTypeParameterForExtendedAbstractClass' => [ 'code' => ' */ class C extends A {}', ], 'importedTypeInsideLocalTypeAliasUsedAsTypeParameter' => [ 'code' => 'value = $value; } } /** * @psalm-type Foo=string */ class B {} /** * @psalm-import-type Foo from B * @psalm-type Baz=Foo * * @extends A */ class C extends A {} $instance = new C("hello"); $output = $instance->value;', 'assertions' => [ '$output' => 'string', ], ], 'importedTypeWithPhpstanAnnotation' => [ 'code' => 'value = $value; } } /** * @phpstan-type Foo=string */ class B {} /** * @phpstan-import-type Foo from B * @phpstan-type Baz=Foo * * @extends A */ class C extends A {} $instance = new C("hello"); $output = $instance->value;', 'assertions' => [ '$output' => 'string', ], ], 'importedTypeUsedInAssertion' => [ 'code' => 'assertFoo($input); return $input; } /** * @param mixed $value * @psalm-assert FooAlias $value */ private function assertFoo($value): void { if(!is_string($value)) { throw new \InvalidArgumentException(); } } } $instance = new B(); $output = $instance->convertToFoo("hallo"); ', 'assertions' => [ '$output' => 'string', ], ], 'importedTypeUsedInOtherType' => [ 'code' => ' */ class Main { /** @return OpeningTypeAssignment */ public function doStuff(): array { return []; } } $instance = new Main(); $output = $instance->doStuff(); ', 'assertions' => [ '$output===' => 'list<1|2>', ], ], 'callableWithReturnTypeTypeAliasWithinBackets' => [ 'code' => ' [ '$output===' => 'callable():int', ], ], 'callableWithReturnTypeTypeAlias' => [ 'code' => ' [ '$output===' => 'callable():int', ], ], 'callableFormats' => [ 'code' => '): array * @psalm-type I callable(array $e): array * @psalm-type J callable(array ...): string * @psalm-type K callable(array ...$e): string * @psalm-type L \Closure(int, int): string * * @method ma(): A * @method mb(): B * @method mc(): C * @method md(): D * @method me(): E * @method mf(): F * @method mg(): G * @method mh(): H * @method mi(): I * @method mj(): J * @method mk(): K * @method ml(): L */ class Foo { public function __call(string $method, array $params) { return 1; } } $foo = new \Foo(); $output_ma = $foo->ma(); $output_mb = $foo->mb(); $output_mc = $foo->mc(); $output_md = $foo->md(); $output_me = $foo->me(); $output_mf = $foo->mf(); $output_mg = $foo->mg(); $output_mh = $foo->mh(); $output_mi = $foo->mi(); $output_mj = $foo->mj(); $output_mk = $foo->mk(); $output_ml = $foo->ml(); ', 'assertions' => [ '$output_ma===' => 'callable(int, int):string', '$output_mb===' => 'callable(int, int=):string', '$output_mc===' => 'callable(int, string):void', '$output_md===' => 'callable(string):mixed', '$output_me===' => 'callable(string):mixed', '$output_mf===' => 'callable(float...):(int|null)', '$output_mg===' => 'callable(float...):(int|null)', '$output_mh===' => 'callable(array):array', '$output_mi===' => 'callable(array):array', '$output_mj===' => 'callable(array...):string', '$output_mk===' => 'callable(array...):string', '$output_ml===' => 'Closure(int, int):string', ], ], 'unionOfStringsContainingBraceChar' => [ 'code' => ' [ '$t===' => '\'{\'|\'}\'', ], ], 'unionOfStringsContainingGTChar' => [ 'code' => '\' */ class Foo { /** @psalm-var T */ public static string $t; } $t = Foo::$t; ', 'assertions' => [ '$t===' => '\'<\'|\'>\'', ], ], 'unionOfStringsContainingBracketChar' => [ 'code' => ' [ '$t===' => '\'(\'|\')\'', ], ], 'bareWordsCommentAfterType' => [ 'code' => ' [ '$t===' => 'string', ], ], 'handlesTypeWhichEndsWithRoundBracket' => [ 'code' => ') */ class A {} ', ], 'commentAfterType' => [ 'code' => ' [ 'code' => ' [ '$output===' => 'array{phone: string}', ], ], 'combineAliasOfArrayAndArrayCorrectly' => [ 'code' => '|D $_doesNotWork */ public function doesNotWork($_doesNotWork): void { /** @psalm-check-type-exact $_doesNotWork = D */; } }', ], 'importFromEnum' => [ 'code' => <<<'PHP' [], 'ignored_issues' => [], 'php_version' => '8.1', ], 'importFromTrait' => [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => <<<'PHP' [ 'code' => ' */ class A {}', 'error_message' => 'InvalidDocblock', ], 'typeAliasInTKeyedArray' => [ 'code' => ' 'InvalidReturnStatement', ], 'classTypeAliasInvalidReturn' => [ 'code' => ' "Nokia"]; } } /** @psalm-type NameType = array{name: string} */ class Name { /** @psalm-return NameType */ function toArray(): array { return ["name" => "Matt"]; } } /** * @psalm-import-type PhoneType from Phone as PhoneType2 * @psalm-import-type NameType from Name as NameType2 * * @psalm-type UserType = PhoneType2&NameType2 */ class User { /** @psalm-return UserType */ function toArray(): array { return array_merge( (new Name)->toArray(), ["foo" => "bar"] ); } }', 'error_message' => 'InvalidReturnStatement', ], 'classTypeInvalidAliasImport' => [ 'code' => ' "Matt"]; } } /** * @psalm-import-type PhoneType from Phone */ class User {}', 'error_message' => 'InvalidTypeImport', ], 'classTypeAliasFromInvalidClass' => [ 'code' => ' 'UndefinedDocblockClass', ], 'malformedImportMissingFrom' => [ 'code' => ' 'InvalidTypeImport', ], 'malformedImportMissingSourceClass' => [ 'code' => ' 'InvalidTypeImport', ], 'malformedImportMisspelledFrom' => [ 'code' => ' 'InvalidTypeImport', ], 'malformedImportMissingAlias' => [ 'code' => ' 'InvalidTypeImport', ], 'noCrashWithPriorReference' => [ 'code' => ' 'UndefinedDocblockClass', ], 'mergeImportedTypes' => [ 'code' => ' 'PossiblyUndefinedArrayOffset', ], 'noCrashWithSelfReferencingType' => [ 'code' => ' 'InvalidDocblock', ], 'invalidTypeWhenNotImported' => [ 'code' => ' */ class C implements B {}', 'error_message' => 'UndefinedDocblockClass', ], 'invalidTypeWhenNotImportedInsideAnotherTypeAlias' => [ 'code' => ' */ class C implements B {}', 'error_message' => 'UndefinedDocblockClass', ], 'duplicateKeyInArrayShapeOnInterfaceIsReported' => [ 'code' => <<<'PHP' 'InvalidDocblock', ], 'duplicateKeyInArrayShapeOnAClassIsReported' => [ 'code' => <<<'PHP' 'InvalidDocblock', ], 'duplicateKeyInArrayShapeOnATraitIsReported' => [ 'code' => <<<'PHP' 'InvalidDocblock', ], 'duplicateKeyInArrayShapeOnAnEnumIsReported' => [ 'code' => <<<'PHP' 'InvalidDocblock', 'ignored_issues' => [], 'php_version' => '8.1', ], ]; } }