Skip to content

Case insensitive method names #99

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

Merged
merged 25 commits into from
Feb 22, 2018

Conversation

emmetog
Copy link
Contributor

@emmetog emmetog commented Feb 12, 2018

Description:

This is a resurrection of #96 with the same outcome but a different implementation. In #96 we added logic to the ClassMethodAnalyzer, in this PR things are a lot cleaner.

The end goal is to trigger case-changes in method names (which PHP ignores) as a PATCH change.

Features:

  • Lots of tests
  • Added .editorconfig file to ensure coding standards are consistent across library (use tabs)

Still to do:

  • Allow case changes in Class names
  • Allow case changes in Interface names
  • Allow case changes in Trait names
  • Allow case changes in Method & Function names

@@ -121,6 +121,9 @@ class LevelMapping
'V115' => Level::MAJOR,
'V116' => Level::MAJOR,
'V117' => Level::MAJOR,
'V150' => Level::PATCH,
'V151' => Level::PATCH,
'V152' => Level::PATCH,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the extract-rules-from-ruleset.php script to generate this entire list.

@emmetog
Copy link
Contributor Author

emmetog commented Feb 12, 2018

@tomzx am I on the right track with this PR?

I haven't yet checked to see if this works for traits, interfaces and function names, I'll do this soon.

use PhpParser\Node\Stmt\Class_;
use PHPSemVerChecker\Node\Statement\Class_ as PClass;

class ClassRenamedCaseOnly extends Operation {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tomzx should this extend from a new class called ClassOperationDelta or ClassOperationUnary or something similar?

Right now the constructor for ClassRenamedCaseOnly is public function __construct($fileAfter, Class_ $classAfter), is this correct?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, all of the operations should extend either the unary of delta variant. But this means it would require the creation of these classes for class, trait, interface as well. I guess this can be done later on in a refactoring pass.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just pushed @ 7944fd1 which creates said classes.

Copy link
Owner

@tomzx tomzx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rename shouldn't be used as the name stays the same, only the casing changes. I'm saying that because it might happen in the future that we want to track name change (for example the typing stays the same but the variable changes name). Maybe something like Class/Function/Interface/Trait name case changed (to better follow the added/changed/removed nomenclature).

['trait', 'private', 'V054'],
];
}
public function providerImplementationChanged()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems all this code is using space indentation.

docs/Ruleset.md Outdated
@@ -158,6 +162,8 @@ V114 | MAJOR | Trait private method parameter default removed
V115 | MAJOR | Trait public method parameter default value changed
V116 | MAJOR | Trait protected method parameter default value changed
V117 | MAJOR | Trait private method parameter default value changed
V152 | PATCH | Trait method renamed (case only)
V155 | PATCH | Trait renamed (case only)

# To classify
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is missing function renaming.

];
}

public function testClassMethodCaseChangeIsIgnored()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be tested against classes, traits and interfaces, at each visibility (public, protected, private). Use a provider similar to providerImplementationChanged to accomplish this.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name shouldn't be testClassMethodCaseChangeIsIgnored but testClassMethodNameCaseChanged.

docs/Ruleset.md Outdated
@@ -70,6 +70,8 @@ V096 | PATCH | Class private method parameter default removed
V097 | MAJOR | Class public method parameter default value changed
V098 | MAJOR | Class protected method parameter default value changed
V099 | PATCH | Class private method parameter default value changed
V150 | PATCH | Class public/protected/private method renamed (case only)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split into 3 rules, one for each visibility level (as it is done for all other rules even if they are all the same value).

docs/Ruleset.md Outdated
@@ -158,6 +162,8 @@ V114 | MAJOR | Trait private method parameter default removed
V115 | MAJOR | Trait public method parameter default value changed
V116 | MAJOR | Trait protected method parameter default value changed
V117 | MAJOR | Trait private method parameter default value changed
V152 | PATCH | Trait method renamed (case only)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split into 3 rules, one for each visibility level (as it is done for all other rules even if they are all the same value).

docs/Ruleset.md Outdated
@@ -109,6 +111,8 @@ V076 | MAJOR | Interface method parameter typing removed
V077 | MINOR | Interface method parameter default added
V078 | MAJOR | Interface method parameter default removed
V079 | MAJOR | Interface method parameter default value changed
V151 | PATCH | Interface method renamed (case only)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be split into 3 rules, one for each visibility level (as it is done for all other rules even if they are all the same value).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interfaces can only have public methods

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. In this case it should only be for the public method visibility. (the message was copy/pasted in each case 😉)

Copy link
Owner

@tomzx tomzx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall.

Other small general comment, the style is that there's a space between the keyword (if/foreach/for/while/etc.) and the opening parenthesis, and a space between the closing parenthesis and opening brace, such as keyword (...) { ... }

use PhpParser\Node\Stmt\Trait_;
use PHPSemVerChecker\Node\Statement\Trait_ as PTrait;

class TraitRenamedCaseOnly extends Operation {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a delta operation.

use PhpParser\Node\Stmt\Interface_;
use PHPSemVerChecker\Node\Statement\Interface_ as PInterface;

class InterfaceRenamedCaseOnly extends Operation {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a delta operation.

use PhpParser\Node\Stmt\Class_;
use PHPSemVerChecker\Node\Statement\Class_ as PClass;

class ClassRenamedCaseOnly extends Operation {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a delta operation.

$classesAfter = $registryAfter->data['class'];

$classesBeforeKeyed = [];
$mappingsBeforeKeyed = [];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe prefer filesBeforeKeyed?

}

$classesAfterKeyed = [];
$mappingsAfterKeyed = [];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe prefer filesAfterKeyed?

];
}

public function testClassMethodCaseChangeIsIgnored()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name shouldn't be testClassMethodCaseChangeIsIgnored but testClassMethodNameCaseChanged.

@@ -62,4 +62,23 @@ public function testTraitAdded()
$this->assertSame('Trait was added.', $report[$context][$expectedLevel][0]->getReason());
$this->assertSame('tmp', $report[$context][$expectedLevel][0]->getTarget());
}

public function testTraitRenamedCaseOnly()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name should be testTraitNameCaseChanged.

@@ -62,4 +62,25 @@ public function testInterfaceAdded()
$this->assertSame('Interface was added.', $report[$context][$expectedLevel][0]->getReason());
$this->assertSame('tmp', $report[$context][$expectedLevel][0]->getTarget());
}

public function testInterfaceRenamedCaseOnly()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name should be testInterfaceNameCaseChanged.


$signatureResult = Signature::analyze($paramsBefore, $paramsAfter);
// Detect method renamed case only.
if(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Break long comparison into variables and test against those, e.g.:

$isSameName = strtolower($methodBefore->name) === strtolower($methodAfter->name);
$isExactName = $methodBefore->name === $methodAfter->name;
if ($isSameName && !$isExactName) { ... }

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason you need to check strtolower($methodBefore->name) === strtolower($methodAfter->name)? They're technically mapped to be since they're part of the $methodsToVerify array.

@emmetog
Copy link
Contributor Author

emmetog commented Feb 15, 2018

A huge thanks for your feedback @tomzx. I'll work on fixing these up over the next few days.

@emmetog
Copy link
Contributor Author

emmetog commented Feb 19, 2018

@tomzx I've cleaned up those few things ;)


$signatureResult = Signature::analyze($paramsBefore, $paramsAfter);
// Check if the name of the interface has changed case.
Copy link
Owner

@tomzx tomzx Feb 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should say "of the function", not "of the interface".

Also make sure not to have a space between the if and the comment.

/**
* @dataProvider providerCaseChanged
*/
public function testClassMethodCaseChangeChanged($context, $visibility, $code)
Copy link
Owner

@tomzx tomzx Feb 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name shouldn't be testClassMethodCaseChangeChanged but testClassMethodCaseChanged.

@tomzx
Copy link
Owner

tomzx commented Feb 22, 2018

Looks good enough now. I'll merge and make a few final fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants