-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issues found by static analysis #394
Changes from all commits
ba1ed0c
cc14790
3fac4b9
b09c165
5ed9c17
b6a4914
633de24
60ac692
c33fedf
688934c
b554734
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -130,6 +130,7 @@ private function compileConstFetch(Node\Expr\ConstFetch $constNode) | |
*/ | ||
private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, CompilerContext $context) | ||
{ | ||
/** @var Node\Name $node->class */ | ||
$className = $node->class->toString(); | ||
|
||
if ($node->name === 'class') { | ||
|
@@ -148,6 +149,7 @@ private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, Compile | |
$classInfo = $context->getReflector()->reflect($className); | ||
} | ||
|
||
/** @var string $node->name */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question about compatibility: what to do here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's keep this for now |
||
$reflectionConstant = $classInfo->getReflectionConstant($node->name); | ||
|
||
return $this->__invoke( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -313,7 +313,7 @@ public function isDestructor() | |
public function getClosure($object = null) | ||
{ | ||
try { | ||
$this->betterReflectionMethod->getClosure($object); | ||
return $this->betterReflectionMethod->getClosure($object); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we never tested this - that's needed here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this needs a test addition too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test added in 74ba592 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! |
||
} catch (NoObjectProvided | NotAnObject $e) { | ||
return null; | ||
} catch (Throwable $e) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -350,7 +350,7 @@ function (ReflectionMethod $method) use ($filter) { | |
*/ | ||
public function getImmediateMethods(?int $filter = null) : array | ||
{ | ||
/** @var \ReflectionMethod[] $methods */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why removing this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it can be inferred easily There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, errata - it can be inferred, it's just that most tooling won't do recursive inferring of types, so this can't really be removed unless the ecosystem evolves There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll revert this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh this was also inaccurate, which is why I made the change in the first place (it shouldn't have the leading slash) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the pic :D I know the tool you built is doing it, but the majority still needs to catch up ;-) |
||
/** @var ReflectionMethod[] $methods */ | ||
$methods = array_map( | ||
function (ClassMethod $methodNode) : ReflectionMethod { | ||
return ReflectionMethod::createFromNode( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ class ReflectionType | |
]; | ||
|
||
/** | ||
* @var $type | ||
* @var string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
*/ | ||
private $type; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,11 +64,20 @@ public function __invoke(CoreReflectionClass $classReflection) : string | |
{ | ||
$classNode = $this->createClass($classReflection); | ||
|
||
$this->addClassModifiers($classNode, $classReflection); | ||
if ($classNode instanceof Class_) { | ||
$this->addClassModifiers($classNode, $classReflection); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can we have abstract/final interfaces or traits? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No fix needed |
||
} | ||
|
||
if ($classNode instanceof Class_ || $classNode instanceof Interface_) { | ||
$this->addExtendsAndImplements($classNode, $classReflection); | ||
} | ||
|
||
if ($classNode instanceof Class_ || $classNode instanceof Trait_) { | ||
$this->addProperties($classNode, $classReflection); | ||
$this->addTraitUse($classNode, $classReflection); | ||
} | ||
|
||
$this->addDocComment($classNode, $classReflection); | ||
$this->addExtendsAndImplements($classNode, $classReflection); | ||
$this->addTraitUse($classNode, $classReflection); | ||
$this->addProperties($classNode, $classReflection); | ||
$this->addConstants($classNode, $classReflection); | ||
$this->addMethods($classNode, $classReflection); | ||
|
||
|
@@ -106,10 +115,7 @@ private function addDocComment(BuilderAbstract $node, CoreReflector $reflection) | |
} | ||
} | ||
|
||
/** | ||
* @param Class_|Interface_|Trait_ $classNode | ||
*/ | ||
private function addClassModifiers(Declaration $classNode, CoreReflectionClass $classReflection) : void | ||
private function addClassModifiers(Class_ $classNode, CoreReflectionClass $classReflection) : void | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Traits/Interfaces can't be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No fix needed |
||
{ | ||
if (! $classReflection->isInterface() && $classReflection->isAbstract()) { | ||
// Interface \Iterator is interface and abstract | ||
|
@@ -122,7 +128,7 @@ private function addClassModifiers(Declaration $classNode, CoreReflectionClass $ | |
} | ||
|
||
/** | ||
* @param Class_|Interface_|Trait_ $classNode | ||
* @param Class_|Interface_ $classNode | ||
*/ | ||
private function addExtendsAndImplements(Declaration $classNode, CoreReflectionClass $classReflection) : void | ||
{ | ||
|
@@ -139,7 +145,7 @@ private function addExtendsAndImplements(Declaration $classNode, CoreReflectionC | |
} | ||
|
||
foreach ($interfaces as $interfaceName) { | ||
if ($classReflection->isInterface()) { | ||
if ($classNode instanceof Interface_) { | ||
$classNode->extend(new FullyQualified($interfaceName)); | ||
} else { | ||
$classNode->implement(new FullyQualified($interfaceName)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,17 +35,28 @@ public function __invoke(?Namespace_ $namespace) : Context | |
private function aliasesToFullyQualifiedNames(Namespace_ $namespace) : array | ||
{ | ||
// flatten(flatten(map(stuff))) | ||
return array_merge([], ...array_merge([], ...array_map(function ($use) : array { | ||
/** @var $use Use_|GroupUse */ | ||
return array_merge( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand what was changed here, since the alignment was changed. The operation was simply turning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems related to https://github.com/Roave/BetterReflection/pull/394/files#r164988430 - type is being inferred over implementation of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not totally related. Psalm has a Psalm doesn't project types into closures, so it's not able to infer this, but it does check the boundaries – e.g. it sees the error in class A {}
class B {}
$as = [new A(), new B()];
$classes = array_map(
function(B $a) : string {
return "hello";
},
$as
); (I don't have link generation set up, but you can always paste into getpsalm.org to verify) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
[], | ||
...array_merge( | ||
[], | ||
...array_map( | ||
/** @param Use_|GroupUse $use */ | ||
function ($use) : array { | ||
return array_map( | ||
function (UseUse $useUse) use ($use) : array { | ||
if ($use instanceof GroupUse) { | ||
return [$useUse->alias => $use->prefix->toString() . '\\' . $useUse->name->toString()]; | ||
} | ||
|
||
return array_map(function (UseUse $useUse) use ($use) : array { | ||
if ($use instanceof GroupUse) { | ||
return [$useUse->alias => $use->prefix->toString() . '\\' . $useUse->name->toString()]; | ||
} | ||
|
||
return [$useUse->alias => $useUse->name->toString()]; | ||
}, $use->uses); | ||
}, $this->classAlikeUses($namespace)))); | ||
return [$useUse->alias => $useUse->name->toString()]; | ||
}, | ||
$use->uses | ||
); | ||
}, | ||
$this->classAlikeUses($namespace) | ||
) | ||
) | ||
); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,8 @@ | |
use Roave\BetterReflection\Reflection\Adapter\Exception\NotImplemented; | ||
use Roave\BetterReflection\Reflection\Adapter\ReflectionClass as ReflectionClassAdapter; | ||
use Roave\BetterReflection\Reflection\Adapter\ReflectionMethod as ReflectionMethodAdapter; | ||
use Roave\BetterReflection\Reflection\Adapter\ReflectionParameter as ReflectionParameterAdapter; | ||
use Roave\BetterReflection\Reflection\Adapter\ReflectionType as ReflectionTypeAdapter; | ||
use Roave\BetterReflection\Reflection\Exception\NoObjectProvided; | ||
use Roave\BetterReflection\Reflection\Exception\NotAnObject; | ||
use Roave\BetterReflection\Reflection\Exception\ObjectNotInstanceOfClass; | ||
|
@@ -67,7 +69,7 @@ public function methodExpectationProvider() : array | |
['isUserDefined', null, true, []], | ||
['getClosureThis', NotImplemented::class, null, []], | ||
['getClosureScopeClass', NotImplemented::class, null, []], | ||
['getDocComment', null, '', []], | ||
['getDocComment', null, false, []], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch here 👍 |
||
['getStartLine', null, 123, []], | ||
['getEndLine', null, 123, []], | ||
['getExtension', NotImplemented::class, null, []], | ||
|
@@ -121,8 +123,25 @@ public function testAdapterMethods(string $methodName, ?string $expectedExceptio | |
$this->expectException($expectedException); | ||
} | ||
|
||
$adapter = new ReflectionMethodAdapter($reflectionStub); | ||
$adapter->{$methodName}(...$args); | ||
$adapter = new ReflectionMethodAdapter($reflectionStub); | ||
$adapterReturnValue = $adapter->{$methodName}(...$args); | ||
|
||
switch ($methodName) { | ||
case 'getParameters': | ||
$this->assertContainsOnly(ReflectionParameterAdapter::class, $adapterReturnValue); | ||
break; | ||
|
||
case 'getReturnType': | ||
$this->assertInstanceOf(ReflectionTypeAdapter::class, $adapterReturnValue); | ||
break; | ||
|
||
case 'getPrototype': | ||
$this->assertInstanceOf(ReflectionMethodAdapter::class, $adapterReturnValue); | ||
break; | ||
|
||
default: | ||
$this->assertEquals($returnValue, $adapterReturnValue); | ||
} | ||
} | ||
|
||
public function testExport() : void | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This syntax is not really compatible with most tooling out there - what should we do about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it breaks anything I'm happy to remove it, or replace with an
assert
.My hope is that the PSR-5 PHPDoc proposal is approved, and the people who make similar tools add support for this. It's a common-sense annotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also that could be fixed with a Psalm config, as it relates to behaviour of PhpParser that will never occur given how it's used in BetterReflection. vimeo/psalm#482 would fix that internally.
Anyway, using an
assert
also fixes a PHPStan error at the same location so maybe that's the way to go here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep them for now 👍