...
 
Commits (4)
......@@ -59,19 +59,20 @@ test:run-phpcs:
dependencies:
- build:php-7.4
# TODO: Enable when all the existing errors have been fixed
# test:run-phpstan:
# image: php:7.4-cli-alpine
# stage: test
# script:
# - php vendor/bin/phpstan analyse --level=max --no-interaction --no-progress --error-format codeClimate src > phpstan-report.json
# artifacts:
# when: always
# expire_in: 1 hrs
# paths:
# - phpstan-report.json
# dependencies:
# - build:php-7.4
test:run-phpstan:
image: php:7.4-cli-alpine
stage: test
script:
# TODO: Enable when all the existing errors have been fixed (https://gitlab.com/Serenata/Serenata/issues/277).
# - php vendor/bin/phpstan analyse --level=max --no-interaction --no-progress --error-format codeClimate src > phpstan-report.json
- php vendor/bin/phpstan analyse --level=1 --no-interaction --no-progress --error-format codeClimate src > phpstan-report.json
artifacts:
when: always
expire_in: 1 hrs
paths:
- phpstan-report.json
dependencies:
- build:php-7.4
.test-run-phpunit: &test-run-phpunit
script:
......
......@@ -3,3 +3,9 @@ includes:
- vendor/phpstan/phpstan-doctrine/extension.neon
- vendor/phpstan/phpstan-php-parser/extension.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon
parameters:
ignoreErrors:
-
message: '#Variable property access on#'
path: 'src/Analysis/Visiting/ScopeLimitingVisitor.php'
......@@ -27,7 +27,7 @@ final class ClassFilteringClasslikeListProvider implements ClasslikeListProvider
*/
public function getAll(): array
{
return array_filter($this->delegate->getAll(), function (array $classlike) {
return array_filter($this->delegate->getAll(), function (array $classlike): bool {
return $classlike['type'] === ClasslikeTypeNameValue::CLASS_;
});
}
......
......@@ -118,7 +118,7 @@ use Serenata\Indexing\StorageInterface;
*/
private function getCheckedClasslikeInfo(string $fqcn, string $originFqcn): ArrayObject
{
if (in_array($fqcn, $this->resolutionStack)) {
if (in_array($fqcn, $this->resolutionStack, true)) {
throw new CircularDependencyException("Circular dependency detected from {$originFqcn} to {$fqcn}!");
}
......@@ -393,7 +393,7 @@ use Serenata\Indexing\StorageInterface;
{
$typeAnalyzer = $this->typeAnalyzer;
$this->walkTypes($result, function (array &$type) use ($elementFqcn, $typeAnalyzer) {
$this->walkTypes($result, function (array &$type) use ($elementFqcn, $typeAnalyzer): void {
if ($type['resolvedType'] !== null) {
$type['resolvedType'] = $typeAnalyzer->interchangeSelfWithActualType(
$type['resolvedType'],
......@@ -413,7 +413,7 @@ use Serenata\Indexing\StorageInterface;
{
$typeAnalyzer = $this->typeAnalyzer;
$this->walkTypes($result, function (array &$type) use ($elementFqcn, $typeAnalyzer) {
$this->walkTypes($result, function (array &$type) use ($elementFqcn, $typeAnalyzer): void {
$replacedThingy = $typeAnalyzer->interchangeStaticWithActualType($type['type'], $elementFqcn);
$replacedThingy = $typeAnalyzer->interchangeThisWithActualType($replacedThingy, $elementFqcn);
......@@ -432,7 +432,7 @@ use Serenata\Indexing\StorageInterface;
{
$typeAnalyzer = $this->typeAnalyzer;
$this->walkTypes($result, function (array &$type) use ($typeAnalyzer) {
$this->walkTypes($result, function (array &$type) use ($typeAnalyzer): void {
if ($type['type'] !== null && $typeAnalyzer->isClassType($type['type'])) {
$type['resolvedType'] = $typeAnalyzer->getNormalizedFqcn($type['type']);
} else {
......
......@@ -12,7 +12,7 @@ interface ClasslikeListProviderInterface
/**
* @throws RuntimeException
*
* @return array array<string, array> mapping FQCN's to classlikes.
* @return array<string, array> mapping FQCN's to classlikes.
*/
public function getAll(): array;
}
......@@ -21,7 +21,7 @@ abstract class AbstractConverter
$types = [];
$docblockTypeTransformer = new DocblockTypeTransformer();
$docblockTypeTransformer->transform($type, function (DocblockType $type) use (&$types) {
$docblockTypeTransformer->transform($type, function (DocblockType $type) use (&$types): DocblockType {
if (!$type instanceof CompoundDocblockType) {
$types[] = [
'type' => $type->toString(),
......
......@@ -28,6 +28,6 @@ final class DocblockAnalyzer
'@inheritDoc',
];
return in_array($shortDescription, $specialTags);
return in_array($shortDescription, $specialTags, true);
}
}
......@@ -27,7 +27,7 @@ final class InterfaceFilteringClasslikeListProvider implements ClasslikeListProv
*/
public function getAll(): array
{
return array_filter($this->delegate->getAll(), function (array $classlike) {
return array_filter($this->delegate->getAll(), function (array $classlike): bool {
return $classlike['type'] === ClasslikeTypeNameValue::INTERFACE_;
});
}
......
......@@ -76,7 +76,7 @@ abstract class AbstractResolver
$info = [];
foreach ($propertyData as $key => $value) {
if (in_array($key, $inheritedKeys)) {
if (in_array($key, $inheritedKeys, true)) {
$info[$key] = $value;
}
}
......@@ -126,7 +126,7 @@ abstract class AbstractResolver
$info = [];
foreach ($methodData as $key => $value) {
if (in_array($key, $inheritedKeys)) {
if (in_array($key, $inheritedKeys, true)) {
$info[$key] = $value;
}
}
......
......@@ -37,7 +37,7 @@ final class TraitUsageResolver extends AbstractResolver
if ($traitAlias->getName() === $method['name'] &&
($traitAlias->getTraitFqcn() === null || $traitAlias->getTraitFqcn() === $trait['fqcn'])
) {
$method['name'] = $traitAlias->getAlias() ?: $method['name'];
$method['name'] = $traitAlias->getAlias() !== null ? $traitAlias->getAlias() : $method['name'];
if ($traitAlias->getAccessModifier()) {
$method['isPublic'] =
......
......@@ -27,7 +27,7 @@ final class TraitFilteringClasslikeListProvider implements ClasslikeListProvider
*/
public function getAll(): array
{
return array_filter($this->delegate->getAll(), function (array $classlike) {
return array_filter($this->delegate->getAll(), function (array $classlike): bool {
return $classlike['type'] === ClasslikeTypeNameValue::TRAIT_;
});
}
......
......@@ -31,14 +31,14 @@ final class CatchNodeTypeDeducer extends AbstractNodeTypeDeducer
throw new TypeDeductionException("Can't handle node of type " . get_class($context->getNode()));
}
$types = array_map(function (Node\Name $name) use ($context) {
$types = array_map(function (Node\Name $name) use ($context): array {
return $this->nodeTypeDeducer->deduce(new TypeDeductionContext(
$name,
$context->getTextDocumentItem()
));
}, $context->getNode()->types);
$types = array_reduce($types, function (array $subTypes, $carry) {
$types = array_reduce($types, function (array $subTypes, $carry): array {
return array_merge($carry, $subTypes);
}, []);
......
......@@ -188,11 +188,11 @@ final class LocalTypeScanner
$selfType = $this->deduceTypesFromSelf($textDocumentItem, $position);
$selfType = array_shift($selfType);
$selfType = $selfType ?: '';
$selfType = $selfType !== null ? $selfType : '';
$staticType = $this->deduceTypesFromStatic($textDocumentItem, $position);
$staticType = array_shift($staticType);
$staticType = $staticType ?: '';
$staticType = $staticType !== null ? $staticType : '';
foreach ($types as $type) {
$type = $this->typeAnalyzer->interchangeSelfWithActualType($type, $selfType);
......
......@@ -32,7 +32,7 @@ final class TernaryNodeTypeDeducer extends AbstractNodeTypeDeducer
}
$firstOperandTypes = $this->nodeTypeDeducer->deduce(new TypeDeductionContext(
$context->getNode()->if ?: $context->getNode()->cond,
$context->getNode()->if !== null ? $context->getNode()->if : $context->getNode()->cond,
$context->getTextDocumentItem()
));
......
......@@ -65,7 +65,7 @@ final class TypeDeductionContext
public function getPosition(): Position
{
if (!$this->position) {
if (!$this->getNode()->getAttribute('startFilePos')) {
if ($this->getNode()->getAttribute('startFilePos') === null) {
throw new LogicException('No startFilePos attribute attached to node');
}
......
......@@ -138,7 +138,10 @@ final class ParameterDocblockTypeSemanticEqualityChecker
if ($docblockType instanceof DocblockTypeParser\CompoundDocblockType) {
return new DocblockTypeParser\CompoundDocblockType(
...array_map(
function (DocblockTypeParser\DocblockType $type) use ($filePosition, $positionalNameResolver) {
function (DocblockTypeParser\DocblockType $type) use (
$filePosition,
$positionalNameResolver
): DocblockTypeParser\DocblockType {
return $this->getResolvedDocblockParameterType($type, $filePosition, $positionalNameResolver);
},
$docblockType->getParts()
......@@ -192,7 +195,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
TypeList $parameterTypeList,
DocblockTypeParser\DocblockType $docblockType
): bool {
$parameterTypeListAsCompoundTypeString = implode('|', array_map(function (Type $type) {
$parameterTypeListAsCompoundTypeString = implode('|', array_map(function (Type $type): string {
return $type->toString();
}, $parameterTypeList->toArray()));
......@@ -209,7 +212,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
*/
private function doesParameterTypeListContainClassType(TypeList $typeList): bool
{
return !$typeList->filter(function (Type $type) {
return !$typeList->filter(function (Type $type): bool {
return $type instanceof ClassType;
})->isEmpty();
}
......@@ -234,7 +237,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
if ($docblockType instanceof DocblockTypeParser\CompoundDocblockType) {
$docblockTypesThatAreNotArrayTypes = $docblockType->filter(
function (DocblockTypeParser\DocblockType $docblockType) {
function (DocblockTypeParser\DocblockType $docblockType): bool {
return
!$docblockType instanceof DocblockTypeParser\ArrayDocblockType &&
!$docblockType instanceof DocblockTypeParser\NullDocblockType;
......@@ -271,7 +274,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
if ($docblockType instanceof DocblockTypeParser\CompoundDocblockType) {
$docblockTypesThatAreNotClassTypes = $docblockType->filter(
function (DocblockTypeParser\DocblockType $docblockType) {
function (DocblockTypeParser\DocblockType $docblockType): bool {
return
!$docblockType instanceof DocblockTypeParser\ClassDocblockType &&
!$docblockType instanceof DocblockTypeParser\NullDocblockType;
......@@ -283,7 +286,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
}
$docblockTypesThatAreClassTypes = $docblockType->filter(
function (DocblockTypeParser\DocblockType $docblockType) {
function (DocblockTypeParser\DocblockType $docblockType): bool {
return $docblockType instanceof DocblockTypeParser\ClassDocblockType;
}
);
......@@ -293,7 +296,7 @@ final class ParameterDocblockTypeSemanticEqualityChecker
$docblockTypesThatAreClassTypes = [$docblockType];
}
$parameterClassTypes = $parameterTypeList->filter(function (Type $type) {
$parameterClassTypes = $parameterTypeList->filter(function (Type $type): bool {
return $type instanceof ClassType;
});
......
......@@ -51,7 +51,7 @@ final class TypeAnalyzer implements TypeNormalizerInterface
SpecialDocblockTypeString::STATIC_,
SpecialDocblockTypeString::THIS_,
SpecialDocblockTypeString::ITERABLE_,
]);
], true);
return $isReservedKeyword || $this->isArraySyntaxTypeHint($type);
}
......
......@@ -75,7 +75,7 @@ final class ExpressionTypeInfoMap
$newMap = [];
foreach ($this->map as $expression => $data) {
if (in_array($expression, $exclusionList)) {
if (in_array($expression, $exclusionList, true)) {
$newMap[$expression] = $data;
}
}
......
......@@ -178,8 +178,8 @@ final class UseStatementFetchingVisitor extends NodeVisitorAbstract
PositionEncoding::VALUE
)
),
'start' => $use->getAttribute('startFilePos') ? $use->getAttribute('startFilePos') : null,
'end' => $use->getAttribute('endFilePos') ? $use->getAttribute('endFilePos') + 1 : null,
'start' => $use->getAttribute('startFilePos'),
'end' => $use->getAttribute('endFilePos') !== null ? $use->getAttribute('endFilePos') + 1 : null,
];
}
}
......@@ -127,7 +127,7 @@ final class ApproximateStringMatchingBestStringApproximationDeterminer implement
*/
private function sortBestMatchScorePairs(array $bestMatchScorePairs): array
{
usort($bestMatchScorePairs, function (array $a, array $b) {
usort($bestMatchScorePairs, function (array $a, array $b): int {
return $a[1] <=> $b[1];
});
......
......@@ -64,7 +64,7 @@ final class ClassConstantAutocompletionProvider implements AutocompletionProvide
true
);
$classlikeInfoElements = array_map(function (string $type) {
$classlikeInfoElements = array_map(function (string $type): ?array {
try {
return $this->classlikeInfoBuilder->build($type);
} catch (UnexpectedValueException|CircularDependencyException $e) {
......
......@@ -83,7 +83,7 @@ final class LocalVariableAutocompletionProvider implements AutocompletionProvide
*/
private function createSuggestion(array $variable, AutocompletionProviderContext $context): CompletionItem
{
$typeArray = array_map(function (string $type) {
$typeArray = array_map(function (string $type): array {
return [
'type' => $type,
];
......
......@@ -91,7 +91,7 @@ final class NonStaticMethodAutocompletionProvider implements AutocompletionProvi
true
);
$classlikeInfoElements = array_map(function (string $type) {
$classlikeInfoElements = array_map(function (string $type): ?array {
try {
return $this->classlikeInfoBuilder->build($type);
} catch (UnexpectedValueException|CircularDependencyException $e) {
......
......@@ -64,7 +64,7 @@ final class NonStaticPropertyAutocompletionProvider implements AutocompletionPro
true
);
$classlikeInfoElements = array_map(function (string $type) {
$classlikeInfoElements = array_map(function (string $type): ?array {
try {
return $this->classlikeInfoBuilder->build($type);
} catch (UnexpectedValueException|CircularDependencyException $e) {
......
......@@ -91,7 +91,7 @@ final class StaticMethodAutocompletionProvider implements AutocompletionProvider
true
);
$classlikeInfoElements = array_map(function (string $type) {
$classlikeInfoElements = array_map(function (string $type): ?array {
try {
return $this->classlikeInfoBuilder->build($type);
} catch (UnexpectedValueException|CircularDependencyException $e) {
......
......@@ -64,7 +64,7 @@ final class StaticPropertyAutocompletionProvider implements AutocompletionProvid
true
);
$classlikeInfoElements = array_map(function (string $type) {
$classlikeInfoElements = array_map(function (string $type): ?array {
try {
return $this->classlikeInfoBuilder->build($type);
} catch (UnexpectedValueException|CircularDependencyException $e) {
......
......@@ -60,7 +60,7 @@ final class DebouncingIndexer implements IndexerInterface
$this->eventLoop->cancelTimer($this->uriTimerMap[$uri]);
}
$callback = function (/*TimerInterface $timer*/) use ($uri, $useLatestState, $jsonRpcMessageSender) {
$callback = function (/*TimerInterface $timer*/) use ($uri, $useLatestState, $jsonRpcMessageSender): void {
$this->delegate->index($uri, $useLatestState, $jsonRpcMessageSender);
unset($this->uriTimerMap[$uri]);
......
......@@ -47,6 +47,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
return $this->managerRegistry->getRepository(Structures\File::class)->findAll();
} catch (Throwable $t) {
$this->handleThrowable($t);
return []; // Only to make PHPStan happy as it does not detect that the above call never terminates.
}
}
......@@ -59,6 +61,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
return $this->managerRegistry->getRepository(Structures\AccessModifier::class)->findAll();
} catch (Throwable $t) {
$this->handleThrowable($t);
return []; // Only to make PHPStan happy as it does not detect that the above call never terminates.
}
}
......@@ -73,6 +77,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
]);
} catch (Throwable $t) {
$this->handleThrowable($t);
return null; // Only to make PHPStan happy as it does not detect that the above call never terminates.
}
}
......@@ -87,6 +93,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
]);
} catch (Throwable $t) {
$this->handleThrowable($t);
$file = null; // Only to make PHPStan happy as it does not detect that the above call never terminates.
}
if ($file === null) {
......@@ -171,6 +179,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
]);
} catch (Throwable $t) {
$this->handleThrowable($t);
return []; // Only to make PHPStan happy as it does not detect that the above call never terminates.
}
}
......@@ -178,6 +188,8 @@ final class DoctrineStorage implements StorageInterface, MetadataProviderInterfa
* @param Throwable $throwable
*
* @throws Throwable
*
* @return never
*/
private function handleThrowable(Throwable $throwable): void
{
......
......@@ -63,7 +63,7 @@ final class IndexableFileIterator implements IteratorAggregate
$isFile = is_file($uri);
/** @var string[] $globsToAdhereTo */
$globsToAdhereTo = array_map(function (string $extension) {
$globsToAdhereTo = array_map(function (string $extension): string {
return '*.' . $extension;
}, $this->extensionsToIndex);
......
......@@ -312,8 +312,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
$fqcn,
$this->file,
$range,
$documentation['descriptions']['short'] ?: null,
$documentation['descriptions']['long'] ?: null,
((bool) $documentation['descriptions']['short']) ? $documentation['descriptions']['short'] : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$node->isAnonymous(),
$node->isAbstract(),
$node->isFinal(),
......@@ -328,8 +328,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
'\\' . $node->namespacedName->toString(),
$this->file,
$range,
$documentation['descriptions']['short'] ?: null,
$documentation['descriptions']['long'] ?: null,
((bool) $documentation['descriptions']['short']) ? $documentation['descriptions']['short'] : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$documentation['deprecated'],
$docComment !== '' && $docComment !== null
);
......@@ -339,8 +339,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
'\\' . $node->namespacedName->toString(),
$this->file,
$range,
$documentation['descriptions']['short'] ?: null,
$documentation['descriptions']['long'] ?: null,
((bool) $documentation['descriptions']['short']) ? $documentation['descriptions']['short'] : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$documentation['deprecated'],
$docComment !== '' && $docComment !== null
);
......@@ -454,7 +454,7 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
}
}
$implementedFqcns = array_unique(array_map(function (Node\Name $name) {
$implementedFqcns = array_unique(array_map(function (Node\Name $name): string {
$resolvedName = NodeHelpers::fetchClassName($name->getAttribute('resolvedName'));
return $this->typeAnalyzer->getNormalizedFqcn($resolvedName);
......@@ -479,7 +479,7 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
*/
private function processInterfaceRelations(Node\Stmt\Interface_ $node, Structures\Interface_ $interface): void
{
$extendedFqcns = array_unique(array_map(function (Node\Name $name) {
$extendedFqcns = array_unique(array_map(function (Node\Name $name): string {
$resolvedName = NodeHelpers::fetchClassName($name->getAttribute('resolvedName'));
return $this->typeAnalyzer->getNormalizedFqcn($resolvedName);
......@@ -709,8 +709,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
false,
$node->isStatic(),
$docComment !== '' && $docComment !== null,
$shortDescription ?: null,
$documentation['descriptions']['long'] ?: null,
$shortDescription !== '' ? $shortDescription : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$varDocumentation ? $varDocumentation['description'] : null,
$this->classlikeStack->peek(),
$accessModifierMap[$accessModifier],
......@@ -817,7 +817,7 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
$throws[] = new Structures\ThrowsInfo(
$localType,
$type->toString(),
$throw['description'] ?: null
$throw['description'] !== '' ? $throw['description'] : null
);
}
......@@ -838,8 +838,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
$this->file,
$range,
$documentation['deprecated'],
$documentation['descriptions']['short'] ?: null,
$documentation['descriptions']['long'] ?: null,
((bool) $documentation['descriptions']['short']) ? $documentation['descriptions']['short'] : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$documentation['return']['description'] ?? null,
$returnTypeHint,
$this->classlikeStack->peek(),
......@@ -1054,8 +1054,8 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
$defaultValue,
$documentation['deprecated'] ? 1 : 0,
$docComment !== '' && $docComment !== null,
$shortDescription ?: null,
$documentation['descriptions']['long'] ?: null,
$shortDescription !== '' ? $shortDescription : null,
((bool) $documentation['descriptions']['long']) ? $documentation['descriptions']['long'] : null,
$varDocumentation ? $varDocumentation['description'] : null,
$type,
$this->classlikeStack->peek(),
......@@ -1099,7 +1099,7 @@ final class ClasslikeIndexingVisitor extends NodeVisitorAbstract
true,
$rawData['isStatic'],
false,
$rawData['description'] ?: null,
$rawData['description'] !== '' ? $rawData['description'] : null,
null,
null,
$classlike,
......
......@@ -118,7 +118,7 @@ final class DefineIndexingVisitor extends NodeVisitorAbstract
// Defines can be namespaced if their name contains slashes, see also
// https://php.net/manual/en/function.define.php#90282
$name = new Node\Name((string) $nameValue->value);
$name = new Node\Name($nameValue->value);
$type = new MixedDocblockType();
......
......@@ -213,7 +213,7 @@ final class FunctionIndexingVisitor extends NodeVisitorAbstract
$throws[] = new Structures\ThrowsInfo(
$localType,
$type->toString(),
$throw['description'] ?: null
$throw['description'] !== '' ? $throw['description'] : null
);
}
......@@ -223,8 +223,8 @@ final class FunctionIndexingVisitor extends NodeVisitorAbstract
$this->file,
$range,
$documentation['deprecated'],
$documentation['descriptions']['short'] ?: null,
$documentation['descriptions']['long'] ?: null,
$documentation['descriptions']['short'] !== '' ? $documentation['descriptions']['short'] : null,
$documentation['descriptions']['long'] !== '' ? $documentation['descriptions']['long'] : null,
$documentation['return']['description'] ?? null,
$returnTypeHint,
$docComment !== '' && $docComment !== null,
......
......@@ -116,7 +116,7 @@ final class UseStatementIndexingVisitor implements NodeVisitor
{
$import = new Structures\FileNamespaceImport(
$useStatement['range'],
$useStatement['alias'] ?: null,
$useStatement['alias'] !== '' ? $useStatement['alias'] : null,
$useStatement['name'],
$useStatement['kind'],
$namespace
......
......@@ -51,7 +51,7 @@ final class CacheClearingEventMediator
*/
private function setup(): void
{
$this->eventEmitter->on($this->eventName, function () {
$this->eventEmitter->on($this->eventName, function (): void {
$this->clearCache();
});
}
......
......@@ -53,11 +53,11 @@ final class ClasslikeIndexingStructureRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(IndexingEventName::CLASSLIKE_UPDATED, function (Structures\Classlike $classlike) {
$this->eventEmitter->on(IndexingEventName::CLASSLIKE_UPDATED, function (Structures\Classlike $classlike): void {
$this->classlikeListRegistry->add($this->classlikeConverter->convert($classlike));
});
$this->eventEmitter->on(IndexingEventName::CLASSLIKE_REMOVED, function (Structures\Classlike $classlike) {
$this->eventEmitter->on(IndexingEventName::CLASSLIKE_REMOVED, function (Structures\Classlike $classlike): void {
$this->classlikeListRegistry->remove($this->classlikeConverter->convert($classlike));
});
}
......
......@@ -53,11 +53,11 @@ final class ConstantIndexingConstantRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(IndexingEventName::CONSTANT_UPDATED, function (Structures\Constant $constant) {
$this->eventEmitter->on(IndexingEventName::CONSTANT_UPDATED, function (Structures\Constant $constant): void {
$this->constantListRegistry->add($this->constantConverter->convert($constant));
});
$this->eventEmitter->on(IndexingEventName::CONSTANT_REMOVED, function (Structures\Constant $constant) {
$this->eventEmitter->on(IndexingEventName::CONSTANT_REMOVED, function (Structures\Constant $constant): void {
$this->constantListRegistry->remove($this->constantConverter->convert($constant));
});
}
......
......@@ -53,11 +53,11 @@ final class FunctionIndexingFunctionRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(IndexingEventName::FUNCTION_UPDATED, function (Structures\Function_ $function) {
$this->eventEmitter->on(IndexingEventName::FUNCTION_UPDATED, function (Structures\Function_ $function): void {
$this->functionListRegistry->add($this->functionConverter->convert($function));
});
$this->eventEmitter->on(IndexingEventName::FUNCTION_REMOVED, function (Structures\Function_ $function) {
$this->eventEmitter->on(IndexingEventName::FUNCTION_REMOVED, function (Structures\Function_ $function): void {
$this->functionListRegistry->remove($this->functionConverter->convert($function));
});
}
......
......@@ -53,12 +53,18 @@ final class NamespaceIndexingNamespaceRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(IndexingEventName::NAMESPACE_UPDATED, function (Structures\FileNamespace $namespace) {
$this->namespaceListRegistry->add($this->namespaceConverter->convert($namespace));
});
$this->eventEmitter->on(
IndexingEventName::NAMESPACE_UPDATED,
function (Structures\FileNamespace $namespace): void {
$this->namespaceListRegistry->add($this->namespaceConverter->convert($namespace));
}
);
$this->eventEmitter->on(IndexingEventName::NAMESPACE_REMOVED, function (Structures\FileNamespace $namespace) {
$this->namespaceListRegistry->remove($this->namespaceConverter->convert($namespace));
});
$this->eventEmitter->on(
IndexingEventName::NAMESPACE_REMOVED,
function (Structures\FileNamespace $namespace): void {
$this->namespaceListRegistry->remove($this->namespaceConverter->convert($namespace));
}
);
}
}
......@@ -42,7 +42,7 @@ final class WorkspaceEventConstantRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath) {
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath): void {
$this->constantListRegistry->reset();
});
}
......
......@@ -42,7 +42,7 @@ final class WorkspaceEventFunctionRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath) {
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath): void {
$this->functionListRegistry->reset();
});
}
......
......@@ -42,7 +42,7 @@ final class WorkspaceEventNamespaceRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath) {
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath): void {
$this->namespaceListRegistry->reset();
});
}
......
......@@ -42,7 +42,7 @@ final class WorkspaceEventStructureRegistryMediator
*/
private function setup(): void
{
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath) {
$this->eventEmitter->on(WorkspaceEventName::CHANGED, function (string $filePath): void {
$this->classlikeListRegistry->reset();
});
}
......
This diff is collapsed.
......@@ -66,17 +66,21 @@ final class PartialParser implements Parser
$correctedExpression = $this->getNormalizedCode($code);
$nodes = $this->tryParse($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithKeywordCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithTrailingSemicolonCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithHeredocTerminationCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithFunctionTerminationCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithFunctionMissingArgumentCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithTernaryOperatorTerminationCorrection($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithDummyInsertion($correctedExpression);
$nodes = $nodes ?: $this->tryParseWithDoubleArrowFix($correctedExpression);
$isValid = function (?array $result): bool {
return $result !== null && $result !== [];
};
return $nodes;
$list = $this->tryParse($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithKeywordCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithTrailingSemicolonCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithHeredocTerminationCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithFunctionTerminationCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithFunctionMissingArgumentCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithTernaryOperatorTerminationCorrection($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithDummyInsertion($correctedExpression);
$list = $isValid($list) ? $list : $this->tryParseWithDoubleArrowFix($correctedExpression);
return $list;
}
/**
......@@ -294,7 +298,7 @@ final class PartialParser implements Parser
$node = $nodes[count($nodes) - 1];
$removeDummies = function (Node $node) use ($dummyName, &$removeDummies) {
$removeDummies = function (Node $node) use ($dummyName, &$removeDummies): void {
if ($node instanceof Node\Expr\PropertyFetch) {
if ($node->var instanceof Node\Expr\ClassConstFetch ||
$node->var instanceof Node\Expr\PropertyFetch
......
......@@ -49,7 +49,7 @@ final class FunctionParameterPrettyPrinter
$label = '';
if (count($parameter['types']) > 0) {
$label .= $this->typeListPrettyPrinter->print(array_map(function (array $type) {
$label .= $this->typeListPrettyPrinter->print(array_map(function (array $type): string {
return $this->getClassNameFromFqcn($type['type']);
}, $parameter['types']));
......
......@@ -27,7 +27,7 @@ final class TypeListPrettyPrinter
*/
public function print(array $types): string
{
return implode('|', array_map(function (string $type) {
return implode('|', array_map(function (string $type): string {
return $this->typePrettyPrinter->print($type);
}, $types));
}
......
......@@ -505,7 +505,9 @@ final class UseStatementInsertionCreator
return mb_strlen($firstClassNameParts[$i]) <=> mb_strlen($secondClassNameParts[$i]);
}
return substr_compare($firstClassNameParts[$i], $secondClassNameParts[$i], 0) ?: 0;
$result = substr_compare($firstClassNameParts[$i], $secondClassNameParts[$i], 0);
return $result !== false ? $result : 0;
}
return count($firstClassNameParts) <=> count($secondClassNameParts);
......@@ -549,16 +551,16 @@ final class UseStatementInsertionCreator
);
}
foreach ($nodes as $node) {
$endFilePos = $node->getAttribute('endFilePos');
$startFilePos = $node->getAttribute('startFilePos');
foreach ($nodes as $codeNode) {
$endFilePos = $codeNode->getAttribute('endFilePos');
$startFilePos = $codeNode->getAttribute('startFilePos');
$byteOffset = $position->getAsByteOffsetInString($textDocumentItem->getText(), PositionEncoding::VALUE);
if ($startFilePos > $byteOffset) {
break;
} elseif ($node instanceof Node\Stmt\Namespace_) {
return $node;
} elseif ($codeNode instanceof Node\Stmt\Namespace_) {
return $codeNode;
}
}
......
......@@ -361,7 +361,7 @@ final class SignatureHelpRetriever
*/
private function formatSignatureLabel(string $name, array $parameters): string
{
return $name . '(' . implode(', ', array_map(function (ParameterInformation $parameterInformation) {
return $name . '(' . implode(', ', array_map(function (ParameterInformation $parameterInformation): string {
return $parameterInformation->getLabel();
}, $parameters)) . ')';
}
......
......@@ -49,7 +49,7 @@ final class SocketServer
$this->connectionMap = new SplObjectStorage();
$this->connectionHandlerFactory = $connectionHandlerFactory;
$this->server->on('connection', function (Connection $connection) {
$this->server->on('connection', function (Connection $connection): void {
$this->onConnectionEstablished($connection);
});
}
......@@ -65,7 +65,7 @@ final class SocketServer
$this->connectionMap->attach($connection, $handler);
$connection->on('close', function () use ($connection) {
$connection->on('close', function () use ($connection): void {
$this->onConnectionClosed($connection);
});
}
......
......@@ -73,7 +73,7 @@ final class DocumentSymbolRetriever
return $this->getMemberSymbolsForClasslike($classlike, $file);
}, $file->getClasslikes());
return array_reduce($symbolLists, function (array $finalSymbolList, array $symbolList) {
return array_reduce($symbolLists, function (array $finalSymbolList, array $symbolList): array {
return array_merge($finalSymbolList, $symbolList);
}, []);
}
......
......@@ -121,7 +121,7 @@ final class FunctionTooltipGenerator
$text = '#### • **' . $text . '**';
if (count($parameter['types']) > 0) {
$value = $this->tooltipTypeListPrettyPrinter->print(array_map(function (array $type) {
$value = $this->tooltipTypeListPrettyPrinter->print(array_map(function (array $type): string {
return $this->getClassNameFromFqcn($type['type']);
}, $parameter['types']));
......@@ -149,7 +149,7 @@ final class FunctionTooltipGenerator
$returnDescription = null;
if (count($functionInfo['returnTypes']) > 0) {
$value = $this->tooltipTypeListPrettyPrinter->print(array_map(function (array $type) {
$value = $this->tooltipTypeListPrettyPrinter->print(array_map(function (array $type): string {
return $this->getClassNameFromFqcn($type['type']);
}, $functionInfo['returnTypes']));
......
......@@ -69,7 +69,7 @@ abstract class AbstractApplication
$container->set('application', $this);
/** @var string $configurator To make setConfigurator below happy, as it does not mention callable. */
$configurator = function (ConfigurableDelegatingNodeTypeDeducer $deducer) use ($container) {
$configurator = function (ConfigurableDelegatingNodeTypeDeducer $deducer) use ($container): void {
/** @var NodeTypeDeducerInterface $nodeTypeDeducer */
$nodeTypeDeducer = $container->get('nodeTypeDeducer.instance');
......
......@@ -136,7 +136,7 @@ final class JsonRpcApplication extends AbstractApplication implements JsonRpcReq
$this->periodicQueueProcessingTimer = $loop->addPeriodicTimer(
self::REQUEST_HANDLE_FREQUENCY_SECONDS,
function () {
function (): void {
$this->processNextQueueItem();
/** @var JsonRpcQueue $queue */
......@@ -194,7 +194,7 @@ final class JsonRpcApplication extends AbstractApplication implements JsonRpcReq
$loop = $this->getContainer()->get('eventLoop');
$loop->addPeriodicTimer(
self::CYCLE_COLLECTION_FREQUENCY_SECONDS,
function () {
function (): void {
// Still try to collect cyclic references every so often. See also Bootstrap.php for the reasoning.
// Do *not* do this after every request handle as it puts a major strain on performance, especially
// during project indexing. Also don't cancel this timer when the last request is handled, as during
......
......@@ -31,7 +31,9 @@ final class CancelRequestJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIte
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($parameters['id'])) {
throw new InvalidArgumentsException('"id" of request to cancel must be passed');
......
......@@ -44,7 +44,9 @@ final class ClassInfoJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($arguments['name'])) {
throw new InvalidArgumentsException(
......
......@@ -56,7 +56,9 @@ final class ClassListJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHan
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$uri = $arguments['uri'] ?? null;
......
......@@ -47,7 +47,9 @@ final class CodeLensJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHand
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -60,7 +60,9 @@ final class CompletionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse($queueItem->getRequest()->getId(), new CompletionList(
true,
......
......@@ -49,7 +49,9 @@ final class DeduceTypesJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($arguments['uri'])) {
throw new InvalidArgumentsException('"uri" must be supplied');
......
......@@ -49,7 +49,9 @@ final class DefinitionJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHa
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -46,7 +46,9 @@ final class DiagnosticsJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($parameters['uri'])) {
throw new InvalidArgumentsException('"uri" parameter must be supplied');
......
......@@ -48,7 +48,9 @@ final class DocumentHighlightJsonRpcQueueItemHandler extends AbstractJsonRpcQueu
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -43,7 +43,9 @@ final class DocumentSymbolJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIt
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -19,7 +19,9 @@ final class EchoMessageJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($arguments['message'])) {
throw new InvalidArgumentsException('Missing "message" in parameters for request');
......
......@@ -54,7 +54,9 @@ final class ExecuteCommandJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIt
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($parameters['command'])) {
throw new InvalidArgumentsException('"command" must be supplied');
......
......@@ -49,7 +49,9 @@ final class HoverJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemHandler
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -49,7 +49,9 @@ final class LocalizeTypeJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItem
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($arguments['type'])) {
throw new InvalidArgumentsException('"type" must be supplied');
......
......@@ -51,7 +51,9 @@ final class ResolveTypeJsonRpcQueueItemHandler extends AbstractJsonRpcQueueItemH
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$arguments = $queueItem->getRequest()->getParams() ?: [];
$arguments = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
if (!isset($arguments['type'])) {
throw new InvalidArgumentsException('"type" must be supplied');
......
......@@ -49,7 +49,9 @@ final class SignatureHelpJsonRpcQueueItemHandler extends AbstractJsonRpcQueueIte
*/
public function execute(JsonRpcQueueItem $queueItem): ExtendedPromiseInterface
{
$parameters = $queueItem->getRequest()->getParams() ?: [];
$parameters = $queueItem->getRequest()->getParams() !== null ?
$queueItem->getRequest()->getParams() :
[];
$response = new JsonRpcResponse(
$queueItem->getRequest()->getId(),
......
......@@ -46,7 +46,11 @@ class ImmutableSet implements IteratorAggregate
*/
public function has($element): bool
{
return in_array($element, $this->elements, $this->isStrict());
// The strict ruleset enforces the third parameter to be true, but we need it to be loose in some cases, so this
// works around it.
$silencePhpStan = 'in_array';
return $silencePhpStan($element, $this->elements, $this->isStrict());
}
/**
......