Skip to content

Add Sniffing support for interfaces and traits #16

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 1 commit into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions BigBite/Docs/Files/FileNameStandard.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<documentation title="File Names">
<standard>
<![CDATA[
Files containing classes should be prefixed with "class-" or "abstract-class", and be named
as the class name in lower-kebab-case. For example:
the file name for abstract class My_Class_Name {} would be "abstract-class-my-class-name.php".
Files containing classes, interfaces, or traits should be prefixed appropriately - prefixed with the type, and then lower-kebab-case matching the name of the type. Examples:
- trait My_Trait {} => 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
]]>
</standard>
</documentation>
128 changes: 99 additions & 29 deletions BigBite/Sniffs/Files/FileNameSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
Expand Down Expand Up @@ -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
*
Expand Down
16 changes: 12 additions & 4 deletions BigBite/Tests/Files/FileNameUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

interface My_Interface {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- Annotation has to be on the second line as errors are thrown on line 1 and errors on annotation lines are ignored. -->
phpcs:set BigBite.Files.FileName strict_class_file_names false

<?php

interface Non_Strict_Interface {}

// phpcs:set BigBite.Files.FileName strict_class_file_names true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- Annotation has to be on the second line as errors are thrown on line 1 and errors on annotation lines are ignored. -->
phpcs:set BigBite.Files.FileName strict_class_file_names false

<?php

trait Non_Strict_Trait {}

// phpcs:set BigBite.Files.FileName strict_class_file_names true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- Annotation has to be on the second line as errors are thrown on line 1 and errors on annotation lines are ignored. -->
phpcs:set BigBite.Files.FileName strict_class_file_names false

<?php

interface Non_Strict_Interface {}

// phpcs:set BigBite.Files.FileName strict_class_file_names true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!-- Annotation has to be on the second line as errors are thrown on line 1 and errors on annotation lines are ignored. -->
phpcs:set BigBite.Files.FileName strict_class_file_names false

<?php

trait Non_Strict_Trait {}

// phpcs:set BigBite.Files.FileName strict_class_file_names true
3 changes: 3 additions & 0 deletions BigBite/Tests/Files/FileNameUnitTests/TraitMyTrait.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

trait My_Trait {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

interface Not_My_Interface {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

interface My_Interface {}
3 changes: 3 additions & 0 deletions BigBite/Tests/Files/FileNameUnitTests/my-interface.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

interface My_Interface {}
3 changes: 3 additions & 0 deletions BigBite/Tests/Files/FileNameUnitTests/my-trait.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

trait My_Trait {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

trait Not_My_Trait {}
3 changes: 3 additions & 0 deletions BigBite/Tests/Files/FileNameUnitTests/trait-my-trait.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

trait My_Trait {}