From 46c549e9d7036ca06edd3b5113f29235ca0555cf Mon Sep 17 00:00:00 2001 From: Marjo Date: Tue, 5 Mar 2024 16:41:29 +0100 Subject: [PATCH] (Added) Add PHPStan for Static Analysis (#23) * Add phpstan.neon configuration file This commit introduces the phpstan.neon configuration file to the project. It includes various configuration parameters such as PHP version, error checking level, and paths to be analyzed. It is intended to standardize PHPStan static analysis settings across different environments. * Enable PHPStan static analysis in workflow Uncommented the PHPStan static analysis step in the GitHub Actions workflow. This will make it run after successful execution of Infection tests, improving overall code quality. * Add PHPStan to composer and testing scripts PHPStan and its PHPUnit extension have been added to our composer dependencies. Additionally, a new script for running PHPStan analysis has been implemented. This change aids in identifying code quality issues through static analysis. * Update packages in localTest.sh The commit revises the packages installed via composer in the localTest.sh script. Instead of "rector/rector", it now requires the "phpstan/phpstan" and "phpstan/phpstan-phpunit" packages with specified versions, aiming to align with the project's dependencies. * Refactor calculateRank method and remove psalm annotation The unnecessary psalm annotation was removed from the rankByMetric method. The calculateRank method was also refactored to include more explicit typing and to update the documentation regarding the method's parameters and return values. * Refactor rank calculation function in Trace Removed uneccessary comments and rearranged the order of types in the parameters within the rank calculation function. Further, the array returned was reformatted for improved readability. The process of incrementing the value of 'sameMetricValueCount' was also changed to the more standard unary operator (++$var). * Add generic class check in PHPStan configuration This commit includes an additional parameter to the PHPStan configuration, `checkGenericClassInNonGenericObjectType: true`. This enhancement ensures a more comprehensive analysis by enforcing checks for generic classes in non-generic object types. * Update method documentation in Trace.php The documentation for the method that calculates the rank for a given metric is updated. To make it more descriptive and clear, extra information is added to indicate that the parameter is --- .github/workflows/php.yml | 10 +++++----- composer.json | 7 ++++++- localTest.sh | 3 ++- phpstan.neon | 12 ++++++++++++ src/Trace.php | 28 ++++++++++++++++++++++------ 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 phpstan.neon diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 121b41b..e03a4c9 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -105,11 +105,11 @@ jobs: if: steps.phpunit.outcome == 'success' run: composer test:infection -# # This step runs static analysis with PHPStan. -# - name: Run static analysis with PHPStan -# id: phpstan -# if: steps.infection.outcome == 'success' -# run: composer test:phpstan + # This step runs static analysis with PHPStan. + - name: Run static analysis with PHPStan + id: phpstan + if: steps.infection.outcome == 'success' + run: composer test:phpstan # # # This step runs static analysis with Phan. # - name: Run static analysis with phan diff --git a/composer.json b/composer.json index 029ce25..cd38c58 100644 --- a/composer.json +++ b/composer.json @@ -52,6 +52,8 @@ "php-parallel-lint/php-console-highlighter": "^1", "php-parallel-lint/php-parallel-lint": "^1", "phpmd/phpmd": "^2", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", "phpunit/php-code-coverage": "^10|^11", "phpunit/phpunit": "^10|^11" }, @@ -66,12 +68,14 @@ "@test:lint", "@test:code-style", "@test:phpmd", - "@test:infection" + "@test:infection", + "@test:phpstan" ], "test:code-style": "pint --test", "test:infection": "infection --min-msi=100 --min-covered-msi=100 --threads=4 --show-mutations --only-covered --formatter=progress", "test:lint": "parallel-lint --exclude vendor --show-deprecated .", "test:phpmd": "phpmd src,tests text phpmd.xml", + "test:phpstan": "php -d memory_limit=-1 ./vendor/bin/phpstan analyse --no-progress --no-interaction", "test:phpunit": "phpunit --no-coverage --no-logging", "test:vulnerabilities-check": "php -d memory_limit=-1 ./vendor/bin/security-checker security:check" }, @@ -80,6 +84,7 @@ "test:infection": "Conduct mutation testing for robustness.", "test:lint": "Search for syntax errors and problematic patterns.", "test:phpmd": "Detect bugs and suboptimal code with PHP Mess Detector.", + "test:phpstan": "Conduct PHPStan static analysis for identifying code quality issues.", "test:phpunit": "Execute PHPUnit tests to verify code functionality.", "test:vulnerabilities-check": "Scan dependencies for known security vulnerabilities." } diff --git a/localTest.sh b/localTest.sh index f6c0236..accb69e 100755 --- a/localTest.sh +++ b/localTest.sh @@ -23,7 +23,8 @@ for version in {81..83}; do rm -f composer.lock && \ $DOCKER_CMD composer install && \ $DOCKER_CMD composer update --with-all-dependencies && \ - $DOCKER_CMD composer require --dev --with-all-dependencies rector/rector + $DOCKER_CMD composer require --dev --with-all-dependencies "phpstan/phpstan":"^1.10" && \ + $DOCKER_CMD composer require --dev --with-all-dependencies "phpstan/phpstan-phpunit":"^1.3" # Check for errors immediately after Composer commands if [ $? -ne 0 ]; then diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..151ec49 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,12 @@ +parameters: + level: max + phpVersion: 80100 + checkMissingIterableValueType: true + checkGenericClassInNonGenericObjectType: true + treatPhpDocTypesAsCertain: false + tipsOfTheDay: false + reportWrongPhpDocTypeInVarTag: true + paths: + - src + - tests + ignoreErrors: \ No newline at end of file diff --git a/src/Trace.php b/src/Trace.php index bbd5d67..75c56e3 100644 --- a/src/Trace.php +++ b/src/Trace.php @@ -288,8 +288,6 @@ private static function computeCombinedRankings(array $filteredData): array * @param array $data * * @return array An associative array where keys are function names and values are their ranks. - * - * @psalm-return array> */ private static function rankByMetric(array $data, string $metric): array { @@ -319,20 +317,38 @@ private static function rankByMetric(array $data, string $metric): array } + /** + * Calculates the rank for a given metric. + * + * @param array{ct: int, wt: int, cpu: int, mu: int, pmu: int, name: string} $item The array containing the metrics + * and name for which the rank is calculated. + * + * @return array{int, int, int|string} + */ private static function calculateRank( array $item, string $metric, int $currentRank, int $sameMetricValueCount, - $previousMetricValue + null|int|string $previousMetricValue ): array { if ($previousMetricValue === null || $item[$metric] === $previousMetricValue) { - $sameMetricValueCount++; - return [$currentRank, $sameMetricValueCount, $item[$metric]]; + ++$sameMetricValueCount; + + return [ + $currentRank, + $sameMetricValueCount, + $item[$metric], + ]; } $currentRank += $sameMetricValueCount; $sameMetricValueCount = 1; - return [$currentRank, $sameMetricValueCount, $item[$metric]]; + + return [ + $currentRank, + $sameMetricValueCount, + $item[$metric], + ]; } }