Skip to content

Commit

Permalink
Fixes #3. Correctly handle union type for Yii::createObject() call an…
Browse files Browse the repository at this point in the history
…d ignore it until I'll implement a support for multiple classes
  • Loading branch information
erickskrauch committed Aug 30, 2023
1 parent 7644e34 commit a157541
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 17 deletions.
19 changes: 13 additions & 6 deletions src/Rule/CreateObjectRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,28 @@ public function processNode(Node $node, Scope $scope): array {
if ($firstArgType->isConstantArray()->yes()) {
/** @var \PHPStan\Type\Constant\ConstantArrayType $config */
$config = $firstArgType->getConstantArrays()[0];
$classNameOrError = $this->configHelper->findClass($config);
if ($classNameOrError instanceof RuleError) {
return [$classNameOrError];
$classNamesOrError = $this->configHelper->findClasses($config);
if ($classNamesOrError instanceof RuleError) {
return [$classNamesOrError];
}

if (!$this->reflectionProvider->hasClass($classNameOrError)) {
// At this moment I'll skip supporting of multiple classes at once
if (count($classNamesOrError) > 1) {
return [];
}

[$className] = $classNamesOrError;

if (!$this->reflectionProvider->hasClass($className)) {
return [
RuleErrorBuilder::message(sprintf('Class %s not found.', $classNameOrError))
RuleErrorBuilder::message(sprintf('Class %s not found.', $className))
->identifier('class.notFound')
->discoveringSymbolsTip()
->build(),
];
}

$classReflection = $this->reflectionProvider->getClass($classNameOrError);
$classReflection = $this->reflectionProvider->getClass($className);

$errors = array_merge($errors, $this->configHelper->validateArray($classReflection, $config, $scope));
} elseif ($firstArgType->isClassStringType()->yes()) {
Expand Down
22 changes: 11 additions & 11 deletions src/Rule/YiiConfigHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ public function __construct(RuleLevelHelper $ruleLevelHelper) {
}

/**
* @param ConstantArrayType $config
* @return string|\PHPStan\Rules\IdentifierRuleError
* @phpstan-return non-empty-list<string>|\PHPStan\Rules\IdentifierRuleError
* @return string[]|\PHPStan\Rules\IdentifierRuleError
*/
public function findClass(ConstantArrayType $config) {
$class = $config->getOffsetValueType(new ConstantStringType('__class'));
if (count($class->getConstantStrings()) === 1) {
return $class->getConstantStrings()[0]->getValue();
}
public function findClasses(ConstantArrayType $config) {
foreach (['__class', 'class'] as $classKey) {
$class = $config->getOffsetValueType(new ConstantStringType($classKey));
$constantStrings = $class->getConstantStrings();
if (empty($constantStrings)) {
continue;
}

$class = $config->getOffsetValueType(new ConstantStringType('class'));
if (count($class->getConstantStrings()) === 1) {
return $class->getConstantStrings()[0]->getValue();
return array_map(fn($string) => $string->getValue(), $constantStrings);
}

return RuleErrorBuilder::message('Configuration params array must have "class" or "__class" key')
Expand Down Expand Up @@ -76,7 +76,7 @@ public function validateArray(ClassReflection $classReflection, ConstantArrayTyp
continue;
}

$errors = array_merge($errors, self::validateConstructorArgs($classReflection, $value->getConstantArrays()[0], $scope));
$errors = array_merge($errors, $this->validateConstructorArgs($classReflection, $value->getConstantArrays()[0], $scope));
continue;
}

Expand Down
1 change: 1 addition & 0 deletions tests/Rule/CreateObjectRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public function testRule(): void {
$this->analyse([__DIR__ . '/_data/create_object_function_arg.php'], []);
$this->analyse([__DIR__ . '/_data/create_object_classname_valid.php'], []);
$this->analyse([__DIR__ . '/_data/create_object_array_valid.php'], []);
$this->analyse([__DIR__ . '/_data/create_object_array_union_type.php'], []);
$this->analyse([__DIR__ . '/_data/create_object_classname_invalid.php'], [
['Parameter #1 stringArg of class ErickSkrauch\PHPStan\Yii2\Tests\Yii\MyComponent constructor expects string, int given.', 6],
['Parameter #2 intArg of class ErickSkrauch\PHPStan\Yii2\Tests\Yii\MyComponent constructor expects int, string given.', 6],
Expand Down
11 changes: 11 additions & 0 deletions tests/Rule/_data/create_object_array_union_type.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
declare(strict_types=1);

use ErickSkrauch\PHPStan\Yii2\Tests\Yii\Article;
use ErickSkrauch\PHPStan\Yii2\Tests\Yii\Comment;

foreach ([Article::class, Comment::class] as $className) {
Yii::createObject([
'class' => $className,
]);
}

0 comments on commit a157541

Please sign in to comment.