diff --git a/composer.json b/composer.json index a8f304c..f802e96 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "ext-simplexml": "*", "php-static-analysis/attributes": "^0.4.1 || dev-main", "php-static-analysis/node-visitor": "^0.4.1 || dev-main", - "vimeo/psalm": "^6", + "vimeo/psalm": "^6.12", "webmozart/assert": "^1.11" }, "require-dev": { diff --git a/patches/vimeo-psalm-src-psalm-internal-codebase-analizer-php.patch b/patches/vimeo-psalm-src-psalm-internal-codebase-analizer-php.patch new file mode 100644 index 0000000..ce549a3 --- /dev/null +++ b/patches/vimeo-psalm-src-psalm-internal-codebase-analizer-php.patch @@ -0,0 +1,16 @@ +diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php +index f9127a517..41f94a174 100644 +--- a/src/Psalm/Internal/Codebase/Analyzer.php ++++ b/src/Psalm/Internal/Codebase/Analyzer.php +@@ -812,7 +812,10 @@ final class Analyzer + ); + } + +- public function shiftFileOffsets(StatementsProvider $statements_provider): void ++ /** ++ * @param StatementsProvider $statements_provider ++ */ ++ public function shiftFileOffsets($statements_provider): void + { + $diff_map = $statements_provider->getDiffMap(); + $deletion_ranges = $statements_provider->getDeletionRanges(); diff --git a/patches/vimeo-psalm-src-psalm-internal-provider-parsercacheprovider-php.patch b/patches/vimeo-psalm-src-psalm-internal-provider-parsercacheprovider-php.patch new file mode 100644 index 0000000..1b0c131 --- /dev/null +++ b/patches/vimeo-psalm-src-psalm-internal-provider-parsercacheprovider-php.patch @@ -0,0 +1,13 @@ +diff --git a/src/Psalm/Internal/Provider/ParserCacheProvider.php b/src/Psalm/Internal/Provider/ParserCacheProvider.php +index f352519f2..c2351841e 100644 +--- a/src/Psalm/Internal/Provider/ParserCacheProvider.php ++++ b/src/Psalm/Internal/Provider/ParserCacheProvider.php +@@ -13,7 +13,7 @@ use function filemtime; + use const DIRECTORY_SEPARATOR; + + /** @internal */ +-final class ParserCacheProvider ++class ParserCacheProvider + { + private const PARSER_CACHE_DIRECTORY = 'php-parser'; + diff --git a/patches/vimeo-psalm-tests-testconfig-php.patch b/patches/vimeo-psalm-tests-testconfig-php.patch new file mode 100644 index 0000000..2166420 --- /dev/null +++ b/patches/vimeo-psalm-tests-testconfig-php.patch @@ -0,0 +1,13 @@ +diff --git a/tests/TestConfig.php b/tests/TestConfig.php +index b5bac8fcc..970ac2b40 100644 +--- a/tests/TestConfig.php ++++ b/tests/TestConfig.php +@@ -12,7 +12,7 @@ use SimpleXMLElement; + + use function getcwd; + +-final class TestConfig extends Config ++class TestConfig extends Config + { + private static ?ProjectFileFilter $cached_project_files = null; + diff --git a/psalm.xml b/psalm.xml index 92e584a..fb591f5 100644 --- a/psalm.xml +++ b/psalm.xml @@ -7,6 +7,7 @@ errorLevel="1" findUnusedBaselineEntry="true" findUnusedCode="false" + ensureOverrideAttribute="false" > diff --git a/src/Composer/Plugin.php b/src/Composer/Plugin.php index 9fe18e9..1a228d8 100644 --- a/src/Composer/Plugin.php +++ b/src/Composer/Plugin.php @@ -9,7 +9,7 @@ use Composer\Script\Event; use PhpStaticAnalysis\Attributes\Returns; -class Plugin implements PluginInterface, EventSubscriberInterface +final class Plugin implements PluginInterface, EventSubscriberInterface { public function activate(Composer $composer, IOInterface $io) { @@ -50,12 +50,25 @@ private static function applyPatches(Event $event): void $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); $dependencyPath = $vendorDir . '/vimeo/psalm'; - $patchFile = __DIR__ . '/../../patches/vimeo-psalm-src-psalm-config-php.patch'; + $patchesDir = __DIR__ . '/../../patches/'; + $patchFiles = glob($patchesDir . '*.patch'); - exec("patch -p1 -d $dependencyPath --forward < $patchFile"); + if ($patchFiles === false) { + echo "No patches to apply\n"; + return; + } + foreach ($patchFiles as $patchFile) { + $escapedPatchFile = escapeshellarg($patchFile); + $escapedDependencyPath = escapeshellarg($dependencyPath); - $patchFile = __DIR__ . '/../../patches/vimeo-psalm-src-psalm-codebase-php.patch'; + $cmd = "patch -p1 -d $escapedDependencyPath --forward < $escapedPatchFile"; + exec($cmd, $output, $returnVar); - exec("patch -p1 -d $dependencyPath --forward < $patchFile"); + if ($returnVar !== 0) { + echo "Failed to apply patch: $patchFile\n"; + } else { + echo "Applied patch: $patchFile\n"; + } + } } } diff --git a/src/Plugin.php b/src/Plugin.php index 98d6997..61ebd9e 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -10,7 +10,7 @@ use Psalm\Plugin\RegistrationInterface; use SimpleXMLElement; -class Plugin implements PluginEntryPointInterface +final class Plugin implements PluginEntryPointInterface { public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement $config = null): void { diff --git a/src/Provider/AttributeStatementProvider.php b/src/Provider/AttributeStatementProvider.php index 14d0ad9..72ab888 100644 --- a/src/Provider/AttributeStatementProvider.php +++ b/src/Provider/AttributeStatementProvider.php @@ -14,7 +14,7 @@ use Psalm\Progress\Progress; use Webmozart\Assert\Assert; -class AttributeStatementProvider +final class AttributeStatementProvider { private StatementsProvider $statementsProvider; @@ -27,12 +27,14 @@ public function __construct(StatementsProvider $statementsProvider) public function getStatementsForFile( string $file_path, int $analysis_php_version_id, + bool $do_diff, ?Progress $progress = null ): array { /** @psalm-suppress InternalMethod */ $ast = $this->statementsProvider->getStatementsForFile( $file_path, $analysis_php_version_id, + $do_diff, $progress ); return $this->traverseAst($ast); diff --git a/tests/AssertAttributeTest.php b/tests/AssertAttributeTest.php index b66c653..d999ad8 100644 --- a/tests/AssertAttributeTest.php +++ b/tests/AssertAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class AssertAttributeTest extends BaseAttributeTestCase +final class AssertAttributeTest extends BaseAttributeTestCase { public function testFunctionAssertAttribute(): void { diff --git a/tests/AssertIfFalseAttributeTest.php b/tests/AssertIfFalseAttributeTest.php index a1c873f..f30d8d6 100644 --- a/tests/AssertIfFalseAttributeTest.php +++ b/tests/AssertIfFalseAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class AssertIfFalseAttributeTest extends BaseAttributeTestCase +final class AssertIfFalseAttributeTest extends BaseAttributeTestCase { public function testFunctionAssertIfFalseAttribute(): void { diff --git a/tests/AssertIfTrueAttributeTest.php b/tests/AssertIfTrueAttributeTest.php index 5a0e0ca..6fe720f 100644 --- a/tests/AssertIfTrueAttributeTest.php +++ b/tests/AssertIfTrueAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class AssertIfTrueAttributeTest extends BaseAttributeTestCase +final class AssertIfTrueAttributeTest extends BaseAttributeTestCase { public function testFunctionAssertIfTrueAttribute(): void { diff --git a/tests/AttributeTestConfig.php b/tests/AttributeTestConfig.php index f4cf439..247c3f9 100644 --- a/tests/AttributeTestConfig.php +++ b/tests/AttributeTestConfig.php @@ -8,7 +8,7 @@ use Psalm\Progress\Progress; use Psalm\Tests\TestConfig; -class AttributeTestConfig extends TestConfig +final class AttributeTestConfig extends TestConfig { protected function getContents(): string { diff --git a/tests/DefineTypeAttributeTest.php b/tests/DefineTypeAttributeTest.php index 7bb3cb4..9c3a6a2 100644 --- a/tests/DefineTypeAttributeTest.php +++ b/tests/DefineTypeAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class DefineTypeAttributeTest extends BaseAttributeTestCase +final class DefineTypeAttributeTest extends BaseAttributeTestCase { public function testClassDefineTypeAttribute(): void { diff --git a/tests/DeprecatedAttributeTest.php b/tests/DeprecatedAttributeTest.php index f3bec7d..8a7c6bf 100644 --- a/tests/DeprecatedAttributeTest.php +++ b/tests/DeprecatedAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class DeprecatedAttributeTest extends BaseAttributeTestCase +final class DeprecatedAttributeTest extends BaseAttributeTestCase { public function testClassDeprecatedAttribute(): void { diff --git a/tests/ImmutableAttributeTest.php b/tests/ImmutableAttributeTest.php index f4c7714..3af7fd4 100644 --- a/tests/ImmutableAttributeTest.php +++ b/tests/ImmutableAttributeTest.php @@ -3,7 +3,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class ImmutableAttributeTest extends BaseAttributeTestCase +final class ImmutableAttributeTest extends BaseAttributeTestCase { public function testClassImmutableAttribute(): void { diff --git a/tests/ImportTypeAttributeTest.php b/tests/ImportTypeAttributeTest.php index 2f9dd06..50687c4 100644 --- a/tests/ImportTypeAttributeTest.php +++ b/tests/ImportTypeAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class ImportTypeAttributeTest extends BaseAttributeTestCase +final class ImportTypeAttributeTest extends BaseAttributeTestCase { public function testClassImportTypeAttribute(): void { diff --git a/tests/InternalAttributeTest.php b/tests/InternalAttributeTest.php index 6891912..5ff614a 100644 --- a/tests/InternalAttributeTest.php +++ b/tests/InternalAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class InternalAttributeTest extends BaseAttributeTestCase +final class InternalAttributeTest extends BaseAttributeTestCase { public function testClassInternalAttribute(): void { diff --git a/tests/IsReadOnlyAttributeTest.php b/tests/IsReadOnlyAttributeTest.php index ccc12ac..c6e20c2 100644 --- a/tests/IsReadOnlyAttributeTest.php +++ b/tests/IsReadOnlyAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class IsReadOnlyAttributeTest extends BaseAttributeTestCase +final class IsReadOnlyAttributeTest extends BaseAttributeTestCase { public function testPropertyIsReadOnlyAttribute(): void { diff --git a/tests/MethodAttributeTest.php b/tests/MethodAttributeTest.php index 46b75d1..d10b1a1 100644 --- a/tests/MethodAttributeTest.php +++ b/tests/MethodAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class MethodAttributeTest extends BaseAttributeTestCase +final class MethodAttributeTest extends BaseAttributeTestCase { public function testClassMethodAttribute(): void { @@ -27,6 +27,7 @@ public function testInvalidClassMethodAttribute(): void $errors = $this->analyzeTestFile( '/data/Method/InvalidClassMethodAttribute.php'); $expectedErrors = [ + 'Magic method test\PhpStaticAnalysis\PsalmPlugin\data\Method\InvalidClassMethodAttribute::badfunction does not exist' => 34, 'No @method entry specified in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\Method\InvalidClassMethodAttribute' => 9, 'Attribute Method cannot be used on a method' => 11, 'string is not a valid method in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\Method\AnotherInvalidClassMethodAttribute' => 29, diff --git a/tests/MixinAttributeTest.php b/tests/MixinAttributeTest.php index 89f0ad2..a089ee0 100644 --- a/tests/MixinAttributeTest.php +++ b/tests/MixinAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class MixinAttributeTest extends BaseAttributeTestCase +final class MixinAttributeTest extends BaseAttributeTestCase { public function testClassMixinAttribute(): void { diff --git a/tests/ParamAttributeTest.php b/tests/ParamAttributeTest.php index ad0d6d2..0aace27 100644 --- a/tests/ParamAttributeTest.php +++ b/tests/ParamAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class ParamAttributeTest extends BaseAttributeTestCase +final class ParamAttributeTest extends BaseAttributeTestCase { public function testFunctionParamAttribute(): void { diff --git a/tests/ParamOutAttributeTest.php b/tests/ParamOutAttributeTest.php index 24243b0..b64a4a1 100644 --- a/tests/ParamOutAttributeTest.php +++ b/tests/ParamOutAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class ParamOutAttributeTest extends BaseAttributeTestCase +final class ParamOutAttributeTest extends BaseAttributeTestCase { public function testMethodParamOutAttribute(): void { diff --git a/tests/PropertyAttributeTest.php b/tests/PropertyAttributeTest.php index e6319df..0e8b844 100644 --- a/tests/PropertyAttributeTest.php +++ b/tests/PropertyAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class PropertyAttributeTest extends BaseAttributeTestCase +final class PropertyAttributeTest extends BaseAttributeTestCase { public function testClassPropertyAttribute(): void { diff --git a/tests/PropertyReadAttributeTest.php b/tests/PropertyReadAttributeTest.php index 229bdc2..ea40bd1 100644 --- a/tests/PropertyReadAttributeTest.php +++ b/tests/PropertyReadAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class PropertyReadAttributeTest extends BaseAttributeTestCase +final class PropertyReadAttributeTest extends BaseAttributeTestCase { public function testClassPropertyReadAttribute(): void { @@ -27,6 +27,7 @@ public function testInvalidClassPropertyReadAttribute(): void $errors = $this->analyzeTestFile('/data/PropertyRead/InvalidClassPropertyReadAttribute.php'); $expectedErrors = [ + 'Magic instance property test\PhpStaticAnalysis\PsalmPlugin\data\PropertyRead\InvalidClassPropertyReadAttribute::$name is not defined' => 39, 'Badly-formatted @property in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\PropertyRead\InvalidClassPropertyReadAttribute' => 9, 'Attribute PropertyRead cannot be used on a method' => 11, 'Badly-formatted @property in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\PropertyRead\AnotherInvalidClassPropertyReadAttribute' => 29, diff --git a/tests/PropertyWriteAttributeTest.php b/tests/PropertyWriteAttributeTest.php index 7ff00fd..cf367d1 100644 --- a/tests/PropertyWriteAttributeTest.php +++ b/tests/PropertyWriteAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class PropertyWriteAttributeTest extends BaseAttributeTestCase +final class PropertyWriteAttributeTest extends BaseAttributeTestCase { public function testClassPropertyWriteAttribute(): void { @@ -27,6 +27,7 @@ public function testInvalidClassPropertyWriteAttribute(): void $errors = $this->analyzeTestFile('/data/PropertyWrite/InvalidClassPropertyWriteAttribute.php'); $expectedErrors = [ + 'Magic instance property test\PhpStaticAnalysis\PsalmPlugin\data\PropertyWrite\InvalidClassPropertyWriteAttribute::$name is not defined' => 39, 'Unable to determine the type that $foo is being assigned to' => 39, 'Badly-formatted @property in docblock for test\PhpStaticAnalysis\PsalmPlugin\data\PropertyWrite\InvalidClassPropertyWriteAttribute' => 9, 'Attribute PropertyWrite cannot be used on a method' => 11, diff --git a/tests/PureAttributeTest.php b/tests/PureAttributeTest.php index 45935d9..0ea6513 100644 --- a/tests/PureAttributeTest.php +++ b/tests/PureAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class PureAttributeTest extends BaseAttributeTestCase +final class PureAttributeTest extends BaseAttributeTestCase { public function testMethodPureAttribute(): void { diff --git a/tests/RequireExtendsAttributeTest.php b/tests/RequireExtendsAttributeTest.php index 174c651..9598d3b 100644 --- a/tests/RequireExtendsAttributeTest.php +++ b/tests/RequireExtendsAttributeTest.php @@ -3,7 +3,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class RequireExtendsAttributeTest extends BaseAttributeTestCase +final class RequireExtendsAttributeTest extends BaseAttributeTestCase { public function testClassRequireExtendsAttribute(): void { diff --git a/tests/RequireImplementsAttributeTest.php b/tests/RequireImplementsAttributeTest.php index d752399..efbed08 100644 --- a/tests/RequireImplementsAttributeTest.php +++ b/tests/RequireImplementsAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class RequireImplementsAttributeTest extends BaseAttributeTestCase +final class RequireImplementsAttributeTest extends BaseAttributeTestCase { public function testClassRequireImplementsAttribute(): void { diff --git a/tests/ReturnsAttributeTest.php b/tests/ReturnsAttributeTest.php index 7c1bd0c..05e6339 100644 --- a/tests/ReturnsAttributeTest.php +++ b/tests/ReturnsAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class ReturnsAttributeTest extends BaseAttributeTestCase +final class ReturnsAttributeTest extends BaseAttributeTestCase { public function testFunctionReturnsAttribute(): void { diff --git a/tests/SelfOutAttributeTest.php b/tests/SelfOutAttributeTest.php index 84148d3..4ddabae 100644 --- a/tests/SelfOutAttributeTest.php +++ b/tests/SelfOutAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class SelfOutAttributeTest extends BaseAttributeTestCase +final class SelfOutAttributeTest extends BaseAttributeTestCase { public function testMethodSelfOutAttribute(): void { diff --git a/tests/TemplateAttributeTest.php b/tests/TemplateAttributeTest.php index 8c0765f..4b40daf 100644 --- a/tests/TemplateAttributeTest.php +++ b/tests/TemplateAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TemplateAttributeTest extends BaseAttributeTestCase +final class TemplateAttributeTest extends BaseAttributeTestCase { public function testFunctionTemplateAttribute(): void { diff --git a/tests/TemplateCovariantAttributeTest.php b/tests/TemplateCovariantAttributeTest.php index ab91a51..f49cb6c 100644 --- a/tests/TemplateCovariantAttributeTest.php +++ b/tests/TemplateCovariantAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TemplateCovariantAttributeTest extends BaseAttributeTestCase +final class TemplateCovariantAttributeTest extends BaseAttributeTestCase { public function testClassTemplateCovariantAttribute(): void { diff --git a/tests/TemplateExtendsAttributeTest.php b/tests/TemplateExtendsAttributeTest.php index 41ac3eb..985aeca 100644 --- a/tests/TemplateExtendsAttributeTest.php +++ b/tests/TemplateExtendsAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TemplateExtendsAttributeTest extends BaseAttributeTestCase +final class TemplateExtendsAttributeTest extends BaseAttributeTestCase { public function testClassTemplateExtendsAttribute(): void { diff --git a/tests/TemplateImplementsAttributeTest.php b/tests/TemplateImplementsAttributeTest.php index bae65f3..aabd475 100644 --- a/tests/TemplateImplementsAttributeTest.php +++ b/tests/TemplateImplementsAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TemplateImplementsAttributeTest extends BaseAttributeTestCase +final class TemplateImplementsAttributeTest extends BaseAttributeTestCase { public function testInterfaceTemplateImplementsAttribute(): void { diff --git a/tests/TemplateUseAttributeTest.php b/tests/TemplateUseAttributeTest.php index 4f36b99..529c059 100644 --- a/tests/TemplateUseAttributeTest.php +++ b/tests/TemplateUseAttributeTest.php @@ -2,7 +2,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TemplateUseAttributeTest extends BaseAttributeTestCase +final class TemplateUseAttributeTest extends BaseAttributeTestCase { public function testTraitTemplateUseAttribute(): void { diff --git a/tests/TypeAttributeTest.php b/tests/TypeAttributeTest.php index eec5ff4..bb0416f 100644 --- a/tests/TypeAttributeTest.php +++ b/tests/TypeAttributeTest.php @@ -4,7 +4,7 @@ namespace test\PhpStaticAnalysis\PsalmPlugin; -class TypeAttributeTest extends BaseAttributeTestCase +final class TypeAttributeTest extends BaseAttributeTestCase { public function testPropertyTypeAttribute(): void {