Skip to content

Commit

Permalink
Handle more PHPStan type edge-cases (#487)
Browse files Browse the repository at this point in the history
  • Loading branch information
shish authored Dec 2, 2024
1 parent 078219f commit a6a57ba
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 17 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ jobs:
- name: "Run static code analysis with phpstan/phpstan in generator/ directory"
run: "composer phpstan"
working-directory: "generator"
- name: "Run static code analysis with rector/rector in generator/ directory"
run: "composer rector --dry-run"
working-directory: "generator"

generated_tests:
name: "Generated Tests"
Expand Down
4 changes: 2 additions & 2 deletions generator/src/GenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ private function runCsFix(OutputInterface $output): void
$process->setTimeout(600);
$process->run(function ($type, $buffer) use ($output) {
if (Process::ERR === $type) {
echo $output->write('<error>'.$buffer.'</error>');
$output->write('<error>'.$buffer.'</error>');
} else {
echo $output->write($buffer);
$output->write($buffer);
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion generator/src/Method.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ private function removeString(string $string, string $search): string
private function getStringForXPath(string $xpath): string
{
$paragraphs = $this->rootEntity->xpath($xpath);
if ($paragraphs === false) {
if ($paragraphs === false || $paragraphs === null) {
throw new \RuntimeException('Error while performing Xpath request.');
}
$str = '';
Expand Down
42 changes: 32 additions & 10 deletions generator/src/PhpStanFunctions/PhpStanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,29 +59,49 @@ public function __construct(string $data, bool $writeOnly = false)
/** @var int $count */
$count = \count($returnTypes);
if ($count === 0) {
throw new \RuntimeException('Error when trying to extract parameter type');
$returnType = '';
}
foreach ($returnTypes as &$returnType) {
$pos = \strpos($returnType, '?');
if ($pos !== false) {
$nullable = true;
$returnType = \str_replace('?', '', $returnType);
}
//remove the parenthesis only if we are not dealing with a callable
if (\strpos($returnType, 'callable') === false) {
// remove the parenthesis only if we are not dealing with a callable
if (!str_contains($returnType, 'callable')) {
$returnType = \str_replace(['(', ')'], '', $returnType);
}
//here we deal with some weird phpstan typings
if ($returnType === 'non-empty-string') {

// here we deal with some weird phpstan typings
if (str_contains($returnType, 'non-falsy-string')) {
$returnType = 'string';
} elseif ($returnType === 'positive-int') {
}

if (str_contains($returnType, 'non-empty-string')) {
$returnType = 'string';
}

if (str_contains($returnType, '__stringAndStringable')) {
$returnType = 'string';
}

if ($returnType === 'positive-int') {
$returnType = 'int';
} elseif (is_numeric($returnType)) {
$returnType = 'int';
}
if (\strpos($returnType, 'list<') !== false) {
if (str_contains($returnType, 'list<')) {
$returnType = \str_replace('list', 'array', $returnType);
}

if (str_contains($returnType, 'int<')) {
$returnType = 'int';
}

if (\preg_match('/__benevolent\<(.*)\>/', $returnType, $regs)) {
$returnType = $regs[1];
}

$returnType = Type::toRootNamespace($returnType);
}
$this->types = array_unique($returnTypes);
Expand Down Expand Up @@ -114,7 +134,7 @@ public function getSignatureType(?int $errorType = null): string
$falsable = $errorType === Method::FALSY_TYPE ? false : $this->falsable;
$types = $this->types;
//no typehint exists for thoses cases
if (\array_intersect(self::NO_SIGNATURE_TYPES, $types)) {
if (\array_intersect(self::NO_SIGNATURE_TYPES, $types) !== []) {
return '';
}

Expand All @@ -135,12 +155,14 @@ public function getSignatureType(?int $errorType = null): string
//if there are several distinct types, no typehint (we use distinct in case doc block contains several times the same type, for example array<int>|array<string>)
if (count(array_unique($types)) > 1) {
return '';
} elseif (\in_array('void', $types) || (count($types) === 0 && !$nullable && !$falsable)) {
}

if (\in_array('void', $types) || ($types === [] && !$nullable && !$falsable)) {
return 'void';
}


$finalType = $types[0];
$finalType = $types[0] ?? '';
if ($finalType === 'bool' && !$nullable && $errorType === Method::FALSY_TYPE) {
// If the function only returns a boolean, since false is for error, true is for success.
// Let's replace this with a "void".
Expand Down
6 changes: 5 additions & 1 deletion generator/tests/PhpStanFunctions/PhpStanTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ public function testVoid(): void
{
$param = new PhpStanType('');
$this->assertEquals('', $param->getDocBlockType());
$this->assertEquals('', $param->getSignatureType());
if (PHP_VERSION_ID >= 80200) {
$this->assertEquals('void', $param->getSignatureType());
} else {
$this->assertEquals('', $param->getSignatureType());
}

$param = new PhpStanType('void');
$this->assertEquals('void', $param->getDocBlockType());
Expand Down

0 comments on commit a6a57ba

Please sign in to comment.