Add Psalm to analysis chain (#1223)

This commit is contained in:
Martin Rademacher 2022-05-04 11:32:59 +12:00 committed by GitHub
parent f0b3b8d23d
commit 86e24665ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 41 additions and 29 deletions

View File

@ -1,4 +1,4 @@
name: phpstan
name: static-analysis
on:
push:

View File

@ -60,7 +60,8 @@
"composer/package-versions-deprecated": "^1.11",
"friendsofphp/php-cs-fixer": "^2.17 || ^3.0",
"phpstan/phpstan": "^1.6",
"phpunit/phpunit": ">=8"
"phpunit/phpunit": ">=8",
"vimeo/psalm": "^4.23"
},
"autoload-dev": {
"exclude-from-classmap": [
@ -85,7 +86,8 @@
"@testlegacy"
],
"analyse": [
"phpstan analyse --memory-limit=2G"
"phpstan analyse --memory-limit=2G",
"psalm"
],
"spectral": "for ff in `find Examples -name '*.yaml'`; do spectral lint $ff; done",
"docs:dev": "cd docs && npm run dev",

8
psalm-baseline.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.23.0@f1fe6ff483bf325c803df9f510d09a03fd796f88">
<file src="src/Serializer.php">
<ReservedWord occurrences="1">
<code>Yaml::parse($contents)</code>
</ReservedWord>
</file>
</files>

View File

@ -5,6 +5,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="src" />
@ -14,6 +15,5 @@
</projectFiles>
<issueHandlers>
<DuplicateClass errorLevel="suppress" />
</issueHandlers>
</psalm>

View File

@ -516,13 +516,18 @@ class TokenAnalyser implements AnalyserInterface
}
}
private function php8NamespaceToken()
/**
* @return int[]
*/
private function php8NamespaceToken(): array
{
return defined('T_NAME_QUALIFIED') ? [T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED] : [];
}
/**
* Parse namespaced string.
*
* @param array|string $token
*/
private function parseNamespace(array &$tokens, &$token, Context $parseContext): string
{
@ -541,6 +546,8 @@ class TokenAnalyser implements AnalyserInterface
/**
* Parse comma separated list of namespaced strings.
*
* @param array|string $token
*/
private function parseNamespaceList(array &$tokens, &$token, Context $parseContext): array
{
@ -560,7 +567,7 @@ class TokenAnalyser implements AnalyserInterface
*/
private function parseUseStatement(array &$tokens, &$token, Context $parseContext): array
{
$normalizeAlias = function ($alias) {
$normalizeAlias = function ($alias): string {
$alias = ltrim($alias, '\\');
$elements = explode('\\', $alias);

View File

@ -37,7 +37,7 @@ class TokenScanner
$lastToken = null;
$stack = [];
$initUnit = function ($uses) {
$initUnit = function ($uses): array {
return [
'uses' => $uses,
'interfaces' => [],
@ -226,7 +226,7 @@ class TokenScanner
return array_values(array_map($resolve, $names));
}
protected function skipTo(array &$tokens, $char, bool $prev = false): void
protected function skipTo(array &$tokens, string $char, bool $prev = false): void
{
while (false !== ($token = next($tokens))) {
if (is_string($token) && $token == $char) {
@ -265,9 +265,9 @@ class TokenScanner
/**
* Parse a use statement.
*/
protected function parseFQNStatement(array &$tokens, &$token): array
protected function parseFQNStatement(array &$tokens, array &$token): array
{
$normalizeAlias = function ($alias) {
$normalizeAlias = function ($alias): string {
$alias = ltrim($alias, '\\');
$elements = explode('\\', $alias);

View File

@ -72,7 +72,7 @@ class Analysis
$this->addAnnotations($annotations, $context);
}
public function addAnnotation($annotation, Context $context): void
public function addAnnotation(object $annotation, Context $context): void
{
if ($this->annotations->contains($annotation)) {
return;
@ -237,7 +237,7 @@ class Analysis
if (!$direct) {
// expand recursively for interfaces extending other interfaces
$collect = function ($interfaces, $cb) use (&$definitions) {
$collect = function ($interfaces, $cb) use (&$definitions): void {
foreach ($interfaces as $interface) {
if (isset($this->interfaces[$interface]['extends'])) {
$cb($this->interfaces[$interface]['extends'], $cb);
@ -283,7 +283,7 @@ class Analysis
if (!$direct) {
// expand recursively for traits using other traits
$collect = function ($traits, $cb) use (&$definitions) {
$collect = function ($traits, $cb) use (&$definitions): void {
foreach ($traits as $trait) {
if (isset($this->traits[$trait]['traits'])) {
$cb($this->traits[$trait]['traits'], $cb);
@ -352,12 +352,7 @@ class Analysis
return null;
}
/**
* @param object $annotation
*
* @return \OpenApi\Context
*/
public function getContext($annotation): Context
public function getContext(object $annotation): ?Context
{
if ($annotation instanceof AbstractAnnotation) {
return $annotation->_context;

View File

@ -267,7 +267,7 @@ abstract class AbstractAnnotation implements \JsonSerializable
/**
* Generate the documentation in JSON format.
*/
public function toJson($flags = null): string
public function toJson(?int $flags = null): string
{
if ($flags === null) {
$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_IGNORE;
@ -510,7 +510,7 @@ abstract class AbstractAnnotation implements \JsonSerializable
*
* @param array|object $fields
*/
private static function _validate($fields, array $stack, array $skip, string $baseRef, $context): bool
private static function _validate($fields, array $stack, array $skip, string $baseRef, ?object $context): bool
{
$valid = true;
$blacklist = [];

View File

@ -207,7 +207,7 @@ class Schema extends AbstractAnnotation
* A numeric instance is valid against "multipleOf" if the result of the division of the instance by this
* property's value is an integer.
*
* @var number
* @var int|float
*/
public $multipleOf = Generator::UNDEFINED;

View File

@ -249,7 +249,7 @@ class Generator
*/
public function updateProcessor(callable $processor, ?callable $matcher = null): Generator
{
$matcher = $matcher ?: function ($other) use ($processor) {
$matcher = $matcher ?: function ($other) use ($processor): bool {
$otherClass = get_class($other);
return $processor instanceof $otherClass;

View File

@ -33,7 +33,7 @@ class ConsoleLogger extends AbstractLogger implements LoggerInterface
$this->debug = $debug;
}
public function loggedMessageAboveNotice()
public function loggedMessageAboveNotice(): bool
{
return $this->loggedMessageAboveNotice;
}

View File

@ -68,14 +68,14 @@ class AugmentProperties
}
}
protected function toRefKey(Context $context, $name)
protected function toRefKey(Context $context, ?string $name): string
{
$fqn = strtolower($context->fullyQualifiedName($name));
return ltrim($fqn, '\\');
}
protected function augmentType(Analysis $analysis, Property $property, Context $context, array $refs, array $varMatches)
protected function augmentType(Analysis $analysis, Property $property, Context $context, array $refs, array $varMatches): void
{
// docblock typehints
if (isset($varMatches['type'])) {

View File

@ -70,7 +70,7 @@ class CleanUnusedComponents
}
}
$detachNested = function (Analysis $analysis, AbstractAnnotation $annotation, callable $detachNested) {
$detachNested = function (Analysis $analysis, AbstractAnnotation $annotation, callable $detachNested): void {
foreach ($annotation::$_nested as $nested) {
$nestedKey = ((array) $nested)[0];
if (!Generator::isDefault($annotation->{$nestedKey})) {

View File

@ -57,7 +57,7 @@ class Serializer
OA\XmlContent::class,
];
protected static function isValidAnnotationClass($className): bool
protected static function isValidAnnotationClass(string $className): bool
{
return in_array($className, self::$VALID_ANNOTATIONS);
}

View File

@ -37,7 +37,7 @@ class Util
'object' => 'object',
];
public static function mapNativeType(Schema $schema, $type): bool
public static function mapNativeType(Schema $schema, string $type): bool
{
if (!array_key_exists($type, self::$NATIVE_TYPE_MAP)) {
return false;