Skip to content

Add support for result cache meta extensions #3765

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

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
9 changes: 9 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@ jobs:
cd e2e/bug-11857
composer install
../../bin/phpstan
- script: |
cd e2e/result-cache-meta-extension
../../bin/phpstan -vvv
../../bin/phpstan -vvv --fail-without-result-cache
echo 'modified-hash' > hash.txt
OUTPUT=$(../bashunit -a exit_code "2" "../../bin/phpstan -vvv --fail-without-result-cache")
echo "$OUTPUT"
../bashunit -a matches "Note: Using configuration file .+phpstan.neon." "$OUTPUT"
../bashunit -a contains 'Result cache not used because the metadata do not match: metaExtensions' "$OUTPUT"

steps:
- name: "Checkout"
Expand Down
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@
"classmap": [
"tests/e2e",
"tests/PHPStan"
],
"files": [
"e2e/result-cache-meta-extension/src/DummyResultCacheMetaExtension.php"
]
},
"repositories": [
Expand Down
1 change: 1 addition & 0 deletions e2e/result-cache-meta-extension/hash.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
initial-hash
10 changes: 10 additions & 0 deletions e2e/result-cache-meta-extension/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
parameters:
level: 8
paths:
- src

services:
-
class: ResultCacheE2E\MetaExtension\DummyResultCacheMetaExtension
tags:
- phpstan.resultCacheMetaExtension
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace ResultCacheE2E\MetaExtension;

use PHPStan\Analyser\ResultCache\ResultCacheMetaExtension;

final class DummyResultCacheMetaExtension implements ResultCacheMetaExtension
{
public function getKey(): string
{
return 'e2e-dummy-result-cache-meta-extension';
}

public function getHash(): string
{
// @phpstan-ignore argument.type (the file is always present so this won't pass `false` as an argument)
return trim(file_get_contents(__DIR__ . '/../hash.txt'));
}
}
28 changes: 28 additions & 0 deletions src/Analyser/ResultCache/ResultCacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Command\Output;
use PHPStan\Dependency\ExportedNodeFetcher;
use PHPStan\Dependency\RootExportedNode;
use PHPStan\DependencyInjection\Container;
use PHPStan\DependencyInjection\ProjectConfigHelper;
use PHPStan\File\CouldNotReadFileException;
use PHPStan\File\FileFinder;
Expand Down Expand Up @@ -66,6 +67,7 @@ final class ResultCacheManager
* @param string[] $scanDirectories
*/
public function __construct(
private Container $container,
private ExportedNodeFetcher $exportedNodeFetcher,
private FileFinder $scanFileFinder,
private ReflectionProvider $reflectionProvider,
Expand Down Expand Up @@ -904,6 +906,7 @@ private function getMeta(array $allAnalysedFiles, ?array $projectConfigArray): a
return [
'cacheVersion' => self::CACHE_VERSION,
'phpstanVersion' => ComposerHelper::getPhpStanVersion(),
'metaExtensions' => $this->getMetaFromPhpStanExtensions(),
'phpVersion' => PHP_VERSION_ID,
'projectConfig' => $projectConfigArray,
'analysedPaths' => $this->analysedPaths,
Expand Down Expand Up @@ -1036,4 +1039,29 @@ private function getStubFiles(): array
return $stubFiles;
}

/**
* @return array<string, string>
* @throws ShouldNotHappenException
*/
private function getMetaFromPhpStanExtensions(): array
{
$meta = [];

/** @var ResultCacheMetaExtension $extension */
foreach ($this->container->getServicesByTag(ResultCacheMetaExtension::EXTENSION_TAG) as $extension) {
if (array_key_exists($extension->getKey(), $meta)) {
throw new ShouldNotHappenException(sprintf(
'Duplicate ResultCacheMetaExtension with key "%s" found.',
$extension->getKey(),
));
}

$meta[$extension->getKey()] = $extension->getHash();
}

ksort($meta);

return $meta;
}

}
39 changes: 39 additions & 0 deletions src/Analyser/ResultCache/ResultCacheMetaExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser\ResultCache;

/**
* ResultCacheMetaExtension can be used for extending PHPStan's built-in mechanism that is used for
* calculating metadata for result cache. Using this extension you may add additional metadata that will
* be used for determining if analysis must be run again, or can be re-used from result cache.
*
* @see https://github.com/phpstan/phpstan-symfony/issues/255 for the context.
*
* To register it in the configuration file use the `phpstan.resultCacheMetaExtension` service tag:
*
* ```
* services:
* -
* class: App\PHPStan\MyExtension
* tags:
* - phpstan.resultCacheMetaExtension
* ```
*
* @api
*/
interface ResultCacheMetaExtension
{

public const EXTENSION_TAG = 'phpstan.resultCacheMetaExtension';

/**
* Returns unique key for this result cache meta entry. This describes the source of the metadata.
*/
public function getKey(): string;

/**
* Returns hash of the result cache meta entry. This represents the current state of the additional meta source.
*/
public function getHash(): string;

}
2 changes: 2 additions & 0 deletions src/DependencyInjection/ConditionalTagsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Nette;
use Nette\DI\CompilerExtension;
use Nette\Schema\Expect;
use PHPStan\Analyser\ResultCache\ResultCacheMetaExtension;
use PHPStan\Analyser\TypeSpecifierFactory;
use PHPStan\Broker\BrokerFactory;
use PHPStan\Collectors\RegistryFactory as CollectorRegistryFactory;
Expand Down Expand Up @@ -59,6 +60,7 @@ public function getConfigSchema(): Nette\Schema\Schema
LazyParameterOutTypeExtensionProvider::METHOD_TAG => $bool,
LazyParameterOutTypeExtensionProvider::STATIC_METHOD_TAG => $bool,
DiagnoseExtension::EXTENSION_TAG => $bool,
ResultCacheMetaExtension::EXTENSION_TAG => $bool,
])->min(1));
}

Expand Down
Loading