1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Merge branch '4.x' into automated-callmap-validation

This commit is contained in:
Sam 2022-06-15 16:06:36 +02:00 committed by GitHub
commit db3447513e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 15 deletions

View File

@ -3,12 +3,15 @@
namespace Psalm\Internal\PhpVisitor\Reflector;
use PhpParser;
use Psalm\CodeLocation;
use Psalm\DocComment;
use Psalm\Exception\DocblockParseException;
use Psalm\Exception\IncorrectDocblockException;
use Psalm\Internal\Analyzer\CommentAnalyzer;
use Psalm\Internal\Scanner\FunctionDocblockComment;
use Psalm\Internal\Scanner\ParsedDocblock;
use Psalm\Issue\InvalidDocblock;
use Psalm\IssueBuffer;
use function array_shift;
use function array_unique;
@ -34,8 +37,11 @@ class FunctionLikeDocblockParser
/**
* @throws DocblockParseException if there was a problem parsing the docblock
*/
public static function parse(PhpParser\Comment\Doc $comment): FunctionDocblockComment
{
public static function parse(
PhpParser\Comment\Doc $comment,
CodeLocation $code_location,
string $cased_function_id
): FunctionDocblockComment {
$parsed_docblock = DocComment::parsePreservingLength($comment);
$comment_text = $comment->getText();
@ -49,7 +55,9 @@ class FunctionLikeDocblockParser
self::extractReturnType(
$comment,
$parsed_docblock->combined_tags['return'],
$info
$info,
$code_location,
$cased_function_id
);
}
@ -107,7 +115,12 @@ class FunctionLikeDocblockParser
$info->params[] = $info_param;
}
} else {
throw new DocblockParseException('Badly-formatted @param');
IssueBuffer::maybeAdd(
new InvalidDocblock(
'Badly-formatted @param in docblock for ' . $cased_function_id,
$code_location
)
);
}
}
}
@ -152,7 +165,12 @@ class FunctionLikeDocblockParser
];
}
} else {
throw new DocblockParseException('Badly-formatted @param');
IssueBuffer::maybeAdd(
new InvalidDocblock(
'Badly-formatted @param in docblock for ' . $cased_function_id,
$code_location
)
);
}
}
}
@ -335,7 +353,12 @@ class FunctionLikeDocblockParser
];
}
} else {
throw new DocblockParseException('Badly-formatted @param');
IssueBuffer::maybeAdd(
new InvalidDocblock(
'Badly-formatted @param in docblock for ' . $cased_function_id,
$code_location
)
);
}
}
}
@ -542,7 +565,9 @@ class FunctionLikeDocblockParser
private static function extractReturnType(
PhpParser\Comment\Doc $comment,
array $return_specials,
FunctionDocblockComment $info
FunctionDocblockComment $info,
CodeLocation $code_location,
string $cased_function_id
): void {
foreach ($return_specials as $offset => $return_block) {
$return_lines = explode("\n", $return_block);
@ -581,7 +606,12 @@ class FunctionLikeDocblockParser
$info->return_type_start = $offset;
$info->return_type_end = $end;
} else {
throw new DocblockParseException('Badly-formatted @return type');
IssueBuffer::maybeAdd(
new InvalidDocblock(
'Badly-formatted @param in docblock for ' . $cased_function_id,
$code_location
)
);
}
break;

View File

@ -467,7 +467,8 @@ class FunctionLikeNodeScanner
if ($doc_comment) {
try {
$docblock_info = FunctionLikeDocblockParser::parse($doc_comment);
$code_location = new CodeLocation($this->file_scanner, $stmt, null, true);
$docblock_info = FunctionLikeDocblockParser::parse($doc_comment, $code_location, $cased_function_id);
} catch (IncorrectDocblockException $e) {
$storage->docblock_issues[] = new MissingDocblockType(
$e->getMessage() . ' in docblock for ' . $cased_function_id,
@ -1041,7 +1042,12 @@ class FunctionLikeNodeScanner
if ($doc_comment) {
$docblock_info = null;
try {
$docblock_info = FunctionLikeDocblockParser::parse($doc_comment);
$code_location = new CodeLocation($this->file_scanner, $stmt, null, true);
$docblock_info = FunctionLikeDocblockParser::parse(
$doc_comment,
$code_location,
$cased_function_id
);
} catch (IncorrectDocblockException|DocblockParseException $e) {
}
if ($docblock_info) {

View File

@ -4,15 +4,47 @@ namespace Psalm\Tests;
use PHPUnit\Framework\TestCase as BaseTestCase;
use PhpParser\Comment\Doc;
use PhpParser\Node\Scalar\String_;
use Psalm\CodeLocation;
use Psalm\Exception\IncorrectDocblockException;
use Psalm\Internal\Analyzer\FileAnalyzer;
use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\PhpVisitor\Reflector\FunctionLikeDocblockParser;
use Psalm\Internal\Provider\FakeFileProvider;
use Psalm\Internal\Provider\Providers;
use Psalm\Internal\RuntimeCaches;
use Psalm\Tests\Internal\Provider\FakeParserCacheProvider;
class FunctionLikeDocblockParserTest extends BaseTestCase
{
/** @var string */
public $test_cased_function_id = 'hello_world';
/** @var CodeLocation */
public $test_code_location;
public function setUp(): void
{
RuntimeCaches::clearAll();
$file_provider = new FakeFileProvider();
$providers = new Providers(
$file_provider,
new FakeParserCacheProvider()
);
$test_config = new TestConfig();
$project_analyzer = new ProjectAnalyzer(
$test_config,
$providers
);
$file_analyzer = new FileAnalyzer($project_analyzer, 'none/none.php', 'none.php');
$stmt = new String_('randomString');
$this->test_code_location = new CodeLocation($file_analyzer, $stmt);
}
public function testDocblockDescription(): void
@ -29,7 +61,11 @@ class FunctionLikeDocblockParserTest extends BaseTestCase
*/
';
$php_parser_doc = new Doc($doc);
$function_docblock = FunctionLikeDocblockParser::parse($php_parser_doc);
$function_docblock = FunctionLikeDocblockParser::parse(
$php_parser_doc,
$this->test_code_location,
$this->test_cased_function_id
);
$this->assertSame('Some Description', $function_docblock->description);
}
@ -49,7 +85,11 @@ class FunctionLikeDocblockParserTest extends BaseTestCase
*/
';
$php_parser_doc = new Doc($doc);
$function_docblock = FunctionLikeDocblockParser::parse($php_parser_doc);
$function_docblock = FunctionLikeDocblockParser::parse(
$php_parser_doc,
$this->test_code_location,
$this->test_cased_function_id
);
$this->assertTrue(isset($function_docblock->params[0]['description']));
$this->assertSame('The BLI tag to iterate over.', $function_docblock->params[0]['description']);
@ -67,7 +107,11 @@ class FunctionLikeDocblockParserTest extends BaseTestCase
$php_parser_doc = new Doc($doc);
$this->expectException(IncorrectDocblockException::class);
$this->expectExceptionMessage('Misplaced variable');
FunctionLikeDocblockParser::parse($php_parser_doc);
FunctionLikeDocblockParser::parse(
$php_parser_doc,
$this->test_code_location,
$this->test_cased_function_id
);
}
public function testPreferPsalmPrefixedAnnotationsOverPhpstanOnes(): void
@ -78,7 +122,11 @@ class FunctionLikeDocblockParserTest extends BaseTestCase
*/
';
$php_parser_doc = new Doc($doc);
$function_docblock = FunctionLikeDocblockParser::parse($php_parser_doc);
$function_docblock = FunctionLikeDocblockParser::parse(
$php_parser_doc,
$this->test_code_location,
$this->test_cased_function_id
);
$this->assertSame([['T', 'of', 'string', false]], $function_docblock->templates);
}
@ -90,7 +138,11 @@ class FunctionLikeDocblockParserTest extends BaseTestCase
*/
';
$php_parser_doc = new Doc($doc, 0);
$function_docblock = FunctionLikeDocblockParser::parse($php_parser_doc);
$function_docblock = FunctionLikeDocblockParser::parse(
$php_parser_doc,
$this->test_code_location,
$this->test_cased_function_id
);
$this->assertEquals(
[
'psalm-import-type' => ['lines' => [1]],