-
-
Notifications
You must be signed in to change notification settings - Fork 50
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
Scrutinizer fixes #76
Conversation
src/ReflectionMethod.php
Outdated
@@ -81,6 +81,7 @@ public function ___debugInfo() | |||
public function __toString() | |||
{ | |||
$hasReturnType = $this->hasReturnType(); | |||
$returnType = $hasReturnType ? $this->getReturnType() : NULL; |
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.
TRUE, FALSE and NULL must be lowercase; expected null
but found NULL
$classToReflect = $node->class; | ||
if ($classToReflect instanceof Expr) { | ||
$refClass = $this->resolve($classToReflect); | ||
} |
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.
Expected 1 space after closing brace; newline found
src/bootstrap.php
Outdated
class ReflectionType {} | ||
} | ||
|
||
require (__DIR__ . '/polyfill.php'); |
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.
Space before opening parenthesis of function call prohibited
src/polyfill.php
Outdated
* versions of PHP, (i.e. PHP < 7). | ||
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
class ReflectionType { |
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.
- Each class must be in a namespace of at least one level (a top-level vendor name)
- Opening brace of a class must be on the line after the definition
src/polyfill.php
Outdated
class ReflectionType { | ||
public function allowsNull() | ||
{ | ||
return TRUE; |
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.
TRUE, FALSE and NULL must be lowercase; expected true
but found TRUE
Isn't that too much? I mean changes made are protection code added for theoretical misuse cases of the library that never happen in reality. Placing protection code only suggests that bad thing are expected to happen. |
src/polyfill.php
Outdated
* versions of PHP, (i.e. PHP < 7). | ||
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
class ReflectionType |
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.
Each class must be in a namespace of at least one level (a top-level vendor name)
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 obviously a non-issue for a polyfill class.
@aik099, My intent was really just good code hygiene. I certainly didn't want to impact performance. For several of the string argument checking, perhaps a docblock annotation is a better resolution? These are the results of Scrutinizer's updated report: https://scrutinizer-ci.com/g/goaop/parser-reflection/inspections/eaf283f6-f982-44a4-bb28-51489bcba537/issues/ Update: I checked the code, and the string arguments that are being type verified are already properly annotated as strings. :-( Update2: I noticed that this reduced code coverage by about 0.8%. I need to add some tests to compensate. I'll have to address this in the morning. |
Ok... Update3: I'm working on improving test coverage, but it's a bit more drastic than I hoped, so I have decided to put it in another PR that I will submit later. @lisachenko , @aik099 can you give this a look, and let me know what you think, as it stands right now? @aik099 pointed out that there is some code that somewhat dubiously bullet proofs agains (hopefully) impossible cases, but the goal was to increase the signal-to-noise ratio in the Scrutinizer report, so it's easier to spot real issues when they arise. Additionally, someone with project write-access should also disable the issues that were intentional violations. (For instance, the None of this is anything earth-shattering. It is intended to help keep the project clean and contributor-friendly. I welcome hearing any reason these changes should not be merged in. My intent was merely to help out. An aside: I mentioned several improvements I've made to this project (and Codeception/AspectMock) for a former employer that I wanted to share. I am no longer with this company, and they have declined any interest in contributing these in the foreseeable future, despite my urging. They did mention they may be willing to release these for a fee. No amount was discussed, but I suggested a hypothetical future employer of mine might want to pay "a few grand" (that's a few $1000 USD to non-native speakers) for such changes, that could save them several months of my salary to reproduce such features. I have no idea how receptive to this idea this company still is, but if any of you want to raise some funds for this, I can help you get in touch with those in a position to discuss releasing those changes. Anyway, I hope you find this PR helpful. |
@loren-osborn , can you list the changes included in there, so that we'll know what's coming? |
Getting higher score on Scrutinizer CI won't be something worth reaching 😉 It's known for some weird rating calculating logic where some good classes are getting small ratings and attempt to fix rating results in making classes worse. In my projects I'm reviewing each of the errors and decide if that is even worth fixing or I can simply ignore that. Not sure if ignoring errors would improve my rating though. 😄 |
By the way I wonder why Scrutinizer CI isn't posting it's build status for this PR. Maybe this feature needs to be enabled manually. |
class ReflectionType {} | ||
} | ||
|
||
require(__DIR__ . '/polyfill.php'); |
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.
It's a fix for https://scrutinizer-ci.com/g/goaop/parser-reflection/inspections/eaf283f6-f982-44a4-bb28-51489bcba537/issues/files/src/bootstrap.php?status=fixed&orderField=path&order=asc&honorSelectedPaths=0 , but I'm not sure it's worth it. Better to reduce file operation count (the require
in this case).
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.
Hmm... I think this is a case of minor improvement in PSR-1 compliance for 1 extra small file load once, during execution. I think it's a worthwhile cost... and I think having Polyfills in a file called polyfill.php helps people know where to find them.
src/ReflectionMethod.php
Outdated
@@ -81,6 +81,7 @@ public function ___debugInfo() | |||
public function __toString() | |||
{ | |||
$hasReturnType = $this->hasReturnType(); | |||
$returnType = $hasReturnType ? $this->getReturnType() : null; |
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.
The $hasReturnType ? $this->getReturnType() : null;
can be replaced with just $this->getReturnType();
, because internally hasReturnType
method is calling getReturnType
and checking result via isset
.
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.
Good catch 👍
@@ -114,7 +115,7 @@ public function __toString() | |||
$this->getEndLine(), | |||
count($methodParameters), | |||
$paramString, | |||
$hasReturnType ? ReflectionType::convertToDisplayType($this->getReturnType()) : '' | |||
$returnType ? ReflectionType::convertToDisplayType($returnType) : '' |
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.
👍 , but also add tests (or post a link in comment if test exists already), that would verify atleast 2 cases:
- the return type was
null
and wasn't present in output - the return type was
ReflectionType
object and it's string representation was shown in output
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.
Ok... Good point on adding tests. As I said, needing to untangle a branch first, but: Note to self... Implement/find relevant test cases. 👍
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.
Ok... I confirmed that both cases are tested... (I did not flag the specific tests, but they're easy to find.) When $returnType
is null
the empty string value isn't used, but it prevents the convertToDisplayType()
static method call that would be illegal with a null
parameter. I am replacing the empty string with a string explaining its purpose.
@@ -85,14 +85,14 @@ public static function convertToDisplayType(\ReflectionType $type) | |||
'int' => 'integer', | |||
'bool' => 'boolean' | |||
]; | |||
$displayType = $type->type; | |||
$displayType = (string)$type; |
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.
👍 , but a test is needed (or post link to existing test), that would make a call to convertToDisplayType
method with:
- native
ReflectionType
class object - with library's own
ReflectionType
object, that hastype
property
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.
As above... add tests 👍
src/ReflectionType.php
Outdated
if (isset($typeMap[$displayType])) { | ||
$displayType = $typeMap[$displayType]; | ||
} | ||
|
||
$displayType = ltrim($displayType, '\\'); | ||
|
||
if ($type->allowsNull()) { | ||
if (method_exists($type, 'allowsNull') && $type->allowsNull()) { |
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.
Please return the original code, because Scrutinizer CI issue in https://scrutinizer-ci.com/g/goaop/parser-reflection/inspections/eaf283f6-f982-44a4-bb28-51489bcba537/issues/files/src/ReflectionType.php?status=fixed&orderField=path&order=asc&honorSelectedPaths=0 likely is reported because they're using incorrect PHP stubs for class method signature resolution. On the PHP docs (see http://php.net/manual/en/reflectiontype.allowsnull.php) there is allowsNull
method and it always was there (as in out ReflectionType
class polyfill).
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.
Hmm... I agree that I should revert this code, but for a different reason. I think this is catching the class definition from the polyfill, which had no $this->allowsNull()
method. I actually added a dummy $this->allowsNull()
method to my polly fill, so this should no longer be an issue. I don't particularly like the dummy method in the polyfill, but I think it's the best solution currently. Either way, this code should no longer be necessary. Thanks for pointing this out. 👍
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.
I think this is catching the class definition from the polyfill, which had no $this->allowsNull() method.
Then I think you need to add stubs in the polyfill class for all 3 methods: http://php.net/manual/en/class.reflectiontype.php
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.
Fair enough! :-) 👍
@@ -175,12 +175,12 @@ protected function resolveScalarMagicConstNamespace() | |||
protected function resolveScalarMagicConstClass() | |||
{ | |||
if ($this->context instanceof \ReflectionClass) { | |||
return $this->context->getName(); | |||
return $this->context->name; |
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.
Looks good.
} | ||
if (method_exists($this->context, 'getDeclaringClass')) { | ||
$declaringClass = $this->context->getDeclaringClass(); | ||
if ($declaringClass instanceof \ReflectionClass) { | ||
return $declaringClass->getName(); | ||
return $declaringClass->name; |
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.
Looks good.
@@ -213,7 +213,7 @@ protected function resolveScalarMagicConstLine(MagicConst\Line $node) | |||
protected function resolveScalarMagicConstTrait() | |||
{ | |||
if ($this->context instanceof \ReflectionClass && $this->context->isTrait()) { | |||
return $this->context->getName(); | |||
return $this->context->name; |
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.
Looks good.
$isFQNConstant = $node->name instanceof Node\Name\FullyQualified; | ||
$constantName = $node->name->toString(); | ||
|
||
if (!$isFQNConstant) { | ||
if (method_exists($this->context, 'getFileName')) { | ||
$fileName = $this->context->getFileName(); | ||
$namespaceName = $this->resolveScalarMagicConstNamespace(); | ||
/** @var ReflectionFileNamespace $fileNamespace */ |
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.
You can safely remove this, because IDE can detect type from new ...
construct by itself 😉
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.
Agreed... This comment just "came along for the ride" when I moved the variable's initialization.
@@ -256,7 +255,12 @@ protected function resolveExprConstFetch(Expr\ConstFetch $node) | |||
|
|||
protected function resolveExprClassConstFetch(Expr\ClassConstFetch $node) | |||
{ | |||
$refClass = $this->fetchReflectionClass($node->class); | |||
$classToReflect = $node->class; |
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.
Doesn't seem to be related to Scrutinizer CI reported problems. Maybe belongs to separate PR with a description.
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.
I'm not sure why this issue isn't showing up for you, nor why I can't find links to individual Scrutinizer issues, but this is to address the Scrutinizer issue reported for this line that reads:
Bug introduced 11 months ago by @lisachenkoIt seems like$node->class
can also be of typeobject<PhpParser\Node\Expr>
; however,Go\ParserReflection\Valu...:fetchReflectionClass()
does only seem to acceptobject<PhpParser\Node\Name>
, maybe add an additional type check?
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.
Interesting. So class constant can be an expression. Seem to addition in PHP syntax, that PHP-Parser now supports. In either cases a test for that is needed too.
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.
Yes, I know you can do a constant fetch from a class name stored in a variable. I'm unsure what other Expr
s are valid. I believe ParserReflection uses this mostly for evaluating constants, so this might not be a valid code path as we are using it, but it is a valid value for $node->class
in some circumstances.
As far as adding corresponding test cases, I agree, but I was lumping my test changes into a separate PR. (I'm shooting for 100% code coverage, but I've always been a cockeyed optimist.) I can add these tests to this PR after I've untangled my current repo branches. (I don't really want to do a stash right now.)
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.
Yes, I know you can do a constant fetch from a class name stored in a variable. I'm unsure what other Exprs are valid.
I've meant Example #4 Constant expression example
from http://php.net/manual/en/language.oop5.constants.php page:
const ONE = 1;
class foo {
// As of PHP 5.6.0
const TWO = ONE * 2;
const THREE = ONE + self::TWO;
const SENTENCE = 'The value of THREE is '.self::THREE;
}
This way you can create test for that kind of syntax.
As far as adding corresponding test cases, I agree, but I was lumping my test changes into a separate PR.
The tests for changed code needs to come as part of PR, where that code is changed. Later you can send another PR for improving code coverage.
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.
I agree we need to test for this case, but it isn't demonstrated in the example above. It would be something like this, which I'm doubting is valid PHP:
const LEFT = 'Foo';
const RIGHT = 'Bar';
class FooBar {
const FILENAME = 'baz.php';
}
require((LEFT . RIGHT)::FILENAME);
Like I said... I'm unsure if this is valid PHP, but I think, given that PhpParser accepts an expression, and we need something that can evaluate at compile time, something like this would be a valid test, even if not legal PHP currently.
Opinions?
Thumbing up to remind myself to add test cases. 👍
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.
Anything that would force PHP-Parser to create Expr
class would do. Code won't be ever evaluated by PHP itself and only needs to be syntactically valid.
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.
Just for reference: Variation of above sample code on 3v4l.org
@loren-osborn , review completed with outcome: don't trust Scrutinizer CI proposed fixes blindly 😉 |
* | ||
* @param Node[] $nodes Array of nodes | ||
* | ||
* @return null|Node[] Array of nodes |
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 really a failed attempt to fix a false-positive in Scrutinizer. I merely copied the original function docblock from PhpParser. The issue is that Scrutinizer is letting the less specific type hint array
take precedence over the compatible and more specific @param Node[]
, and saying that array
does not satisfy the specification @return null|Node[]
. I expect this change should actually be reverted, but I didn't want to do so without feedback.
As far as the false-positive, I'm trying to notify Scrutinizer about it, but haven't gotten any confirmation yet.
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.
Thumbing myself up purely so I remember to revert this change: 👍
@aik099, I'm sorry that I'm attacking this code review a bit piecemeal. I will push a new commit when I'm finished... In the meantime:
I actually posted a link to this above. Please let me know if this isn't valid: Scrutinizer-CI issue report for PR #76 |
Perfectly fine. I was thinking about proper integration with GitHub where PR build status would fail if issues are found by Scrutinizer CI. |
Hi! |
So, guys, is this ready for merge? |
@lisachenko, thanks, but not ready to merge yet... I've only gone through two-thirds of @aik099's code review. I still need to make suggested changes to PR. When the PR is would you like these squashed into a single commit? |
This (squash) will be done automatically during the merge, no need to squash it before. |
Your response is needed about inlining |
@aik099, @lisachenko, I'm not opposed to inlining the whole trait, if that's the direction we deem appropriate, but I was only suggesting adding a single protected method to |
@loren-osborn , you seem to have closed this PR by mistake. This usually happens when you rename a branch and push changes. |
Gyus! ) Stop blaming PR and let's move to the merge part, it's impossible to do everything just in one single PR. @aik099 I think we should review only critical parts, all imrovements in docs, tests and code style should be accepted. |
src/ReflectionFileNamespace.php
Outdated
if (!is_string($fileName)) { | ||
throw new \InvalidArgumentException(sprintf( | ||
'$fileName must be a string, but a %s was passed', | ||
gettype($fileName))); |
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.
- Multi-line function call not indented correctly; expected 12 spaces but found 16
- Closing parenthesis of a multi-line function call must be on a line by itself
src/ReflectionMethod.php
Outdated
join(' ', \Reflection::getModifierNames($this->getModifiers() & 1792)), | ||
join(' ', \Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE))), |
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.
- Multi-line function call not indented correctly; expected 12 spaces but found 16
- Closing parenthesis of a multi-line function call must be on a line by itself
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
/* Dummy polyfill class */ | ||
class ReflectionType |
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.
Each class must be in a namespace of at least one level (a top-level vendor name)
src/ReflectionMethod.php
Outdated
' ', | ||
\Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE) |
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.
Multi-line function call not indented correctly; expected 20 spaces but found 24
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
/* Dummy polyfill class */ | ||
class ReflectionType |
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.
Each class must be in a namespace of at least one level (a top-level vendor name)
@aik099, @lisachenko, I hope this is closer to what you were hoping for: I left the filename string argument type check in place because scrutinizer had been complaining about them, but added tests for these cases. (Like I said, even though @aik099 didn't notice these until later, they were in the PR from the beginning.) If you both agree I should back these out, I'm perfectly willing to. I also added two more test files, as the cases I was trying to cover didn't seem to fit any of the existing files. I believe the PR is ready for a second review. @lisachenko, can you weigh in on the filename type checking? Thanks to both of you. |
src/ReflectionMethod.php
Outdated
$hasReturnType ? ReflectionType::convertToDisplayType($this->getReturnType()) : '' | ||
( $returnType ? | ||
ReflectionType::convertToDisplayType($returnType) : | ||
'UNUSED: Prevents convertToDisplayType() being called.') |
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.
😄 , what is that? Are you sure code is never executed under normal conditions?
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.
Ok, I guess my "not quite a comment" explanatory string was unclear. When $returnType
is non-null, this is definitely used. When $returnType
is null
, however, the '%s'
substring that includes this in sprintf()
's return value, isn't included in the format string. If you can think of a clearer way to say this, I welcome suggestions.
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 UNUSED: Prevents convertToDisplayType() being called.
text isn't actually displayed anywhere, then it doesn't make sense to write it.
If it's displayed, but same text isn't displayed in built-in reflection api, then this won't be compatible.
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.
It is indeed not displayed. I can easily change it back to the empty string. I'm trying to decide if I need a comment there to replace it.
I admit that from a clarity standpoint, I don't like the way this function reads, but I think anything but an empty string probably just muddies the water. @aik099, what do you think?
src/ReflectionMethod.php
Outdated
' ', | ||
\Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE) |
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.
I guess this more expressive form of same thing? I wonder why you've added this in this PR?
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.
Yeh... probably less relevant to this PR, but I generally hate non-expressive "magic numbers", and I can across this one while working on this PR. It probably doesn't belong, but I felt like it made the code clearer.
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.
OK, let's keep it then.
src/ReflectionMethod.php
Outdated
@@ -80,7 +80,8 @@ public function ___debugInfo() | |||
*/ | |||
public function __toString() | |||
{ | |||
$hasReturnType = $this->hasReturnType(); | |||
$returnType = $this->getReturnType(); | |||
$hasReturnType = ($returnType !== null); // Internally same as: $this->hasReturnType(); |
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.
Not sure, that comment is needed.
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.
It came up in our discussion, and it wasn't obvious to me, so I added the comment.
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.
I thought that you will change
$hasReturnType = ($returnType !== null); // Internally same as: $this->hasReturnType();
into
$hasReturnType = $returnType !== null;
but you haven't.
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.
Adding the parentheses was inadvertent and I'll remove them, but I do think the comment is helpful. It's an explanation why we aren't calling hasReturnType()
. @lisachenko seems to be deferring to you on this PR, so it's your call, but I think the comment has value.
if you disagree, I'll remove it; or if you prefer, I can put the comment on it's own line.
Update: To expedite things, I'll give you some unambiguous options ordered by my personal preference:
- Put the comment on its own line:
// Internally $this->getReturnType() !== null same as $this->hasReturnType()
$returnType = $this->getReturnType();
$hasReturnType = $returnType !== null;
- Just remove the parenthesis:
$returnType = $this->getReturnType();
$hasReturnType = $returnType !== null; // Internally same as: $this->hasReturnType();
- Strip the comment:
$returnType = $this->getReturnType();
$hasReturnType = $returnType !== null;
tests/ReflectionTypeTest.php
Outdated
public function testTypeConvertToDisplayTypeWithNullableNativeType() | ||
{ | ||
if (PHP_VERSION_ID < 70100) { | ||
$this->markTestIncomplete('PHP >= 7.1 implements Nullable types'); |
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 PHP 7.1+ implements nullable types, then test must be marked as skipped on other PHP versions, not an incomplete one.
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.
Agreed. My mistake. 👍
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.
PHP 7.1+ implements explicit nullable types. I was considering including a 7.0+ test for implicit nullable types. It doesn't test a distinct code path, at least not in the code I was operating on here. Do you think I should add this test?
(By "implicit nullable types", I'm referring to parameters with class name type hints that default to null
. I believe PHP 7.0+ is supposed to report those as isNullable()
. I will double check this.)
tests/ReflectionTypeTest.php
Outdated
public function testTypeConvertToDisplayTypeWithNativeType() | ||
{ | ||
if (PHP_VERSION_ID < 70000) { | ||
$this->markTestIncomplete('PHP >= 7.0 implements ReflectionType'); |
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 PHP 7.0+ implements ReflectionType
, then test must be marked as skipped on other PHP versions, not an incomplete one.
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.
Noted. I'll fix this. 👍
Just so you're aware, my laptop (which is my primary computer) is on the fritz so this may delay additional commits right now. |
src/ReflectionMethod.php
Outdated
' ', | ||
\Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE) |
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.
Multi-line function call not indented correctly; expected 20 spaces but found 24
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.
Any way so solve this CS issue?
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 I read the issue correctly, @Nitpick-CI wants $this->getModifiers()
intended the same as (self::IS_PUBLIC
which I was concerned may be easily mistaken as a second argument to getModifierNames()
. Despite not liking overly long lines, I think getting rid of the line break is the best option.
As above, unambiguous options in my personal order of preference:
- Remove the newline:
join(
' ',
\Reflection::getModifierNames(
$this->getModifiers() & (self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE)
)
),
- Square up the two lines:
join(
' ',
\Reflection::getModifierNames(
$this->getModifiers() &
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE)
)
),
- Leave them as-is:
join(
' ',
\Reflection::getModifierNames(
$this->getModifiers() &
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE)
)
),
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
/* Dummy polyfill class */ | ||
class ReflectionType |
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.
Each class must be in a namespace of at least one level (a top-level vendor name)
I changed the explicit compatibility checks to PHPUnit @aik099, @lisachenko, Any other changes you want me to make before merging this in? |
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.
Hopefully this is last review on this long running PR.
@@ -83,6 +83,9 @@ class ReflectionFileNamespace | |||
*/ | |||
public function __construct($fileName, $namespaceName, Namespace_ $namespaceNode = null) | |||
{ | |||
if (!is_string($fileName)) { |
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.
What is the 3rd place, can you post a link to that code line? If total call count in that 3rd place is much smaller than sum of other 2 places, then from performance point it would be better to type cast before calling this method instead of checking in constructor.
Same is valid for other similar place.
src/ReflectionMethod.php
Outdated
@@ -80,7 +80,8 @@ public function ___debugInfo() | |||
*/ | |||
public function __toString() | |||
{ | |||
$hasReturnType = $this->hasReturnType(); | |||
$returnType = $this->getReturnType(); | |||
$hasReturnType = ($returnType !== null); // Internally same as: $this->hasReturnType(); |
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.
I thought that you will change
$hasReturnType = ($returnType !== null); // Internally same as: $this->hasReturnType();
into
$hasReturnType = $returnType !== null;
but you haven't.
src/ReflectionMethod.php
Outdated
' ', | ||
\Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE) |
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.
OK, let's keep it then.
src/ReflectionMethod.php
Outdated
' ', | ||
\Reflection::getModifierNames( | ||
$this->getModifiers() & | ||
(self::IS_PUBLIC | self::IS_PROTECTED | self::IS_PRIVATE) |
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.
Any way so solve this CS issue?
src/ReflectionMethod.php
Outdated
$this->getName(), | ||
$this->getFileName(), | ||
$this->getStartLine(), | ||
$this->getEndLine(), | ||
count($methodParameters), | ||
$paramString, | ||
$hasReturnType ? ReflectionType::convertToDisplayType($this->getReturnType()) : '' | ||
($returnType ? ReflectionType::convertToDisplayType($returnType) : '') |
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.
Parenthesis around construct aren't required.
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.
That's fine... you want me to ditch the parenthesis? Can do...
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.
Yes, please.
src/ReflectionType.php
Outdated
@@ -85,7 +85,7 @@ public static function convertToDisplayType(\ReflectionType $type) | |||
'int' => 'integer', | |||
'bool' => 'boolean' | |||
]; | |||
$displayType = $type->type; | |||
$displayType = (string) $type; |
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.
Are you sure, that according to coding standard there should be space between type name and variable?
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.
I don't like the way it looks either... it's what Scrutinizer was suggesting. I'm happy to loose the ugly space. It's your call.
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.
Please locate other type cast operators in the code (not added by you) and see which style is used most. Then use most used style.
@aik099, Thanks for the review. I'm ready to accept whatever changes you think are best. Just give me your final decisions on the following few alternatives: (I'm including my understanding of your current perference in parenthases.)
While I hope I've been able to change your mind about the Thanks again for all the time and attention to detail. |
Nope. Please see #76 (comment) for actual idea.
Actually keeping. After pondering on this for a while I think comment here will help others to understand code better.
Whatever solves CS issue. I like the change in general.
Please locate other type cast operators in the code (not added by you) and see which style is used most. Then use most used style. I hope my responses would allow you to make final changes to the PR. |
@aik099, I'm rather confused. I'm happy to add explicit type casts to the three places Thanks |
Would you believe that the project's type casts were split 50/50? 2 had whitespace after the cast, and 2 didn't... Made them all consistant.
*/ | ||
if (!class_exists(ReflectionType::class, false)) { | ||
/* Dummy polyfill class */ | ||
class ReflectionType |
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.
Each class must be in a namespace of at least one level (a top-level vendor name)
The inspection completed: 1 new issues, 9 updated code elements |
@aik099, would you believe the whitespace after cast operators were split 50-50? There were only 4 casts total, so I made them all consistent by removing the whitespace from 2 existing casts. Everything else is what we discussed. Thanks again. |
Merging, thanks @loren-osborn . |
@aik099, Thanks again for all your hard work on this PR.
I never did see any reaction from you to this list of changes. I any of us is likely to be willing (or in my case able right now) to pay for these by themselves, but:
Perhaps someone could setup a GoFundMe page for this? (I suspect I would likely be the wrong person to do this. I don't want to rub anyone at my previous contract employer the wrong way.) What are your thoughts? |
You can create each of mentioned improvements as an issue (lots of small manageable issues) and then anybody who is interested can express that interest. I haven't personally encountered any of fixed issues or a need to described improvements.
If there is a platform for funding such type of work (e.g. KickStarter), then why not. I have no experience with cases like this (when former employer doesn't want to opensource changes for free).
Time is not an issue here. If you report the issues/features as separate tasks, then you can eventually solve them. |
@aik099, as was mentioned already, many of the improvements already have open issues for this project. Oh, one other cool feature I didn't include in the above list (which is really more part of ApectMock, but I feel still relevant here) is ability to capture and intercept some custom autoloaders, overriding their |
Fixing issues, reported by Scrutinizer CI 1. most of issues addressed 2. normalized typecast operator look 3. replaced magic numbers with PHP constants 4. added parameter type checks for `ReflectionFile` and `ReflectionFileNamespace` classes
This PR addresses most of the issues highlighted by the Scrutinizer code analysis tool this package is already coupled to.