From 37ecdadcdf42ff26323890ad6f19a9f32d4a63d3 Mon Sep 17 00:00:00 2001 From: Bastien Philippe Date: Fri, 11 Mar 2022 09:01:29 +0100 Subject: [PATCH] Publish internal package --- .php-cs-fixer.dist.php | 6 +- composer.json | 27 +++---- config/phpstan-extension.php | 4 - database/factories/ModelFactory.php | 19 ----- .../create_phpstan_extension_table.php.stub | 19 ----- extension.neon | 15 ++++ phpstan.neon.dist | 4 +- resources/views/.gitkeep | 0 src/Commands/PhpstanExtensionCommand.php | 19 ----- src/Facades/PhpstanExtension.php | 16 ---- src/PhpstanExtension.php | 7 -- src/PhpstanExtensionServiceProvider.php | 25 ------- src/ReturnTypes/DateExtension.php | 72 ++++++++++++++++++ src/ReturnTypes/NowAndTodayExtension.php | 27 +++++++ src/Rules/CarbonCopyRule.php | 73 +++++++++++++++++++ src/Rules/NoAliasUseRule.php | 45 ++++++++++++ src/Rules/NoMutableDateTimeStaticCallRule.php | 50 +++++++++++++ src/Rules/NoMutableDateTimeUseRule.php | 44 +++++++++++ src/Rules/NoNewMutableDateTimeRule.php | 50 +++++++++++++ tests/ExampleTest.php | 5 -- tests/ExecutesLarastan.php | 50 +++++++++++++ tests/FeatureTest.php | 54 ++++++++++++++ .../DateCarbonImmutable/DateExtension.php | 16 ++++ .../NowAndTodayExtension.php | 15 ++++ .../DateCarbonImmutable/bootstrap.php | 6 ++ .../DateCarbonImmutable/phpstan-tests.neon | 15 ++++ tests/Features/Default/DateExtension.php | 16 ++++ .../Features/Default/NowAndTodayExtension.php | 15 ++++ tests/Features/phpstan-tests.neon | 11 +++ tests/Fixtures/CarbonCopy.php | 28 +++++++ tests/Fixtures/NoAliasUse.php | 13 ++++ .../Fixtures/NoMutableDateTimeStaticCall.php | 22 ++++++ tests/Fixtures/NoMutableDateTimeUse.php | 27 +++++++ tests/Fixtures/NoNewMutableDateTime.php | 22 ++++++ tests/Rules/CarbonCopyRuleTest.php | 24 ++++++ tests/Rules/NoAliasUseRuleTest.php | 23 ++++++ .../NoMutableDateTimeStaticCallRuleTest.php | 24 ++++++ tests/Rules/NoMutableDateTimeUseRuleTest.php | 24 ++++++ tests/Rules/NoNewMutableDateTimeRuleTest.php | 24 ++++++ tests/RulesTest.php | 41 +++++++++++ tests/TestCase.php | 27 ------- tests/phpstan-tests.neon | 3 + 42 files changed, 866 insertions(+), 161 deletions(-) delete mode 100644 config/phpstan-extension.php delete mode 100644 database/factories/ModelFactory.php delete mode 100644 database/migrations/create_phpstan_extension_table.php.stub create mode 100644 extension.neon delete mode 100644 resources/views/.gitkeep delete mode 100644 src/Commands/PhpstanExtensionCommand.php delete mode 100644 src/Facades/PhpstanExtension.php delete mode 100755 src/PhpstanExtension.php delete mode 100644 src/PhpstanExtensionServiceProvider.php create mode 100644 src/ReturnTypes/DateExtension.php create mode 100644 src/ReturnTypes/NowAndTodayExtension.php create mode 100644 src/Rules/CarbonCopyRule.php create mode 100644 src/Rules/NoAliasUseRule.php create mode 100644 src/Rules/NoMutableDateTimeStaticCallRule.php create mode 100644 src/Rules/NoMutableDateTimeUseRule.php create mode 100644 src/Rules/NoNewMutableDateTimeRule.php delete mode 100644 tests/ExampleTest.php create mode 100644 tests/ExecutesLarastan.php create mode 100644 tests/FeatureTest.php create mode 100644 tests/Features/DateCarbonImmutable/DateExtension.php create mode 100644 tests/Features/DateCarbonImmutable/NowAndTodayExtension.php create mode 100644 tests/Features/DateCarbonImmutable/bootstrap.php create mode 100644 tests/Features/DateCarbonImmutable/phpstan-tests.neon create mode 100644 tests/Features/Default/DateExtension.php create mode 100644 tests/Features/Default/NowAndTodayExtension.php create mode 100644 tests/Features/phpstan-tests.neon create mode 100644 tests/Fixtures/CarbonCopy.php create mode 100644 tests/Fixtures/NoAliasUse.php create mode 100644 tests/Fixtures/NoMutableDateTimeStaticCall.php create mode 100644 tests/Fixtures/NoMutableDateTimeUse.php create mode 100644 tests/Fixtures/NoNewMutableDateTime.php create mode 100644 tests/Rules/CarbonCopyRuleTest.php create mode 100644 tests/Rules/NoAliasUseRuleTest.php create mode 100644 tests/Rules/NoMutableDateTimeStaticCallRuleTest.php create mode 100644 tests/Rules/NoMutableDateTimeUseRuleTest.php create mode 100644 tests/Rules/NoNewMutableDateTimeRuleTest.php create mode 100644 tests/RulesTest.php create mode 100644 tests/phpstan-tests.neon diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 7143f8a..2239e2f 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,8 +1,6 @@ in([ - 'config', - 'database', 'src', 'tests', ]); @@ -94,7 +92,7 @@ /* * Class Usage */ - 'date_time_immutable' => true, // risky + 'date_time_immutable' => false, // risky /* * Comment */ @@ -177,7 +175,7 @@ * Import */ 'fully_qualified_strict_types' => true, - 'global_namespace_import' => ['import_constants' => false, 'import_functions' => true, 'import_classes' => true], + 'global_namespace_import' => ['import_constants' => false, 'import_functions' => true, 'import_classes' => null], 'group_import' => false, 'no_leading_import_slash' => true, 'no_unneeded_import_alias' => true, diff --git a/composer.json b/composer.json index 2d96302..f4d120d 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "keywords": [ "soyhuce", "laravel", - "phpstan-extension" + "phpstan" ], "homepage": "https://github.com/soyhuce/phpstan-extension", "license": "MIT", @@ -17,8 +17,9 @@ ], "require": { "php": "^8.1", - "spatie/laravel-package-tools": "^1.9.2", - "illuminate/contracts": "^9.0" + "illuminate/support": "^9.0", + "nesbot/carbon": "^2.0", + "phpstan/phpstan": "^1.4.5" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.7", @@ -34,8 +35,7 @@ }, "autoload": { "psr-4": { - "Soyhuce\\PhpstanExtension\\": "src", - "Soyhuce\\PhpstanExtension\\Database\\Factories\\": "database/factories" + "Soyhuce\\PhpstanExtension\\": "src" } }, "autoload-dev": { @@ -55,16 +55,17 @@ ] }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true, + "phpstan/extension-installer": true + } }, "extra": { - "laravel": { - "providers": [ - "Soyhuce\\PhpstanExtension\\PhpstanExtensionServiceProvider" - ], - "aliases": { - "PhpstanExtension": "Soyhuce\\PhpstanExtension\\Facades\\PhpstanExtension" - } + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "minimum-stability": "dev", diff --git a/config/phpstan-extension.php b/config/phpstan-extension.php deleted file mode 100644 index 6ee696e..0000000 --- a/config/phpstan-extension.php +++ /dev/null @@ -1,4 +0,0 @@ -id(); - - // add fields - - $table->timestamps(); - }); - } -}; diff --git a/extension.neon b/extension.neon new file mode 100644 index 0000000..752d473 --- /dev/null +++ b/extension.neon @@ -0,0 +1,15 @@ +services: + - class: Soyhuce\PhpstanExtension\ReturnTypes\DateExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - class: Soyhuce\PhpstanExtension\ReturnTypes\NowAndTodayExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension + +rules: + - Soyhuce\PhpstanExtension\Rules\CarbonCopyRule + - Soyhuce\PhpstanExtension\Rules\NoAliasUseRule + - Soyhuce\PhpstanExtension\Rules\NoMutableDateTimeStaticCallRule + - Soyhuce\PhpstanExtension\Rules\NoMutableDateTimeUseRule + - Soyhuce\PhpstanExtension\Rules\NoNewMutableDateTimeRule diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e273d91..e862c6c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,11 +2,9 @@ includes: - phpstan-baseline.neon parameters: - level: 8 + level: 9 paths: - src - - config - - database checkOctaneCompatibility: true checkModelProperties: true checkMissingIterableValueType: true diff --git a/resources/views/.gitkeep b/resources/views/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/Commands/PhpstanExtensionCommand.php b/src/Commands/PhpstanExtensionCommand.php deleted file mode 100644 index 1d754a8..0000000 --- a/src/Commands/PhpstanExtensionCommand.php +++ /dev/null @@ -1,19 +0,0 @@ -comment('All done'); - - return self::SUCCESS; - } -} diff --git a/src/Facades/PhpstanExtension.php b/src/Facades/PhpstanExtension.php deleted file mode 100644 index fdcac17..0000000 --- a/src/Facades/PhpstanExtension.php +++ /dev/null @@ -1,16 +0,0 @@ -name('phpstan-extension') - ->hasConfigFile() - ->hasViews() - ->hasMigration('create_phpstan-extension_table') - ->hasCommand(PhpstanExtensionCommand::class); - } -} diff --git a/src/ReturnTypes/DateExtension.php b/src/ReturnTypes/DateExtension.php new file mode 100644 index 0000000..f1e92d3 --- /dev/null +++ b/src/ReturnTypes/DateExtension.php @@ -0,0 +1,72 @@ +getName(), + [ + 'create', + 'createFromDate', + 'createFromTime', + 'createFromTimeString', + 'createFromTimestamp', + 'createFromTimestampMs', + 'createFromTimestampUTC', + 'createMidnightDate', + 'fromSerialized', + 'getTestNow', + 'instance', + 'isMutable', + 'maxValue', + 'minValue', + 'now', + 'parse', + 'today', + 'tomorrow', + 'yesterday', + 'createFromFormat', + 'createSafe', + 'make', + ] + ); + } + + public function getTypeFromStaticMethodCall( + MethodReflection $methodReflection, + StaticCall $methodCall, + Scope $scope, + ): Type { + $dateType = new ObjectType(get_class(now())); + + if (in_array($methodReflection->getName(), ['createFromFormat', 'createSafe'])) { + return TypeCombinator::union($dateType, new ConstantBooleanType(false)); + } + + if (in_array($methodReflection->getName(), ['getTestNow', 'make'])) { + return TypeCombinator::addNull($dateType); + } + + return $dateType; + } +} diff --git a/src/ReturnTypes/NowAndTodayExtension.php b/src/ReturnTypes/NowAndTodayExtension.php new file mode 100644 index 0000000..db34e18 --- /dev/null +++ b/src/ReturnTypes/NowAndTodayExtension.php @@ -0,0 +1,27 @@ +getName() === 'now' || $functionReflection->getName() === 'today'; + } + + public function getTypeFromFunctionCall( + FunctionReflection $functionReflection, + FuncCall $functionCall, + Scope $scope, + ): Type { + return new ObjectType(get_class(now())); + } +} diff --git a/src/Rules/CarbonCopyRule.php b/src/Rules/CarbonCopyRule.php new file mode 100644 index 0000000..6b90d35 --- /dev/null +++ b/src/Rules/CarbonCopyRule.php @@ -0,0 +1,73 @@ + + */ +class CarbonCopyRule implements Rule +{ + public function __construct( + protected RuleLevelHelper $ruleLevelHelper, + ) { + } + + public function getNodeType(): string + { + return MethodCall::class; + } + + /** + * @param \PhpParser\Node\Expr\MethodCall $node + * @return array + */ + public function processNode(Node $node, Scope $scope): array + { + if (!$node->name instanceof Node\Identifier) { + return []; + } + + $name = $node->name->name; + if (!in_array($name, ['copy', 'clone'])) { + return []; + } + + $typeResult = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->var, + '', + static function (Type $type) use ($name): bool { + return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes(); + } + ); + + $type = $typeResult->getType(); + + if ($type instanceof ErrorType) { + return []; + } + + if (!$type->hasMethod($name)->yes()) { + return []; + } + + if (!(new ObjectType(CarbonInterface::class))->isSuperTypeOf($type)->yes()) { + return []; + } + + return [ + "Usage of \\Carbon\\CarbonInterface::{$name}() is prohibited. You should use CarbonImmutable and remove {$name}() call.", + ]; + } +} diff --git a/src/Rules/NoAliasUseRule.php b/src/Rules/NoAliasUseRule.php new file mode 100644 index 0000000..fa7651f --- /dev/null +++ b/src/Rules/NoAliasUseRule.php @@ -0,0 +1,45 @@ + + */ +class NoAliasUseRule implements Rule +{ + /** @var array */ + private array $aliases; + + public function __construct() + { + $this->aliases = AliasLoader::getInstance()->getAliases(); + } + + public function getNodeType(): string + { + return UseUse::class; + } + + /** + * @param \PhpParser\Node\Stmt\UseUse $node + * @return array + */ + public function processNode(Node $node, Scope $scope): array + { + $usedClass = $node->name->toString(); + + $aliasedClass = $this->aliases[$usedClass] ?? null; + + if ($aliasedClass === null) { + return []; + } + + return ["Usage of alias {$usedClass} is prohibited, prefer the use of {$aliasedClass}."]; + } +} diff --git a/src/Rules/NoMutableDateTimeStaticCallRule.php b/src/Rules/NoMutableDateTimeStaticCallRule.php new file mode 100644 index 0000000..029d0b3 --- /dev/null +++ b/src/Rules/NoMutableDateTimeStaticCallRule.php @@ -0,0 +1,50 @@ + + */ +class NoMutableDateTimeStaticCallRule implements Rule +{ + public function getNodeType(): string + { + return StaticCall::class; + } + + /** + * @param \PhpParser\Node\Expr\StaticCall $node + * @return array + */ + public function processNode(Node $node, Scope $scope): array + { + if (!method_exists($node->class, 'toString')) { + return []; + } + + $class = $node->class->toString(); + + if ($this->isAllowed($class)) { + return []; + } + + return [ + "Static calls of mutable DateTime is forbidden, currently using {$class}.", + ]; + } + + private function isAllowed(string $class): bool + { + if ($class === DateTime::class) { + return false; + } + + return !is_subclass_of($class, DateTime::class); + } +} diff --git a/src/Rules/NoMutableDateTimeUseRule.php b/src/Rules/NoMutableDateTimeUseRule.php new file mode 100644 index 0000000..d8b9373 --- /dev/null +++ b/src/Rules/NoMutableDateTimeUseRule.php @@ -0,0 +1,44 @@ + + */ +class NoMutableDateTimeUseRule implements Rule +{ + public function getNodeType(): string + { + return UseUse::class; + } + + /** + * @param \PhpParser\Node\Stmt\UseUse $node + * @return array + */ + public function processNode(Node $node, Scope $scope): array + { + $usedClass = $node->name->toString(); + + if ($this->isAllowed($usedClass)) { + return []; + } + + return ["Usage of mutable DateTime is forbidden, currently using {$usedClass}."]; + } + + private function isAllowed(string $class): bool + { + if ($class === DateTime::class) { + return false; + } + + return !is_subclass_of($class, DateTime::class); + } +} diff --git a/src/Rules/NoNewMutableDateTimeRule.php b/src/Rules/NoNewMutableDateTimeRule.php new file mode 100644 index 0000000..e5a25e9 --- /dev/null +++ b/src/Rules/NoNewMutableDateTimeRule.php @@ -0,0 +1,50 @@ + + */ +class NoNewMutableDateTimeRule implements Rule +{ + public function getNodeType(): string + { + return New_::class; + } + + /** + * @param \PhpParser\Node\Expr\New_ $node + * @return array + */ + public function processNode(Node $node, Scope $scope): array + { + if (!method_exists($node->class, 'toString')) { + return []; + } + + $class = $node->class->toString(); + + if ($this->isAllowed($class)) { + return []; + } + + return [ + "Instanciations of mutable DateTime is forbidden, currently using {$class}.", + ]; + } + + private function isAllowed(string $class): bool + { + if ($class === DateTime::class) { + return false; + } + + return !is_subclass_of($class, DateTime::class); + } +} diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php deleted file mode 100644 index e38d639..0000000 --- a/tests/ExampleTest.php +++ /dev/null @@ -1,5 +0,0 @@ -toBeTrue(); -}); diff --git a/tests/ExecutesLarastan.php b/tests/ExecutesLarastan.php new file mode 100644 index 0000000..47dd788 --- /dev/null +++ b/tests/ExecutesLarastan.php @@ -0,0 +1,50 @@ +configPath), + escapeshellarg($filename) + ), + $jsonResult + ); + + return json_decode($jsonResult[0], true); + } + + private function analyze(string $file): int + { + $result = $this->execLarastan($file); + + if (!$result || $result['totals']['errors'] > 0 || $result['totals']['file_errors'] > 0) { + $this->fail(json_encode($result, JSON_PRETTY_PRINT)); + } + + return 0; + } + + /** + * @return static + */ + public function setConfigPath(string $configPath): self + { + $this->configPath = $configPath; + + return $this; + } +} diff --git a/tests/FeatureTest.php b/tests/FeatureTest.php new file mode 100644 index 0000000..fe6e44e --- /dev/null +++ b/tests/FeatureTest.php @@ -0,0 +1,54 @@ +configPath = __DIR__ . '/Features/phpstan-tests.neon'; + } + + public function getFeatures(): array + { + $calls = []; + $baseDir = __DIR__ . DIRECTORY_SEPARATOR . 'Features' . DIRECTORY_SEPARATOR; + + /** @var SplFileInfo $file */ + foreach ((new Finder())->in($baseDir)->files()->name('*.php')->notName('bootstrap.php') as $file) { + $fullPath = realpath((string) $file); + $calls[str_replace($baseDir, '', $fullPath)] = [$fullPath]; + } + + return $calls; + } + + /** + * @dataProvider getFeatures + * + * @test + */ + public function features(string $file): void + { + $configFile = dirname($file) . '/phpstan-tests.neon'; + if (file_exists($configFile)) { + $this->configPath = $configFile; + } + + if ($this->analyze($file) === 0) { + $this->assertTrue(true); + } + } +} diff --git a/tests/Features/DateCarbonImmutable/DateExtension.php b/tests/Features/DateCarbonImmutable/DateExtension.php new file mode 100644 index 0000000..63c673d --- /dev/null +++ b/tests/Features/DateCarbonImmutable/DateExtension.php @@ -0,0 +1,16 @@ +copy(); + } + + public function runClone(CarbonInterface $carbon): CarbonInterface + { + return $carbon->clone(); + } + + public function noError(): self + { + return $this->copy(); + } + + private function copy(): self + { + return $this; + } +} diff --git a/tests/Fixtures/NoAliasUse.php b/tests/Fixtures/NoAliasUse.php new file mode 100644 index 0000000..aa74f9c --- /dev/null +++ b/tests/Fixtures/NoAliasUse.php @@ -0,0 +1,13 @@ +isAfter($start); + } + + public function runImmutable(): bool + { + $start = \DateTimeImmutable::createFromFormat('Y-m-d', '2021-01-01'); + $end = \Carbon\CarbonImmutable::createFromFormat('Y-m-d', '2021-01-01'); + + return $end !== false && $end->isAfter($start); + } +} diff --git a/tests/Fixtures/NoMutableDateTimeUse.php b/tests/Fixtures/NoMutableDateTimeUse.php new file mode 100644 index 0000000..ebe5f99 --- /dev/null +++ b/tests/Fixtures/NoMutableDateTimeUse.php @@ -0,0 +1,27 @@ +isAfter($start); + } + + public function runImmutable(): bool + { + $start = new \DateTimeImmutable('2021-01-01'); + $end = new \Carbon\CarbonImmutable('2021-01-01'); + + return $end->isAfter($start); + } +} diff --git a/tests/Rules/CarbonCopyRuleTest.php b/tests/Rules/CarbonCopyRuleTest.php new file mode 100644 index 0000000..8066f03 --- /dev/null +++ b/tests/Rules/CarbonCopyRuleTest.php @@ -0,0 +1,24 @@ +findErrorsByLine(__DIR__ . '/../Fixtures/CarbonCopy.php'); + + $this->assertEquals([ + 11 => 'Usage of \Carbon\CarbonInterface::copy() is prohibited. You should use CarbonImmutable and remove copy() call.', + 16 => 'Usage of \Carbon\CarbonInterface::clone() is prohibited. You should use CarbonImmutable and remove clone() call.', + ], $errors); + } +} diff --git a/tests/Rules/NoAliasUseRuleTest.php b/tests/Rules/NoAliasUseRuleTest.php new file mode 100644 index 0000000..83aa346 --- /dev/null +++ b/tests/Rules/NoAliasUseRuleTest.php @@ -0,0 +1,23 @@ +findErrorsByLine(__DIR__ . '/../Fixtures/NoAliasUse.php'); + + $this->assertEquals([ + 5 => 'Usage of alias DB is prohibited, prefer the use of Illuminate\\Support\\Facades\\DB.', + ], $errors); + } +} diff --git a/tests/Rules/NoMutableDateTimeStaticCallRuleTest.php b/tests/Rules/NoMutableDateTimeStaticCallRuleTest.php new file mode 100644 index 0000000..8117ed7 --- /dev/null +++ b/tests/Rules/NoMutableDateTimeStaticCallRuleTest.php @@ -0,0 +1,24 @@ +findErrorsByLine(__DIR__ . '/../Fixtures/NoMutableDateTimeStaticCall.php'); + + $this->assertEquals([ + 9 => 'Static calls of mutable DateTime is forbidden, currently using DateTime.', + 10 => 'Static calls of mutable DateTime is forbidden, currently using Carbon\Carbon.', + ], $errors); + } +} diff --git a/tests/Rules/NoMutableDateTimeUseRuleTest.php b/tests/Rules/NoMutableDateTimeUseRuleTest.php new file mode 100644 index 0000000..ae25f5e --- /dev/null +++ b/tests/Rules/NoMutableDateTimeUseRuleTest.php @@ -0,0 +1,24 @@ +findErrorsByLine(__DIR__ . '/../Fixtures/NoMutableDateTimeUse.php'); + + $this->assertEquals([ + 5 => 'Usage of mutable DateTime is forbidden, currently using Carbon\Carbon.', + 7 => 'Usage of mutable DateTime is forbidden, currently using DateTime.', + ], $errors); + } +} diff --git a/tests/Rules/NoNewMutableDateTimeRuleTest.php b/tests/Rules/NoNewMutableDateTimeRuleTest.php new file mode 100644 index 0000000..52774a5 --- /dev/null +++ b/tests/Rules/NoNewMutableDateTimeRuleTest.php @@ -0,0 +1,24 @@ +findErrorsByLine(__DIR__ . '/../Fixtures/NoNewMutableDateTime.php'); + + $this->assertEquals([ + 9 => 'Instanciations of mutable DateTime is forbidden, currently using DateTime.', + 10 => 'Instanciations of mutable DateTime is forbidden, currently using Carbon\Carbon.', + ], $errors); + } +} diff --git a/tests/RulesTest.php b/tests/RulesTest.php new file mode 100644 index 0000000..d362efe --- /dev/null +++ b/tests/RulesTest.php @@ -0,0 +1,41 @@ +configPath = __DIR__ . '/phpstan-tests.neon'; + } + + /** + * Returns an array of errors that were found after analyzing $filename. + */ + protected function findErrors(string $filename): array + { + return $this->execLarastan($filename)['files'][$filename] ?? []; + } + + /** + * Returns an associative Collection where each key represents the line + * number and the value represents the error found. Will return + * at most one error per line. + * + * @return array + */ + protected function findErrorsByLine(string $filename): array + { + $errors = $this->findErrors(realpath($filename)); + + return collect($errors['messages'] ?? [])->mapWithKeys(function ($message) { + return [$message['line'] => $message['message']]; + })->toArray(); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 6421420..ecfb5a1 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,38 +2,11 @@ namespace Soyhuce\PhpstanExtension\Tests; -use Illuminate\Database\Eloquent\Factories\Factory; use Orchestra\Testbench\TestCase as Orchestra; -use Soyhuce\PhpstanExtension\PhpstanExtensionServiceProvider; /** * @coversNothing */ class TestCase extends Orchestra { - protected function setUp(): void - { - parent::setUp(); - - Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Soyhuce\\PhpstanExtension\\Database\\Factories\\' . class_basename($modelName) . 'Factory' - ); - } - - protected function getPackageProviders($app) - { - return [ - PhpstanExtensionServiceProvider::class, - ]; - } - - public function getEnvironmentSetUp($app): void - { - config()->set('database.default', 'testing'); - - /* - $migration = include __DIR__.'/../database/migrations/create_phpstan-extension_table.php.stub'; - $migration->up(); - */ - } } diff --git a/tests/phpstan-tests.neon b/tests/phpstan-tests.neon new file mode 100644 index 0000000..7067a58 --- /dev/null +++ b/tests/phpstan-tests.neon @@ -0,0 +1,3 @@ +includes: + - ../extension.neon + - ../vendor/phpstan/phpstan/conf/bleedingEdge.neon