-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from bigbite/feature/filename-sniff
Add sniff for file name conventions
- Loading branch information
Showing
69 changed files
with
2,949 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# editorconfig.org | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
end_of_line = lf | ||
indent_size = 2 | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
|
||
[*.{json,php}] | ||
indent_size = 4 | ||
indent_style = tab | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
composer.phar | ||
.vscode/ | ||
/vendor/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?xml version="1.0"?> | ||
<ruleset name="Big Bite CS" namespace="BigBite"> | ||
<description>The Coding Standard for the Big Bite Coding Standards.</description> | ||
|
||
<file>.</file> | ||
|
||
<config name="encoding" value="utf-8" /> | ||
<config name="testVersion" value="7.0-" /> | ||
|
||
<arg name="basepath" value="." /> | ||
<arg name="extensions" value="php" /> | ||
<arg name="tab-width" value="4" /> | ||
<arg value="qs" /> | ||
|
||
<!-- Exclude Composer vendor directory. --> | ||
<exclude-pattern>*/vendor/*</exclude-pattern> | ||
|
||
<rule ref="BigBite"> | ||
<exclude name="BigBite.Files.FileName" /> | ||
<exclude name="WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition" /> | ||
<exclude name="WordPress.NamingConventions.ValidVariableName" /> | ||
</rule> | ||
|
||
<!-- Enforce PSR1 compatible namespaces. --> | ||
<rule ref="PSR1.Classes.ClassDeclaration" /> | ||
|
||
<!-- prevent empty lines between method bodies and closing braces --> | ||
<rule ref="PSR2.Methods.FunctionClosingBrace" /> | ||
|
||
<!-- Check code for cross-version PHP compatibility. --> | ||
<rule ref="PHPCompatibility"> | ||
<!-- Exclude PHP constants back-filled by PHPCS. --> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_finallyFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_yieldFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_ellipsisFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_powFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_pow_equalFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_spaceshipFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_coalesceFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_coalesce_equalFound" /> | ||
<exclude name="PHPCompatibility.Constants.NewConstants.t_yield_fromFound" /> | ||
</rule> | ||
</ruleset> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<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". | ||
]]> | ||
</standard> | ||
</documentation> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
<?php | ||
|
||
/** | ||
* BigBite Coding Standards. | ||
* | ||
* @package BigBite\phpcs-config | ||
* @link https://github.com/bigbite/phpcs-config | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
declare( strict_types = 1 ); | ||
|
||
namespace BigBiteCS\BigBite\Sniffs\Files; | ||
|
||
use WordPressCS\WordPress\Sniffs\Files\FileNameSniff as WPFileNameSniff; | ||
|
||
/** | ||
* Ensures filenames are kebab-case, and are named appropriately | ||
*/ | ||
class FileNameSniff extends WPFileNameSniff { | ||
|
||
/** | ||
* Processes this test when one of its tokens is encountered. | ||
* | ||
* @param int $stackPtr The position of the current token in the stack. | ||
* | ||
* @return int|void Integer stack pointer to skip forward or void to continue | ||
* normal file processing. | ||
*/ | ||
public function process_token( $stackPtr ) { | ||
// strip quotes to ensure `stdin_path` passed by IDEs does not include quotes. | ||
$file = preg_replace( '`^([\'"])(.*)\1$`Ds', '$2', $this->phpcsFile->getFileName() ); | ||
|
||
if ( 'STDIN' === $file ) { | ||
return; | ||
} | ||
|
||
if ( $this->is_disabled_by_comments() ) { | ||
return; | ||
} | ||
|
||
$fileName = basename( $file ); | ||
|
||
list( $ext, $file ) = explode( '.', strrev( $fileName ), 2 ); | ||
|
||
$expected = $this->kebab( strrev( $file ) ) . '.' . strrev( $ext ); | ||
|
||
/* | ||
* Generic check for lowercase hyphenated file names. | ||
*/ | ||
if ( $fileName !== $expected && ( false === $this->is_theme || 1 !== preg_match( self::THEME_EXCEPTIONS_REGEX, $fileName ) ) ) { | ||
$this->phpcsFile->addError( | ||
'Filenames should be all lowercase with hyphens as word separators. Expected %s, but found %s.', | ||
0, | ||
'NotHyphenatedLowercase', | ||
[ $expected, $fileName ] | ||
); | ||
} | ||
|
||
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 ); | ||
$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 ); | ||
} | ||
} | ||
|
||
// Only run this sniff once per file, no need to run it again. | ||
return ( $this->phpcsFile->numTokens + 1 ); | ||
} | ||
|
||
/** | ||
* Respect phpcs:disable comments as long as they are not accompanied by an enable (PHPCS 3.2+). | ||
* | ||
* @return bool | ||
*/ | ||
protected function is_disabled_by_comments() { | ||
if ( ! \defined( '\T_PHPCS_DISABLE' ) || ! \defined( '\T_PHPCS_ENABLE' ) ) { | ||
return false; | ||
} | ||
|
||
$i = -1; | ||
while ( $i = $this->phpcsFile->findNext( \T_PHPCS_DISABLE, ( $i + 1 ) ) ) { | ||
if ( empty( $this->tokens[ $i ]['sniffCodes'] ) | ||
|| isset( $this->tokens[ $i ]['sniffCodes']['BigBite'] ) | ||
|| isset( $this->tokens[ $i ]['sniffCodes']['BigBite.Files'] ) | ||
|| isset( $this->tokens[ $i ]['sniffCodes']['BigBite.Files.FileName'] ) | ||
) { | ||
do { | ||
$i = $this->phpcsFile->findNext( \T_PHPCS_ENABLE, ( $i + 1 ) ); | ||
} while ( false !== $i | ||
&& ! empty( $this->tokens[ $i ]['sniffCodes'] ) | ||
&& ! isset( $this->tokens[ $i ]['sniffCodes']['BigBite'] ) | ||
&& ! isset( $this->tokens[ $i ]['sniffCodes']['BigBite.Files'] ) | ||
&& ! isset( $this->tokens[ $i ]['sniffCodes']['BigBite.Files.FileName'] ) ); | ||
|
||
if ( false === $i ) { | ||
// The entire (rest of the) file is disabled. | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Convert a string to kebab-case | ||
* | ||
* @param string $string the string to texturise | ||
* | ||
* @return string | ||
*/ | ||
protected function kebab( $string = '' ) { | ||
$kebab = preg_replace( '/(?>(?!^[A-Z]))([a-z])([A-Z])/', '$1-$2', $string ); | ||
$kebab = strtolower( $kebab ); | ||
$kebab = str_replace( '_', '-', $kebab ); | ||
|
||
// allow wordpress to be one word | ||
if ( false !== strpos( $string, 'WordPress' ) ) { | ||
$kebab = str_replace( 'word-press', 'wordpress', $kebab ); | ||
} | ||
|
||
return $kebab; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace BigBiteCS\BigBite\Tests; | ||
|
||
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest as PhpCsAbstractSniffUnitTest; | ||
|
||
abstract class AbstractSniffUnitTest extends PhpCsAbstractSniffUnitTest { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<?php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
<?php | ||
/** | ||
* Unit test class for BigBite Coding Standard. | ||
* | ||
* @package BigBiteCS\BigBite | ||
* @link https://github.com/bigbite/phpcs-config | ||
* @license https://opensource.org/licenses/MIT MIT | ||
*/ | ||
|
||
namespace BigBiteCS\BigBite\Tests\Files; | ||
|
||
use BigBiteCS\BigBite\Tests\AbstractSniffUnitTest; | ||
|
||
/** | ||
* Unit test class for the FileName sniff. | ||
* | ||
* @package BigBiteCS\BigBite | ||
*/ | ||
class FileNameUnitTest extends AbstractSniffUnitTest { | ||
|
||
/** | ||
* Error files with the expected nr of errors. | ||
* | ||
* @var array | ||
*/ | ||
private $expected_results = array( | ||
|
||
/* | ||
* In /FileNameUnitTests. | ||
*/ | ||
|
||
// File names generic. | ||
'some_file.inc' => 1, | ||
'SomeFile.inc' => 1, | ||
'some-File.inc' => 1, | ||
'SomeView.inc' => 1, | ||
|
||
// Class file names. | ||
'my-class.inc' => 1, | ||
'my-abstract-class.inc' => 1, | ||
'class-different-class.inc' => 1, | ||
'abstract-class-different-class.inc' => 1, | ||
'ClassMyClass.inc' => 2, | ||
'AbstractClassMyClass.inc' => 2, | ||
|
||
// Theme specific exceptions in a non-theme context. | ||
'single-my_post_type.inc' => 1, | ||
'taxonomy-post_format-post-format-audio.inc' => 1, | ||
|
||
/* | ||
* In /FileNameUnitTests/NonStrictClassNames. | ||
*/ | ||
|
||
// Non-strict class names still have to comply with lowercase hyphenated. | ||
'ClassNonStrictClass.inc' => 1, | ||
'AbstractClassNonStrictClass.inc' => 1, | ||
|
||
/* | ||
* In /FileNameUnitTests/PHPCSAnnotations. | ||
*/ | ||
|
||
// Non-strict class names still have to comply with lowercase hyphenated. | ||
'blanket-disable.inc' => 0, | ||
'non-relevant-disable.inc' => 1, | ||
'partial-file-disable.inc' => 1, | ||
'rule-disable.inc' => 0, | ||
'wordpress-disable.inc' => 0, | ||
|
||
/* | ||
* In /FileNameUnitTests/TestFiles. | ||
*/ | ||
'test-sample-phpunit.inc' => 0, | ||
'test-sample-phpunit6.inc' => 0, | ||
'test-sample-wpunit.inc' => 0, | ||
'test-sample-custom-unit.inc' => 0, | ||
'test-sample-namespaced-declaration-1.inc' => 0, | ||
'test-sample-namespaced-declaration-2.inc' => 1, // Namespaced vs non-namespaced. | ||
'test-sample-namespaced-declaration-3.inc' => 1, // Wrong namespace. | ||
'test-sample-namespaced-declaration-4.inc' => 1, // Non-namespaced vs namespaced. | ||
'test-sample-global-namespace-extends-1.inc' => 0, // Prefixed user input. | ||
'test-sample-global-namespace-extends-2.inc' => 1, // Non-namespaced vs namespaced. | ||
'test-sample-extends-with-use.inc' => 0, | ||
'test-sample-namespaced-extends-1.inc' => 0, | ||
'test-sample-namespaced-extends-2.inc' => 1, // Wrong namespace. | ||
'test-sample-namespaced-extends-3.inc' => 1, // Namespaced vs non-namespaced. | ||
'test-sample-namespaced-extends-4.inc' => 1, // Non-namespaced vs namespaced. | ||
'test-sample-namespaced-extends-5.inc' => 0, | ||
|
||
/* | ||
* In /FileNameUnitTests/ThemeExceptions. | ||
*/ | ||
|
||
// Files in a theme context. | ||
'front_page.inc' => 1, | ||
'FrontPage.inc' => 1, | ||
'author-nice_name.inc' => 1, | ||
|
||
/* | ||
* In /FileNameUnitTests/wp-includes. | ||
*/ | ||
|
||
// Files containing template tags. | ||
'general.inc' => 1, | ||
|
||
/* | ||
* In /. | ||
*/ | ||
|
||
// Fall-back file in case glob() fails. | ||
'FileNameUnitTest.inc' => 1, | ||
); | ||
|
||
/** | ||
* Get a list of all test files to check. | ||
* | ||
* @param string $testFileBase The base path that the unit tests files will have. | ||
* | ||
* @return string[] | ||
*/ | ||
protected function getTestFiles( $testFileBase ) { | ||
$sep = \DIRECTORY_SEPARATOR; | ||
$test_files = glob( dirname( $testFileBase ) . $sep . 'FileNameUnitTests{' . $sep . ',' . $sep . '*' . $sep . '}*.inc', \GLOB_BRACE ); | ||
|
||
if ( ! empty( $test_files ) ) { | ||
return $test_files; | ||
} | ||
|
||
return array( $testFileBase . '.inc' ); | ||
} | ||
|
||
/** | ||
* Returns the lines where errors should occur. | ||
* | ||
* @param string $testFile The name of the file being tested. | ||
* @return array <int line number> => <int number of errors> | ||
*/ | ||
public function getErrorList( $testFile = '' ) { | ||
if ( isset( $this->expected_results[ $testFile ] ) ) { | ||
return array( | ||
1 => $this->expected_results[ $testFile ], | ||
); | ||
} | ||
|
||
return array(); | ||
} | ||
|
||
/** | ||
* Returns the lines where warnings should occur. | ||
* | ||
* @return array <int line number> => <int number of warnings> | ||
*/ | ||
public function getWarningList() { | ||
return array(); | ||
} | ||
|
||
} |
3 changes: 3 additions & 0 deletions
3
BigBite/Tests/Files/FileNameUnitTests/AbstractClassMyClass.inc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
abstract class My_Class {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<?php | ||
|
||
class My_Class {} |
Oops, something went wrong.