Skip to content

Commit 72305ce

Browse files
jiripudilondrejmirtes
authored andcommitted
LocalTypeAliasesRule: report invalid imported type alias names
1 parent df66449 commit 72305ce

File tree

3 files changed

+34
-17
lines changed

3 files changed

+34
-17
lines changed

src/Rules/Classes/LocalTypeAliasesRule.php

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Rules\Classes;
44

55
use PhpParser\Node;
6+
use PHPStan\Analyser\NameScope;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Node\InClassNode;
89
use PHPStan\PhpDoc\TypeNodeResolver;
@@ -97,6 +98,12 @@ public function processNode(Node $node, Scope $scope): array
9798
continue;
9899
}
99100

101+
$importedAs = $typeAliasImportTag->getImportedAs();
102+
if ($importedAs !== null && !$this->isAliasNameValid($importedAs, $nameScope)) {
103+
$errors[] = RuleErrorBuilder::message(sprintf('Imported type alias %s has an invalid name: %s.', $importedAlias, $importedAs))->build();
104+
continue;
105+
}
106+
100107
$importedAliases[] = $aliasName;
101108
}
102109

@@ -118,15 +125,9 @@ public function processNode(Node $node, Scope $scope): array
118125
continue;
119126
}
120127

121-
if ($nameScope !== null) {
122-
$aliasNameResolvedType = $this->typeNodeResolver->resolve(new IdentifierTypeNode($aliasName), $nameScope);
123-
if (!($aliasNameResolvedType instanceof ObjectType)
124-
&& !($aliasNameResolvedType instanceof TemplateType) // aliases take precedence over type parameters, this is reported by other rules using TemplateTypeCheck
125-
|| in_array($aliasName, ['self', 'parent'], true)
126-
) {
127-
$errors[] = RuleErrorBuilder::message(sprintf('Type alias has an invalid name: %s.', $aliasName))->build();
128-
continue;
129-
}
128+
if (!$this->isAliasNameValid($aliasName, $nameScope)) {
129+
$errors[] = RuleErrorBuilder::message(sprintf('Type alias has an invalid name: %s.', $aliasName))->build();
130+
continue;
130131
}
131132

132133
$resolvedType = $typeAliasTag->getTypeAlias()->resolve($this->typeNodeResolver);
@@ -149,4 +150,15 @@ public function processNode(Node $node, Scope $scope): array
149150
return $errors;
150151
}
151152

153+
private function isAliasNameValid(string $aliasName, ?NameScope $nameScope): bool
154+
{
155+
if ($nameScope === null) {
156+
return true;
157+
}
158+
159+
$aliasNameResolvedType = $this->typeNodeResolver->resolve(new IdentifierTypeNode($aliasName), $nameScope);
160+
return ($aliasNameResolvedType instanceof ObjectType && !in_array($aliasName, ['self', 'parent'], true))
161+
|| $aliasNameResolvedType instanceof TemplateType; // aliases take precedence over type parameters, this is reported by other rules using TemplateTypeCheck
162+
}
163+
152164
}

tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,35 +50,39 @@ public function testRule(): void
5050
],
5151
[
5252
'Cannot import type alias ImportedAliasFromNonClass: class LocalTypeAliases\int does not exist.',
53-
38,
53+
39,
5454
],
5555
[
5656
'Cannot import type alias ImportedAliasFromUnknownClass: class LocalTypeAliases\UnknownClass does not exist.',
57-
38,
57+
39,
5858
],
5959
[
6060
'Cannot import type alias ImportedUnknownAlias: type alias does not exist in LocalTypeAliases\Foo.',
61-
38,
61+
39,
6262
],
6363
[
6464
'Type alias ExistingClassAlias already exists as a class in scope of LocalTypeAliases\Baz.',
65-
38,
65+
39,
6666
],
6767
[
6868
'Type alias GlobalTypeAlias already exists as a global type alias.',
69-
38,
69+
39,
70+
],
71+
[
72+
'Imported type alias ExportedTypeAlias has an invalid name: int.',
73+
39,
7074
],
7175
[
7276
'Type alias OverwrittenTypeAlias overwrites an imported type alias of the same name.',
73-
38,
77+
39,
7478
],
7579
[
7680
'Circular definition detected in type alias CircularTypeAliasImport2.',
77-
38,
81+
39,
7882
],
7983
[
8084
'Circular definition detected in type alias CircularTypeAliasImport1.',
81-
46,
85+
47,
8286
],
8387
]);
8488
}

tests/PHPStan/Rules/Classes/data/local-type-aliases.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Bar
3131
* @phpstan-import-type ExportedTypeAlias from Foo as ExistingClassAlias
3232
* @phpstan-import-type ExportedTypeAlias from Foo as GlobalTypeAlias
3333
* @phpstan-import-type ExportedTypeAlias from Foo as OverwrittenTypeAlias
34+
* @phpstan-import-type ExportedTypeAlias from Foo as int
3435
* @phpstan-type OverwrittenTypeAlias string
3536
* @phpstan-import-type CircularTypeAliasImport1 from Qux
3637
* @phpstan-type CircularTypeAliasImport2 CircularTypeAliasImport1

0 commit comments

Comments
 (0)