[ 'code' => ' */ abstract class BaseRepository {} class StudentViewData implements IBaseViewData {} class TeacherViewData implements IBaseViewData {} /** @extends BaseModel */ class StudentModel extends BaseModel {} /** @extends BaseModel */ class TeacherModel extends BaseModel {} /** @extends BaseRepository */ class StudentRepository extends BaseRepository {} /** @extends BaseRepository */ class TeacherRepository extends BaseRepository {}', ], 'unwrapIndirectGenericTemplated' => [ 'code' => ' * @param TWrapper2 $wrapper * @return TInner2 */ function indirectUnwrap(Wrapper $wrapper) : object { return unwrapGeneric($wrapper); } /** * @template TInner1 * @template TWrapper1 of Wrapper * @param TWrapper1 $wrapper * @return TInner1 */ function unwrapGeneric(Wrapper $wrapper) { return $wrapper->unwrap(); }', ], 'unwrapFromTemplatedClassString' => [ 'code' => ' */ class StringWrapper implements Wrapper { public function unwrap() { return "hello"; } } /** * @template TInner * @template TWrapper of Wrapper * * @param class-string $class * @return TInner */ function load(string $class) { $package = new $class(); return $package->unwrap(); } $result = load(StringWrapper::class);', ], 'unwrapNestedTemplateWithReset' => [ 'code' => ' * @param TArray $arr * @return TValue */ function toList(array $arr): array { return reset($arr); }', ], '3levelNestedTemplatesOfMixed' => [ 'code' => ' */ interface B {} /** @template T */ interface J {} /** * @template T * @template U of A * @implements J */ class K2 implements J {} /** * @template T * @template U of A * @template V of B * @extends J */ interface K3 extends J {} /** * @template T * @template U of A * @template V of B * @implements J */ class K1 implements J {}', ], '4levelNestedTemplatesOfObjects' => [ 'code' => ' */ abstract class DbEntityRepository extends EntityRepository {} interface ObjectId {} /** * @template I of ObjectId */ interface AnObject {} /** * Base entity repository with common tooling. * * @template I of ObjectId * @template O of AnObject * @template E of DbEntity * @extends DbEntityRepository */ abstract class AnObjectEntityRepository extends DbEntityRepository {} /** * Base repository implementation backed by a Db repository. * * @template T * @template E of DbEntity * @template R of DbEntityRepository */ abstract class DbRepositoryWrapper { /** @var R $repo Db repository */ private DbEntityRepository $repo; /** * Getter for the Db repository. * * @return DbEntityRepository The Db repository. * @psalm-return R */ protected function getDbRepo(): DbEntityRepository { return $this->repo; } } /** * Base implementation for all custom repositories that map to Core objects. * * @template I of ObjectId * @template O of AnObject * @template E of DbEntity * @template R of AnObjectEntityRepository * @extends DbRepositoryWrapper */ abstract class AnObjectDbRepositoryWrapper extends DbRepositoryWrapper {}', ], '4levelNestedTemplateAsFunctionParameter' => [ 'code' => ' */ abstract class DbEntityRepository extends EntityRepository {} interface ObjectId {} /** * @template I of ObjectId */ interface AnObject {} /** * Base entity repository with common tooling. * * @template I of ObjectId * @template O of AnObject * @template E of DbEntity * @extends DbEntityRepository */ abstract class AnObjectEntityRepository extends DbEntityRepository {} /** * Base repository implementation backed by a Db repository. * * @template T * @template E of DbEntity * @template R of DbEntityRepository */ abstract class DbRepositoryWrapper { /** @var R $repo Db repository */ private DbEntityRepository $repo; /** * Getter for the Db repository. * * @return DbEntityRepository The Db repository. * @psalm-return R */ protected function getDbRepo(): DbEntityRepository { return $this->repo; } } /** * Base implementation for all custom repositories that map to Core objects. * * @template I of ObjectId * @template O of AnObject * @template E of DbEntity * @template R of AnObjectEntityRepository * @extends DbRepositoryWrapper */ abstract class AnObjectDbRepositoryWrapper extends DbRepositoryWrapper {} abstract class Utilities { /** * @template I of ObjectId * @template O of AnObject * @template E of DbEntity * @template R of AnObjectEntityRepository * @psalm-param AnObjectDbRepositoryWrapper $repo * @return void */ abstract public static function doSomething(AnObjectDbRepositoryWrapper $repo): void; }', ], ]; } public function providerInvalidCodeParse(): iterable { return [ 'nestedTemplateExtendsInvalid' => [ 'code' => ' */ abstract class BaseRepository {} class StudentViewData implements IBaseViewData {} class TeacherViewData implements IBaseViewData {} /** @extends BaseModel */ class StudentModel extends BaseModel {} /** @extends BaseModel */ class TeacherModel extends BaseModel {} /** @extends BaseRepository */ class StudentRepository extends BaseRepository {}', 'error_message' => 'InvalidTemplateParam', ], ]; } }