Skip to content

Commit e2abc3e

Browse files
authored
Merge pull request #9509 from ptomulik/issue-9506
Fixed #9506
2 parents c6f66bf + ed1d095 commit e2abc3e

4 files changed

Lines changed: 91 additions & 2 deletions

File tree

src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public function __construct(
143143

144144
/**
145145
* @return false|null
146+
* @psalm-suppress ComplexMethod
146147
*/
147148
public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool
148149
{
@@ -420,10 +421,17 @@ public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool
420421

421422
if ($template_map[1] !== null && $template_map[2] !== null) {
422423
if (trim($template_map[2])) {
424+
$type_string = $template_map[2];
425+
try {
426+
$type_string = CommentAnalyzer::splitDocLine($type_string)[0];
427+
} catch (DocblockParseException $e) {
428+
throw new DocblockParseException($type_string . ' is not a valid type: '.$e->getMessage());
429+
}
430+
$type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
423431
try {
424432
$template_type = TypeParser::parseTokens(
425433
TypeTokenizer::getFullyQualifiedTokens(
426-
$template_map[2],
434+
$type_string,
427435
$this->aliases,
428436
$storage->template_types,
429437
$this->type_aliases,

src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
use Psalm\CodeLocation\DocblockTypeLocation;
1010
use Psalm\Codebase;
1111
use Psalm\Config;
12+
use Psalm\Exception\DocblockParseException;
1213
use Psalm\Exception\InvalidMethodOverrideException;
1314
use Psalm\Exception\TypeParseTreeException;
15+
use Psalm\Internal\Analyzer\CommentAnalyzer;
1416
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
1517
use Psalm\Internal\Scanner\FileScanner;
1618
use Psalm\Internal\Scanner\FunctionDocblockComment;
@@ -1440,10 +1442,17 @@ private static function handleTemplates(
14401442

14411443
if ($template_map[1] !== null && $template_map[2] !== null) {
14421444
if (trim($template_map[2])) {
1445+
$type_string = $template_map[2];
1446+
try {
1447+
$type_string = CommentAnalyzer::splitDocLine($type_string)[0];
1448+
} catch (DocblockParseException $e) {
1449+
throw new DocblockParseException($type_string . ' is not a valid type: '.$e->getMessage());
1450+
}
1451+
$type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
14431452
try {
14441453
$template_type = TypeParser::parseTokens(
14451454
TypeTokenizer::getFullyQualifiedTokens(
1446-
$template_map[2],
1455+
$type_string,
14471456
$aliases,
14481457
$storage->template_types + ($template_types ?: []),
14491458
$type_aliases,

tests/Template/ClassTemplateTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,6 +4051,64 @@ public function __construct(
40514051
'ignored_issues' => [],
40524052
'php_version' => '8.0',
40534053
],
4054+
'template of simple type with additional comment without dot' => [
4055+
'code' => '<?php
4056+
/**
4057+
* @psalm-template T of string
4058+
*
4059+
* lorem ipsum
4060+
*/
4061+
class Foo {
4062+
/** @psalm-var T */
4063+
public string $t;
4064+
4065+
/** @psalm-param T $t */
4066+
public function __construct(string $t) {
4067+
$this->t = $t;
4068+
}
4069+
4070+
/**
4071+
* @psalm-return T
4072+
*/
4073+
public function t(): string {
4074+
return $this->t;
4075+
}
4076+
}
4077+
$t = (new Foo(\'\'))->t();
4078+
',
4079+
'assertions' => [
4080+
'$t===' => '\'\'',
4081+
],
4082+
],
4083+
'template of simple type with additional comment with dot' => [
4084+
'code' => '<?php
4085+
/**
4086+
* @psalm-template T of string
4087+
*
4088+
* lorem ipsum.
4089+
*/
4090+
class Foo {
4091+
/** @psalm-var T */
4092+
public string $t;
4093+
4094+
/** @psalm-param T $t */
4095+
public function __construct(string $t) {
4096+
$this->t = $t;
4097+
}
4098+
4099+
/**
4100+
* @psalm-return T
4101+
*/
4102+
public function t(): string {
4103+
return $this->t;
4104+
}
4105+
}
4106+
$t = (new Foo(\'\'))->t();
4107+
',
4108+
'assertions' => [
4109+
'$t===' => '\'\'',
4110+
],
4111+
],
40544112
];
40554113
}
40564114

tests/Template/FunctionTemplateTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,20 @@ function normalizeField(mixed $value, Norm $n): void
16591659
'ignored_issues' => [],
16601660
'php_version' => '8.0',
16611661
],
1662+
'templateWithCommentAfterSimpleType' => [
1663+
'code' => '<?php
1664+
/**
1665+
* @template T of string
1666+
*
1667+
* lorem ipsumm
1668+
*
1669+
* @param T $t
1670+
*/
1671+
function foo(string $t): string
1672+
{
1673+
return $t;
1674+
}',
1675+
],
16621676
];
16631677
}
16641678

0 commit comments

Comments
 (0)