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

replace fully qualified names by imports

This commit is contained in:
orklah 2021-12-27 20:18:33 +01:00
parent 3e29a3d961
commit 65fffd2116
18 changed files with 95 additions and 45 deletions

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Psalm\Examples\Template; namespace Psalm\Examples\Template;
use InvalidArgumentException;
use PhpParser; use PhpParser;
use Psalm; use Psalm;
use Psalm\CodeLocation; use Psalm\CodeLocation;
@ -12,6 +13,7 @@ use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\ClassLikeNameOptions; use Psalm\Internal\Analyzer\ClassLikeNameOptions;
use Psalm\Internal\Analyzer\MethodAnalyzer; use Psalm\Internal\Analyzer\MethodAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer; use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Provider\NodeDataProvider;
use Psalm\Node\Stmt\VirtualClass; use Psalm\Node\Stmt\VirtualClass;
use Psalm\Node\Stmt\VirtualClassMethod; use Psalm\Node\Stmt\VirtualClassMethod;
use Psalm\Storage\MethodStorage; use Psalm\Storage\MethodStorage;
@ -48,7 +50,7 @@ class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer
$matches = []; $matches = [];
if (!preg_match($first_line_regex, $variables_from, $matches)) { if (!preg_match($first_line_regex, $variables_from, $matches)) {
throw new \InvalidArgumentException('Could not interpret doc comment correctly'); throw new InvalidArgumentException('Could not interpret doc comment correctly');
} }
/** @psalm-suppress ArgumentTypeCoercion */ /** @psalm-suppress ArgumentTypeCoercion */
@ -167,7 +169,7 @@ class TemplateAnalyzer extends Psalm\Internal\Analyzer\FileAnalyzer
$statements_source = new StatementsAnalyzer( $statements_source = new StatementsAnalyzer(
$view_method_analyzer, $view_method_analyzer,
new \Psalm\Internal\Provider\NodeDataProvider() new NodeDataProvider()
); );
$statements_source->analyze($pseudo_method_stmts, $context); $statements_source->analyze($pseudo_method_stmts, $context);

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Psalm\Examples\Template; namespace Psalm\Examples\Template;
use InvalidArgumentException;
use PhpParser; use PhpParser;
use Psalm; use Psalm;
use Psalm\Checker\CommentChecker; use Psalm\Checker\CommentChecker;
@ -45,7 +46,7 @@ class TemplateScanner extends Psalm\Internal\Scanner\FileScanner
$matches = []; $matches = [];
if (!preg_match($first_line_regex, $variables_from, $matches)) { if (!preg_match($first_line_regex, $variables_from, $matches)) {
throw new \InvalidArgumentException('Could not interpret doc comment correctly'); throw new InvalidArgumentException('Could not interpret doc comment correctly');
} }
[$fq_class_name] = explode('::', $matches[1]); [$fq_class_name] = explode('::', $matches[1]);

View File

@ -2,8 +2,10 @@
namespace Psalm\Example\Plugin; namespace Psalm\Example\Plugin;
use Psalm\FileManipulation; use Psalm\FileManipulation;
use Psalm\Internal\Type\TypeTokenizer;
use Psalm\Plugin\EventHandler\AfterClassLikeExistenceCheckInterface; use Psalm\Plugin\EventHandler\AfterClassLikeExistenceCheckInterface;
use Psalm\Plugin\EventHandler\Event\AfterClassLikeExistenceCheckEvent; use Psalm\Plugin\EventHandler\Event\AfterClassLikeExistenceCheckEvent;
use function strpos;
use function strtolower; use function strtolower;
use function implode; use function implode;
use function array_map; use function array_map;
@ -25,8 +27,8 @@ class ClassUnqualifier implements AfterClassLikeExistenceCheckInterface
return; return;
} }
if (\strpos($candidate_type, '\\' . $fq_class_name) !== false) { if (strpos($candidate_type, '\\' . $fq_class_name) !== false) {
$type_tokens = \Psalm\Internal\Type\TypeTokenizer::tokenize($candidate_type, false); $type_tokens = TypeTokenizer::tokenize($candidate_type, false);
foreach ($type_tokens as &$type_token) { foreach ($type_tokens as &$type_token) {
if ($type_token[0] === ('\\' . $fq_class_name) if ($type_token[0] === ('\\' . $fq_class_name)

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Psalm\Example\Plugin; namespace Psalm\Example\Plugin;
use Exception;
use PhpParser; use PhpParser;
use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Expr\StaticCall;
@ -8,6 +9,8 @@ use Psalm\Checker;
use Psalm\Checker\StatementsChecker; use Psalm\Checker\StatementsChecker;
use Psalm\CodeLocation; use Psalm\CodeLocation;
use Psalm\FileManipulation; use Psalm\FileManipulation;
use Psalm\Issue\PluginIssue;
use Psalm\IssueBuffer;
use Psalm\Plugin\EventHandler\AfterFunctionCallAnalysisInterface; use Psalm\Plugin\EventHandler\AfterFunctionCallAnalysisInterface;
use Psalm\Plugin\EventHandler\AfterMethodCallAnalysisInterface; use Psalm\Plugin\EventHandler\AfterMethodCallAnalysisInterface;
use Psalm\Plugin\EventHandler\Event\AfterFunctionCallAnalysisEvent; use Psalm\Plugin\EventHandler\Event\AfterFunctionCallAnalysisEvent;
@ -49,7 +52,7 @@ class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, After
} }
if ($function_storage->cased_name !== (string)$expr->name) { if ($function_storage->cased_name !== (string)$expr->name) {
if (\Psalm\IssueBuffer::accepts( if (IssueBuffer::accepts(
new IncorrectFunctionCasing( new IncorrectFunctionCasing(
'Function is incorrectly cased, expecting ' . $function_storage->cased_name, 'Function is incorrectly cased, expecting ' . $function_storage->cased_name,
new CodeLocation($statements_source, $expr->name) new CodeLocation($statements_source, $expr->name)
@ -59,7 +62,7 @@ class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, After
// fall through // fall through
} }
} }
} catch (\Exception $e) { } catch (Exception $e) {
// can throw if storage is missing // can throw if storage is missing
} }
} }
@ -93,7 +96,7 @@ class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, After
$function_name_parts = explode('\\', $function_storage->cased_name); $function_name_parts = explode('\\', $function_storage->cased_name);
if (end($function_name_parts) !== end($expr->name->parts)) { if (end($function_name_parts) !== end($expr->name->parts)) {
if (\Psalm\IssueBuffer::accepts( if (IssueBuffer::accepts(
new IncorrectFunctionCasing( new IncorrectFunctionCasing(
'Function is incorrectly cased, expecting ' . $function_storage->cased_name, 'Function is incorrectly cased, expecting ' . $function_storage->cased_name,
new CodeLocation($statements_source, $expr->name) new CodeLocation($statements_source, $expr->name)
@ -103,12 +106,12 @@ class FunctionCasingChecker implements AfterFunctionCallAnalysisInterface, After
// fall through // fall through
} }
} }
} catch (\Exception $e) { } catch (Exception $e) {
// can throw if storage is missing // can throw if storage is missing
} }
} }
} }
class IncorrectFunctionCasing extends \Psalm\Issue\PluginIssue class IncorrectFunctionCasing extends PluginIssue
{ {
} }

View File

@ -5,6 +5,8 @@ use PhpParser;
use Psalm\Checker; use Psalm\Checker;
use Psalm\CodeLocation; use Psalm\CodeLocation;
use Psalm\FileManipulation; use Psalm\FileManipulation;
use Psalm\Issue\PluginIssue;
use Psalm\IssueBuffer;
use Psalm\Plugin\EventHandler\AfterExpressionAnalysisInterface; use Psalm\Plugin\EventHandler\AfterExpressionAnalysisInterface;
use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent; use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent;
@ -25,7 +27,7 @@ class PreventFloatAssignmentChecker implements AfterExpressionAnalysisInterface
&& ($expr_type = $statements_source->getNodeTypeProvider()->getType($expr->expr)) && ($expr_type = $statements_source->getNodeTypeProvider()->getType($expr->expr))
&& $expr_type->hasFloat() && $expr_type->hasFloat()
) { ) {
if (\Psalm\IssueBuffer::accepts( if (IssueBuffer::accepts(
new NoFloatAssignment( new NoFloatAssignment(
'Dont assign to floats', 'Dont assign to floats',
new CodeLocation($statements_source, $expr) new CodeLocation($statements_source, $expr)
@ -40,5 +42,5 @@ class PreventFloatAssignmentChecker implements AfterExpressionAnalysisInterface
} }
} }
class NoFloatAssignment extends \Psalm\Issue\PluginIssue { class NoFloatAssignment extends PluginIssue {
} }

View File

@ -6,6 +6,9 @@ use Psalm\Checker;
use Psalm\Checker\StatementsChecker; use Psalm\Checker\StatementsChecker;
use Psalm\CodeLocation; use Psalm\CodeLocation;
use Psalm\FileManipulation; use Psalm\FileManipulation;
use Psalm\Issue\InvalidClass;
use Psalm\Issue\UndefinedMethod;
use Psalm\IssueBuffer;
use Psalm\Plugin\EventHandler\AfterExpressionAnalysisInterface; use Psalm\Plugin\EventHandler\AfterExpressionAnalysisInterface;
use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent; use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent;
@ -29,8 +32,8 @@ class StringChecker implements AfterExpressionAnalysisInterface
) { ) {
$absolute_class = preg_split('/[:]/', $expr->value)[0]; $absolute_class = preg_split('/[:]/', $expr->value)[0];
if (\Psalm\IssueBuffer::accepts( if (IssueBuffer::accepts(
new \Psalm\Issue\InvalidClass( new InvalidClass(
'Use ::class constants when representing class names', 'Use ::class constants when representing class names',
new CodeLocation($statements_source, $expr), new CodeLocation($statements_source, $expr),
$absolute_class $absolute_class
@ -54,8 +57,8 @@ class StringChecker implements AfterExpressionAnalysisInterface
$appearing_method_id = $codebase->getAppearingMethodId($method_id); $appearing_method_id = $codebase->getAppearingMethodId($method_id);
if (!$appearing_method_id) { if (!$appearing_method_id) {
if (\Psalm\IssueBuffer::accepts( if (IssueBuffer::accepts(
new \Psalm\Issue\UndefinedMethod( new UndefinedMethod(
'Method ' . $method_id . ' does not exist', 'Method ' . $method_id . ' does not exist',
new CodeLocation($statements_source, $expr), new CodeLocation($statements_source, $expr),
$method_id $method_id

5
psalm
View File

@ -1,4 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Psalm\Internal\Cli\Psalm;
require_once __DIR__ . '/src/Psalm/Internal/Cli/Psalm.php'; require_once __DIR__ . '/src/Psalm/Internal/Cli/Psalm.php';
\Psalm\Internal\Cli\Psalm::run($argv); Psalm::run($argv);

View File

@ -1,4 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Psalm\Internal\Cli\LanguageServer;
require_once __DIR__ . '/src/Psalm/Internal/Cli/LanguageServer.php'; require_once __DIR__ . '/src/Psalm/Internal/Cli/LanguageServer.php';
\Psalm\Internal\Cli\LanguageServer::run($argv); LanguageServer::run($argv);

View File

@ -1,4 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Psalm\Internal\Cli\Plugin;
require_once __DIR__ . '/src/Psalm/Internal/Cli/Plugin.php'; require_once __DIR__ . '/src/Psalm/Internal/Cli/Plugin.php';
\Psalm\Internal\Cli\Plugin::run(); Plugin::run();

View File

@ -1,4 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Psalm\Internal\Cli\Refactor;
require_once __DIR__ . '/src/Psalm/Internal/Cli/Refactor.php'; require_once __DIR__ . '/src/Psalm/Internal/Cli/Refactor.php';
\Psalm\Internal\Cli\Refactor::run($argv); Refactor::run($argv);

View File

@ -1,4 +1,7 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
use Psalm\Internal\Cli\Psalter;
require_once __DIR__ . '/src/Psalm/Internal/Cli/Psalter.php'; require_once __DIR__ . '/src/Psalm/Internal/Cli/Psalter.php';
\Psalm\Internal\Cli\Psalter::run($argv); Psalter::run($argv);

View File

@ -1,5 +1,7 @@
<?php <?php
use Composer\Autoload\ClassLoader;
return [ return [
'patchers' => [ 'patchers' => [
function ($filePath, $prefix, $contents) { function ($filePath, $prefix, $contents) {
@ -79,7 +81,7 @@ return [
}, },
], ],
'whitelist' => [ 'whitelist' => [
\Composer\Autoload\ClassLoader::class, ClassLoader::class,
'Psalm\*', 'Psalm\*',
], ],
'files-whitelist' => [ 'files-whitelist' => [

View File

@ -2,6 +2,7 @@
namespace Psalm\Internal\Cli; namespace Psalm\Internal\Cli;
use Composer\Autoload\ClassLoader;
use Psalm\Config; use Psalm\Config;
use Psalm\Internal\Analyzer\ProjectAnalyzer; use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\CliUtils; use Psalm\Internal\CliUtils;
@ -219,6 +220,7 @@ HELP;
$include_collector = new IncludeCollector(); $include_collector = new IncludeCollector();
$first_autoloader = $include_collector->runAndCollect( $first_autoloader = $include_collector->runAndCollect(
// we ignore the FQN because of a hack in scoper.inc that needs full path
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader { function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader {
return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);

View File

@ -211,8 +211,9 @@ final class Psalm
$include_collector = new IncludeCollector(); $include_collector = new IncludeCollector();
$first_autoloader = $include_collector->runAndCollect( $first_autoloader = $include_collector->runAndCollect(
// we ignore the FQN because of a hack in scoper.inc that needs full path
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
function () use ($current_dir, $options, $vendor_dir): ?ClassLoader { function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader {
return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);
} }
); );

View File

@ -2,6 +2,7 @@
namespace Psalm\Internal\Cli; namespace Psalm\Internal\Cli;
use Composer\Autoload\ClassLoader;
use Composer\XdebugHandler\XdebugHandler; use Composer\XdebugHandler\XdebugHandler;
use Psalm\Config; use Psalm\Config;
use Psalm\Exception\UnsupportedIssueToFixException; use Psalm\Exception\UnsupportedIssueToFixException;
@ -202,6 +203,7 @@ HELP;
$include_collector = new IncludeCollector(); $include_collector = new IncludeCollector();
$first_autoloader = $include_collector->runAndCollect( $first_autoloader = $include_collector->runAndCollect(
// we ignore the FQN because of a hack in scoper.inc that needs full path
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader { function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader {
return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);

View File

@ -2,6 +2,7 @@
namespace Psalm\Internal\Cli; namespace Psalm\Internal\Cli;
use Composer\Autoload\ClassLoader;
use Composer\XdebugHandler\XdebugHandler; use Composer\XdebugHandler\XdebugHandler;
use Psalm\Internal\Analyzer\ProjectAnalyzer; use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\CliUtils; use Psalm\Internal\CliUtils;
@ -177,6 +178,7 @@ HELP;
$include_collector = new IncludeCollector(); $include_collector = new IncludeCollector();
$first_autoloader = $include_collector->runAndCollect( $first_autoloader = $include_collector->runAndCollect(
// we ignore the FQN because of a hack in scoper.inc that needs full path
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName // phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader { function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\ClassLoader {
return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);

View File

@ -3,6 +3,8 @@
namespace Psalm\Internal\Stubs\Generator; namespace Psalm\Internal\Stubs\Generator;
use PhpParser; use PhpParser;
use Psalm\Codebase;
use Psalm\Internal\Codebase\ConstantTypeResolver;
use Psalm\Node\Name\VirtualFullyQualified; use Psalm\Node\Name\VirtualFullyQualified;
use Psalm\Node\Stmt\VirtualClass; use Psalm\Node\Stmt\VirtualClass;
use Psalm\Node\Stmt\VirtualClassConst; use Psalm\Node\Stmt\VirtualClassConst;
@ -18,7 +20,10 @@ use Psalm\Internal\Scanner\ParsedDocblock;
use Psalm\Type; use Psalm\Type;
use Psalm\Type\Union; use Psalm\Type\Union;
use ReflectionProperty;
use UnexpectedValueException;
use function array_slice; use function array_slice;
use function rtrim;
class ClassLikeStubGenerator class ClassLikeStubGenerator
{ {
@ -26,7 +31,7 @@ class ClassLikeStubGenerator
* @return PhpParser\Node\Stmt\Class_|PhpParser\Node\Stmt\Interface_|PhpParser\Node\Stmt\Trait_ * @return PhpParser\Node\Stmt\Class_|PhpParser\Node\Stmt\Interface_|PhpParser\Node\Stmt\Trait_
*/ */
public static function getClassLikeNode( public static function getClassLikeNode(
\Psalm\Codebase $codebase, Codebase $codebase,
ClassLikeStorage $storage, ClassLikeStorage $storage,
string $classlike_name string $classlike_name
) : PhpParser\Node\Stmt\ClassLike { ) : PhpParser\Node\Stmt\ClassLike {
@ -61,7 +66,7 @@ class ClassLikeStubGenerator
'comments' => $docblock->tags 'comments' => $docblock->tags
? [ ? [
new PhpParser\Comment\Doc( new PhpParser\Comment\Doc(
\rtrim($docblock->render(' ')) rtrim($docblock->render(' '))
) )
] ]
: [] : []
@ -112,14 +117,14 @@ class ClassLikeStubGenerator
/** /**
* @return list<PhpParser\Node\Stmt\ClassConst> * @return list<PhpParser\Node\Stmt\ClassConst>
*/ */
private static function getConstantNodes(\Psalm\Codebase $codebase, ClassLikeStorage $storage): array private static function getConstantNodes(Codebase $codebase, ClassLikeStorage $storage): array
{ {
$constant_nodes = []; $constant_nodes = [];
foreach ($storage->constants as $constant_name => $constant_storage) { foreach ($storage->constants as $constant_name => $constant_storage) {
if ($constant_storage->unresolved_node) { if ($constant_storage->unresolved_node) {
$type = new Union([ $type = new Union([
\Psalm\Internal\Codebase\ConstantTypeResolver::resolve( ConstantTypeResolver::resolve(
$codebase->classlikes, $codebase->classlikes,
$constant_storage->unresolved_node $constant_storage->unresolved_node
) )
@ -127,7 +132,7 @@ class ClassLikeStubGenerator
} elseif ($constant_storage->type) { } elseif ($constant_storage->type) {
$type = $constant_storage->type; $type = $constant_storage->type;
} else { } else {
throw new \UnexpectedValueException('bad'); throw new UnexpectedValueException('bad');
} }
$constant_nodes[] = new VirtualClassConst( $constant_nodes[] = new VirtualClassConst(
@ -197,7 +202,7 @@ class ClassLikeStubGenerator
'comments' => $docblock->tags 'comments' => $docblock->tags
? [ ? [
new PhpParser\Comment\Doc( new PhpParser\Comment\Doc(
\rtrim($docblock->render(' ')) rtrim($docblock->render(' '))
) )
] ]
: [] : []
@ -220,14 +225,14 @@ class ClassLikeStubGenerator
foreach ($storage->methods as $method_storage) { foreach ($storage->methods as $method_storage) {
if (!$method_storage->cased_name) { if (!$method_storage->cased_name) {
throw new \UnexpectedValueException('very bad'); throw new UnexpectedValueException('very bad');
} }
switch ($method_storage->visibility) { switch ($method_storage->visibility) {
case \ReflectionProperty::IS_PRIVATE: case ReflectionProperty::IS_PRIVATE:
$flag = PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE; $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PRIVATE;
break; break;
case \ReflectionProperty::IS_PROTECTED: case ReflectionProperty::IS_PROTECTED:
$flag = PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED; $flag = PhpParser\Node\Stmt\Class_::MODIFIER_PROTECTED;
break; break;
default: default:
@ -296,7 +301,7 @@ class ClassLikeStubGenerator
'comments' => $docblock->tags 'comments' => $docblock->tags
? [ ? [
new PhpParser\Comment\Doc( new PhpParser\Comment\Doc(
\rtrim($docblock->render(' ')) rtrim($docblock->render(' '))
) )
] ]
: [] : []

View File

@ -2,6 +2,10 @@
namespace Psalm\Internal\Stubs\Generator; namespace Psalm\Internal\Stubs\Generator;
use Psalm\Codebase;
use Psalm\Internal\Provider\ClassLikeStorageProvider;
use Psalm\Internal\Provider\FileStorageProvider;
use Psalm\Storage\FunctionLikeStorage;
use Psalm\Type\Atomic\TAnonymousClassInstance; use Psalm\Type\Atomic\TAnonymousClassInstance;
use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TArrayKey; use Psalm\Type\Atomic\TArrayKey;
@ -98,21 +102,25 @@ use Psalm\Node\VirtualParam;
use Psalm\Type; use Psalm\Type;
use Psalm\Type\Union; use Psalm\Type\Union;
use UnexpectedValueException;
use function dirname; use function dirname;
use function is_int;
use function rtrim;
use function strpos;
class StubsGenerator class StubsGenerator
{ {
public static function getAll( public static function getAll(
\Psalm\Codebase $codebase, Codebase $codebase,
\Psalm\Internal\Provider\ClassLikeStorageProvider $class_provider, ClassLikeStorageProvider $class_provider,
\Psalm\Internal\Provider\FileStorageProvider $file_provider FileStorageProvider $file_provider
): string { ): string {
$namespaced_nodes = []; $namespaced_nodes = [];
$psalm_base = dirname(__DIR__, 5); $psalm_base = dirname(__DIR__, 5);
foreach ($class_provider->getAll() as $storage) { foreach ($class_provider->getAll() as $storage) {
if (\strpos($storage->name, 'Psalm\\') === 0) { if (strpos($storage->name, 'Psalm\\') === 0) {
continue; continue;
} }
@ -146,13 +154,13 @@ class StubsGenerator
foreach ($codebase->functions->getAllStubbedFunctions() as $function_storage) { foreach ($codebase->functions->getAllStubbedFunctions() as $function_storage) {
if ($function_storage->location if ($function_storage->location
&& \strpos($function_storage->location->file_path, $psalm_base) === 0 && strpos($function_storage->location->file_path, $psalm_base) === 0
) { ) {
continue; continue;
} }
if (!$function_storage->cased_name) { if (!$function_storage->cased_name) {
throw new \UnexpectedValueException('very bad'); throw new UnexpectedValueException('very bad');
} }
$fq_name = $function_storage->cased_name; $fq_name = $function_storage->cased_name;
@ -192,7 +200,7 @@ class StubsGenerator
} }
foreach ($file_provider->getAll() as $file_storage) { foreach ($file_provider->getAll() as $file_storage) {
if (\strpos($file_storage->file_path, $psalm_base) === 0) { if (strpos($file_storage->file_path, $psalm_base) === 0) {
continue; continue;
} }
@ -265,7 +273,7 @@ class StubsGenerator
} }
private static function getFunctionNode( private static function getFunctionNode(
\Psalm\Storage\FunctionLikeStorage $function_storage, FunctionLikeStorage $function_storage,
string $function_name, string $function_name,
string $namespace_name string $namespace_name
) : PhpParser\Node\Stmt\Function_ { ) : PhpParser\Node\Stmt\Function_ {
@ -327,7 +335,7 @@ class StubsGenerator
'comments' => $docblock->tags 'comments' => $docblock->tags
? [ ? [
new PhpParser\Comment\Doc( new PhpParser\Comment\Doc(
\rtrim($docblock->render(' ')) rtrim($docblock->render(' '))
) )
] ]
: [] : []
@ -338,7 +346,7 @@ class StubsGenerator
/** /**
* @return list<PhpParser\Node\Param> * @return list<PhpParser\Node\Param>
*/ */
public static function getFunctionParamNodes(\Psalm\Storage\FunctionLikeStorage $method_storage): array public static function getFunctionParamNodes(FunctionLikeStorage $method_storage): array
{ {
$param_nodes = []; $param_nodes = [];
@ -379,7 +387,7 @@ class StubsGenerator
$identifier_string = $atomic_type->toPhpString(null, [], null, 8, 0); $identifier_string = $atomic_type->toPhpString(null, [], null, 8, 0);
if ($identifier_string === null) { if ($identifier_string === null) {
throw new \UnexpectedValueException( throw new UnexpectedValueException(
$atomic_type->getId() . ' could not be converted to an identifier' $atomic_type->getId() . ' could not be converted to an identifier'
); );
} }
@ -447,7 +455,7 @@ class StubsGenerator
foreach ($atomic_type->properties as $property_name => $property_type) { foreach ($atomic_type->properties as $property_name => $property_type) {
if ($atomic_type->is_list) { if ($atomic_type->is_list) {
$key_type = null; $key_type = null;
} elseif (\is_int($property_name)) { } elseif (is_int($property_name)) {
$key_type = new VirtualLNumber($property_name); $key_type = new VirtualLNumber($property_name);
} else { } else {
$key_type = new VirtualString($property_name); $key_type = new VirtualString($property_name);