diff --git a/composer.json b/composer.json
index 9874dc49e..4da00a804 100644
--- a/composer.json
+++ b/composer.json
@@ -16,10 +16,10 @@
"require": {
"php": "^7.3 || ^8.0",
"ext-json": "*",
+ "composer-plugin-api": "~1.0 || ~2.0",
"amphp/amp": "^2.4",
"amphp/parallel": "^1.4",
"amphp/parallel-functions": "^1.0",
- "composer-plugin-api": "~1.0 || ~2.0",
"doctrine/collections": "^1.6.7",
"gitonomy/gitlib": "^1.0.3",
"monolog/monolog": "~1.16 || ^2.0",
diff --git a/grumphp.yml.dist b/grumphp.yml.dist
index a333a3151..f2a490571 100644
--- a/grumphp.yml.dist
+++ b/grumphp.yml.dist
@@ -36,6 +36,7 @@ grumphp:
functional: true
psalm:
show_info: true
+ no_cache: true
testsuites:
git_pre_commit:
tasks: [phpcs, phpspec, phpunit, composer, composer_normalize, yamllint, phplint, phpparser, psalm]
diff --git a/phive.xml b/phive.xml
index d28752319..905d55981 100644
--- a/phive.xml
+++ b/phive.xml
@@ -1,7 +1,7 @@
-
-
-
-
+
+
+
+
diff --git a/psalm.xml b/psalm.xml
index 53275583b..1b82c729f 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -1,7 +1,7 @@
getIterator(), [$closure]);
+ $filter = new Iterator\CustomFilterIterator($this->getIterator(), [$p]);
return new self(iterator_to_array($filter));
}
@@ -221,11 +223,9 @@ public function ignoreSymlinks(): FilesCollection
public function serialize(): string
{
return serialize($this->map(function (SplFileInfo $fileInfo): string {
- return (string) (
- $fileInfo instanceof SymfonySplFileInfo
- ? $fileInfo->getRelativePathname()
- : $fileInfo->getPathname()
- );
+ return $fileInfo instanceof SymfonySplFileInfo
+ ? $fileInfo->getRelativePathname()
+ : $fileInfo->getPathname();
})->toArray());
}
diff --git a/src/Configuration/Model/FixerConfig.php b/src/Configuration/Model/FixerConfig.php
index b540ab856..f4d02fc64 100644
--- a/src/Configuration/Model/FixerConfig.php
+++ b/src/Configuration/Model/FixerConfig.php
@@ -33,8 +33,8 @@ public function __construct(
public static function fromArray(array $config): self
{
return new self(
- (bool) ($config['enabled'] ?? false),
- (bool) ($config['fix_by_default'] ?? false)
+ ($config['enabled'] ?? false),
+ ($config['fix_by_default'] ?? false)
);
}
diff --git a/src/Configuration/Model/ParallelConfig.php b/src/Configuration/Model/ParallelConfig.php
index a984e50b9..32a87ee3c 100644
--- a/src/Configuration/Model/ParallelConfig.php
+++ b/src/Configuration/Model/ParallelConfig.php
@@ -33,8 +33,8 @@ public function __construct(
public static function fromArray(array $config): self
{
return new self(
- (bool) ($config['enabled'] ?? false),
- (int) ($config['max_workers'] ?? 1)
+ ($config['enabled'] ?? false),
+ ($config['max_workers'] ?? 1)
);
}
diff --git a/src/Console/Command/Git/InitCommand.php b/src/Console/Command/Git/InitCommand.php
index e618a39fd..604d0759a 100644
--- a/src/Console/Command/Git/InitCommand.php
+++ b/src/Console/Command/Git/InitCommand.php
@@ -153,7 +153,10 @@ private function parseHookVariable(string $key, $value): string
case 'ENV':
return DotEnvSerializer::serialize($value);
default:
- /** @var string $value */
+ /**
+ * @var string $value
+ * @psalm-suppress PossiblyInvalidCast, RedundantCastGivenDocblockType
+ */
return (string) $value;
}
}
diff --git a/src/Event/Dispatcher/Bridge/SymfonyEventDispatcher.php b/src/Event/Dispatcher/Bridge/SymfonyEventDispatcher.php
index 684c0761a..eeb8dd01e 100644
--- a/src/Event/Dispatcher/Bridge/SymfonyEventDispatcher.php
+++ b/src/Event/Dispatcher/Bridge/SymfonyEventDispatcher.php
@@ -24,7 +24,7 @@ public function __construct($eventDispatcher)
$this->dispatcher = $eventDispatcher;
}
- public function dispatch(Event $event, string $eventName = null): void
+ public function dispatch(Event $event, string $name = null): void
{
$interfacesImplemented = class_implements($this->dispatcher);
if (in_array(SymfonyEventDispatcherContract::class, $interfacesImplemented, true)) {
@@ -32,7 +32,7 @@ public function dispatch(Event $event, string $eventName = null): void
* @psalm-suppress InvalidArgument
* @psalm-suppress TooManyArguments
*/
- $this->dispatcher->dispatch($event, $eventName);
+ $this->dispatcher->dispatch($event, $name);
return;
}
@@ -40,6 +40,6 @@ public function dispatch(Event $event, string $eventName = null): void
* @psalm-suppress InvalidArgument
* @psalm-suppress TooManyArguments
*/
- $this->dispatcher->dispatch($eventName, $event);
+ $this->dispatcher->dispatch($name, $event);
}
}
diff --git a/src/Fixer/FixerUpper.php b/src/Fixer/FixerUpper.php
index 0b5e85e05..0321e27ff 100644
--- a/src/Fixer/FixerUpper.php
+++ b/src/Fixer/FixerUpper.php
@@ -57,8 +57,8 @@ static function (TaskResultInterface $result): bool {
$result->ok() ? $this->IO->colorize(['✔'], 'green') : $this->IO->colorize(['✘'], 'red')
);
- if ($this->IO->isVerbose() && $result->error()) {
- $this->IO->writeError($this->IO->colorize([$result->error()->getMessage()], 'red'));
+ if ($this->IO->isVerbose() && $error = $result->error()) {
+ $this->IO->writeError($this->IO->colorize([$error->getMessage()], 'red'));
}
$count++;
diff --git a/src/Fixer/Provider/FixableProcessResultProvider.php b/src/Fixer/Provider/FixableProcessResultProvider.php
index e127f81f0..fcf08a53f 100644
--- a/src/Fixer/Provider/FixableProcessResultProvider.php
+++ b/src/Fixer/Provider/FixableProcessResultProvider.php
@@ -19,6 +19,7 @@ public static function provide(
array $successExitCodes = [0]
): FixableTaskResult {
$fixerProcess = $fixerProcessBuilder();
+ /** @psalm-suppress RedundantConditionGivenDocblockType */
assert($fixerProcess instanceof Process);
$fixerCommand = $fixerProcess->getCommandLine();
diff --git a/src/Formatter/GitBlacklistFormatter.php b/src/Formatter/GitBlacklistFormatter.php
index 4c8ab45ed..9c6ad2f8c 100644
--- a/src/Formatter/GitBlacklistFormatter.php
+++ b/src/Formatter/GitBlacklistFormatter.php
@@ -45,7 +45,7 @@ private function formatOutput(string $output): string
{
$result = static::RESET_COLOR;
foreach (array_filter(explode("\n", $output)) as $lineNumber => $line) {
- $result .= preg_match('/^[0-9]+/', $line) ? $this->trimOutputLine($line, (int) $lineNumber) : $line;
+ $result .= preg_match('/^[0-9]+/', $line) ? $this->trimOutputLine($line, $lineNumber) : $line;
$result .= PHP_EOL;
}
diff --git a/src/Process/ProcessFactory.php b/src/Process/ProcessFactory.php
index ffd8d155d..b7a73708a 100644
--- a/src/Process/ProcessFactory.php
+++ b/src/Process/ProcessFactory.php
@@ -22,6 +22,6 @@ public static function fromArguments(ProcessArgumentsCollection $arguments): Pro
*/
public static function fromScalar($arguments): Process
{
- return is_array($arguments) ? new Process($arguments) : Process::fromShellCommandline((string) $arguments);
+ return is_array($arguments) ? new Process($arguments) : Process::fromShellCommandline($arguments);
}
}
diff --git a/src/Process/TmpFileUsingProcessRunner.php b/src/Process/TmpFileUsingProcessRunner.php
index 069607102..51618beb0 100644
--- a/src/Process/TmpFileUsingProcessRunner.php
+++ b/src/Process/TmpFileUsingProcessRunner.php
@@ -29,7 +29,7 @@ public static function run(callable $processBuilder, callable $writer): Process
}
foreach ($writer() as $entry) {
- fwrite($tmp, (string) $entry);
+ fwrite($tmp, $entry);
}
fseek($tmp, 0);
diff --git a/src/Runner/FixableTaskResult.php b/src/Runner/FixableTaskResult.php
index 033c46b61..d94079735 100644
--- a/src/Runner/FixableTaskResult.php
+++ b/src/Runner/FixableTaskResult.php
@@ -69,10 +69,10 @@ public function getContext(): ContextInterface
return $this->result->getContext();
}
- public function withAppendedMessage(string $additionalMessage): TaskResultInterface
+ public function withAppendedMessage(string $message): TaskResultInterface
{
$new = clone $this;
- $new->result = $this->result->withAppendedMessage($additionalMessage);
+ $new->result = $this->result->withAppendedMessage($message);
return $new;
}
diff --git a/src/Runner/Middleware/HandleRunnerMiddleware.php b/src/Runner/Middleware/HandleRunnerMiddleware.php
index fc3db12a3..30a4c3fe4 100644
--- a/src/Runner/Middleware/HandleRunnerMiddleware.php
+++ b/src/Runner/Middleware/HandleRunnerMiddleware.php
@@ -38,7 +38,7 @@ public function __construct(TaskHandler $taskHandler, RunnerConfig $config)
public function handle(TaskRunnerContext $context, callable $next): TaskResultCollection
{
return new TaskResultCollection(
- (array) wait(
+ wait(
/**
* @return \Generator
*/
diff --git a/src/Runner/MiddlewareStack.php b/src/Runner/MiddlewareStack.php
index 21f890871..f71e2f4f9 100644
--- a/src/Runner/MiddlewareStack.php
+++ b/src/Runner/MiddlewareStack.php
@@ -7,6 +7,9 @@
use GrumPHP\Collection\TaskResultCollection;
use GrumPHP\Runner\Middleware\RunnerMiddlewareInterface;
+/**
+ * @psalm-immutable
+ */
class MiddlewareStack
{
/**
@@ -30,9 +33,6 @@ public static function fromIterable(iterable $middlewares): self
);
}
- /**
- * @psalm-pure
- */
public function handle(TaskRunnerContext $context): TaskResultCollection
{
return ($this->stack)($context);
diff --git a/src/Runner/Promise/MultiPromise.php b/src/Runner/Promise/MultiPromise.php
index 89dbdeebc..37a925639 100644
--- a/src/Runner/Promise/MultiPromise.php
+++ b/src/Runner/Promise/MultiPromise.php
@@ -20,7 +20,7 @@ class MultiPromise
* @param array> $promises
* @param callable(TValue):bool $shouldCancel
*
- * @return Promise
+ * @return Promise
*/
public static function cancelable(array $promises, callable $shouldCancel): Promise
{
@@ -50,26 +50,31 @@ static function (CancelledException $error) use ($deferred, $watcherId): void {
});
};
- $promise->onResolve(static function (
- ?\Throwable $error,
- $result
- ) use (
- $deferred,
- $cancel,
- $shouldCancel
- ): void {
- if ($error instanceof \Throwable) {
- $cancel($error);
- $deferred->fail($error);
- return;
- }
+ $promise->onResolve(
+ /**
+ * @param TValue $result
+ */
+ static function (
+ ?\Throwable $error,
+ $result
+ ) use (
+ $deferred,
+ $cancel,
+ $shouldCancel
+ ): void {
+ if ($error instanceof \Throwable) {
+ $cancel($error);
+ $deferred->fail($error);
+ return;
+ }
- if ($result && $shouldCancel($result)) {
- $cancel();
- }
+ if ($result && $shouldCancel($result)) {
+ $cancel();
+ }
- $deferred->resolve($result);
- });
+ $deferred->resolve($result);
+ }
+ );
}
);
diff --git a/src/Runner/Reporting/RunnerReporter.php b/src/Runner/Reporting/RunnerReporter.php
index 7996accb8..aac0c81d6 100644
--- a/src/Runner/Reporting/RunnerReporter.php
+++ b/src/Runner/Reporting/RunnerReporter.php
@@ -41,8 +41,8 @@ public function __construct(
public function start(TaskRunnerContext $context): void
{
$this->IO->write($this->IO->colorize(['GrumPHP is sniffing your code!'], 'yellow'));
- if ($context->getTestSuite()) {
- $this->IO->style()->note('Running testsuite: '.$context->getTestSuite()->getName());
+ if ($testSuite = $context->getTestSuite()) {
+ $this->IO->style()->note('Running testsuite: '.$testSuite->getName());
}
}
diff --git a/src/Runner/TaskHandler/Middleware/TaskHandlerMiddlewareInterface.php b/src/Runner/TaskHandler/Middleware/TaskHandlerMiddlewareInterface.php
index e8f792bb6..8ee61884f 100644
--- a/src/Runner/TaskHandler/Middleware/TaskHandlerMiddlewareInterface.php
+++ b/src/Runner/TaskHandler/Middleware/TaskHandlerMiddlewareInterface.php
@@ -17,7 +17,7 @@ interface TaskHandlerMiddlewareInterface
*/
public function handle(
TaskInterface $task,
- TaskRunnerContext $runnercontext,
+ TaskRunnerContext $runnerContext,
callable $next
): Promise;
}
diff --git a/src/Runner/TaskHandler/TaskHandler.php b/src/Runner/TaskHandler/TaskHandler.php
index fcd30e678..c681177c3 100644
--- a/src/Runner/TaskHandler/TaskHandler.php
+++ b/src/Runner/TaskHandler/TaskHandler.php
@@ -12,6 +12,9 @@
use GrumPHP\Runner\TaskRunnerContext;
use GrumPHP\Task\TaskInterface;
+/**
+ * @psalm-immutable
+ */
class TaskHandler
{
/**
@@ -37,7 +40,6 @@ public static function fromIterable(iterable $handlers): self
}
/**
- * @psalm-pure
* @return Promise
*/
public function handle(TaskInterface $task, TaskRunnerContext $runnerContext): Promise
diff --git a/src/Runner/TaskResult.php b/src/Runner/TaskResult.php
index d58c56ab6..35ccc8f94 100644
--- a/src/Runner/TaskResult.php
+++ b/src/Runner/TaskResult.php
@@ -95,10 +95,10 @@ public function getContext(): ContextInterface
return $this->context;
}
- public function withAppendedMessage(string $additionalMessage): TaskResultInterface
+ public function withAppendedMessage(string $message): TaskResultInterface
{
$new = clone $this;
- $new->message = $this->message . $additionalMessage;
+ $new->message = $this->message . $message;
return $new;
}
diff --git a/src/Task/AbstractExternalTask.php b/src/Task/AbstractExternalTask.php
index ed0d6928d..5aa8c8fb3 100644
--- a/src/Task/AbstractExternalTask.php
+++ b/src/Task/AbstractExternalTask.php
@@ -9,6 +9,9 @@
use GrumPHP\Task\Config\EmptyTaskConfig;
use GrumPHP\Task\Config\TaskConfigInterface;
+/**
+ * @template-covariant Formatter extends ProcessFormatterInterface
+ */
abstract class AbstractExternalTask implements TaskInterface
{
/**
@@ -22,10 +25,13 @@ abstract class AbstractExternalTask implements TaskInterface
protected $processBuilder;
/**
- * @var ProcessFormatterInterface
+ * @var Formatter
*/
protected $formatter;
+ /**
+ * @param Formatter $formatter
+ */
public function __construct(ProcessBuilder $processBuilder, ProcessFormatterInterface $formatter)
{
$this->config = new EmptyTaskConfig();
diff --git a/src/Task/AbstractLinterTask.php b/src/Task/AbstractLinterTask.php
index 4091e7d2c..1bd1686ad 100644
--- a/src/Task/AbstractLinterTask.php
+++ b/src/Task/AbstractLinterTask.php
@@ -12,6 +12,9 @@
use GrumPHP\Task\Config\TaskConfigInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
+/**
+ * @template-covariant Linter extends LinterInterface
+ */
abstract class AbstractLinterTask implements TaskInterface
{
/**
@@ -20,10 +23,13 @@ abstract class AbstractLinterTask implements TaskInterface
protected $config;
/**
- * @var LinterInterface
+ * @var Linter
*/
protected $linter;
+ /**
+ * @param Linter $linter
+ */
public function __construct(LinterInterface $linter)
{
$this->linter = $linter;
diff --git a/src/Task/AbstractParserTask.php b/src/Task/AbstractParserTask.php
index ee9c82bff..3ef2409c2 100644
--- a/src/Task/AbstractParserTask.php
+++ b/src/Task/AbstractParserTask.php
@@ -12,6 +12,9 @@
use GrumPHP\Task\Config\TaskConfigInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
+/**
+ * @template-covariant Parser extends ParserInterface
+ */
abstract class AbstractParserTask implements TaskInterface
{
/**
@@ -20,10 +23,13 @@ abstract class AbstractParserTask implements TaskInterface
protected $configuration;
/**
- * @var ParserInterface
+ * @var Parser
*/
protected $parser;
+ /**
+ * @param Parser $parser
+ */
public function __construct(ParserInterface $parser)
{
$this->configuration = new EmptyTaskConfig();
diff --git a/src/Task/CloverCoverage.php b/src/Task/CloverCoverage.php
index 01297f511..bbd9829b7 100644
--- a/src/Task/CloverCoverage.php
+++ b/src/Task/CloverCoverage.php
@@ -102,7 +102,7 @@ public function run(ContextInterface $context): TaskResultInterface
$totalElements = (int) current($xml->xpath('/coverage/project/metrics/@elements'));
$checkedElements = (int) current($xml->xpath('/coverage/project/metrics/@coveredelements'));
- if (0 === (int) $totalElements) {
+ if (0 === $totalElements) {
return TaskResult::createSkipped($this, $context);
}
diff --git a/src/Task/Git/CommitMessage.php b/src/Task/Git/CommitMessage.php
index 192e99c84..ae31b387b 100644
--- a/src/Task/Git/CommitMessage.php
+++ b/src/Task/Git/CommitMessage.php
@@ -136,7 +136,7 @@ public function run(ContextInterface $context): TaskResultInterface
}
- if ((bool) $this->enforceTypeScopeConventions()) {
+ if ($this->enforceTypeScopeConventions()) {
try {
$this->checkTypeScopeConventions($context);
} catch (RuntimeException $e) {
@@ -287,7 +287,7 @@ private function subjectIsCapitalized(GitCommitMsgContext $context): bool
return false;
}
- $firstLetter = (string) ($match[1] ?? '');
+ $firstLetter = $match[1] ?? '';
return !(1 !== preg_match('/^(fixup|squash)!/u', $subject) && 1 !== preg_match('/[[:upper:]]/u', $firstLetter));
}
@@ -317,13 +317,16 @@ function (): ?string {
$lines = preg_split('/\R/u', $commitMessage);
$everythingBelowWillBeIgnored = false;
- return array_values(array_filter($lines, function ($line) use (&$everythingBelowWillBeIgnored, $commentChar) {
- if (mb_stripos($line, $commentChar.' Everything below it will be ignored.') !== false) {
- $everythingBelowWillBeIgnored = true;
- return false;
+ return array_values(array_filter(
+ $lines,
+ function (string $line) use (&$everythingBelowWillBeIgnored, $commentChar) {
+ if (mb_stripos($line, $commentChar.' Everything below it will be ignored.') !== false) {
+ $everythingBelowWillBeIgnored = true;
+ return false;
+ }
+ return 0 !== strpos($line, $commentChar) && !$everythingBelowWillBeIgnored;
}
- return 0 !== strpos($line, $commentChar) && !$everythingBelowWillBeIgnored;
- }));
+ ));
}
private function enforceTypeScopeConventions(): bool
diff --git a/src/Task/JsonLint.php b/src/Task/JsonLint.php
index 73d9b1f5c..8dea47440 100644
--- a/src/Task/JsonLint.php
+++ b/src/Task/JsonLint.php
@@ -13,6 +13,9 @@
use GrumPHP\Task\Context\RunContext;
use Symfony\Component\OptionsResolver\OptionsResolver;
+/**
+ * @extends AbstractLinterTask
+ */
class JsonLint extends AbstractLinterTask
{
/**
diff --git a/src/Task/PhpParser.php b/src/Task/PhpParser.php
index 12aae4f6a..03765ec5d 100644
--- a/src/Task/PhpParser.php
+++ b/src/Task/PhpParser.php
@@ -11,6 +11,9 @@
use GrumPHP\Runner\TaskResultInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
+/**
+ * @extends AbstractParserTask
+ */
class PhpParser extends AbstractParserTask
{
const KIND_PHP5 = 'php5';
diff --git a/src/Task/XmlLint.php b/src/Task/XmlLint.php
index 0ece6d6c6..d9620b4d6 100644
--- a/src/Task/XmlLint.php
+++ b/src/Task/XmlLint.php
@@ -14,7 +14,7 @@
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
- * @property \GrumPHP\Linter\Xml\XmlLinter $linter
+ * @extends AbstractLinterTask
*/
class XmlLint extends AbstractLinterTask
{
diff --git a/src/Task/YamlLint.php b/src/Task/YamlLint.php
index e139e60cb..75aa1422c 100644
--- a/src/Task/YamlLint.php
+++ b/src/Task/YamlLint.php
@@ -14,6 +14,9 @@
use GrumPHP\Task\Context\RunContext;
use Symfony\Component\OptionsResolver\OptionsResolver;
+/**
+ * @extends AbstractLinterTask
+ */
class YamlLint extends AbstractLinterTask
{
diff --git a/src/Util/PhpVersion.php b/src/Util/PhpVersion.php
index 4e711ca7e..372153843 100644
--- a/src/Util/PhpVersion.php
+++ b/src/Util/PhpVersion.php
@@ -21,7 +21,7 @@ public function isSupportedVersion(string $currentVersion): bool
$now = new \DateTime();
foreach ($this->versions as $number => $eol) {
$eol = new \DateTime($eol);
- if ($now < $eol && (int) version_compare($currentVersion, $number) >= 0) {
+ if ($now < $eol && version_compare($currentVersion, $number) >= 0) {
return true;
}
}
@@ -31,6 +31,6 @@ public function isSupportedVersion(string $currentVersion): bool
public function isSupportedProjectVersion(string $currentVersion, string $projectVersion): bool
{
- return (int) version_compare($currentVersion, $projectVersion) >= 0;
+ return version_compare($currentVersion, $projectVersion) >= 0;
}
}
diff --git a/src/Util/Regex.php b/src/Util/Regex.php
index ccfe4f2d5..6ef046341 100644
--- a/src/Util/Regex.php
+++ b/src/Util/Regex.php
@@ -57,6 +57,7 @@ private function toRegex(string $string): string
public function addPatternModifier(string $modifier): void
{
+ /** @psalm-suppress InvalidLiteralArgument */
if ('' === $modifier || false === strpos(self::ALLOWED_MODIFIERS, $modifier)) {
throw new RuntimeException('Invalid regex modifier: '.$modifier);
}
diff --git a/stubs/Amp.php b/stubs/Amp.php
index 32ff3e85c..0611e5bec 100644
--- a/stubs/Amp.php
+++ b/stubs/Amp.php
@@ -1,77 +1,113 @@
$gen
- *
- * @return callable():Promise
- */
-function coroutine(callable $gen) : callable
-{
-}
-
-/**
- * @template TReturn
- *
- * @param callable():(\Generator|TReturn) $gen
- *
- * @return Promise
- */
-function call(callable $gen) : Promise
-{
-}
-
-
-/**
- * @template TReturn
- */
-interface Promise
-{
/**
- * @param callable(?\Throwable, ?TReturn):void $onResolved
+ * @template TReturn
*
- * @return void
+ * @param callable():\Generator $gen
+ *
+ * @return callable():Promise
*/
- public function onResolve(callable $onResolved);
-}
+ function coroutine(callable $gen) : callable
+ {
+ }
-/**
- * @template TReturn
- */
-final class LazyPromise
-{
/**
- * @param callable(?\Throwable, ?TReturn):void $onResolved
+ * @template TReturn
*
- * @return void
+ * @param callable():(\Generator|TReturn) $gen
+ *
+ * @return Promise
*/
- public function onResolve(callable $onResolved)
+ function call(callable $gen) : Promise
{
}
-}
-/**
- * @template TReturn
- *
- * @template-implements Promise
- */
-class Success implements Promise
-{
+
/**
- * @param TReturn|null $value
+ * @template TReturn
*/
- public function __construct($value = null)
+ interface Promise
{
+ /**
+ * @param callable(?\Throwable, ?TReturn):void $onResolved
+ *
+ * @return void
+ */
+ public function onResolve(callable $onResolved);
}
/**
- * @param callable(?Throwable, ?TReturn):void $onResolved
+ * @template TReturn
+ */
+ final class LazyPromise
+ {
+ /**
+ * @param callable(?\Throwable, ?TReturn):void $onResolved
+ *
+ * @return void
+ */
+ public function onResolve(callable $onResolved)
+ {
+ }
+ }
+
+ /**
+ * @template TReturn
*
- * @return void
+ * @template-implements Promise
*/
- public function onResolve(callable $onResolved)
+ class Success implements Promise
{
+ /**
+ * @param TReturn|null $value
+ */
+ public function __construct($value = null)
+ {
+ }
+
+ /**
+ * @param callable(?Throwable, ?TReturn):void $onResolved
+ *
+ * @return void
+ */
+ public function onResolve(callable $onResolved)
+ {
+ }
}
}
+
+namespace Amp\Promise {
+ use React\Promise\Promise as ReactPromise;
+ use Amp\Promise;
+
+ /**
+ * @template TPromise
+ * @template T as Promise|ReactPromise
+ *
+ * @param Promise|ReactPromise $promise Promise to wait for.
+ *
+ * @return mixed Promise success value.
+ *
+ * @psalm-param T $promise
+ * @psalm-return (T is Promise ? TPromise : mixed)
+ *
+ * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
+ * @throws \Error If the event loop stopped without the $promise being resolved.
+ * @throws \Throwable Promise failure reason.
+ */
+ function wait($promise){}
+
+ /**
+ * @template TValue
+ *
+ * @param Promise[]|\React\Promise\PromiseInterface[] $promises
+ *
+ * @return Promise
+ *
+ * @throws \Error If a non-Promise is in the array.
+ */
+ function any(array $promises): Promise {}
+}
+
+
diff --git a/tools/composer-normalize b/tools/composer-normalize
index 6a5c3ae83..dfa36f728 100755
Binary files a/tools/composer-normalize and b/tools/composer-normalize differ
diff --git a/tools/phpcbf b/tools/phpcbf
index 791da6988..dcf50adc3 100755
Binary files a/tools/phpcbf and b/tools/phpcbf differ
diff --git a/tools/phpcs b/tools/phpcs
index 1989255de..f49d1379e 100755
Binary files a/tools/phpcs and b/tools/phpcs differ
diff --git a/tools/psalm b/tools/psalm
index 81abe7e18..35b6dd494 100755
Binary files a/tools/psalm and b/tools/psalm differ