Skip to content

Commit 263c841

Browse files
committed
Fix build
1 parent f0d21a7 commit 263c841

File tree

6 files changed

+145
-56
lines changed

6 files changed

+145
-56
lines changed

src/Analyser/Generator/ExprHandler/VariableHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public function analyseExpr(Expr $expr, GeneratorScope $scope): Generator
3131
throw new ShouldNotHappenException('Not implemented');
3232
}
3333

34-
$exprTypeFromScope = $scope->expressionTypes['$' . $expr->name] ?? null;
34+
$exprTypeFromScope = $scope->getExpressionType($expr);
3535
if ($exprTypeFromScope !== null) {
36-
return new ExprAnalysisResult($exprTypeFromScope->getType(), $scope);
36+
return new ExprAnalysisResult($exprTypeFromScope, $scope);
3737
}
3838

3939
yield from [];

src/Analyser/Generator/GeneratorScope.php

Lines changed: 62 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
use PHPStan\Analyser\NodeCallbackInvoker;
1212
use PHPStan\Analyser\Scope;
1313
use PHPStan\Analyser\ScopeContext;
14+
use PHPStan\Node\Printer\ExprPrinter;
1415
use PHPStan\Php\PhpVersions;
15-
use PHPStan\Reflection\Assertions;
1616
use PHPStan\Reflection\ClassConstantReflection;
1717
use PHPStan\Reflection\ClassReflection;
1818
use PHPStan\Reflection\ExtendedMethodReflection;
@@ -23,22 +23,54 @@
2323
use PHPStan\ShouldNotHappenException;
2424
use PHPStan\TrinaryLogic;
2525
use PHPStan\Type\ClosureType;
26-
use PHPStan\Type\Generic\TemplateTypeMap;
2726
use PHPStan\Type\Type;
2827
use PHPStan\Type\TypeWithClassName;
28+
use function array_key_exists;
2929

3030
final class GeneratorScope implements Scope, NodeCallbackInvoker
3131
{
3232

33+
/** @var non-empty-string|null */
34+
private ?string $namespace;
35+
3336
/**
3437
* @param array<string, ExpressionTypeHolder> $expressionTypes
38+
* @param array<string, ExpressionTypeHolder> $nativeExpressionTypes
3539
*/
3640
public function __construct(
3741
private InternalGeneratorScopeFactory $scopeFactory,
42+
private ExprPrinter $exprPrinter,
3843
private ScopeContext $context,
39-
public array $expressionTypes,
44+
private bool $declareStrictTypes = false,
45+
private PhpFunctionFromParserNodeReflection|null $function = null,
46+
?string $namespace = null,
47+
private array $expressionTypes = [],
48+
private array $nativeExpressionTypes = [],
4049
)
4150
{
51+
if ($namespace === '') {
52+
$namespace = null;
53+
}
54+
55+
$this->namespace = $namespace;
56+
}
57+
58+
/**
59+
* This method is meant to be called for expressions for which the type
60+
* should be stored in Scope itself.
61+
*
62+
* This is meant to be used only by handlers in PHPStan\Analyser\Generator namespace.
63+
*
64+
* All other code should use `getType()` method.
65+
*/
66+
public function getExpressionType(Expr $expr): ?Type
67+
{
68+
$exprString = $this->exprPrinter->printExpr($expr);
69+
if (array_key_exists($exprString, $this->expressionTypes)) {
70+
return $this->expressionTypes[$exprString]->getType();
71+
}
72+
73+
return null;
4274
}
4375

4476
public function assignVariable(string $variableName, Type $type): self
@@ -50,57 +82,22 @@ public function assignVariable(string $variableName, Type $type): self
5082

5183
return $this->scopeFactory->create(
5284
$this->context,
85+
$this->declareStrictTypes,
86+
$this->function,
87+
$this->namespace,
5388
$expressionTypes,
5489
);
5590
}
5691

92+
/** @api */
5793
public function enterNamespace(string $namespaceName): self
5894
{
59-
// TODO: Implement enterNamespace() method.
60-
throw new ShouldNotHappenException('Not implemented yet');
61-
}
62-
63-
public function enterClass(ClassReflection $classReflection): self
64-
{
65-
// TODO: Implement enterClass() method.
66-
throw new ShouldNotHappenException('Not implemented yet');
67-
}
68-
69-
/**
70-
* @param Type[] $phpDocParameterTypes
71-
* @param Type[] $parameterOutTypes
72-
* @param array<string, bool> $immediatelyInvokedCallableParameters
73-
* @param array<string, Type> $phpDocClosureThisTypeParameters
74-
*/
75-
public function enterClassMethod(
76-
Node\Stmt\ClassMethod $classMethod,
77-
TemplateTypeMap $templateTypeMap,
78-
array $phpDocParameterTypes,
79-
?Type $phpDocReturnType,
80-
?Type $throwType,
81-
?string $deprecatedDescription,
82-
bool $isDeprecated,
83-
bool $isInternal,
84-
bool $isFinal,
85-
?bool $isPure = null,
86-
bool $acceptsNamedArguments = true,
87-
?Assertions $asserts = null,
88-
?Type $selfOutType = null,
89-
?string $phpDocComment = null,
90-
array $parameterOutTypes = [],
91-
array $immediatelyInvokedCallableParameters = [],
92-
array $phpDocClosureThisTypeParameters = [],
93-
bool $isConstructor = false,
94-
): self
95-
{
96-
// TODO: Implement enterClassMethod() method.
97-
throw new ShouldNotHappenException('Not implemented yet');
98-
}
99-
100-
public function generalizeWith(self $otherScope): self
101-
{
102-
// TODO: Implement generalizeWith() method.
103-
throw new ShouldNotHappenException('Not implemented yet');
95+
return $this->scopeFactory->create(
96+
$this->context->beginFile(),
97+
$this->isDeclareStrictTypes(),
98+
null,
99+
$namespaceName,
100+
);
104101
}
105102

106103
public function isInClass(): bool
@@ -145,10 +142,10 @@ public function canAccessConstant(ClassConstantReflection $constantReflection):
145142
throw new ShouldNotHappenException('Not implemented yet');
146143
}
147144

145+
/** @api */
148146
public function getNamespace(): ?string
149147
{
150-
// TODO: Implement getNamespace() method.
151-
return null;
148+
return $this->namespace;
152149
}
153150

154151
public function getFile(): string
@@ -163,10 +160,22 @@ public function getFileDescription(): string
163160
return 'foo.php';
164161
}
165162

163+
/** @api */
166164
public function isDeclareStrictTypes(): bool
167165
{
168-
// TODO: Implement isDeclareStrictTypes() method.
169-
throw new ShouldNotHappenException('Not implemented yet');
166+
return $this->declareStrictTypes;
167+
}
168+
169+
public function enterDeclareStrictTypes(): self
170+
{
171+
return $this->scopeFactory->create(
172+
$this->context,
173+
true,
174+
null,
175+
null,
176+
$this->expressionTypes,
177+
$this->nativeExpressionTypes,
178+
);
170179
}
171180

172181
public function isInTrait(): bool
@@ -301,6 +310,7 @@ public function getAnonymousFunctionReturnType(): ?Type
301310
throw new ShouldNotHappenException('Not implemented yet');
302311
}
303312

313+
/** @api */
304314
public function getType(Expr $node): Type
305315
{
306316
return Fiber::suspend(new ExprAnalysisRequest($node, $this))->type;

src/Analyser/Generator/InternalGeneratorScopeFactory.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,22 @@
44

55
use PHPStan\Analyser\ExpressionTypeHolder;
66
use PHPStan\Analyser\ScopeContext;
7+
use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection;
78

89
interface InternalGeneratorScopeFactory
910
{
1011

1112
/**
1213
* @param array<string, ExpressionTypeHolder> $expressionTypes
14+
* @param array<string, ExpressionTypeHolder> $nativeExpressionTypes
1315
*/
1416
public function create(
1517
ScopeContext $context,
18+
bool $declareStrictTypes = false,
19+
PhpFunctionFromParserNodeReflection|null $function = null,
20+
?string $namespace = null,
1621
array $expressionTypes = [],
22+
array $nativeExpressionTypes = [],
1723
): GeneratorScope;
1824

1925
}

src/Analyser/Generator/LazyInternalGeneratorScopeFactory.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,36 @@
44

55
use PHPStan\Analyser\ScopeContext;
66
use PHPStan\DependencyInjection\AutowiredService;
7+
use PHPStan\DependencyInjection\Container;
8+
use PHPStan\Node\Printer\ExprPrinter;
9+
use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection;
710

811
#[AutowiredService(as: InternalGeneratorScopeFactory::class)]
912
final class LazyInternalGeneratorScopeFactory implements InternalGeneratorScopeFactory
1013
{
1114

12-
public function create(ScopeContext $context, array $expressionTypes = []): GeneratorScope
15+
public function __construct(private Container $container)
16+
{
17+
}
18+
19+
public function create(
20+
ScopeContext $context,
21+
bool $declareStrictTypes = false,
22+
PhpFunctionFromParserNodeReflection|null $function = null,
23+
?string $namespace = null,
24+
array $expressionTypes = [],
25+
array $nativeExpressionTypes = [],
26+
): GeneratorScope
1327
{
1428
return new GeneratorScope(
1529
$this,
30+
$this->container->getByType(ExprPrinter::class),
1631
$context,
32+
$declareStrictTypes,
33+
$function,
34+
$namespace,
1735
$expressionTypes,
36+
$nativeExpressionTypes,
1837
);
1938
}
2039

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser\Generator\StmtHandler;
4+
5+
use Generator;
6+
use PhpParser\Node\Scalar\Int_;
7+
use PhpParser\Node\Stmt;
8+
use PhpParser\Node\Stmt\Declare_;
9+
use PHPStan\Analyser\Generator\ExprAnalysisRequest;
10+
use PHPStan\Analyser\Generator\GeneratorScope;
11+
use PHPStan\Analyser\Generator\NodeCallbackRequest;
12+
use PHPStan\Analyser\Generator\StmtAnalysisResult;
13+
use PHPStan\Analyser\Generator\StmtHandler;
14+
use PHPStan\Analyser\Generator\StmtsAnalysisRequest;
15+
use PHPStan\DependencyInjection\AutowiredService;
16+
17+
/**
18+
* @implements StmtHandler<Declare_>
19+
*/
20+
#[AutowiredService]
21+
final class DeclareHandler implements StmtHandler
22+
{
23+
24+
public function supports(Stmt $stmt): bool
25+
{
26+
return $stmt instanceof Declare_;
27+
}
28+
29+
public function analyseStmt(Stmt $stmt, GeneratorScope $scope): Generator
30+
{
31+
foreach ($stmt->declares as $declare) {
32+
yield new NodeCallbackRequest($declare, $scope);
33+
yield new ExprAnalysisRequest($declare->value, $scope);
34+
if (
35+
$declare->key->name !== 'strict_types'
36+
|| !($declare->value instanceof Int_)
37+
|| $declare->value->value !== 1
38+
) {
39+
continue;
40+
}
41+
42+
$scope = $scope->enterDeclareStrictTypes();
43+
}
44+
45+
if ($stmt->stmts !== null) {
46+
/** @var StmtAnalysisResult */
47+
return yield new StmtsAnalysisRequest($stmt->stmts, $scope);
48+
49+
}
50+
51+
return new StmtAnalysisResult($scope);
52+
}
53+
54+
}

tests/PHPStan/Analyser/Generator/data/gnsr.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php
1+
<?php declare(strict_types = 1);
22

33
namespace GeneratorNodeScopeResolverTest;
44

0 commit comments

Comments
 (0)