Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: psalm plugin #469

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ database-generate-migration: database-drop-schema ### Generate new migration bas
.PHONY: database-validate-mapping
database-validate-mapping: database-drop-schema ### Validate mapping in Zenstruck\Foundry\Tests\Fixtures\Entity
@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:migrate --no-interaction --allow-no-migration
@${DOCKER_PHP} bin/doctrine orm:validate-schema
@${DOCKER_PHP} bin/doctrine orm:validate-schema -v

.PHONY: database-drop-schema
database-drop-schema: vendor ### Drop database schema
Expand Down Expand Up @@ -150,7 +150,7 @@ docker-start: ### Start containers

.PHONY: docker-stop
docker-stop: ### Stop containers
@rm $(DOCKER_PHP_CONTAINER_FLAG)
@rm $(DOCKER_PHP_CONTAINER_FLAG) || true
@$(DOCKER_COMPOSE) stop

.PHONY: docker-purge
Expand Down
9 changes: 9 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"zenstruck/callback": "^1.1"
},
"require-dev": {
"ext-simplexml": "*",
"bamarni/composer-bin-plugin": "^1.4",
"dama/doctrine-test-bundle": "^7.0",
"doctrine/doctrine-bundle": "^2.5",
Expand Down Expand Up @@ -63,6 +64,14 @@
"target-directory": "bin/tools",
"bin-links": true,
"forward-command": false
},
"phpstan": {
"includes": [
"phpstan-foundry.neon"
]
},
"psalm": {
"pluginClass": "Zenstruck\\Foundry\\Psalm\\FoundryPlugin"
}
},
"minimum-stability": "dev",
Expand Down
30 changes: 0 additions & 30 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ parameters:
count: 1
path: src/AnonymousFactory.php

-
message: "#^Method Zenstruck\\\\Foundry\\\\AnonymousFactory\\:\\:many\\(\\) should return Zenstruck\\\\Foundry\\\\FactoryCollection\\<TModel of object\\> but returns Zenstruck\\\\Foundry\\\\FactoryCollection\\<object\\>\\.$#"
count: 1
path: src/AnonymousFactory.php

-
message: "#^Method Zenstruck\\\\Foundry\\\\AnonymousFactory\\:\\:sequence\\(\\) should return Zenstruck\\\\Foundry\\\\FactoryCollection\\<TModel of object\\> but returns Zenstruck\\\\Foundry\\\\FactoryCollection\\<object\\>\\.$#"
count: 1
path: src/AnonymousFactory.php

-
message: "#^Parameter \\#1 \\$objectOrClass of class ReflectionClass constructor expects class\\-string\\<T of object\\>\\|T of object, string\\|null given\\.$#"
count: 1
Expand Down Expand Up @@ -89,23 +79,3 @@ parameters:
message: "#^Parameter \\#2 \\$configuration of static method Zenstruck\\\\Foundry\\\\BaseFactory\\<mixed\\>\\:\\:boot\\(\\) expects Zenstruck\\\\Foundry\\\\Configuration, object\\|null given\\.$#"
count: 1
path: src/ZenstruckFoundryBundle.php

-
message: "#^Function Zenstruck\\\\Foundry\\\\create\\(\\) should return \\(T of object\\)\\|Zenstruck\\\\Foundry\\\\Proxy\\<T of object\\> but returns object\\.$#"
count: 1
path: src/functions.php

-
message: "#^Function Zenstruck\\\\Foundry\\\\create_many\\(\\) should return array\\<int, \\(T of object\\)\\|Zenstruck\\\\Foundry\\\\Proxy\\<T of object\\>\\> but returns array\\<int, object\\>\\.$#"
count: 1
path: src/functions.php

-
message: "#^Function Zenstruck\\\\Foundry\\\\instantiate\\(\\) should return \\(T of object\\)\\|Zenstruck\\\\Foundry\\\\Proxy\\<T of object\\> but returns object\\.$#"
count: 1
path: src/functions.php

-
message: "#^Function Zenstruck\\\\Foundry\\\\instantiate_many\\(\\) should return array\\<int, \\(T of object\\)\\|Zenstruck\\\\Foundry\\\\Proxy\\<T of object\\>\\> but returns array\\<int, object\\>\\.$#"
count: 1
path: src/functions.php
4 changes: 2 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ parameters:
- ./src

# let's analyse factories generated with maker
- ./tests/Fixtures/Maker/expected/can_create_factory_for_entity_with_repository_with_data_set_phpstan.php
- ./tests/Fixtures/Maker/expected/can_create_factory_with_static_analysis_annotations_with_data_set_phpstan.php
- ./tests/Fixtures/Maker/expected/can_create_factory.php
level: 8
bootstrapFiles:
- ./vendor/autoload.php
Expand All @@ -35,3 +34,4 @@ parameters:
excludePaths:
- ./src/Bundle/Resources
- ./src/PhpStan
- ./src/Psalm
9 changes: 7 additions & 2 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
xsi:schemaLocation="https://getpsalm.org/schema/config bin/tools/psalm/vendor/vimeo/psalm/config.xsd"
findUnusedBaselineEntry="true"
findUnusedCode="false"
autoloader="vendor/autoload.php"
>
<projectFiles>
<file name="tests/Fixtures/Maker/expected/can_create_factory_for_entity_with_repository_with_data_set_psalm.php" />
<file name="tests/Fixtures/Maker/expected/can_create_factory_with_static_analysis_annotations_with_data_set_psalm.php" />
<file name="tests/Fixtures/Maker/expected/can_create_factory.php"/>
<file name="tests/Fixtures/Psalm/test-types-with-persistence.php"/>
<file name="tests/Fixtures/Psalm/test-types-without-persistence.php"/>
</projectFiles>
<plugins>
<pluginClass class="Zenstruck\Foundry\Psalm\FoundryPlugin"/>
</plugins>
</psalm>
2 changes: 1 addition & 1 deletion src/AnonymousFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* @deprecated
*
* @phpstan-import-type SequenceAttributes from BaseFactory
* @psalm-import-type SequenceAttributes from BaseFactory
*/
final class AnonymousFactory implements \Countable, \IteratorAggregate
{
Expand Down
27 changes: 13 additions & 14 deletions src/BaseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@
*
* @template T
*
* @method static list<T> createMany(int $number, Attributes $attributes = [])
*
* @phpstan-type Parameters array<string,mixed>
* @phpstan-type Attributes Parameters|(callable():Parameters)
* @phpstan-type SequenceAttributes iterable<Parameters>|(callable(): iterable<Parameters>)
* @psalm-type Parameters = array<string,mixed>
* @psalm-type Attributes = Parameters|(callable():Parameters)
* @psalm-type SequenceAttributes = iterable<Parameters>|callable(): iterable<Parameters>
*/
abstract class BaseFactory
{
Expand All @@ -51,15 +49,6 @@ public function __call(string $name, array $arguments): array
return $this->many($arguments[0])->create($arguments[1] ?? []);
}

public static function __callStatic(string $name, array $arguments): array
{
if ('createMany' !== $name) {
throw new \BadMethodCallException(\sprintf('Call to undefined static method "%s::%s".', static::class, $name));
}

return static::new()->many($arguments[0])->create($arguments[1] ?? []);
}

/**
* @param Attributes|string $attributes
*/
Expand Down Expand Up @@ -117,6 +106,16 @@ final public static function createOne(array|callable $attributes = []): mixed
*/
abstract public function create(array|callable $attributes = []): mixed;

/**
* @param Attributes $attributes
*
* @return list<T>
*/
public static function createMany(int $min, array|callable $attributes = []): array
{
return static::new()->many($min)->create($attributes);
}

/**
* @param int|null $max If set, when created, the collection will be a random size between $min and $max
*
Expand Down
15 changes: 0 additions & 15 deletions src/Bundle/Maker/Factory/FactoryGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,16 @@
use Symfony\Bundle\MakerBundle\Str;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Bundle\Maker\Factory\Exception\FactoryClassAlreadyExistException;

/**
* @internal
*/
final class FactoryGenerator
{
public const PHPSTAN_PATH = '/vendor/phpstan/phpstan/phpstan';
public const PSALM_PATH = '/vendor/vimeo/psalm/psalm';

/** @param \Traversable<int, DefaultPropertiesGuesser> $defaultPropertiesGuessers */
public function __construct(
private ManagerRegistry $managerRegistry,
private KernelInterface $kernel,
private \Traversable $defaultPropertiesGuessers,
private FactoryClassMap $factoryClassMap,
private NamespaceGuesser $namespaceGuesser,
Expand Down Expand Up @@ -136,17 +131,7 @@ private function createMakeFactoryData(Generator $generator, string $class, Make
$object,
$factory,
$repository ?? null,
$this->staticAnalysisTool(),
$persisted
);
}

private function staticAnalysisTool(): string
{
return match (true) {
\file_exists($this->kernel->getProjectDir().self::PHPSTAN_PATH) => MakeFactoryData::STATIC_ANALYSIS_TOOL_PHPSTAN,
\file_exists($this->kernel->getProjectDir().self::PSALM_PATH) => MakeFactoryData::STATIC_ANALYSIS_TOOL_PSALM,
default => MakeFactoryData::STATIC_ANALYSIS_TOOL_NONE,
};
}
}
16 changes: 1 addition & 15 deletions src/Bundle/Maker/Factory/MakeFactoryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,14 @@
*/
final class MakeFactoryData
{
public const STATIC_ANALYSIS_TOOL_NONE = 'none';
public const STATIC_ANALYSIS_TOOL_PHPSTAN = 'phpstan';
public const STATIC_ANALYSIS_TOOL_PSALM = 'psalm';

/** @var list<string> */
private array $uses;
/** @var array<string, string> */
private array $defaultProperties = [];
/** @var non-empty-list<MakeFactoryPHPDocMethod> */
private array $methodsInPHPDoc;

public function __construct(private \ReflectionClass $object, private ClassNameDetails $factoryClassNameDetails, private ?\ReflectionClass $repository, private string $staticAnalysisTool, private bool $persisted)
public function __construct(private \ReflectionClass $object, private ClassNameDetails $factoryClassNameDetails, private ?\ReflectionClass $repository, private bool $persisted)
{
$this->uses = [
PersistentObjectFactory::class,
Expand Down Expand Up @@ -80,16 +76,6 @@ public function isPersisted(): bool
return $this->persisted;
}

public function hasStaticAnalysisTool(): bool
{
return self::STATIC_ANALYSIS_TOOL_NONE !== $this->staticAnalysisTool;
}

public function staticAnalysisTool(): string
{
return $this->staticAnalysisTool;
}

/** @param class-string $use */
public function addUse(string $use): void
{
Expand Down
19 changes: 6 additions & 13 deletions src/Bundle/Maker/Factory/MakeFactoryPHPDocMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,20 @@ public static function createAll(MakeFactoryData $makeFactoryData): array
return $methods;
}

public function toString(string|null $staticAnalysisTool = null): string
public function toString(): string
{
$annotation = $staticAnalysisTool ? "{$staticAnalysisTool}-method" : 'method';
$static = $this->isStatic ? 'static' : ' ';

if ($this->repository) {
$returnType = match ((bool) $staticAnalysisTool) {
false => "{$this->repository}|RepositoryProxy",
true => "RepositoryProxy<{$this->objectName}>",
};
$returnType = "{$this->repository}|RepositoryProxy";
} else {
/** @phpstan-ignore-next-line */
$returnType = match ([$this->returnsCollection, (bool) $staticAnalysisTool]) {
[true, true] => "list<Proxy<{$this->objectName}>>",
[true, false] => "{$this->objectName}[]|Proxy[]",
[false, true] => "Proxy<{$this->objectName}>",
[false, false] => "{$this->objectName}|Proxy",
$returnType = match ($this->returnsCollection) {
true => "{$this->objectName}[]|Proxy[]",
false => "{$this->objectName}|Proxy",
};
}

return " * @{$annotation} {$static} {$returnType} {$this->prototype}";
return " * @method {$static} {$returnType} {$this->prototype}";
}

public function sortValue(): string
Expand Down
1 change: 0 additions & 1 deletion src/Bundle/Resources/config/maker.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@

<service id=".zenstruck_foundry.maker.factory.generator" class="Zenstruck\Foundry\Bundle\Maker\Factory\FactoryGenerator">
<argument type="service" id=".zenstruck_foundry.chain_manager_registry" />
<argument type="service" id="kernel" />
<argument type="tagged_iterator" tag="foundry.make_factory.default_properties_guesser" />
<argument type="service" id=".zenstruck_foundry.maker.factory.factory_class_map" />
<argument type="service" id=".zenstruck_foundry.maker.factory.namespace_guesser" />
Expand Down
8 changes: 0 additions & 8 deletions src/Bundle/Resources/skeleton/Factory.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
foreach ($makeFactoryData->getMethodsPHPDoc() as $methodPHPDoc) {
echo "{$methodPHPDoc->toString()}\n";
}

//if ($makeFactoryData->hasStaticAnalysisTool()) {
// echo " *\n";
//
// foreach ($makeFactoryData->getMethodsPHPDoc() as $methodPHPDoc) {
// echo "{$methodPHPDoc->toString($makeFactoryData->staticAnalysisTool())}\n";
// }
//}
?>
*/
final class <?= $class_name ?> extends PersistentObjectFactory
Expand Down
4 changes: 2 additions & 2 deletions src/FactoryCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
*
* @author Kevin Bond <kevinbond@gmail.com>
*
* @phpstan-import-type Parameters from BaseFactory
* @phpstan-import-type Attributes from BaseFactory
* @psalm-import-type Parameters from BaseFactory
* @psalm-import-type Attributes from BaseFactory
*/
final class FactoryCollection implements \IteratorAggregate
{
Expand Down
2 changes: 1 addition & 1 deletion src/FactoryManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*
* @internal
*
* @phpstan-import-type CallableInstantiator from ObjectFactory
* @psalm-import-type CallableInstantiator from ObjectFactory
*/
final class FactoryManager
{
Expand Down
2 changes: 1 addition & 1 deletion src/Instantiator.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* @author Kevin Bond <kevinbond@gmail.com>
* @template T of object
*
* @phpstan-import-type Parameters from BaseFactory
* @psalm-import-type Parameters from BaseFactory
*/
final class Instantiator
{
Expand Down
11 changes: 8 additions & 3 deletions src/Object/ObjectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
* @template T of object
* @extends BaseFactory<T>
*
* @phpstan-type CallableInstantiator Instantiator<T>|\Closure(Parameters,class-string<T>):T
* @psalm-type CallableInstantiator = Instantiator<T>|\Closure(Parameters,class-string<T>):T
*
* @phpstan-import-type Parameters from BaseFactory
* @phpstan-import-type Attributes from BaseFactory
* @psalm-import-type Parameters from BaseFactory
* @psalm-import-type Attributes from BaseFactory
*/
abstract class ObjectFactory extends BaseFactory
{
Expand All @@ -42,6 +42,11 @@ abstract class ObjectFactory extends BaseFactory
*/
abstract public static function class(): string;

/**
* @param Attributes $attributes
*
* @return T
*/
public function create(array|callable $attributes = []): object
{
return $this->normalizeAndInstantiate($attributes)[0];
Expand Down
Loading