Skip to content

Commit 2d93b10

Browse files
authored
Add support for result cache meta extensions
1 parent af1722d commit 2d93b10

File tree

8 files changed

+113
-0
lines changed

8 files changed

+113
-0
lines changed

Diff for: .github/workflows/e2e-tests.yml

+9
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,15 @@ jobs:
233233
cd e2e/bug-11857
234234
composer install
235235
../../bin/phpstan
236+
- script: |
237+
cd e2e/result-cache-meta-extension
238+
../../bin/phpstan -vvv
239+
../../bin/phpstan -vvv --fail-without-result-cache
240+
echo 'modified-hash' > hash.txt
241+
OUTPUT=$(../bashunit -a exit_code "2" "../../bin/phpstan -vvv --fail-without-result-cache")
242+
echo "$OUTPUT"
243+
../bashunit -a matches "Note: Using configuration file .+phpstan.neon." "$OUTPUT"
244+
../bashunit -a contains 'Result cache not used because the metadata do not match: metaExtensions' "$OUTPUT"
236245
237246
steps:
238247
- name: "Checkout"

Diff for: composer.json

+3
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@
140140
"classmap": [
141141
"tests/e2e",
142142
"tests/PHPStan"
143+
],
144+
"files": [
145+
"e2e/result-cache-meta-extension/src/DummyResultCacheMetaExtension.php"
143146
]
144147
},
145148
"repositories": [

Diff for: e2e/result-cache-meta-extension/hash.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
initial-hash

Diff for: e2e/result-cache-meta-extension/phpstan.neon

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
parameters:
2+
level: 8
3+
paths:
4+
- src
5+
6+
services:
7+
-
8+
class: ResultCacheE2E\MetaExtension\DummyResultCacheMetaExtension
9+
tags:
10+
- phpstan.resultCacheMetaExtension
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ResultCacheE2E\MetaExtension;
6+
7+
use PHPStan\Analyser\ResultCache\ResultCacheMetaExtension;
8+
9+
final class DummyResultCacheMetaExtension implements ResultCacheMetaExtension
10+
{
11+
public function getKey(): string
12+
{
13+
return 'e2e-dummy-result-cache-meta-extension';
14+
}
15+
16+
public function getHash(): string
17+
{
18+
// @phpstan-ignore argument.type (the file is always present so this won't pass `false` as an argument)
19+
return trim(file_get_contents(__DIR__ . '/../hash.txt'));
20+
}
21+
}

Diff for: src/Analyser/ResultCache/ResultCacheManager.php

+28
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPStan\Command\Output;
1111
use PHPStan\Dependency\ExportedNodeFetcher;
1212
use PHPStan\Dependency\RootExportedNode;
13+
use PHPStan\DependencyInjection\Container;
1314
use PHPStan\DependencyInjection\ProjectConfigHelper;
1415
use PHPStan\File\CouldNotReadFileException;
1516
use PHPStan\File\FileFinder;
@@ -66,6 +67,7 @@ final class ResultCacheManager
6667
* @param string[] $scanDirectories
6768
*/
6869
public function __construct(
70+
private Container $container,
6971
private ExportedNodeFetcher $exportedNodeFetcher,
7072
private FileFinder $scanFileFinder,
7173
private ReflectionProvider $reflectionProvider,
@@ -904,6 +906,7 @@ private function getMeta(array $allAnalysedFiles, ?array $projectConfigArray): a
904906
return [
905907
'cacheVersion' => self::CACHE_VERSION,
906908
'phpstanVersion' => ComposerHelper::getPhpStanVersion(),
909+
'metaExtensions' => $this->getMetaFromPhpStanExtensions(),
907910
'phpVersion' => PHP_VERSION_ID,
908911
'projectConfig' => $projectConfigArray,
909912
'analysedPaths' => $this->analysedPaths,
@@ -1036,4 +1039,29 @@ private function getStubFiles(): array
10361039
return $stubFiles;
10371040
}
10381041

1042+
/**
1043+
* @return array<string, string>
1044+
* @throws ShouldNotHappenException
1045+
*/
1046+
private function getMetaFromPhpStanExtensions(): array
1047+
{
1048+
$meta = [];
1049+
1050+
/** @var ResultCacheMetaExtension $extension */
1051+
foreach ($this->container->getServicesByTag(ResultCacheMetaExtension::EXTENSION_TAG) as $extension) {
1052+
if (array_key_exists($extension->getKey(), $meta)) {
1053+
throw new ShouldNotHappenException(sprintf(
1054+
'Duplicate ResultCacheMetaExtension with key "%s" found.',
1055+
$extension->getKey(),
1056+
));
1057+
}
1058+
1059+
$meta[$extension->getKey()] = $extension->getHash();
1060+
}
1061+
1062+
ksort($meta);
1063+
1064+
return $meta;
1065+
}
1066+
10391067
}
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\ResultCache;
4+
5+
/**
6+
* ResultCacheMetaExtension can be used for extending PHPStan's built-in mechanism that is used for
7+
* calculating metadata for result cache. Using this extension you may add additional metadata that will
8+
* be used for determining if analysis must be run again, or can be re-used from result cache.
9+
*
10+
* @see https://github.com/phpstan/phpstan-symfony/issues/255 for the context.
11+
*
12+
* To register it in the configuration file use the `phpstan.resultCacheMetaExtension` service tag:
13+
*
14+
* ```
15+
* services:
16+
* -
17+
* class: App\PHPStan\MyExtension
18+
* tags:
19+
* - phpstan.resultCacheMetaExtension
20+
* ```
21+
*
22+
* @api
23+
*/
24+
interface ResultCacheMetaExtension
25+
{
26+
27+
public const EXTENSION_TAG = 'phpstan.resultCacheMetaExtension';
28+
29+
/**
30+
* Returns unique key for this result cache meta entry. This describes the source of the metadata.
31+
*/
32+
public function getKey(): string;
33+
34+
/**
35+
* Returns hash of the result cache meta entry. This represents the current state of the additional meta source.
36+
*/
37+
public function getHash(): string;
38+
39+
}

Diff for: src/DependencyInjection/ConditionalTagsExtension.php

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Nette;
66
use Nette\DI\CompilerExtension;
77
use Nette\Schema\Expect;
8+
use PHPStan\Analyser\ResultCache\ResultCacheMetaExtension;
89
use PHPStan\Analyser\TypeSpecifierFactory;
910
use PHPStan\Broker\BrokerFactory;
1011
use PHPStan\Collectors\RegistryFactory as CollectorRegistryFactory;
@@ -59,6 +60,7 @@ public function getConfigSchema(): Nette\Schema\Schema
5960
LazyParameterOutTypeExtensionProvider::METHOD_TAG => $bool,
6061
LazyParameterOutTypeExtensionProvider::STATIC_METHOD_TAG => $bool,
6162
DiagnoseExtension::EXTENSION_TAG => $bool,
63+
ResultCacheMetaExtension::EXTENSION_TAG => $bool,
6264
])->min(1));
6365
}
6466

0 commit comments

Comments
 (0)