Skip to content

Commit

Permalink
Support array and offset access on const types
Browse files Browse the repository at this point in the history
  • Loading branch information
rvanvelzen committed May 6, 2024
1 parent 9bb3855 commit 536889f
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 11 deletions.
1 change: 0 additions & 1 deletion src/Ast/Type/OffsetAccessTypeNode.php
Expand Up @@ -25,7 +25,6 @@ public function __toString(): string
{
if (
$this->type instanceof CallableTypeNode
|| $this->type instanceof ConstTypeNode
|| $this->type instanceof NullableTypeNode
) {
return '(' . $this->type . ')[' . $this->offset . ']';
Expand Down
26 changes: 18 additions & 8 deletions src/Parser/TypeParser.php
Expand Up @@ -232,7 +232,17 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
);
}

return $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex);
$type = $this->enrichWithAttributes(
$tokens,
new Ast\Type\ConstTypeNode($constExpr),
$startLine,
$startIndex
);
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
}

return $type;
} catch (LogicException $e) {
throw new ParserException(
$currentTokenValue,
Expand Down Expand Up @@ -733,14 +743,14 @@ private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNo
);
}

$type = new Ast\Type\ConstTypeNode($constExpr);
$type = $this->enrichWithAttributes(
$tokens,
new Ast\Type\ConstTypeNode($constExpr),
$startLine,
$startIndex
);
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
$type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes(
$tokens,
$type,
$startLine,
$startIndex
));
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
}

return $type;
Expand Down
2 changes: 0 additions & 2 deletions src/Printer/Printer.php
Expand Up @@ -141,7 +141,6 @@ final class Printer
CallableTypeNode::class,
UnionTypeNode::class,
IntersectionTypeNode::class,
ConstTypeNode::class,
NullableTypeNode::class,
],
];
Expand Down Expand Up @@ -512,7 +511,6 @@ private function printOffsetAccessType(TypeNode $type): string
$type instanceof CallableTypeNode
|| $type instanceof UnionTypeNode
|| $type instanceof IntersectionTypeNode
|| $type instanceof ConstTypeNode
|| $type instanceof NullableTypeNode
) {
return $this->wrapInParentheses($type);
Expand Down
7 changes: 7 additions & 0 deletions tests/PHPStan/Parser/TypeParserTest.php
Expand Up @@ -1067,6 +1067,13 @@ public function provideParseData(): array
new IdentifierTypeNode('int')
),
],
[
'self::TYPES[ int ]',
new OffsetAccessTypeNode(
new ConstTypeNode(new ConstFetchNode('self', 'TYPES')),
new IdentifierTypeNode('int')
),
],
[
"?\t\xA009", // edge-case with \h
new NullableTypeNode(
Expand Down
24 changes: 24 additions & 0 deletions tests/PHPStan/Printer/PrinterTest.php
Expand Up @@ -1723,6 +1723,23 @@ public function enterNode(Node $node)

},
];

yield [
'/** @return Foo[abc] */',
'/** @return self::FOO[abc] */',
new class extends AbstractNodeVisitor {

public function enterNode(Node $node)
{
if ($node instanceof ReturnTagValueNode && $node->type instanceof OffsetAccessTypeNode) {
$node->type->type = new ConstTypeNode(new ConstFetchNode('self', 'FOO'));
}

return $node;
}

},
];
}

/**
Expand Down Expand Up @@ -1862,6 +1879,13 @@ public function dataPrintType(): iterable
]),
'Foo|Bar|(Baz|Lorem)',
];
yield [
new OffsetAccessTypeNode(
new ConstTypeNode(new ConstFetchNode('self', 'TYPES')),
new IdentifierTypeNode('int')
),
'self::TYPES[int]',
];
}

/**
Expand Down

0 comments on commit 536889f

Please sign in to comment.