Skip to content

Commit

Permalink
Expire comments by virtual packages (#43)
Browse files Browse the repository at this point in the history
Co-authored-by: clxmstaab <[email protected]>
  • Loading branch information
staabm and clxmstaab authored Jan 3, 2024
1 parent 5e702b2 commit a1932b1
Show file tree
Hide file tree
Showing 9 changed files with 496 additions and 377 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
include:
- os: ubuntu-latest
php-version: '8.2'
test-dir: tests-e2e/bug52/
script: |
cd tests-e2e/bug52/
composer install
../../vendor/bin/phpstan analyse
vendor/bin/phpstan analyse
steps:
- name: Checkout
Expand All @@ -35,10 +35,9 @@ jobs:
extensions: gd, intl, pdo_mysql
coverage: none # disable xdebug, pcov

- name: Composer install
uses: ramsey/composer-install@v2
with:
composer-options: '--ansi --prefer-dist'
- run: "composer require --dev staabm/phpstan-todo-by:dev-${{ github.head_ref || github.ref_name }}"
working-directory: ${{ matrix.test-dir }}

- name: "Tests"
run: "${{ matrix.script }}"
working-directory: ${{ matrix.test-dir }}
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ When a text is given after the date, this text will be picked up for the PHPStan
The comment can expire by different constraints, examples are:
- by date with format of `YYYY-MM-DD` matched against the [reference-time](https://github.com/staabm/phpstan-todo-by#reference-time)
- by a semantic version constraint matched against the projects [reference-version](https://github.com/staabm/phpstan-todo-by#reference-version)
- by a semantic version constraint matched against a Composer dependency (via `composer.lock`)
- by a semantic version constraint matched against a Composer dependency (via `composer.lock` or [`virtualPackages`](https://github.com/staabm/phpstan-todo-by#virtual-packages) config)
- by ticket reference, matched against the status of a ticket (e.g. in JIRA)

see examples of different comment variants which are supported:
Expand Down Expand Up @@ -158,6 +158,23 @@ In case you are using git submodules, or the analyzed codebase consists of multi
set the `singleGitRepo` option to `false` which resolves the reference version for each directory beeing analyzed.


#### Virtual packages

Within the PHPStan config file you can define additional packages, to match against package-version-todo-comments.

```neon
parameters:
todo_by:
virtualPackages:
'staabm/mypackage': '2.1.0'
'staabm/my-api': '3.1.0'
```

Reference these virtual packages like any other package in your todo-comments:

`// TODO staabm/mypackage:2.2.0 remove the following function once staabm/mypackage is updated to 2.2.0`


### Issue tracker key support

Optionally you can configure this extension to analyze your comments with issue tracker ticket keys.
Expand Down
7 changes: 6 additions & 1 deletion extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ parametersSchema:
referenceTime: string()
referenceVersion: string()
singleGitRepo: bool()
virtualPackages: arrayOf(string(), string())
ticket: structure([
enabled: bool()
keyPrefixes: listOf(string())
Expand Down Expand Up @@ -31,6 +32,9 @@ parameters:
# If set to false, the git tags are fetched for each directory individually (slower)
singleGitRepo: true

# a map of additional packages to match package-comments against
virtualPackages: []

ticket:
# whether to analyze comments by issue tracker ticket key
enabled: false
Expand Down Expand Up @@ -84,7 +88,8 @@ services:
class: staabm\PHPStanTodoBy\TodoByPackageVersionRule
tags: [phpstan.rules.rule]
arguments:
- %currentWorkingDirectory%
workingDirectory: %currentWorkingDirectory%
virtualPackages: %todo_by.virtualPackages%

-
class: staabm\PHPStanTodoBy\utils\GitTagFetcher
Expand Down
50 changes: 48 additions & 2 deletions src/TodoByPackageVersionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use staabm\PHPStanTodoBy\utils\ExpiredCommentErrorBuilder;
use UnexpectedValueException;

use function array_key_exists;
use function in_array;
use function is_array;
use function is_string;
Expand Down Expand Up @@ -52,11 +53,21 @@ final class TodoByPackageVersionRule implements Rule
*/
private $phpPlatformVersion;

/**
* @var array<string, string>
*/
private array $virtualPackages;

/**
* @param array<string, string> $virtualPackages
*/
public function __construct(
ExpiredCommentErrorBuilder $errorBuilder,
string $workingDirectory,
ExpiredCommentErrorBuilder $errorBuilder
array $virtualPackages
) {
$this->workingDirectory = $workingDirectory;
$this->virtualPackages = $virtualPackages;
$this->errorBuilder = $errorBuilder;

// require the top level installed versions, so we don't mix it up with the one in phpstan.phar
Expand Down Expand Up @@ -90,6 +101,8 @@ public function processNode(Node $node, Scope $scope): array

if ('php' === $package) {
$satisfiesOrError = $this->satisfiesPhpPlatformPackage($package, $version, $comment, $match[0][1]);
} elseif (array_key_exists($package, $this->virtualPackages)) {
$satisfiesOrError = $this->satisfiesVirtualPackage($package, $version, $comment, $match[0][1]);
} else {
$satisfiesOrError = $this->satisfiesInstalledPackage($package, $version, $comment, $match[0][1]);
}
Expand Down Expand Up @@ -148,6 +161,39 @@ private function satisfiesPhpPlatformPackage(string $package, string $version, C
return $provided->matches($constraint);
}

/**
* @return bool|\PHPStan\Rules\RuleError
*/
private function satisfiesVirtualPackage(string $package, string $version, Comment $comment, int $wholeMatchStartOffset)
{
$versionParser = new VersionParser();
try {
$provided = $versionParser->parseConstraints(
$this->virtualPackages[$package]
);
} catch (UnexpectedValueException $e) {
return $this->errorBuilder->buildError(
$comment,
'Invalid virtual-package "' . $package . '": "' . $this->virtualPackages[$package] . '" provided via PHPStan config file.',
null,
$wholeMatchStartOffset
);
}

try {
$constraint = $versionParser->parseConstraints($version);
} catch (UnexpectedValueException $e) {
return $this->errorBuilder->buildError(
$comment,
'Invalid version constraint "' . $version . '" for virtual-package "' . $package . '".',
null,
$wholeMatchStartOffset
);
}

return $provided->matches($constraint);
}

/**
* @return RuleError|string
*/
Expand Down Expand Up @@ -203,7 +249,7 @@ private function satisfiesInstalledPackage(string $package, string $version, Com
if (!InstalledVersions::isInstalled($package)) {
return $this->errorBuilder->buildError(
$comment,
'Package "' . $package . '" is not installed via Composer.',
'Unknown package "' . $package . '". It is neither installed via composer.json nor declared as virtual package via PHPStan config.',
null,
$wholeMatchStartOffset
);
Expand Down
1 change: 1 addition & 0 deletions tests-e2e/bug52/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/vendor/
/public/
1 change: 0 additions & 1 deletion tests-e2e/bug52/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
}
},
"require-dev": {
"staabm/phpstan-todo-by": "^0.1.16",
"phpstan/phpstan": "^1.10",
"phpstan/extension-installer": "^1.3"
}
Expand Down
Loading

0 comments on commit a1932b1

Please sign in to comment.