Skip to content

Commit

Permalink
gh-2576: Basic array_reduce stub
Browse files Browse the repository at this point in the history
  • Loading branch information
dantleech committed Mar 11, 2024
1 parent 0ea4ab7 commit d72b74f
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 18 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,13 @@
Changelog
=========

## master

Improvements:

- Basic support for `array_reduce` stub #2576


## 2024-03-09

Features:
Expand Down
Expand Up @@ -7,7 +7,6 @@
use Phpactor\WorseReflection\Core\Inference\FunctionStub;
use Phpactor\WorseReflection\Core\Inference\NodeContext;
use Phpactor\WorseReflection\Core\TypeFactory;
use Phpactor\WorseReflection\Core\Type\ClosureType;

class ArrayReduceStub implements FunctionStub
{
Expand All @@ -16,15 +15,12 @@ public function resolve(
NodeContext $context,
FunctionArguments $args
): NodeContext {
if (!$args->at(0)->type()->isDefined()) {
return $context;
$initialType = $args->at(2)->type();
if ($initialType->isDefined()) {
return $context->withType($initialType->generalize());
}

$closureType = $args->at(1);
if (!$closureType instanceof ClosureType) {
return $context;
}
return $context->withType(TypeFactory::array());

return $context->withType(TypeFactory::array($closureType->returnType()));
}
}
Expand Up @@ -179,11 +179,13 @@ private function walkSubscriptExpression(NodeContextResolver $resolver, Frame $f
return;
}

$frame->locals()->set(
$variable->withType(
$type->set($accessType->value(), $rightContext->type())
)->withOffset($leftOperand->getStartPosition())
);
if ($type instanceof ArrayLiteral) {
$frame->locals()->set(
$variable->withType(
$type->set($accessType->value(), $rightContext->type())
)->withOffset($leftOperand->getStartPosition())
);
}
continue;
}

Expand Down
11 changes: 11 additions & 0 deletions lib/WorseReflection/Core/Type/ArrayType.php
Expand Up @@ -54,4 +54,15 @@ public function allTypes(): Types
{
return (new Types([TypeFactory::array()]))->merge(parent::allTypes());
}

public function add(Type $type): self
{
if (null === $this->valueType) {
return new self($this->keyType, $type);
}
if (!$this->valueType->isDefined()) {
return new self($this->keyType, $type);
}
return new self($this->keyType, $this->valueType->addType($type));
}
}
33 changes: 28 additions & 5 deletions lib/WorseReflection/Tests/Inference/function/array_reduce.test
@@ -1,7 +1,30 @@
<?php

array_reduce(['foobar'], function (array $carry, string $foo): array {
$carry[] = $foo;
wrAssertType('array<string>', $carry);
return $carry;
}, []),
$reduced = array_reduce(['foobar'], function (int $carry, string $foo): int {
}, 0);

wrAssertType('int', $reduced);

$reduced = array_reduce(['foobar'], function (int $carry, string $foo): int {
}, ['string']);

wrAssertType('array<int,string>', $reduced);


// we cannot currently analyze the closure to determine the
$reduced = array_reduce(['foobar'], function (array $carry, string $foo): int {
$carry[] = 'foo';
return $carry;
}, []);

// should be string[] but we can't currently analyze the closure frames return type
wrAssertType('array', $reduced);

$reduced = array_reduce(['foobar'], function (int $carry, string $foo): int {
}, '');

wrAssertType('string', $reduced);

$reduced = array_reduce(['foobar'], function (int $carry, string $foo): int {
});
wrAssertType('array', $reduced);

0 comments on commit d72b74f

Please sign in to comment.