-
Notifications
You must be signed in to change notification settings - Fork 59
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
Verify method, function, property, constant and interface changes and report BC breaks #38
Conversation
…erface in `BetterReflection`
…erface in `BetterReflection`
…` for `ReflectionClass` (where applicable) to avoid passing around a `Reflector`
…ionClass` for `ReflectionClass` (where applicable) to avoid passing around a `Reflector`" This reverts commit e07a9ce.
…veraging the BetterReflection `AbstractReflectionFunction` existing API
…njected `FunctionBased` comparators
…uctor in `api-compare.php` (for now)
… an exit code of `2` (as per mutation tests)
…ntee strictness on type checks, but rather fails silently
…hout any need for that
… given or not, there is no `null`
…th completely different checks
@@ -31,7 +40,210 @@ | |||
new GetVersionCollectionFromGitRepository(), | |||
new PickLastMinorVersionFromCollection(), | |||
new Comparator( | |||
new Comparator\BackwardsCompatibility\ClassBased\PropertyRemoved() |
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.
Note: this tree of checks is quite huge, but is pretty much describing what kinds of BC breaks we want to rely upon.
If we want to make it more "friendly", I can move the instantiation to Roave\ApiCompare\ApiCompare#defaultClassChecks()
, Roave\ApiCompare\ApiCompare#defaultInterfaceChecks()
, Roave\ApiCompare\ApiCompare#defaultTraitChecks()
in a separate patch.
@asgrim this is ready for another round. Renamed few things, introduced traits checks. |
@@ -132,7 +129,7 @@ public function execute(InputInterface $input, OutputInterface $output) : int | |||
$outputFormats = $input->getOption('format') ?: []; | |||
Assert::that($outputFormats)->isArray(); | |||
|
|||
if (in_array('markdown', $outputFormats, true)) { | |||
if (ArrayHelpers::stringArrayContainsString('markdown', $outputFormats)) { |
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.
Uhh, probably a little OTT on the checking here... passing true
includes type checks anyway, so the array
passed doesn't even need to be all strings, if it matches, it matches, if not, it doesn'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.
I want to avoid colliding with various tools that say different things here:
- infection
- ea inspections
- phpstan strict checks
Segregating it out was easy peasy, so I just did it, and we have a single location where in_array()
still exists.
Yes, this is indeed overblown, but I'd be OK with this particular addition, considering that it really is the only thing needed to make mutation tests work without problems (could've been much worse).
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.
Another potential issue: contributors (me included) will likely default to just using in_array
in future contributions, that may slip through the net :/ it's a non-standard approach, which is "unexpected" and inconsistent with current ... "ways" (for want of a better word)
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 may slip through the net
Build will catch it 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.
Does the build fail with a message that indicates that ArrayHelpers::stringArrayContainsString
should be used instead? (rhetorical question: it doesn't). The point is, you're solving a problem caused by the tooling (because in_array
with strict param set to true
is fine), and the solution is not what people will expect. I understand the technical reasoning here, and it's perfectly sound logic: my concern is that when you don't know what the issue is, the solution is unexpected and unconventional. I don't have a better answer, apart from this shouldn't be a problem and that the finger points back to the tools (phpstan, in this specific case)... :s
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.
No, it won't fail with a matching error message, obviously.
the solution is not what people will expect.
Agreed, but I don't expect that to be a blocker, as a quick review can deal with most of these errors.
the solution is unexpected and unconventional.
Agreed again, as I said, the mutation testing outcome was much better than expected, so I'm quite happy with having this deviation from the standard compared to what it could have been if we had much more mutations.
apart from this shouldn't be a problem and that the finger points back to the tools (phpstan, in this specific case)...
Possible, but I don't think that should become a blocker for just a workaround in here. Assuming that we fix phpstan there, we can really just revert this addition (API is marked @internal
anyway) and that's the end of the story :-P
src/Comparator.php
Outdated
@@ -19,12 +20,17 @@ class Comparator | |||
/** @var InterfaceBased */ | |||
private $interfaceBasedComparisons; | |||
|
|||
/** @var TraitBased */ | |||
private $traitBasedComparisons; |
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.
Wish we'd added traits as a different PR :s this PR is getting way too big, stuff is gonna get missed
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 - did it mostly due to time constraints on my end, as I was in a hurry/constantly on the road yesterday.
@@ -21,7 +21,8 @@ | |||
"phpunit/phpunit": "^7.0", | |||
"doctrine/coding-standard": "^4.0", | |||
"squizlabs/php_codesniffer": "^3.2", | |||
"phpstan/phpstan": "^0.9.2" | |||
"phpstan/phpstan": "^0.9.2", | |||
"infection/infection": "^0.8.1" |
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 infection/infection
could've been a separate 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.
Same as #38 (comment) - indeed creeped in too much
{ | ||
public function compare(ReflectionClass $fromClass, ReflectionClass $toClass) : Changes | ||
{ | ||
Assert::that($fromClass->getName())->same($toClass->getName()); |
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.
Is this not an assumption that's made everywhere anyway...? i.e. afaik, we don't detect git renames
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.
Aye, should probably drop these assertions from all ClassBased
checks
return Changes::fromArray([Change::changed( | ||
sprintf('Class %s became a trait', $fromClass->getName()), | ||
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.
Alignment looks wonky here?
/** | ||
* According to the current state of the PHP ecosystem, we only have traits, interfaces and classes | ||
*/ | ||
private function isClass(ReflectionClass $class) : bool |
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.
Does ReflectionClass
really not have an isClass
method... seems like an oversight >.<
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 have one, no. That's because we mimicked the existing ext-reflection
API, without designing our own API from scratch upfront.
return Changes::fromArray([Change::changed( | ||
sprintf('Interface %s became a trait', $fromClass->getName()), | ||
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.
Something weird causing these alignment issues in phpcs I expect...
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.
Verified this: it's an issue in one of the sniffs.
Basically, single-value array should be on a single line, but then the value turns out to be multi-line here. Trying to fix it leads to a phpcs violation being reported, so I'll keep these wonky ones as they are here, and talk to the doctrine folks about it.
} | ||
|
||
return Changes::fromArray([Change::changed( | ||
sprintf('Interface %s became a class', $fromTrait->getName()), |
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.
Trait %s became a class
} | ||
|
||
return Changes::fromArray([Change::changed( | ||
sprintf('Interface %s became an interface', $fromTrait->getName()), |
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.
Trait %s became an interface
*/ | ||
public static function stringArrayContainsString(string $value, array $arrayOfStrings) : bool | ||
{ | ||
Assert::that($arrayOfStrings)->all()->string(); |
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.
Really not sure we need this... seems to just be avoiding false positives; don't know specifically what mutations phpstan performs, but adding an integer onto this array shouldn't be a problem if the expected value is still in there (because we (were) using "strict" mode)... Think this conversation should be moved to a discussion upstream in phpstan, not solved with a wrapper IMO
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.
See #38 (comment) for reasoning for this class first.
As for the assertion:
seems to just be avoiding false positives;
We use the in_array()
-ish check mostly where reflection returns something to us. As PHP has no way to check type invariants on array values, having a type assertion is still probably a good idea. Can drop it, of course.
@asgrim feedback incorporated into the patch, but I'll keep the |
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
Fixes #7
Fixes #8
Fixes #9
Fixes #10
Fixes #11
Fixes #12
Fixes #41
Fixes #43
Fixes #46
ReflectionType
API so that a target reflection class can directly be retrieved, removed existing named constructor BetterReflection#415