From 9812cd0314e53553e9f6625e83f5255b7f7bbc4e Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 10:52:25 +0100 Subject: [PATCH 1/8] feat(ValidClassName): Check traits and enums for valid upperCamel names --- .../NamingConventions/ValidClassNameSniff.php | 12 +++- .../ValidClassNameUnitTest.inc | 25 ++++++++ .../ValidClassNameUnitTest.php | 58 +++++++++++++++++++ .../ValidEnumCaseUnitTest.inc | 4 ++ .../ValidEnumCaseUnitTest.php | 3 +- tests/Drupal/bad/BadUnitTest.php | 2 +- 6 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc create mode 100644 tests/Drupal/NamingConventions/ValidClassNameUnitTest.php diff --git a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php index 11ae5f89..7e0980ac 100644 --- a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php +++ b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -15,7 +15,7 @@ /** * \Drupal\Sniffs\NamingConventions\ValidClassNameSniff. * - * Ensures class and interface names start with a capital letter + * Ensures class, enum, interface and trait names start with a capital letter * and do not use _ separators. * * @category PHP @@ -35,7 +35,9 @@ public function register() { return [ T_CLASS, + T_ENUM, T_INTERFACE, + T_TRAIT, ]; }//end register() @@ -60,7 +62,7 @@ public function process(File $phpcsFile, $stackPtr) // Make sure the first letter is a capital. if (preg_match('|^[A-Z]|', $name) === 0) { - $error = '%s name must begin with a capital letter'; + $error = '%s name must use UpperCamel naming and begin with a capital letter'; $phpcsFile->addError($error, $stackPtr, 'StartWithCapital', $errorData); } @@ -70,6 +72,12 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->addError($error, $stackPtr, 'NoUnderscores', $errorData); } + // Ensure the name is not all uppercase. + if (strtoupper($name) === $name) { + $error = '%s name must use UpperCamel naming and not be all uppercase'; + $phpcsFile->addError($error, $stackPtr, 'NotAllUppercase', $errorData); + } + }//end process() diff --git a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc new file mode 100644 index 00000000..bc1d120d --- /dev/null +++ b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc @@ -0,0 +1,25 @@ + + */ + protected function getErrorList(string $testFile): array + { + return [ + 5 => 2, + 6 => 1, + 7 => 1, + 11 => 2, + 12 => 1, + 13 => 1, + 17 => 2, + 18 => 1, + 19 => 1, + 23 => 2, + 24 => 1, + 25 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + protected function getWarningList(string $testFile): array + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc index d1819d99..e9d6e3c4 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc @@ -5,4 +5,8 @@ enum Test: int { case one = 1; // Must not contain underscores. case TWO_TEST = 2; + // Must not contain only upper case. + case THREE = 3; + // Some upper case parts are allowed for now. + case FourJSONCase = 4; } diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php index eea3216c..28a5135b 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php @@ -22,7 +22,8 @@ protected function getErrorList(string $testFile): array { return [ 5 => 1, - 7 => 1, + 7 => 2, + 9 => 1, ]; }//end getErrorList() diff --git a/tests/Drupal/bad/BadUnitTest.php b/tests/Drupal/bad/BadUnitTest.php index 15c4f045..e9a855ce 100644 --- a/tests/Drupal/bad/BadUnitTest.php +++ b/tests/Drupal/bad/BadUnitTest.php @@ -380,7 +380,7 @@ protected function getErrorList(string $testFile): array 827 => 1, 829 => 1, 836 => 1, - 838 => 1, + 838 => 3, 849 => 2, 860 => 2, 867 => 1, From 71b9bb67120dec1e499a7abb0dce4cad031676ac Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 10:55:00 +0100 Subject: [PATCH 2/8] cs --- tests/Drupal/NamingConventions/ValidClassNameUnitTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.php b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.php index ac8138b5..37803750 100644 --- a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.php +++ b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.php @@ -21,9 +21,9 @@ class ValidClassNameUnitTest extends CoderSniffUnitTest protected function getErrorList(string $testFile): array { return [ - 5 => 2, - 6 => 1, - 7 => 1, + 5 => 2, + 6 => 1, + 7 => 1, 11 => 2, 12 => 1, 13 => 1, From 73c7b84b35d8825c4b266bb19c384680827d4b51 Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 12:18:34 +0100 Subject: [PATCH 3/8] Add support for ignoring --- .../Sniffs/Commenting/ClassCommentSniff.php | 17 ++++++++++++----- tests/Drupal/good/good.php | 9 +++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php index a0c6bb6c..75de9c9b 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php @@ -53,16 +53,23 @@ public function register() */ public function process(File $phpcsFile, $stackPtr) { - $tokens = $phpcsFile->getTokens(); - $find = Tokens::$methodPrefixes; - $find[T_WHITESPACE] = T_WHITESPACE; - $find[T_READONLY] = T_READONLY; + $tokens = $phpcsFile->getTokens(); + $find = ([ + T_ABSTRACT => T_ABSTRACT, + T_FINAL => T_FINAL, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + ] + Tokens::$phpcsCommentTokens); $name = $tokens[$stackPtr]['content']; $classCodeStart = $stackPtr; $previousContent = null; for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { if (isset($find[$tokens[$commentEnd]['code']]) === true) { + if (isset(Tokens::$phpcsCommentTokens[$tokens[$commentEnd]['code']]) === true) { + $classCodeStart = $commentEnd; + } + continue; } @@ -78,7 +85,7 @@ public function process(File $phpcsFile, $stackPtr) } break; - } + }//end for if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index b3b828b7..f3243ec9 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1905,3 +1905,12 @@ public function __construct( ) {} } + +/** + * Doc block is here and an ignore directive is ok. + */ +// phpcs:ignore Drupal.NamingConventions.ValidClassName +enum PUROSELY_WRONG_BUT_OK: int { + case One = 1; + case Two = 2; +} From 22eea724ddd7365ebf2ff8fedce57a2efc3e8a2b Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 12:28:04 +0100 Subject: [PATCH 4/8] implement acronyms --- .../Sniffs/NamingConventions/ValidClassNameSniff.php | 8 ++++---- tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc | 8 ++++---- tests/Drupal/NamingConventions/ValidClassNameUnitTest.php | 4 ++++ tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc | 3 ++- tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php | 7 ++++--- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php index 7e0980ac..373a3372 100644 --- a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php +++ b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -72,10 +72,10 @@ public function process(File $phpcsFile, $stackPtr) $phpcsFile->addError($error, $stackPtr, 'NoUnderscores', $errorData); } - // Ensure the name is not all uppercase. - if (strtoupper($name) === $name) { - $error = '%s name must use UpperCamel naming and not be all uppercase'; - $phpcsFile->addError($error, $stackPtr, 'NotAllUppercase', $errorData); + // Ensure the name does not contain acronyms. + if (preg_match('|[A-Z]{2}|', $name) === 1) { + $error = '%s name must use UpperCamel naming and not contain multiple upper case letters in a row'; + $phpcsFile->addError($error, $stackPtr, 'NoUpperAcronyms', $errorData); } }//end process() diff --git a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc index bc1d120d..960b1665 100644 --- a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc @@ -1,25 +1,25 @@ 1, 5 => 2, 6 => 1, 7 => 1, + 10 => 1, 11 => 2, 12 => 1, 13 => 1, + 16 => 1, 17 => 2, 18 => 1, 19 => 1, + 22 => 1, 23 => 2, 24 => 1, 25 => 1, diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc index e9d6e3c4..adb7a133 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc @@ -7,6 +7,7 @@ enum Test: int { case TWO_TEST = 2; // Must not contain only upper case. case THREE = 3; - // Some upper case parts are allowed for now. + // Upper case parts are not allowed. case FourJSONCase = 4; + case FiveCorrect = 5; } diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php index 28a5135b..ee810ff3 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.php @@ -21,9 +21,10 @@ class ValidEnumCaseUnitTest extends CoderSniffUnitTest protected function getErrorList(string $testFile): array { return [ - 5 => 1, - 7 => 2, - 9 => 1, + 5 => 1, + 7 => 2, + 9 => 1, + 11 => 1, ]; }//end getErrorList() From 70592da5220a3b7f162e6ed7589fb994afda3c78 Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 12:29:30 +0100 Subject: [PATCH 5/8] good spacing --- tests/Drupal/good/good.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index f3243ec9..1e0b252d 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1124,7 +1124,7 @@ public function test8() {} } -t('Some long mulit-line +t('Some long mulit-line text is weird, but allowed.'); // Anonymous functions should not throw indentation errors here. @@ -1911,6 +1911,6 @@ public function __construct( */ // phpcs:ignore Drupal.NamingConventions.ValidClassName enum PUROSELY_WRONG_BUT_OK: int { - case One = 1; - case Two = 2; + case One = 1; + case Two = 2; } From 3f0ca5e727e039305579547a27e5240e2951463d Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 12:48:24 +0100 Subject: [PATCH 6/8] Allow one letter upper case words --- .../NamingConventions/ValidClassNameSniff.php | 2 +- .../ValidClassNameUnitTest.inc | 4 ++++ .../ValidClassNameUnitTest.php | 24 +++++++++---------- .../ValidEnumCaseUnitTest.inc | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php index 373a3372..915d5eff 100644 --- a/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php +++ b/coder_sniffer/Drupal/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -73,7 +73,7 @@ public function process(File $phpcsFile, $stackPtr) } // Ensure the name does not contain acronyms. - if (preg_match('|[A-Z]{2}|', $name) === 1) { + if (preg_match('|[A-Z]{3}|', $name) === 1) { $error = '%s name must use UpperCamel naming and not contain multiple upper case letters in a row'; $phpcsFile->addError($error, $stackPtr, 'NoUpperAcronyms', $errorData); } diff --git a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc index 960b1665..6b5dd4ad 100644 --- a/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidClassNameUnitTest.inc @@ -1,24 +1,28 @@ 1, - 5 => 2, - 6 => 1, + 5 => 1, + 6 => 2, 7 => 1, - 10 => 1, - 11 => 2, + 8 => 1, 12 => 1, - 13 => 1, - 16 => 1, - 17 => 2, - 18 => 1, + 13 => 2, + 14 => 1, + 15 => 1, 19 => 1, + 20 => 2, + 21 => 1, 22 => 1, - 23 => 2, - 24 => 1, - 25 => 1, + 26 => 1, + 27 => 2, + 28 => 1, + 29 => 1, ]; }//end getErrorList() diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc index adb7a133..d3eb6681 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc @@ -9,5 +9,5 @@ enum Test: int { case THREE = 3; // Upper case parts are not allowed. case FourJSONCase = 4; - case FiveCorrect = 5; + case FiveAndAHorseCorrect = 5; } From 9edfa56d79f282be429ac9a30b07a8d2e6b1dbe0 Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sun, 5 Jan 2025 12:51:27 +0100 Subject: [PATCH 7/8] revert good --- tests/Drupal/good/good.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 1e0b252d..bd8d911b 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1124,7 +1124,7 @@ public function test8() {} } -t('Some long mulit-line +t('Some long mulit-line text is weird, but allowed.'); // Anonymous functions should not throw indentation errors here. From d40ade4e5205bd72766eab0b9fb707a4484b31ea Mon Sep 17 00:00:00 2001 From: Klaus Purer Date: Sat, 11 Jan 2025 16:43:45 +0100 Subject: [PATCH 8/8] add short test case --- .../NamingConventions/ValidEnumCaseUnitTest.inc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc index d3eb6681..1bd88114 100644 --- a/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc +++ b/tests/Drupal/NamingConventions/ValidEnumCaseUnitTest.inc @@ -11,3 +11,17 @@ enum Test: int { case FourJSONCase = 4; case FiveAndAHorseCorrect = 5; } + +// Those are all ok. +enum FiscalQuarter { + case Q1; + case Q2; + case Q3; + case Q4; +} + +enum Plan { + case A; + case B; + case C; +}