Skip to content

Commit

Permalink
Fixed encapsed string and concat in regard to non-empty-string
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jul 14, 2021
1 parent 520ae22 commit 1283db7
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 19 deletions.
46 changes: 36 additions & 10 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
use PHPStan\Reflection\TrivialParametersAcceptor;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BenevolentUnionType;
use PHPStan\Type\BooleanType;
Expand Down Expand Up @@ -1045,6 +1046,13 @@ private function resolveType(Expr $node): Type
return $leftStringType->append($rightStringType);
}

if ($leftStringType->isNonEmptyString()->or($rightStringType->isNonEmptyString())->yes()) {
return new IntersectionType([
new StringType(),
new AccessoryNonEmptyStringType(),
]);
}

return new StringType();
}

Expand Down Expand Up @@ -1316,22 +1324,40 @@ private function resolveType(Expr $node): Type
} elseif ($node instanceof String_) {
return new ConstantStringType($node->value);
} elseif ($node instanceof Node\Scalar\Encapsed) {
$constantString = new ConstantStringType('');
$parts = [];
foreach ($node->parts as $part) {
if ($part instanceof EncapsedStringPart) {
$partStringType = new ConstantStringType($part->value);
} else {
$partStringType = $this->getType($part)->toString();
if ($partStringType instanceof ErrorType) {
return new ErrorType();
}
if (!$partStringType instanceof ConstantStringType) {
return new StringType();
$parts[] = new ConstantStringType($part->value);
continue;
}

$partStringType = $this->getType($part)->toString();
if ($partStringType instanceof ErrorType) {
return new ErrorType();
}

$parts[] = $partStringType;
}

$constantString = new ConstantStringType('');
foreach ($parts as $part) {
if ($part instanceof ConstantStringType) {
$constantString = $constantString->append($part);
continue;
}

foreach ($parts as $partType) {
if ($partType->isNonEmptyString()->yes()) {
return new IntersectionType([
new StringType(),
new AccessoryNonEmptyStringType(),
]);
}
}

$constantString = $constantString->append($partStringType);
return new StringType();
}

return $constantString;
} elseif ($node instanceof DNumber) {
return new ConstantFloatType($node->value);
Expand Down
10 changes: 5 additions & 5 deletions tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2496,11 +2496,11 @@ public function dataBinaryOperations(): array
'min(1, 2.2, 3.3)',
],
[
'string',
'non-empty-string',
'"Hello $world"',
],
[
'string',
'non-empty-string',
'$string .= "str"',
],
[
Expand Down Expand Up @@ -3072,15 +3072,15 @@ public function dataBinaryOperations(): array
'$decrementedFooString',
],
[
'string',
'non-empty-string',
'$conditionalString . $conditionalString',
],
[
'string',
'non-empty-string',
'$conditionalString . $anotherConditionalString',
],
[
'string',
'non-empty-string',
'$anotherConditionalString . $conditionalString',
],
[
Expand Down
19 changes: 19 additions & 0 deletions tests/PHPStan/Analyser/data/non-empty-string.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,22 @@ public function nonE2($glue, array $a) {
}

}

class LiteralString
{

function x(string $tableName, string $original): void {
assertType('non-empty-string', "from `$tableName`");
}

/**
* @param non-empty-string $nonEmpty
*/
function concat(string $s, string $nonEmpty): void
{
assertType('string', $s . '');
assertType('non-empty-string', $nonEmpty . '');
assertType('non-empty-string', $nonEmpty . $s);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -563,11 +563,11 @@ public function testArrayReduceCallback(): void
5,
],
[
'Parameter #2 $callback of function array_reduce expects callable(string|null, int): string|null, Closure(string, int): string given.',
'Parameter #2 $callback of function array_reduce expects callable(non-empty-string|null, int): non-empty-string|null, Closure(string, int): non-empty-string given.',
13,
],
[
'Parameter #2 $callback of function array_reduce expects callable(string|null, int): string|null, Closure(string, int): string given.',
'Parameter #2 $callback of function array_reduce expects callable(non-empty-string|null, int): non-empty-string|null, Closure(string, int): non-empty-string given.',
22,
],
]);
Expand All @@ -584,11 +584,11 @@ public function testArrayReduceArrowFunctionCallback(): void
5,
],
[
'Parameter #2 $callback of function array_reduce expects callable(string|null, int): string|null, Closure(string, int): string given.',
'Parameter #2 $callback of function array_reduce expects callable(non-empty-string|null, int): non-empty-string|null, Closure(string, int): non-empty-string given.',
11,
],
[
'Parameter #2 $callback of function array_reduce expects callable(string|null, int): string|null, Closure(string, int): string given.',
'Parameter #2 $callback of function array_reduce expects callable(non-empty-string|null, int): non-empty-string|null, Closure(string, int): non-empty-string given.',
18,
],
]);
Expand Down

0 comments on commit 1283db7

Please sign in to comment.