From 08d8c9fe2a75f8c2642210aea4e2c6f9d9680684 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 08:17:36 +0100 Subject: [PATCH 01/18] Extend id vs ID Rule. - Refactored `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, method names and class names for incorrect capitalization of "Id" - Add `Idt` to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` --- CHANGELOG.md | 7 ++ src/PHPStan/Rules/NameIdToIDRule.php | 82 +++++++++++++++++++ src/PHPStan/Rules/VariableNameIdToIDRule.php | 56 ------------- ...oIDRuleTest.php => NameIdToIDRuleTest.php} | 11 +-- 4 files changed, 95 insertions(+), 61 deletions(-) create mode 100644 src/PHPStan/Rules/NameIdToIDRule.php delete mode 100644 src/PHPStan/Rules/VariableNameIdToIDRule.php rename tests/PHPStan/Rules/{VariableNameIdToIDRuleTest.php => NameIdToIDRuleTest.php} (76%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7dd88..b5d3f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). ## Unreleased +## v6.0.0 + +### Changed + +- Refactored `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, method names and class names for incorrect capitalization of "Id" +- Add `Idt` to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` + ## v5.8.0 ### Added diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php new file mode 100644 index 0000000..2b8479e --- /dev/null +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -0,0 +1,82 @@ + */ +class NameIdToIDRule implements Rule +{ + /** Lists words or phrases that contain "Id" but are fine. */ + protected const FALSE_POSITIVES = [ + 'Identifier', + 'Idt', // IDT is an abbreviation for the brand "Integrated DNA Technologies, Inc." + ]; + + public function getNodeType(): string + { + return Node::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $result = $this->extractNodeNameAndType($node); + + if ($result === null) { + return []; + } + + [$nodeName, $type] = $result; + + if (! static::containsWrongIDCapitalization($nodeName)) { + return []; + } + + $expectedName = static::fixIDCapitalization($nodeName); + + return [ + RuleErrorBuilder::message( + <<build(), + ]; + } + + public static function containsWrongIDCapitalization(string $nodeName): bool + { + return \Safe\preg_match('/Id/', $nodeName) === 1 + && ! Str::contains($nodeName, self::FALSE_POSITIVES); + } + + public static function fixIDCapitalization(string $nodeName): string + { + if ($nodeName === 'Id') { + return 'id'; + } + + return str_replace('Id', 'ID', $nodeName); + } + + /** @return array{0: string, 1: string}|null */ + public function extractNodeNameAndType(Node $node): ?array + { + if ($node instanceof Variable && is_string($node->name)) { + return [$node->name, 'Variable']; + } + if ($node instanceof ClassMethod) { + return [$node->name->toString(), 'ClassMethod']; + } + if ($node instanceof Node\Stmt\Class_ && $node->name instanceof Node\Identifier) { + return [$node->name->toString(), 'Class']; + } + + return null; + } +} diff --git a/src/PHPStan/Rules/VariableNameIdToIDRule.php b/src/PHPStan/Rules/VariableNameIdToIDRule.php deleted file mode 100644 index 7968f00..0000000 --- a/src/PHPStan/Rules/VariableNameIdToIDRule.php +++ /dev/null @@ -1,56 +0,0 @@ - */ -class VariableNameIdToIDRule implements Rule -{ - /** Lists words or phrases that contain "Id" but are fine. */ - protected const FALSE_POSITIVES = ['Identifier']; - - public function getNodeType(): string - { - return Variable::class; - } - - public function processNode(Node $node, Scope $scope): array - { - $nodeName = $node->name; - - if (is_string($nodeName) - && static::containsWrongIDCapitalization($nodeName) - ) { - $expectedName = static::fixIDCapitalization($nodeName); - - return [ - RuleErrorBuilder::message(<<build(), - ]; - } - - return []; - } - - public static function containsWrongIDCapitalization(string $nodeName): bool - { - return \Safe\preg_match('/Id/', $nodeName) === 1 - && ! Str::contains($nodeName, self::FALSE_POSITIVES); - } - - public static function fixIDCapitalization(string $nodeName): string - { - if ($nodeName === 'Id') { - return 'id'; - } - - return str_replace('Id', 'ID', $nodeName); - } -} diff --git a/tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php b/tests/PHPStan/Rules/NameIdToIDRuleTest.php similarity index 76% rename from tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php rename to tests/PHPStan/Rules/NameIdToIDRuleTest.php index d6499ba..9f511d9 100644 --- a/tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php +++ b/tests/PHPStan/Rules/NameIdToIDRuleTest.php @@ -2,17 +2,17 @@ namespace MLL\Utils\Tests\PHPStan\Rules; -use MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule; +use MLL\Utils\PHPStan\Rules\NameIdToIDRule; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -final class VariableNameIdToIDRuleTest extends TestCase +final class NameIdToIDRuleTest extends TestCase { /** @dataProvider wrongID */ #[DataProvider('wrongID')] public function testRecognizesWrongCapitalizations(string $variableName): void { - self::assertTrue(VariableNameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertTrue(NameIdToIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -27,7 +27,7 @@ public static function wrongID(): iterable #[DataProvider('correctID')] public function testAllowsCorrectCapitalizations(string $variableName): void { - self::assertFalse(VariableNameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertFalse(NameIdToIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -39,13 +39,14 @@ public static function correctID(): iterable yield ['labID']; yield ['labIDs']; yield ['testIdentifier']; + yield ['openIdtAnalyses']; } /** @dataProvider wrongToRight */ #[DataProvider('wrongToRight')] public function testFixIDCapitalization(string $wrong, string $right): void { - self::assertSame($right, VariableNameIdToIDRule::fixIDCapitalization($wrong)); + self::assertSame($right, NameIdToIDRule::fixIDCapitalization($wrong)); } /** @return iterable */ From 5b8bd09fcb4cd67390555adad3b20cba8e8393d7 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 08:17:36 +0100 Subject: [PATCH 02/18] Extend id vs ID Rule. - Refactored `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, method names and class names for incorrect capitalization of "Id" - Add `Idt` to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` --- CHANGELOG.md | 7 ++ src/PHPStan/Rules/NameIdToIDRule.php | 85 +++++++++++++++++++ src/PHPStan/Rules/VariableNameIdToIDRule.php | 56 ------------ ...oIDRuleTest.php => NameIdToIDRuleTest.php} | 11 +-- 4 files changed, 98 insertions(+), 61 deletions(-) create mode 100644 src/PHPStan/Rules/NameIdToIDRule.php delete mode 100644 src/PHPStan/Rules/VariableNameIdToIDRule.php rename tests/PHPStan/Rules/{VariableNameIdToIDRuleTest.php => NameIdToIDRuleTest.php} (76%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7dd88..b5d3f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). ## Unreleased +## v6.0.0 + +### Changed + +- Refactored `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, method names and class names for incorrect capitalization of "Id" +- Add `Idt` to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` + ## v5.8.0 ### Added diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php new file mode 100644 index 0000000..9ca8171 --- /dev/null +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -0,0 +1,85 @@ + */ +class NameIdToIDRule implements Rule +{ + /** Lists words or phrases that contain "Id" but are fine. */ + protected const FALSE_POSITIVES = [ + 'Identifier', + 'Idt', // IDT is an abbreviation for the brand "Integrated DNA Technologies, Inc." + ]; + + public function getNodeType(): string + { + return Node::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $result = $this->extractNodeNameAndType($node); + + if ($result === null) { + return []; + } + + [$nodeName, $type] = $result; + + if (! static::containsWrongIDCapitalization($nodeName)) { + return []; + } + + $expectedName = static::fixIDCapitalization($nodeName); + + return [ + RuleErrorBuilder::message( + <<build(), + ]; + } + + public static function containsWrongIDCapitalization(string $nodeName): bool + { + return \Safe\preg_match('/Id/', $nodeName) === 1 + && ! Str::contains($nodeName, self::FALSE_POSITIVES); + } + + public static function fixIDCapitalization(string $nodeName): string + { + if ($nodeName === 'Id') { + return 'id'; + } + + return str_replace('Id', 'ID', $nodeName); + } + + /** @return array{0: string, 1: string}|null */ + public function extractNodeNameAndType(Node $node): ?array + { + if ($node instanceof Variable && is_string($node->name)) { + return [$node->name, 'Variable']; + } + if ($node instanceof Node\Param && $node->var instanceof Variable && is_string($node->var->name)) { + return [$node->var->name, 'Parameter']; + } + if ($node instanceof ClassMethod) { + return [$node->name->toString(), 'ClassMethod']; + } + if ($node instanceof Node\Stmt\Class_ && $node->name instanceof Node\Identifier) { + return [$node->name->toString(), 'Class']; + } + + return null; + } +} diff --git a/src/PHPStan/Rules/VariableNameIdToIDRule.php b/src/PHPStan/Rules/VariableNameIdToIDRule.php deleted file mode 100644 index 7968f00..0000000 --- a/src/PHPStan/Rules/VariableNameIdToIDRule.php +++ /dev/null @@ -1,56 +0,0 @@ - */ -class VariableNameIdToIDRule implements Rule -{ - /** Lists words or phrases that contain "Id" but are fine. */ - protected const FALSE_POSITIVES = ['Identifier']; - - public function getNodeType(): string - { - return Variable::class; - } - - public function processNode(Node $node, Scope $scope): array - { - $nodeName = $node->name; - - if (is_string($nodeName) - && static::containsWrongIDCapitalization($nodeName) - ) { - $expectedName = static::fixIDCapitalization($nodeName); - - return [ - RuleErrorBuilder::message(<<build(), - ]; - } - - return []; - } - - public static function containsWrongIDCapitalization(string $nodeName): bool - { - return \Safe\preg_match('/Id/', $nodeName) === 1 - && ! Str::contains($nodeName, self::FALSE_POSITIVES); - } - - public static function fixIDCapitalization(string $nodeName): string - { - if ($nodeName === 'Id') { - return 'id'; - } - - return str_replace('Id', 'ID', $nodeName); - } -} diff --git a/tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php b/tests/PHPStan/Rules/NameIdToIDRuleTest.php similarity index 76% rename from tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php rename to tests/PHPStan/Rules/NameIdToIDRuleTest.php index d6499ba..9f511d9 100644 --- a/tests/PHPStan/Rules/VariableNameIdToIDRuleTest.php +++ b/tests/PHPStan/Rules/NameIdToIDRuleTest.php @@ -2,17 +2,17 @@ namespace MLL\Utils\Tests\PHPStan\Rules; -use MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule; +use MLL\Utils\PHPStan\Rules\NameIdToIDRule; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -final class VariableNameIdToIDRuleTest extends TestCase +final class NameIdToIDRuleTest extends TestCase { /** @dataProvider wrongID */ #[DataProvider('wrongID')] public function testRecognizesWrongCapitalizations(string $variableName): void { - self::assertTrue(VariableNameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertTrue(NameIdToIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -27,7 +27,7 @@ public static function wrongID(): iterable #[DataProvider('correctID')] public function testAllowsCorrectCapitalizations(string $variableName): void { - self::assertFalse(VariableNameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertFalse(NameIdToIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -39,13 +39,14 @@ public static function correctID(): iterable yield ['labID']; yield ['labIDs']; yield ['testIdentifier']; + yield ['openIdtAnalyses']; } /** @dataProvider wrongToRight */ #[DataProvider('wrongToRight')] public function testFixIDCapitalization(string $wrong, string $right): void { - self::assertSame($right, VariableNameIdToIDRule::fixIDCapitalization($wrong)); + self::assertSame($right, NameIdToIDRule::fixIDCapitalization($wrong)); } /** @return iterable */ From fe0addfef54bbcd9eae77727bce933a8aa3cd4ef Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 08:32:51 +0100 Subject: [PATCH 03/18] add identifier --- CHANGELOG.md | 6 ++++-- src/PHPStan/Rules/NameIdToIDRule.php | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b16db5..4d95027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,10 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). ### Changed -- Refactored `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, parameter names, method names and class names for incorrect capitalization of "Id" -- Add `Idt` to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Breaking Change: Renamed class `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Refactored `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, parameter names, method names and class names for incorrect capitalization of "Id" +- Add 'Idt' to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add RuleIdentifier 'mllLabRules.nameIdToID' to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` ## v5.8.0 diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php index 9ca8171..fbb318a 100644 --- a/src/PHPStan/Rules/NameIdToIDRule.php +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -45,7 +45,8 @@ public function processNode(Node $node, Scope $scope): array <<build(), + )->identifier('mllLabRules.nameIdToID') + ->build(), ]; } From 50dcabff101c0d79de7a007a61a761956417c639 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 08:44:29 +0100 Subject: [PATCH 04/18] Identical --- CHANGELOG.md | 2 +- src/PHPStan/Rules/NameIdToIDRule.php | 1 + tests/PHPStan/Rules/NameIdToIDRuleTest.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d95027..6bcb87b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). - Breaking Change: Renamed class `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` - Refactored `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, parameter names, method names and class names for incorrect capitalization of "Id" -- Add 'Idt' to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add 'Idt' and 'Identical' to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` - Add RuleIdentifier 'mllLabRules.nameIdToID' to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` ## v5.8.0 diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php index fbb318a..03e552e 100644 --- a/src/PHPStan/Rules/NameIdToIDRule.php +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -16,6 +16,7 @@ class NameIdToIDRule implements Rule /** Lists words or phrases that contain "Id" but are fine. */ protected const FALSE_POSITIVES = [ 'Identifier', + 'Identical', 'Idt', // IDT is an abbreviation for the brand "Integrated DNA Technologies, Inc." ]; diff --git a/tests/PHPStan/Rules/NameIdToIDRuleTest.php b/tests/PHPStan/Rules/NameIdToIDRuleTest.php index 9f511d9..aff6383 100644 --- a/tests/PHPStan/Rules/NameIdToIDRuleTest.php +++ b/tests/PHPStan/Rules/NameIdToIDRuleTest.php @@ -40,6 +40,7 @@ public static function correctID(): iterable yield ['labIDs']; yield ['testIdentifier']; yield ['openIdtAnalyses']; + yield ['isIdenticalThing']; } /** @dataProvider wrongToRight */ From 850c64029ae2fb5bdf624c67919b5ba78b70b5ca Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:12:52 +0100 Subject: [PATCH 05/18] Add CanonicalCapitalization.php --- CHANGELOG.md | 1 + src/PHPStan/Rules/CanonicalCapitalization.php | 72 +++++++++++++++++++ src/PHPStan/Rules/NameIdToIDRule.php | 23 +----- src/PHPStan/Rules/NodeIdentifier.php | 31 ++++++++ .../Rules/CanonicalCapitalizationTest.php | 57 +++++++++++++++ 5 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 src/PHPStan/Rules/CanonicalCapitalization.php create mode 100644 src/PHPStan/Rules/NodeIdentifier.php create mode 100644 tests/PHPStan/Rules/CanonicalCapitalizationTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bcb87b..8472e59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). - Refactored `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, parameter names, method names and class names for incorrect capitalization of "Id" - Add 'Idt' and 'Identical' to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` - Add RuleIdentifier 'mllLabRules.nameIdToID' to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add PHPStan-Rule `MLL\Utils\PHPStan\Rules\CanonicalCapitalizations` to check spelling of LabID ## v5.8.0 diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php new file mode 100644 index 0000000..c5d5a9c --- /dev/null +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -0,0 +1,72 @@ + */ +final class CanonicalCapitalization implements Rule +{ + private const CANONICAL_CAPITALIZATIONS = [ + 'Lab ID' => ['lab id', 'Lab-ID', 'LabID ', ' LabID', 'labID', 'LABID', 'Labid', 'lab-Id', 'Lab Id'], + ]; + + public function getNodeType(): string + { + return Node\Expr\Variable::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $result = NodeIdentifier::extractNodeNameAndType($node); + + if ($result === null) { + return []; + } + + [$nodeName, $type] = $result; + + $wrongCapitalization = CanonicalCapitalization::findWrongCapitalization($nodeName); + + if ($wrongCapitalization === null) { + return []; + } + + [$correct, $incorrect] = $wrongCapitalization; + + $expectedName = self::fixIDCapitalization($nodeName, $correct, $incorrect); + + return [ + RuleErrorBuilder::message( + <<identifier('mllLabRules.nameIdToID') + ->build(), + ]; + } + + /** @return array{0: string, 1: string}|null */ + public static function findWrongCapitalization(string $nodeName): ?array + { + foreach (self::CANONICAL_CAPITALIZATIONS as $correct => $incorrectVariants) { + foreach ($incorrectVariants as $incorrect) { + if (preg_match('/' . $incorrect . '/', $nodeName) === 1) { + return [$correct, $incorrect]; + } + } + } + + return null; + } + + public static function fixIDCapitalization(string $nodeName, string $correct, string $incorrect): string + { + return str_replace(trim($incorrect), trim($correct), $nodeName); + } +} diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php index 03e552e..d47685c 100644 --- a/src/PHPStan/Rules/NameIdToIDRule.php +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -4,8 +4,6 @@ use Illuminate\Support\Str; use PhpParser\Node; -use PhpParser\Node\Expr\Variable; -use PhpParser\Node\Stmt\ClassMethod; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -27,7 +25,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $result = $this->extractNodeNameAndType($node); + $result = NodeIdentifier::extractNodeNameAndType($node); if ($result === null) { return []; @@ -65,23 +63,4 @@ public static function fixIDCapitalization(string $nodeName): string return str_replace('Id', 'ID', $nodeName); } - - /** @return array{0: string, 1: string}|null */ - public function extractNodeNameAndType(Node $node): ?array - { - if ($node instanceof Variable && is_string($node->name)) { - return [$node->name, 'Variable']; - } - if ($node instanceof Node\Param && $node->var instanceof Variable && is_string($node->var->name)) { - return [$node->var->name, 'Parameter']; - } - if ($node instanceof ClassMethod) { - return [$node->name->toString(), 'ClassMethod']; - } - if ($node instanceof Node\Stmt\Class_ && $node->name instanceof Node\Identifier) { - return [$node->name->toString(), 'Class']; - } - - return null; - } } diff --git a/src/PHPStan/Rules/NodeIdentifier.php b/src/PHPStan/Rules/NodeIdentifier.php new file mode 100644 index 0000000..eb36747 --- /dev/null +++ b/src/PHPStan/Rules/NodeIdentifier.php @@ -0,0 +1,31 @@ +name)) { + return [$node->name, 'Variable']; + } + if ($node instanceof Node\Param && $node->var instanceof Variable && is_string($node->var->name)) { + return [$node->var->name, 'Parameter']; + } + if ($node instanceof ClassMethod) { + return [$node->name->toString(), 'ClassMethod']; + } + if ($node instanceof Node\Stmt\Class_ && $node->name instanceof Node\Identifier) { + return [$node->name->toString(), 'Class']; + } + + return null; + } +} diff --git a/tests/PHPStan/Rules/CanonicalCapitalizationTest.php b/tests/PHPStan/Rules/CanonicalCapitalizationTest.php new file mode 100644 index 0000000..1b85019 --- /dev/null +++ b/tests/PHPStan/Rules/CanonicalCapitalizationTest.php @@ -0,0 +1,57 @@ + */ + public static function wrongCapitalizationProvider(): iterable + { + yield 'Should correct capitalization for "LabID "' => ['The LabID is incorrect', ['Lab ID', 'LabID ', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "Lab-ID"' => ['The Lab-ID is incorrect', ['Lab ID', 'Lab-ID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "lab id"' => ['The lab id is incorrect', ['Lab ID', 'lab id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "labID"' => ['The labID is incorrect', ['Lab ID', 'labID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for " LabID"' => ['The LabID', ['Lab ID', ' LabID', 'The Lab ID']]; + yield 'Should correct capitalization for "LABID"' => ['The LABID is incorrect', ['Lab ID', 'LABID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "Labid"' => ['The Labid is incorrect', ['Lab ID', 'Labid', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "lab-Id"' => ['The lab-Id is incorrect', ['Lab ID', 'lab-Id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "Lab Id"' => ['The Lab Id is incorrect', ['Lab ID', 'Lab Id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + } + + /** @dataProvider rightCapitalizationProvider */ + #[DataProvider('rightCapitalizationProvider')] + public function testFindWrongCapitalizationFalse(string $nodeName): void + { + self::assertNull(CanonicalCapitalization::findWrongCapitalization($nodeName)); + } + + /** @return iterable> */ + public static function rightCapitalizationProvider(): iterable + { + yield 'Should not be fixed because it might be in a non-space case written' => ['TheLabIDIsIncorrect']; + } +} From 26412deb6aa95f6468850b454bc625096b3a71ba Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:19:10 +0100 Subject: [PATCH 06/18] fix LabId-var name case --- src/PHPStan/Rules/CanonicalCapitalization.php | 13 ++++++++++++- tests/PHPStan/Rules/CanonicalCapitalizationTest.php | 4 +++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index c5d5a9c..556a095 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -13,7 +13,18 @@ final class CanonicalCapitalization implements Rule { private const CANONICAL_CAPITALIZATIONS = [ - 'Lab ID' => ['lab id', 'Lab-ID', 'LabID ', ' LabID', 'labID', 'LABID', 'Labid', 'lab-Id', 'Lab Id'], + 'Lab ID' => [ + 'lab id', + 'Lab-ID', + 'LabID ', + ' LabID', + ' labID', + 'labID ', + 'LABID', + 'Labid', + 'lab-Id', + 'Lab Id', + ], ]; public function getNodeType(): string diff --git a/tests/PHPStan/Rules/CanonicalCapitalizationTest.php b/tests/PHPStan/Rules/CanonicalCapitalizationTest.php index 1b85019..26f0b24 100644 --- a/tests/PHPStan/Rules/CanonicalCapitalizationTest.php +++ b/tests/PHPStan/Rules/CanonicalCapitalizationTest.php @@ -34,7 +34,8 @@ public static function wrongCapitalizationProvider(): iterable yield 'Should correct capitalization for "LabID "' => ['The LabID is incorrect', ['Lab ID', 'LabID ', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "Lab-ID"' => ['The Lab-ID is incorrect', ['Lab ID', 'Lab-ID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "lab id"' => ['The lab id is incorrect', ['Lab ID', 'lab id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for "labID"' => ['The labID is incorrect', ['Lab ID', 'labID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for " labID"' => ['The labID is incorrect', ['Lab ID', ' labID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "labID "' => ['labID is incorrect', ['Lab ID', 'labID ', 'Lab ID is incorrect']]; yield 'Should correct capitalization for " LabID"' => ['The LabID', ['Lab ID', ' LabID', 'The Lab ID']]; yield 'Should correct capitalization for "LABID"' => ['The LABID is incorrect', ['Lab ID', 'LABID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "Labid"' => ['The Labid is incorrect', ['Lab ID', 'Labid', self::EXPECTED_LAB_ID_IS_INCORRECT]]; @@ -53,5 +54,6 @@ public function testFindWrongCapitalizationFalse(string $nodeName): void public static function rightCapitalizationProvider(): iterable { yield 'Should not be fixed because it might be in a non-space case written' => ['TheLabIDIsIncorrect']; + yield 'Should not be fixed because it might be a varName' => ['labID']; } } From b1d91070a8aca75a71e8c34ec6edb3cf2cd966b4 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:28:01 +0100 Subject: [PATCH 07/18] check in string --- src/PHPStan/Rules/CanonicalCapitalization.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 556a095..ac8fe94 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -3,6 +3,7 @@ namespace MLL\Utils\PHPStan\Rules; use PhpParser\Node; +use PhpParser\Node\Expr\Variable; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -36,6 +37,10 @@ public function processNode(Node $node, Scope $scope): array { $result = NodeIdentifier::extractNodeNameAndType($node); + if ($node instanceof Node\Scalar\String_) { + $result = [$node->value, 'String']; + } + if ($result === null) { return []; } From e32eba640be1fbc96194d22d442bbb3a461b964f Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:30:27 +0100 Subject: [PATCH 08/18] check LabID in string --- src/PHPStan/Rules/CanonicalCapitalization.php | 4 ++-- src/PHPStan/Rules/NodeIdentifier.php | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index ac8fe94..7c9b797 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -3,7 +3,7 @@ namespace MLL\Utils\PHPStan\Rules; use PhpParser\Node; -use PhpParser\Node\Expr\Variable; +use PhpParser\Node\Scalar\String_; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -37,7 +37,7 @@ public function processNode(Node $node, Scope $scope): array { $result = NodeIdentifier::extractNodeNameAndType($node); - if ($node instanceof Node\Scalar\String_) { + if ($node instanceof String_) { $result = [$node->value, 'String']; } diff --git a/src/PHPStan/Rules/NodeIdentifier.php b/src/PHPStan/Rules/NodeIdentifier.php index eb36747..8c80fd6 100644 --- a/src/PHPStan/Rules/NodeIdentifier.php +++ b/src/PHPStan/Rules/NodeIdentifier.php @@ -8,9 +8,7 @@ class NodeIdentifier { - /** - * @return array{0: string, 1: string}|null - */ + /** @return array{0: string, 1: string}|null */ public static function extractNodeNameAndType(Node $node): ?array { if ($node instanceof Variable && is_string($node->name)) { From f080da29ea91fc413c562c0f4a835313321dead9 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:36:05 +0100 Subject: [PATCH 09/18] concatinated string --- src/PHPStan/Rules/CanonicalCapitalization.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 7c9b797..5892ddf 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -39,6 +39,8 @@ public function processNode(Node $node, Scope $scope): array if ($node instanceof String_) { $result = [$node->value, 'String']; + } elseif ($node instanceof Node\Expr\BinaryOp\Concat) { + $result = $this->extractConcatString($node); } if ($result === null) { @@ -85,4 +87,22 @@ public static function fixIDCapitalization(string $nodeName, string $correct, st { return str_replace(trim($incorrect), trim($correct), $nodeName); } + + private function extractConcatString(Node\Expr\BinaryOp\Concat $concat): array + { + $parts = []; + $this->gatherConcatParts($concat, $parts); + $string = implode('', $parts); + return [$string, 'String']; + } + + private function gatherConcatParts(Node $node, array &$parts): void + { + if ($node instanceof Node\Expr\BinaryOp\Concat) { + $this->gatherConcatParts($node->left, $parts); + $this->gatherConcatParts($node->right, $parts); + } elseif ($node instanceof String_) { + $parts[] = $node->value; + } + } } From 2e64ac50d1bd4eeb2c6f4aced23fbac8bb475993 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 16:50:21 +0100 Subject: [PATCH 10/18] concatinated string --- src/PHPStan/Rules/CanonicalCapitalization.php | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 5892ddf..1ef669b 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -30,7 +30,7 @@ final class CanonicalCapitalization implements Rule public function getNodeType(): string { - return Node\Expr\Variable::class; + return Node::class; } public function processNode(Node $node, Scope $scope): array @@ -39,8 +39,6 @@ public function processNode(Node $node, Scope $scope): array if ($node instanceof String_) { $result = [$node->value, 'String']; - } elseif ($node instanceof Node\Expr\BinaryOp\Concat) { - $result = $this->extractConcatString($node); } if ($result === null) { @@ -62,7 +60,7 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message( <<identifier('mllLabRules.nameIdToID') ->build(), @@ -87,22 +85,4 @@ public static function fixIDCapitalization(string $nodeName, string $correct, st { return str_replace(trim($incorrect), trim($correct), $nodeName); } - - private function extractConcatString(Node\Expr\BinaryOp\Concat $concat): array - { - $parts = []; - $this->gatherConcatParts($concat, $parts); - $string = implode('', $parts); - return [$string, 'String']; - } - - private function gatherConcatParts(Node $node, array &$parts): void - { - if ($node instanceof Node\Expr\BinaryOp\Concat) { - $this->gatherConcatParts($node->left, $parts); - $this->gatherConcatParts($node->right, $parts); - } elseif ($node instanceof String_) { - $parts[] = $node->value; - } - } } From 482b3e7c952116811df82fd94c3b2540a67426fc Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 17:16:26 +0100 Subject: [PATCH 11/18] concatinated string --- src/PHPStan/Rules/CanonicalCapitalization.php | 8 ++------ src/PHPStan/Rules/NodeIdentifier.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 1ef669b..5b262ac 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -3,7 +3,6 @@ namespace MLL\Utils\PHPStan\Rules; use PhpParser\Node; -use PhpParser\Node\Scalar\String_; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -35,11 +34,8 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $result = NodeIdentifier::extractNodeNameAndType($node); - - if ($node instanceof String_) { - $result = [$node->value, 'String']; - } + $result = NodeIdentifier::extractNodeNameAndType($node) + ?? NodeIdentifier::nodeNameForString($node); if ($result === null) { return []; diff --git a/src/PHPStan/Rules/NodeIdentifier.php b/src/PHPStan/Rules/NodeIdentifier.php index 8c80fd6..d3a0c93 100644 --- a/src/PHPStan/Rules/NodeIdentifier.php +++ b/src/PHPStan/Rules/NodeIdentifier.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\Variable; +use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\ClassMethod; class NodeIdentifier @@ -26,4 +27,18 @@ public static function extractNodeNameAndType(Node $node): ?array return null; } + + /** @return array{0: string, 1: string}|null */ + public static function nodeNameForString(Node $node): ?array + { + if ($node instanceof String_) { + return [$node->value, 'String']; + } + + if ($node instanceof Node\Scalar\EncapsedStringPart) { + return [$node->value, 'String']; + } + + return null; + } } From 79f83fe45bdd923cfd8c34aba803275886eccbff Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Fri, 6 Dec 2024 20:01:20 +0100 Subject: [PATCH 12/18] canonicalCapitalization identifier --- src/PHPStan/Rules/CanonicalCapitalization.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 5b262ac..9a8c5b0 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -58,7 +58,7 @@ public function processNode(Node $node, Scope $scope): array <<identifier('mllLabRules.nameIdToID') + )->identifier('mllLabRules.canonicalCapitalization') ->build(), ]; } From 61c3032ed96fdd626f59a7dc8c674c4c87679d08 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Sat, 7 Dec 2024 14:49:03 +0100 Subject: [PATCH 13/18] Apply suggestions from code review Co-authored-by: Benedikt Franke --- src/PHPStan/Rules/CanonicalCapitalization.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 9a8c5b0..adf023f 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -10,7 +10,7 @@ use function Safe\preg_match; /** @implements Rule */ -final class CanonicalCapitalization implements Rule +class CanonicalCapitalization implements Rule { private const CANONICAL_CAPITALIZATIONS = [ 'Lab ID' => [ @@ -35,7 +35,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $result = NodeIdentifier::extractNodeNameAndType($node) - ?? NodeIdentifier::nodeNameForString($node); + ?? NodeIdentifier::nodeNameForString($node); if ($result === null) { return []; @@ -54,11 +54,10 @@ public function processNode(Node $node, Scope $scope): array $expectedName = self::fixIDCapitalization($nodeName, $correct, $incorrect); return [ - RuleErrorBuilder::message( - <<identifier('mllLabRules.canonicalCapitalization') + TXT) + ->identifier('mll.canonicalCapitalization') ->build(), ]; } @@ -68,7 +67,7 @@ public static function findWrongCapitalization(string $nodeName): ?array { foreach (self::CANONICAL_CAPITALIZATIONS as $correct => $incorrectVariants) { foreach ($incorrectVariants as $incorrect) { - if (preg_match('/' . $incorrect . '/', $nodeName) === 1) { + if (preg_match("/{$incorrect}/", $nodeName) === 1) { return [$correct, $incorrect]; } } From 9f84d2350eb8f0cafa8cf0f32f7141da23734047 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Mon, 9 Dec 2024 09:26:40 +0100 Subject: [PATCH 14/18] clean up --- CHANGELOG.md | 14 +++++++------- src/PHPStan/Rules/CanonicalCapitalization.php | 7 ++++--- src/PHPStan/Rules/NameIdToIDRule.php | 9 +++------ 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8472e59..543a337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,23 +13,23 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). ### Changed -- Breaking Change: Renamed class `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` -- Refactored `MLL\Utils\PHPStan\Rules\NameIdToIDRule` to handle variable names, parameter names, method names and class names for incorrect capitalization of "Id" -- Add 'Idt' and 'Identical' to the list of incorrect capitalizations for "Id" of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` -- Add RuleIdentifier 'mllLabRules.nameIdToID' to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` -- Add PHPStan-Rule `MLL\Utils\PHPStan\Rules\CanonicalCapitalizations` to check spelling of LabID +- Breaking Change: Rename class `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Make `MLL\Utils\PHPStan\Rules\NameIdToIDRule` handle variable names, parameter names, method names, and class names for incorrect capitalization of `Id` +- Add `Idt` and `Identical` to the list of incorrect capitalizations for `Id` of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add RuleIdentifier `mllLabRules.nameIdToID` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add PHPStan-rule `MLL\Utils\PHPStan\Rules\CanonicalCapitalizations` to check spelling of LabID ## v5.8.0 ### Added -- Add PHPStan-Rule `MLL\Utils\PHPStan\Rules\ThrowableClassNameRule` +- Add PHPStan-rule `MLL\Utils\PHPStan\Rules\ThrowableClassNameRule` ## v5.7.0 ### Added -- Add PHPStan-Rule `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` +- Add PHPStan-rule `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` ## v5.6.0 diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index adf023f..276c71b 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -36,7 +36,6 @@ public function processNode(Node $node, Scope $scope): array { $result = NodeIdentifier::extractNodeNameAndType($node) ?? NodeIdentifier::nodeNameForString($node); - if ($result === null) { return []; } @@ -44,7 +43,6 @@ public function processNode(Node $node, Scope $scope): array [$nodeName, $type] = $result; $wrongCapitalization = CanonicalCapitalization::findWrongCapitalization($nodeName); - if ($wrongCapitalization === null) { return []; } @@ -78,6 +76,9 @@ public static function findWrongCapitalization(string $nodeName): ?array public static function fixIDCapitalization(string $nodeName, string $correct, string $incorrect): string { - return str_replace(trim($incorrect), trim($correct), $nodeName); + $trimmedIncorrect = trim($incorrect); + $trimmedCorrect = trim($correct); + + return str_replace($trimmedIncorrect, $trimmedCorrect, $nodeName); } } diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/NameIdToIDRule.php index d47685c..17e8c42 100644 --- a/src/PHPStan/Rules/NameIdToIDRule.php +++ b/src/PHPStan/Rules/NameIdToIDRule.php @@ -26,13 +26,11 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $result = NodeIdentifier::extractNodeNameAndType($node); - if ($result === null) { return []; } [$nodeName, $type] = $result; - if (! static::containsWrongIDCapitalization($nodeName)) { return []; } @@ -40,11 +38,10 @@ public function processNode(Node $node, Scope $scope): array $expectedName = static::fixIDCapitalization($nodeName); return [ - RuleErrorBuilder::message( - <<identifier('mllLabRules.nameIdToID') + TXT) + ->identifier('mllLabRules.nameIdToID') ->build(), ]; } From 02f521b511cd41ab8c76f099bd4320915b002d99 Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Mon, 9 Dec 2024 21:28:09 +0100 Subject: [PATCH 15/18] rename --- .../{NameIdToIDRule.php => CapitalizationOfIDRule.php} | 4 ++-- src/PHPStan/Rules/NodeIdentifier.php | 5 ++++- ...ToIDRuleTest.php => CapitalizationOfIDRuleTest.php} | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) rename src/PHPStan/Rules/{NameIdToIDRule.php => CapitalizationOfIDRule.php} (94%) rename tests/PHPStan/Rules/{NameIdToIDRuleTest.php => CapitalizationOfIDRuleTest.php} (77%) diff --git a/src/PHPStan/Rules/NameIdToIDRule.php b/src/PHPStan/Rules/CapitalizationOfIDRule.php similarity index 94% rename from src/PHPStan/Rules/NameIdToIDRule.php rename to src/PHPStan/Rules/CapitalizationOfIDRule.php index 17e8c42..6f10670 100644 --- a/src/PHPStan/Rules/NameIdToIDRule.php +++ b/src/PHPStan/Rules/CapitalizationOfIDRule.php @@ -9,7 +9,7 @@ use PHPStan\Rules\RuleErrorBuilder; /** @implements Rule */ -class NameIdToIDRule implements Rule +class CapitalizationOfIDRule implements Rule { /** Lists words or phrases that contain "Id" but are fine. */ protected const FALSE_POSITIVES = [ @@ -41,7 +41,7 @@ public function processNode(Node $node, Scope $scope): array RuleErrorBuilder::message(<<identifier('mllLabRules.nameIdToID') + ->identifier('mll.capitalizationOfID') ->build(), ]; } diff --git a/src/PHPStan/Rules/NodeIdentifier.php b/src/PHPStan/Rules/NodeIdentifier.php index d3a0c93..d19c44e 100644 --- a/src/PHPStan/Rules/NodeIdentifier.php +++ b/src/PHPStan/Rules/NodeIdentifier.php @@ -15,7 +15,10 @@ public static function extractNodeNameAndType(Node $node): ?array if ($node instanceof Variable && is_string($node->name)) { return [$node->name, 'Variable']; } - if ($node instanceof Node\Param && $node->var instanceof Variable && is_string($node->var->name)) { + if ($node instanceof Node\Param + && $node->var instanceof Variable + && is_string($node->var->name) + ) { return [$node->var->name, 'Parameter']; } if ($node instanceof ClassMethod) { diff --git a/tests/PHPStan/Rules/NameIdToIDRuleTest.php b/tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php similarity index 77% rename from tests/PHPStan/Rules/NameIdToIDRuleTest.php rename to tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php index aff6383..b99043f 100644 --- a/tests/PHPStan/Rules/NameIdToIDRuleTest.php +++ b/tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php @@ -2,17 +2,17 @@ namespace MLL\Utils\Tests\PHPStan\Rules; -use MLL\Utils\PHPStan\Rules\NameIdToIDRule; +use MLL\Utils\PHPStan\Rules\CapitalizationOfIDRule; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -final class NameIdToIDRuleTest extends TestCase +final class CapitalizationOfIDRuleTest extends TestCase { /** @dataProvider wrongID */ #[DataProvider('wrongID')] public function testRecognizesWrongCapitalizations(string $variableName): void { - self::assertTrue(NameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertTrue(CapitalizationOfIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -27,7 +27,7 @@ public static function wrongID(): iterable #[DataProvider('correctID')] public function testAllowsCorrectCapitalizations(string $variableName): void { - self::assertFalse(NameIdToIDRule::containsWrongIDCapitalization($variableName)); + self::assertFalse(CapitalizationOfIDRule::containsWrongIDCapitalization($variableName)); } /** @return iterable */ @@ -47,7 +47,7 @@ public static function correctID(): iterable #[DataProvider('wrongToRight')] public function testFixIDCapitalization(string $wrong, string $right): void { - self::assertSame($right, NameIdToIDRule::fixIDCapitalization($wrong)); + self::assertSame($right, CapitalizationOfIDRule::fixIDCapitalization($wrong)); } /** @return iterable */ From 123d8b6b1f4c92976b60ed4498857993ecec7a1b Mon Sep 17 00:00:00 2001 From: Simon Bigelmayr Date: Mon, 9 Dec 2024 22:43:13 +0100 Subject: [PATCH 16/18] restructure --- .../ClassMethodNameExtractor.php | 18 +++++++ .../NodeNameExtractor/ClassNameExtractor.php | 19 ++++++++ .../NodeNameExtractor/NodeNameExtractor.php | 10 ++++ .../NodeNameExtractor/StringNameExtractor.php | 22 +++++++++ .../VariableNameExtractor.php | 25 ++++++++++ src/PHPStan/Rules/CanonicalCapitalization.php | 28 ++++++++--- src/PHPStan/Rules/CapitalizationOfIDRule.php | 27 ++++++++--- src/PHPStan/Rules/NodeIdentifier.php | 47 ------------------- .../CanonicalCapitalizationTest.php | 14 +++--- .../CapitalizationOfIDRuleTest.php | 2 +- 10 files changed, 145 insertions(+), 67 deletions(-) create mode 100644 src/PHPStan/NodeNameExtractor/ClassMethodNameExtractor.php create mode 100644 src/PHPStan/NodeNameExtractor/ClassNameExtractor.php create mode 100644 src/PHPStan/NodeNameExtractor/NodeNameExtractor.php create mode 100644 src/PHPStan/NodeNameExtractor/StringNameExtractor.php create mode 100644 src/PHPStan/NodeNameExtractor/VariableNameExtractor.php delete mode 100644 src/PHPStan/Rules/NodeIdentifier.php rename tests/PHPStan/Rules/{ => CanonicalCapitalization}/CanonicalCapitalizationTest.php (97%) rename tests/PHPStan/Rules/{ => CapitalizationOfIDRule}/CapitalizationOfIDRuleTest.php (96%) diff --git a/src/PHPStan/NodeNameExtractor/ClassMethodNameExtractor.php b/src/PHPStan/NodeNameExtractor/ClassMethodNameExtractor.php new file mode 100644 index 0000000..11b1277 --- /dev/null +++ b/src/PHPStan/NodeNameExtractor/ClassMethodNameExtractor.php @@ -0,0 +1,18 @@ +name->toString(); + } + + return null; + } +} diff --git a/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php b/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php new file mode 100644 index 0000000..1e9a286 --- /dev/null +++ b/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php @@ -0,0 +1,19 @@ +name instanceof Identifier) { + return $node->name->toString(); + } + + return null; + } +} diff --git a/src/PHPStan/NodeNameExtractor/NodeNameExtractor.php b/src/PHPStan/NodeNameExtractor/NodeNameExtractor.php new file mode 100644 index 0000000..49d533b --- /dev/null +++ b/src/PHPStan/NodeNameExtractor/NodeNameExtractor.php @@ -0,0 +1,10 @@ +value; + } + if ($node instanceof EncapsedStringPart) { + return $node->value; + } + + return null; + } +} diff --git a/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php b/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php new file mode 100644 index 0000000..1673bd9 --- /dev/null +++ b/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php @@ -0,0 +1,25 @@ +name)) { + return $node->name; + } + if ($node instanceof Param + && $node->var instanceof Variable + && is_string($node->var->name) + ) { + return $node->var->name; + } + + return null; + } +} diff --git a/src/PHPStan/Rules/CanonicalCapitalization.php b/src/PHPStan/Rules/CanonicalCapitalization.php index 276c71b..0bd172f 100644 --- a/src/PHPStan/Rules/CanonicalCapitalization.php +++ b/src/PHPStan/Rules/CanonicalCapitalization.php @@ -2,6 +2,10 @@ namespace MLL\Utils\PHPStan\Rules; +use MLL\Utils\PHPStan\NodeNameExtractor\ClassMethodNameExtractor; +use MLL\Utils\PHPStan\NodeNameExtractor\ClassNameExtractor; +use MLL\Utils\PHPStan\NodeNameExtractor\StringNameExtractor; +use MLL\Utils\PHPStan\NodeNameExtractor\VariableNameExtractor; use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; @@ -34,13 +38,25 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $result = NodeIdentifier::extractNodeNameAndType($node) - ?? NodeIdentifier::nodeNameForString($node); - if ($result === null) { - return []; + $extractors = [ + new ClassMethodNameExtractor(), + new ClassNameExtractor(), + new VariableNameExtractor(), + new StringNameExtractor(), + ]; + + $nodeName = null; + foreach ($extractors as $extractor) { + $extractedName = $extractor->extract($node); + if ($extractedName !== null) { + $nodeName = $extractedName; + break; + } } - [$nodeName, $type] = $result; + if ($nodeName === null) { + return []; + } $wrongCapitalization = CanonicalCapitalization::findWrongCapitalization($nodeName); if ($wrongCapitalization === null) { @@ -53,7 +69,7 @@ public function processNode(Node $node, Scope $scope): array return [ RuleErrorBuilder::message(<<getType()} "{$nodeName}" should use "{$correct}" instead of "{$incorrect}", rename it to "{$expectedName}". TXT) ->identifier('mll.canonicalCapitalization') ->build(), diff --git a/src/PHPStan/Rules/CapitalizationOfIDRule.php b/src/PHPStan/Rules/CapitalizationOfIDRule.php index 6f10670..66eaa9b 100644 --- a/src/PHPStan/Rules/CapitalizationOfIDRule.php +++ b/src/PHPStan/Rules/CapitalizationOfIDRule.php @@ -3,6 +3,9 @@ namespace MLL\Utils\PHPStan\Rules; use Illuminate\Support\Str; +use MLL\Utils\PHPStan\NodeNameExtractor\ClassMethodNameExtractor; +use MLL\Utils\PHPStan\NodeNameExtractor\ClassNameExtractor; +use MLL\Utils\PHPStan\NodeNameExtractor\VariableNameExtractor; use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Rules\Rule; @@ -25,21 +28,33 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $result = NodeIdentifier::extractNodeNameAndType($node); - if ($result === null) { + $extractors = [ + new ClassMethodNameExtractor(), + new ClassNameExtractor(), + new VariableNameExtractor(), + ]; + $nodeName = null; + foreach ($extractors as $extractor) { + $extractedName = $extractor->extract($node); + if ($extractedName !== null) { + $nodeName = $extractedName; + break; + } + } + + if ($nodeName === null) { return []; } - [$nodeName, $type] = $result; - if (! static::containsWrongIDCapitalization($nodeName)) { + if (! self::containsWrongIDCapitalization($nodeName)) { return []; } - $expectedName = static::fixIDCapitalization($nodeName); + $expectedName = self::fixIDCapitalization($nodeName); return [ RuleErrorBuilder::message(<<getType()} "{$nodeName}" should use "ID" instead of "Id", rename it to "{$expectedName}". TXT) ->identifier('mll.capitalizationOfID') ->build(), diff --git a/src/PHPStan/Rules/NodeIdentifier.php b/src/PHPStan/Rules/NodeIdentifier.php deleted file mode 100644 index d19c44e..0000000 --- a/src/PHPStan/Rules/NodeIdentifier.php +++ /dev/null @@ -1,47 +0,0 @@ -name)) { - return [$node->name, 'Variable']; - } - if ($node instanceof Node\Param - && $node->var instanceof Variable - && is_string($node->var->name) - ) { - return [$node->var->name, 'Parameter']; - } - if ($node instanceof ClassMethod) { - return [$node->name->toString(), 'ClassMethod']; - } - if ($node instanceof Node\Stmt\Class_ && $node->name instanceof Node\Identifier) { - return [$node->name->toString(), 'Class']; - } - - return null; - } - - /** @return array{0: string, 1: string}|null */ - public static function nodeNameForString(Node $node): ?array - { - if ($node instanceof String_) { - return [$node->value, 'String']; - } - - if ($node instanceof Node\Scalar\EncapsedStringPart) { - return [$node->value, 'String']; - } - - return null; - } -} diff --git a/tests/PHPStan/Rules/CanonicalCapitalizationTest.php b/tests/PHPStan/Rules/CanonicalCapitalization/CanonicalCapitalizationTest.php similarity index 97% rename from tests/PHPStan/Rules/CanonicalCapitalizationTest.php rename to tests/PHPStan/Rules/CanonicalCapitalization/CanonicalCapitalizationTest.php index 26f0b24..0839034 100644 --- a/tests/PHPStan/Rules/CanonicalCapitalizationTest.php +++ b/tests/PHPStan/Rules/CanonicalCapitalization/CanonicalCapitalizationTest.php @@ -1,6 +1,6 @@ */ public static function wrongCapitalizationProvider(): iterable { - yield 'Should correct capitalization for "LabID "' => ['The LabID is incorrect', ['Lab ID', 'LabID ', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for "Lab-ID"' => ['The Lab-ID is incorrect', ['Lab ID', 'Lab-ID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for "lab id"' => ['The lab id is incorrect', ['Lab ID', 'lab id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for " labID"' => ['The labID is incorrect', ['Lab ID', ' labID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for "labID "' => ['labID is incorrect', ['Lab ID', 'labID ', 'Lab ID is incorrect']]; yield 'Should correct capitalization for " LabID"' => ['The LabID', ['Lab ID', ' LabID', 'The Lab ID']]; + yield 'Should correct capitalization for " labID"' => ['The labID is incorrect', ['Lab ID', ' labID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "LABID"' => ['The LABID is incorrect', ['Lab ID', 'LABID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "Lab Id"' => ['The Lab Id is incorrect', ['Lab ID', 'Lab Id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "Lab-ID"' => ['The Lab-ID is incorrect', ['Lab ID', 'Lab-ID', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "LabID "' => ['The LabID is incorrect', ['Lab ID', 'LabID ', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "Labid"' => ['The Labid is incorrect', ['Lab ID', 'Labid', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "lab id"' => ['The lab id is incorrect', ['Lab ID', 'lab id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; yield 'Should correct capitalization for "lab-Id"' => ['The lab-Id is incorrect', ['Lab ID', 'lab-Id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; - yield 'Should correct capitalization for "Lab Id"' => ['The Lab Id is incorrect', ['Lab ID', 'Lab Id', self::EXPECTED_LAB_ID_IS_INCORRECT]]; + yield 'Should correct capitalization for "labID "' => ['labID is incorrect', ['Lab ID', 'labID ', 'Lab ID is incorrect']]; } /** @dataProvider rightCapitalizationProvider */ diff --git a/tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php b/tests/PHPStan/Rules/CapitalizationOfIDRule/CapitalizationOfIDRuleTest.php similarity index 96% rename from tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php rename to tests/PHPStan/Rules/CapitalizationOfIDRule/CapitalizationOfIDRuleTest.php index b99043f..b423aae 100644 --- a/tests/PHPStan/Rules/CapitalizationOfIDRuleTest.php +++ b/tests/PHPStan/Rules/CapitalizationOfIDRule/CapitalizationOfIDRuleTest.php @@ -1,6 +1,6 @@ Date: Mon, 9 Dec 2024 22:46:16 +0100 Subject: [PATCH 17/18] capitalizationOfID --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 543a337..5419f9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ See [GitHub releases](https://github.com/mll-lab/php-utils/releases). - Breaking Change: Rename class `MLL\Utils\PHPStan\Rules\VariableNameIdToIDRule` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` - Make `MLL\Utils\PHPStan\Rules\NameIdToIDRule` handle variable names, parameter names, method names, and class names for incorrect capitalization of `Id` - Add `Idt` and `Identical` to the list of incorrect capitalizations for `Id` of `MLL\Utils\PHPStan\Rules\NameIdToIDRule` -- Add RuleIdentifier `mllLabRules.nameIdToID` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` +- Add RuleIdentifier `mll.capitalizationOfID` to `MLL\Utils\PHPStan\Rules\NameIdToIDRule` - Add PHPStan-rule `MLL\Utils\PHPStan\Rules\CanonicalCapitalizations` to check spelling of LabID ## v5.8.0 From 144e5413555ba1a9e22c0888261d927513597e4b Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Tue, 10 Dec 2024 08:57:44 +0100 Subject: [PATCH 18/18] one thing per line, avoid redundant attribute access --- .../NodeNameExtractor/ClassNameExtractor.php | 7 +++++-- .../NodeNameExtractor/StringNameExtractor.php | 1 + .../VariableNameExtractor.php | 21 ++++++++++++------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php b/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php index 1e9a286..6c80cf3 100644 --- a/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php +++ b/src/PHPStan/NodeNameExtractor/ClassNameExtractor.php @@ -10,8 +10,11 @@ class ClassNameExtractor implements NodeNameExtractor { public function extract(Node $node): ?string { - if ($node instanceof Class_ && $node->name instanceof Identifier) { - return $node->name->toString(); + if ($node instanceof Class_) { + $name = $node->name; + if ($name instanceof Identifier) { + return $name->toString(); + } } return null; diff --git a/src/PHPStan/NodeNameExtractor/StringNameExtractor.php b/src/PHPStan/NodeNameExtractor/StringNameExtractor.php index ba0c586..bca9c99 100644 --- a/src/PHPStan/NodeNameExtractor/StringNameExtractor.php +++ b/src/PHPStan/NodeNameExtractor/StringNameExtractor.php @@ -13,6 +13,7 @@ public function extract(Node $node): ?string if ($node instanceof String_) { return $node->value; } + if ($node instanceof EncapsedStringPart) { return $node->value; } diff --git a/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php b/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php index 1673bd9..8b9dc48 100644 --- a/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php +++ b/src/PHPStan/NodeNameExtractor/VariableNameExtractor.php @@ -10,14 +10,21 @@ class VariableNameExtractor implements NodeNameExtractor { public function extract(Node $node): ?string { - if ($node instanceof Variable && is_string($node->name)) { - return $node->name; + if ($node instanceof Variable) { + $name = $node->name; + if (is_string($name)) { + return $name; + } } - if ($node instanceof Param - && $node->var instanceof Variable - && is_string($node->var->name) - ) { - return $node->var->name; + + if ($node instanceof Param) { + $var = $node->var; + if ($var instanceof Variable) { + $name = $var->name; + if (is_string($name)) { + return $name; + } + } } return null;