Skip to content
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
85 changes: 33 additions & 52 deletions src/Cache/AnalysisResultCache.php
Original file line numberDiff line numberDiff line change
Expand Up@@ -197,26 +197,7 @@ public function loadClassNodes(string $file, string $namespace): ?array
return null;
}

$classNodes = $this->classNodesFromPayload($payload);
$anonymousClassNodes = $this->anonymousClassNodesFromPayload($payload);
$fileReferences = $this->fileReferencesFromPayload($payload);
$fileInstantiations = $this->fileInstantiationsFromPayload($payload);

if (
$classNodes === null
|| $anonymousClassNodes === null
|| $fileReferences === null
|| $fileInstantiations === null
) {
return null;
}

return [
'classNodes' => $classNodes,
'anonymousClassNodes' => $anonymousClassNodes,
'fileReferences' => $fileReferences,
'fileInstantiations' => $fileInstantiations,
];
return $this->classNodeResultFromPayload($payload);
}

/**
Expand All@@ -236,20 +217,46 @@ public function loadClassNodesWithFileAnalysis(string $file, string $namespace):
return null;
}

$fileAnalysis = is_array($payload['fileAnalysis'] ?? null)
? $this->fileAnalysisFromArray($payload['fileAnalysis'])
: null;

if (! $fileAnalysis instanceof FileAnalysis) {
return null;
}

$result = $this->classNodeResultFromPayload($payload);

if ($result === null) {
return null;
}

$result['fileAnalysis'] = $fileAnalysis;

return $result;
}

/**
* @param array<string, mixed> $payload
* @return array{
* classNodes: list<ClassNode>,
* anonymousClassNodes: list<AnonymousClassNode>,
* fileReferences: list<string>,
* fileInstantiations: list<string>
* }|null
*/
private function classNodeResultFromPayload(array $payload): ?array
{
$classNodes = $this->classNodesFromPayload($payload);
$anonymousClassNodes = $this->anonymousClassNodesFromPayload($payload);
$fileReferences = $this->fileReferencesFromPayload($payload);
$fileInstantiations = $this->fileInstantiationsFromPayload($payload);
$fileAnalysis = is_array($payload['fileAnalysis'] ?? null)
? $this->fileAnalysisFromArray($payload['fileAnalysis'])
: null;

if (
$classNodes === null
|| $anonymousClassNodes === null
|| $fileReferences === null
|| $fileInstantiations === null
|| ! $fileAnalysis instanceof FileAnalysis
) {
return null;
}
Expand All@@ -259,7 +266,6 @@ public function loadClassNodesWithFileAnalysis(string $file, string $namespace):
'anonymousClassNodes' => $anonymousClassNodes,
'fileReferences' => $fileReferences,
'fileInstantiations' => $fileInstantiations,
'fileAnalysis' => $fileAnalysis,
];
}

Expand DownExpand Up@@ -367,10 +373,6 @@ private function readPath(string $path): ?array
*/
private function ruleViolationFromArray(array $violation): ?RuleViolation
{
if (! $this->hasOnlyStringKeys($violation)) {
return null;
}

$ruleKey = $violation['rule'] ?? null;
$message = $violation['message'] ?? null;
$file = $violation['file'] ?? null;
Expand DownExpand Up@@ -462,7 +464,7 @@ private function anonymousClassNodesFromPayload(array $payload): ?array
$anonymousClassNodes = [];

foreach ($rawNodes as $rawNode) {
if (! is_array($rawNode) || ! $this->hasOnlyStringKeys($rawNode)) {
if (! is_array($rawNode)) {
return null;
}

Expand DownExpand Up@@ -532,10 +534,6 @@ private function classNodeToArray(ClassNode $classNode): array
*/
private function classNodeFromArray(array $node): ?ClassNode
{
if (! $this->hasOnlyStringKeys($node)) {
return null;
}

$className = $node['className'] ?? null;
$file = $node['file'] ?? null;
$line = $node['line'] ?? null;
Expand DownExpand Up@@ -752,10 +750,6 @@ private function enumCaseNodeToArray(EnumCaseNode $enumCaseNode): array
*/
private function methodNodeFromArray(array $method): ?MethodNode
{
if (! $this->hasOnlyStringKeys($method)) {
return null;
}

if (
! is_string($method['name'] ?? null)
|| ! is_string($method['visibility'] ?? null)
Expand DownExpand Up@@ -790,10 +784,6 @@ private function methodNodeFromArray(array $method): ?MethodNode
*/
private function constantNodeFromArray(array $constant): ?ConstantNode
{
if (! $this->hasOnlyStringKeys($constant)) {
return null;
}

if (
! is_string($constant['name'] ?? null)
|| ! is_string($constant['visibility'] ?? null)
Expand All@@ -816,10 +806,6 @@ private function constantNodeFromArray(array $constant): ?ConstantNode
*/
private function propertyNodeFromArray(array $property): ?PropertyNode
{
if (! $this->hasOnlyStringKeys($property)) {
return null;
}

if (
! is_string($property['name'] ?? null)
|| ! is_string($property['visibility'] ?? null)
Expand All@@ -842,10 +828,6 @@ private function propertyNodeFromArray(array $property): ?PropertyNode
*/
private function enumCaseNodeFromArray(array $enumCase): ?EnumCaseNode
{
if (! $this->hasOnlyStringKeys($enumCase)) {
return null;
}

$value = $enumCase['value'] ?? null;

if (
Expand DownExpand Up@@ -882,8 +864,7 @@ private function fileAnalysisToArray(FileAnalysis $fileAnalysis): array
private function fileAnalysisFromArray(array $analysis): ?FileAnalysis
{
if (
! $this->hasOnlyStringKeys($analysis)
|| ! is_string($analysis['file'] ?? null)
! is_string($analysis['file'] ?? null)
|| ! is_bool($analysis['hasUtf8Bom'] ?? null)
|| ! is_bool($analysis['hasValidUtf8'] ?? null)
|| ! array_key_exists('invalidPhpTagLine', $analysis)
Expand Down
29 changes: 29 additions & 0 deletions tests/Cache/AnalysisResultCacheTest.php
Original file line numberDiff line numberDiff line change
Expand Up@@ -1291,6 +1291,35 @@ public function testClassNodesWithFileAnalysisMissesMalformedFacts(array $fileAn
}
}

public function testClassNodesWithFileAnalysisMissesMalformedNodesWhenFactsAreValid(): void
{
$cacheDirectory = $this->createTempDirectory();
$sourceFile = $cacheDirectory . '/Foo.php';
$analysisResultCache = new AnalysisResultCache(__DIR__, new FileHashProvider(), $cacheDirectory);

file_put_contents($sourceFile, '<?php class Foo {}');

try {
$analysisResultCache->storeClassNodes(
$sourceFile,
'config',
[$this->makeClassNode($sourceFile)],
new FileAnalysis($sourceFile, false, true, null, true, true, false, 1),
);

$cacheFile = $this->firstJsonFile($cacheDirectory);
$payload = json_decode((string) file_get_contents($cacheFile), true, 512, JSON_THROW_ON_ERROR);
$this->assertIsArray($payload);
$payload['nodes'] = 'invalid';
$this->writeCachePayload($cacheDirectory, $payload, $cacheFile);

$this->assertNull($analysisResultCache->loadClassNodesWithFileAnalysis($sourceFile, 'config'));
} finally {
unlink($sourceFile);
$this->removeTempDirectory($cacheDirectory);
}
}

public function testClassNodesMissWhenFileMetadataChanges(): void
{
$cacheDirectory = $this->createTempDirectory();
Expand Down
Loading