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
18 changes: 16 additions & 2 deletions src/Analyser/AnalysisNodeCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,15 @@ final class AnalysisNodeCollector extends NodeVisitorAbstract
*/
private array $fileFunctionLikeAnalyses = [];

/**
* @param bool $withFileAnalysis Whether to record the facts only file-analysis
* rules read ({@see getNonCanonicalKeywordConstants()},
* {@see getNumericLiterals()}); an architecture-only
* run never reads them
*/
public function __construct(
private readonly LayerResolverInterface $layerResolver
private readonly LayerResolverInterface $layerResolver,
private readonly bool $withFileAnalysis = true,
) {
$this->constExprEvaluator = new ConstExprEvaluator(function (Expr $expr): string {
if (
Expand Down Expand Up @@ -1116,6 +1123,10 @@ private function finishFunctionLikeAnalysis(): void
private function collectNodeAnalysis(Node $node): void
{
if ($node instanceof Int_ || $node instanceof Float_) {
if (! $this->withFileAnalysis) {
return;
}

$rawValue = $node->getAttribute('rawValue');

// Parser-created scalar nodes always carry rawValue. Programmatic
Expand Down Expand Up @@ -1178,7 +1189,10 @@ private function collectNodeAnalysis(Node $node): void
if ($node instanceof ConstFetch) {
$name = $node->name;
$name->setAttribute(self::NON_CLASS_NAME_ATTRIBUTE, true);
$this->collectKeywordConstant($name);

if ($this->withFileAnalysis) {
$this->collectKeywordConstant($name);
}

if ($this->activeClassLikeAnalyses !== [] && ! isset(self::KEYWORD_CONSTANTS[$name->toLowerString()])) {
// An unqualified fetch in a namespace is not a FullyQualified
Expand Down
10 changes: 5 additions & 5 deletions src/Analyser/AnalysisNodeExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function extract(

$progressHandler?->start(count($filesToParse));

$analysisNodeCollector = new AnalysisNodeCollector($this->layerResolver);
$analysisNodeCollector = new AnalysisNodeCollector($this->layerResolver, $withFileAnalysis);
$nodeTraverser = new NodeTraverser(new NameResolver(), $analysisNodeCollector);
$fileAnalyses = [];

Expand All @@ -67,13 +67,13 @@ public function extract(
$analysisNodeCollector->setCurrentFile($fileToParse, $this->fileAnalysisProvider->tokens());
$resolvedAst = $nodeTraverser->traverse($ast);

$nonCanonicalKeywordConstants = $analysisNodeCollector->getNonCanonicalKeywordConstants();
$numericLiterals = $analysisNodeCollector->getNumericLiterals();
$fileFunctions = $analysisNodeCollector->getFileFunctions();

// The same traversal ran NameResolver, so the file analysis
// reuses its AST instead of resolving names in a second walk.
if ($withFileAnalysis) {
$nonCanonicalKeywordConstants = $analysisNodeCollector->getNonCanonicalKeywordConstants();
$numericLiterals = $analysisNodeCollector->getNumericLiterals();
$fileFunctions = $analysisNodeCollector->getFileFunctions();

$this->fileAnalysisProvider->replaceResolvedAst($fileToParse, $resolvedAst);
}
}
Expand Down
29 changes: 27 additions & 2 deletions tests/Analyser/AnalysisNodeCollectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,31 @@ public function testCollectsNumericLiteralSpellingsAndValues(): void
$this->assertSame([], $analysisNodeCollector->getNumericLiterals());
}

public function testSkipsFileAnalysisFactsWhenDisabledButStillCollectsClassDependencies(): void
{
$analysisNodeCollector = $this->makeCollector(<<<'PHP'
<?php

namespace App;

final class Foo
{
public function bar(): int
{
return TRUE ? 10000 : \M_PI + 1.5;
}
}
PHP, withFileAnalysis: false);

$this->assertSame([], $analysisNodeCollector->getNonCanonicalKeywordConstants());
$this->assertSame([], $analysisNodeCollector->getNumericLiterals());

$classNodes = $analysisNodeCollector->getClassNodes();

$this->assertCount(1, $classNodes);
$this->assertTrue($classNodes[0]->usesConstant('M_PI'));
}

public function testExposesUnconditionallyDeclaredFunctionsOfTheFileTraversedLast(): void
{
$analysisNodeCollector = $this->makeCollector(<<<'PHP'
Expand Down Expand Up @@ -175,10 +200,10 @@ private function collectAnonymousClassNodes(string $code): array
return $this->makeCollector($code)->getAnonymousClassNodes();
}

private function makeCollector(string $code): AnalysisNodeCollector
private function makeCollector(string $code, bool $withFileAnalysis = true): AnalysisNodeCollector
{
$namespaceLayerResolver = new NamespaceLayerResolver(['Domain' => 'src/Domain/'], self::BASE_PATH);
$analysisNodeCollector = new AnalysisNodeCollector($namespaceLayerResolver);
$analysisNodeCollector = new AnalysisNodeCollector($namespaceLayerResolver, $withFileAnalysis);
$parser = (new ParserFactory())->createForNewestSupportedVersion();
$ast = $parser->parse($code);

Expand Down
Loading