From 45fb487d6462f51b1fda91ca5085c9498ff7e508 Mon Sep 17 00:00:00 2001 From: Jon McPartland Date: Thu, 14 Apr 2022 14:09:51 +0100 Subject: [PATCH] Add Sniffing support for interfaces and traits --- BigBite/Docs/Files/FileNameStandard.xml | 8 +- BigBite/Sniffs/Files/FileNameSniff.php | 128 ++++++++++++++---- BigBite/Tests/Files/FileNameUnitTest.php | 16 ++- .../InterfaceMyInterface.inc | 3 + .../InterfaceNonStrictClass.inc | 8 ++ .../TraitNonStrictClass.inc | 8 ++ .../non-strict-interface.inc | 8 ++ .../NonStrictClassNames/non-strict-trait.inc | 8 ++ .../Files/FileNameUnitTests/TraitMyTrait.inc | 3 + .../interface-different-interface.inc | 3 + .../interface-my-interface.inc | 3 + .../Files/FileNameUnitTests/my-interface.inc | 3 + .../Files/FileNameUnitTests/my-trait.inc | 3 + .../trait-different-trait.inc | 3 + .../FileNameUnitTests/trait-my-trait.inc | 3 + 15 files changed, 172 insertions(+), 36 deletions(-) create mode 100644 BigBite/Tests/Files/FileNameUnitTests/InterfaceMyInterface.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/NonStrictClassNames/InterfaceNonStrictClass.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/NonStrictClassNames/TraitNonStrictClass.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/NonStrictClassNames/non-strict-interface.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/NonStrictClassNames/non-strict-trait.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/TraitMyTrait.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/interface-different-interface.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/interface-my-interface.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/my-interface.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/my-trait.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/trait-different-trait.inc create mode 100644 BigBite/Tests/Files/FileNameUnitTests/trait-my-trait.inc diff --git a/BigBite/Docs/Files/FileNameStandard.xml b/BigBite/Docs/Files/FileNameStandard.xml index 0478b06..e75d80a 100644 --- a/BigBite/Docs/Files/FileNameStandard.xml +++ b/BigBite/Docs/Files/FileNameStandard.xml @@ -1,9 +1,11 @@ trait-my-trait.php + - interface My_Interface {} => interface-my-interface.php + - class My_Class {} => class-my-class.php + - abstract class My_Abstract_Class {} => abstract-class-my-abstract-class.php ]]> diff --git a/BigBite/Sniffs/Files/FileNameSniff.php b/BigBite/Sniffs/Files/FileNameSniff.php index f31b50e..bcbe164 100644 --- a/BigBite/Sniffs/Files/FileNameSniff.php +++ b/BigBite/Sniffs/Files/FileNameSniff.php @@ -59,37 +59,14 @@ public function process_token( $stackPtr ) { unset( $expected ); - /* - * Check files containing a class for the "class-" prefix and that the rest of - * the file name reflects the class name. Accounts for abstract classes. - */ - if ( true === $this->strict_class_file_names ) { - $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); - - if ( false !== $has_class && false === $this->is_test_class( $has_class ) ) { - $is_abstract = $this->phpcsFile->findPrevious( \T_ABSTRACT, $has_class ); - $class_name = $this->phpcsFile->getDeclarationName( $has_class ); - - if ( is_null( $class_name ) ) { - $class_name = 'anonymous'; - } - - $expected = 'class-' . $this->kebab( $class_name ); - $err_message = 'Class file names should be based on the class name with "class-" prepended. Expected %s, but found %s.'; - - if ( $is_abstract ) { - $expected = 'abstract-' . $expected; - $err_message = 'Abstract class file names should be based on the class name with "abstract-class-" prepended. Expected %s, but found %s.'; - } - - if ( substr( $fileName, 0, -4 ) !== $expected ) { - $this->phpcsFile->addError( $err_message, 0, 'InvalidClassFileName', [ $expected . '.php', $fileName ] ); - } - - unset( $expected ); - } + if ( true !== $this->strict_class_file_names ) { + return ( $this->phpcsFile->numTokens + 1 ); } + $this->check_maybe_class( $stackPtr, $fileName ); + $this->check_maybe_trait( $stackPtr, $fileName ); + $this->check_maybe_interface( $stackPtr, $fileName ); + // Only run this sniff once per file, no need to run it again. return ( $this->phpcsFile->numTokens + 1 ); } @@ -129,6 +106,99 @@ protected function is_disabled_by_comments() { return false; } + /** + * Check files containing a class for the "class-" prefix, + * and that the rest of the file name reflects the class name. + * Accounts for abstract classes. + * + * @param mixed $stackPtr the token stack + * @param string $fileName the name of the file + * + * @return void + */ + protected function check_maybe_class( $stackPtr, $fileName ) { + $has_class = $this->phpcsFile->findNext( \T_CLASS, $stackPtr ); + + if ( false === $has_class || false !== $this->is_test_class( $has_class ) ) { + return; + } + + $is_abstract = $this->phpcsFile->findPrevious( \T_ABSTRACT, $has_class ); + $class_name = $this->phpcsFile->getDeclarationName( $has_class ); + + if ( is_null( $class_name ) ) { + $class_name = 'anonymous'; + } + + $expected = 'class-' . $this->kebab( $class_name ); + $err_message = 'Class file names should be based on the class name with "class-" prepended. Expected %s, but found %s.'; + + if ( $is_abstract ) { + $expected = 'abstract-' . $expected; + $err_message = 'Abstract class file names should be based on the class name with "abstract-class-" prepended. Expected %s, but found %s.'; + } + + if ( substr( $fileName, 0, -4 ) === $expected ) { + return; + } + + $this->phpcsFile->addError( $err_message, 0, 'InvalidClassFileName', [ $expected . '.php', $fileName ] ); + } + + /** + * Check files containing a trait for the "trait-" prefix, + * and that the rest of the file name reflects the trait name. + * + * @param mixed $stackPtr the token stack + * @param string $fileName the name of the file + * + * @return void + */ + protected function check_maybe_trait( $stackPtr, $fileName ) { + $has_trait = $this->phpcsFile->findNext( \T_TRAIT, $stackPtr ); + + if ( false === $has_trait || false !== $this->is_test_class( $has_trait ) ) { + return; + } + + $trait_name = $this->phpcsFile->getDeclarationName( $has_trait ); + $expected = 'trait-' . $this->kebab( $trait_name ); + $err_message = 'Trait file names should be based on the class name with "trait-" prepended. Expected %s, but found %s.'; + + if ( substr( $fileName, 0, -4 ) === $expected ) { + return; + } + + $this->phpcsFile->addError( $err_message, 0, 'InvalidTraitFileName', [ $expected . '.php', $fileName ] ); + } + + /** + * Check files containing an interface for the "interface-" prefix, + * and that the rest of the file name reflects the interface name. + * + * @param mixed $stackPtr the token stack + * @param string $fileName the name of the file + * + * @return void + */ + protected function check_maybe_interface( $stackPtr, $fileName ) { + $has_interface = $this->phpcsFile->findNext( \T_INTERFACE, $stackPtr ); + + if ( false === $has_interface || false !== $this->is_test_class( $has_interface ) ) { + return; + } + + $interface_name = $this->phpcsFile->getDeclarationName( $has_interface ); + $expected = 'interface-' . $this->kebab( $interface_name ); + $err_message = 'Interface file names should be based on the interface name with "interface-" prepended. Expected %s, but found %s.'; + + if ( substr( $fileName, 0, -4 ) === $expected ) { + return; + } + + $this->phpcsFile->addError( $err_message, 0, 'InvalidInterfaceFileName', [ $expected . '.php', $fileName ] ); + } + /** * Convert a string to kebab-case * diff --git a/BigBite/Tests/Files/FileNameUnitTest.php b/BigBite/Tests/Files/FileNameUnitTest.php index 7cbeccd..64541a7 100644 --- a/BigBite/Tests/Files/FileNameUnitTest.php +++ b/BigBite/Tests/Files/FileNameUnitTest.php @@ -36,12 +36,18 @@ class FileNameUnitTest extends AbstractSniffUnitTest { 'SomeView.inc' => 1, // Class file names. - 'my-class.inc' => 1, 'my-abstract-class.inc' => 1, - 'class-different-class.inc' => 1, + 'my-class.inc' => 1, + 'my-interface.inc' => 1, + 'my-trait.inc' => 1, 'abstract-class-different-class.inc' => 1, - 'ClassMyClass.inc' => 2, + 'class-different-class.inc' => 1, + 'interface-different-interface.inc' => 1, + 'trait-different-trait.inc' => 1, 'AbstractClassMyClass.inc' => 2, + 'ClassMyClass.inc' => 2, + 'InterfaceMyInterface.inc' => 2, + 'TraitMyTrait.inc' => 2, // Theme specific exceptions in a non-theme context. 'single-my_post_type.inc' => 1, @@ -52,8 +58,10 @@ class FileNameUnitTest extends AbstractSniffUnitTest { */ // Non-strict class names still have to comply with lowercase hyphenated. - 'ClassNonStrictClass.inc' => 1, 'AbstractClassNonStrictClass.inc' => 1, + 'ClassNonStrictClass.inc' => 1, + 'InterfaceNonStrictClass.inc' => 1, + 'TraitNonStrictClass.inc' => 1, /* * In /FileNameUnitTests/PHPCSAnnotations. diff --git a/BigBite/Tests/Files/FileNameUnitTests/InterfaceMyInterface.inc b/BigBite/Tests/Files/FileNameUnitTests/InterfaceMyInterface.inc new file mode 100644 index 0000000..9046a49 --- /dev/null +++ b/BigBite/Tests/Files/FileNameUnitTests/InterfaceMyInterface.inc @@ -0,0 +1,3 @@ + +phpcs:set BigBite.Files.FileName strict_class_file_names false + + +phpcs:set BigBite.Files.FileName strict_class_file_names false + + +phpcs:set BigBite.Files.FileName strict_class_file_names false + + +phpcs:set BigBite.Files.FileName strict_class_file_names false + +