Add Psalm to analysis chain (#1223)
This commit is contained in:
parent
f0b3b8d23d
commit
86e24665ba
|
@ -1,4 +1,4 @@
|
|||
name: phpstan
|
||||
name: static-analysis
|
||||
|
||||
on:
|
||||
push:
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = [];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -33,7 +33,7 @@ class ConsoleLogger extends AbstractLogger implements LoggerInterface
|
|||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
public function loggedMessageAboveNotice()
|
||||
public function loggedMessageAboveNotice(): bool
|
||||
{
|
||||
return $this->loggedMessageAboveNotice;
|
||||
}
|
||||
|
|
|
@ -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'])) {
|
||||
|
|
|
@ -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})) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue