-
-
Notifications
You must be signed in to change notification settings - Fork 7
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 #119 from PHPCSStandards/feature/new-namingconvent…
…ions-class New `NamingConventions` class
- Loading branch information
Showing
3 changed files
with
344 additions
and
0 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,113 @@ | ||
<?php | ||
/** | ||
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers. | ||
* | ||
* @package PHPCSUtils | ||
* @copyright 2019-2020 PHPCSUtils Contributors | ||
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3 | ||
* @link https://github.com/PHPCSStandards/PHPCSUtils | ||
*/ | ||
|
||
namespace PHPCSUtils\Utils; | ||
|
||
/** | ||
* Utility functions for working with identifier names. | ||
* | ||
* Identifiers in PHP are namespace names, class/trait/interface names, function names, | ||
* variable names and constant names. | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class NamingConventions | ||
{ | ||
|
||
/** | ||
* Regular expression to check if a given identifier name is valid for use in PHP. | ||
* | ||
* @link http://php.net/manual/en/language.variables.basics.php | ||
* @link http://php.net/manual/en/language.constants.php | ||
* @link http://php.net/manual/en/functions.user-defined.php | ||
* @link http://php.net/manual/en/language.oop5.basic.php | ||
* | ||
* @since 1.0.0 | ||
* | ||
* @var string | ||
*/ | ||
const PHP_LABEL_REGEX = '`^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$`'; | ||
|
||
/** | ||
* Uppercase A-Z. | ||
* | ||
* @since 1.0.0 | ||
* | ||
* @var string | ||
*/ | ||
const AZ_UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; | ||
|
||
/** | ||
* Lowercase a-z. | ||
* | ||
* @since 1.0.0 | ||
* | ||
* @var string | ||
*/ | ||
const AZ_LOWER = 'abcdefghijklmnopqrstuvwxyz'; | ||
|
||
/** | ||
* Verify whether an arbitrary text string is valid as an identifier name in PHP. | ||
* | ||
* For variable names: the leading `$` needs to be removed prior to passing the name to this method. | ||
* | ||
* @since 1.0.0 | ||
* | ||
* @param string $name The name. | ||
* | ||
* @return bool | ||
*/ | ||
public static function isValidIdentifierName($name) | ||
{ | ||
if (is_string($name) === false || $name === '' || \strpos($name, ' ') !== false) { | ||
return false; | ||
} | ||
|
||
return (\preg_match(self::PHP_LABEL_REGEX, $name) === 1); | ||
} | ||
|
||
/** | ||
* Check if two arbitrary identifier names will be seen as the same in PHP. | ||
* | ||
* This method should not be used for variable or constant names, but *should* be used | ||
* when comparing namespace, class/trait/interface and function names. | ||
* | ||
* Variable and constant names in PHP are case-sensitive, except for constants explicitely | ||
* declared case-insensitive using the third parameter for `define()`. | ||
* | ||
* All other names are case-insensitive for the most part, but as it's PHP, not completely. | ||
* Basically ASCII chars used are case-insensitive, but anything from 0x80 up is case-sensitive. | ||
* | ||
* This method takes this case-(in)sensitivity into account when comparing identifier names. | ||
* | ||
* Note: this method does not check whether the passed names would be valid for identifiers! | ||
* See the {@see \PHPCSUtils\Utils\NamingConventions::isValidIdentifierName()} method. | ||
* | ||
* @since 1.0.0 | ||
* | ||
* @param string $nameA The first identifier name. | ||
* @param string $nameB The second identifier name. | ||
* | ||
* @return bool TRUE if these names would be considered the same in PHP, FALSE otherwise. | ||
*/ | ||
public static function isEqual($nameA, $nameB) | ||
{ | ||
// Simple quick check first. | ||
if ($nameA === $nameB) { | ||
return true; | ||
} | ||
|
||
// OK, so these may be different names or they may be the same name with case differences. | ||
$nameA = \strtr($nameA, self::AZ_UPPER, self::AZ_LOWER); | ||
$nameB = \strtr($nameB, self::AZ_UPPER, self::AZ_LOWER); | ||
|
||
return ($nameA === $nameB); | ||
} | ||
} |
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,101 @@ | ||
<?php | ||
/** | ||
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers. | ||
* | ||
* @package PHPCSUtils | ||
* @copyright 2019-2020 PHPCSUtils Contributors | ||
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3 | ||
* @link https://github.com/PHPCSStandards/PHPCSUtils | ||
*/ | ||
|
||
namespace PHPCSUtils\Tests\Utils\NamingConventions; | ||
|
||
use PHPCSUtils\Utils\NamingConventions; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* Tests for the \PHPCSUtils\Utils\NamingConventions::isEqual() method. | ||
* | ||
* @covers \PHPCSUtils\Utils\NamingConventions::isEqual | ||
* | ||
* @group namingconventions | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class IsEqualTest extends TestCase | ||
{ | ||
|
||
/** | ||
* Test whether two arbitrary strings are considered equal for PHP identifier names. | ||
* | ||
* @dataProvider dataIsEqual | ||
* | ||
* @param string $inputA The first name. | ||
* @param string $inputB The second name. | ||
* @param array $expected The expected function output. | ||
* | ||
* @return void | ||
*/ | ||
public function testIsEqual($inputA, $inputB, $expected) | ||
{ | ||
$this->assertSame($expected, NamingConventions::isEqual($inputA, $inputB)); | ||
} | ||
|
||
/** | ||
* Data provider. | ||
* | ||
* @see testIsEqual() For the array format. | ||
* | ||
* @return array | ||
*/ | ||
public function dataIsEqual() | ||
{ | ||
return [ | ||
'a-z-0-9-only-same-case' => [ | ||
'abcdefghijklmnopqrstuvwxyz_0123456789', | ||
'abcdefghijklmnopqrstuvwxyz_0123456789', | ||
true, | ||
], | ||
'a-z-0-9-only-different-case' => [ | ||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789', | ||
'abcdefghijklmnopqrstuvwxyz_0123456789', | ||
true, | ||
], | ||
'extended-ascii-same-case' => [ | ||
'ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢áíóúñÑ', | ||
'ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢áíóúñÑ', | ||
true, | ||
], | ||
'extended-ascii-different-case' => [ | ||
'ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢áíóúñÑ', | ||
'çÜÉÂÄÀÅÇÊËÈÏÎÌäåéÆæÔÖÒÛÙŸöü¢ÁÍÓÚÑñ', | ||
false, | ||
], | ||
'mixed-ascii-extended-ascii-same-case' => [ | ||
'Déjàvü', | ||
'Déjàvü', | ||
true, | ||
], | ||
'mixed-ascii-extended-ascii-different-case-only-for-ascii' => [ | ||
'Déjàvü', | ||
'déJàVü', | ||
true, | ||
], | ||
'mixed-ascii-extended-ascii-different-case' => [ | ||
'Déjàvü', | ||
'DÉJÀVÜ', | ||
false, | ||
], | ||
'emoji-name' => [ | ||
'💩💩💩', | ||
'💩💩💩', | ||
true, | ||
], | ||
'invalid-input-but-not-relevant' => [ | ||
true, | ||
true, | ||
true, | ||
], | ||
]; | ||
} | ||
} |
130 changes: 130 additions & 0 deletions
130
Tests/Utils/NamingConventions/IsValidIdentifierNameTest.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,130 @@ | ||
<?php | ||
/** | ||
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers. | ||
* | ||
* @package PHPCSUtils | ||
* @copyright 2019-2020 PHPCSUtils Contributors | ||
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3 | ||
* @link https://github.com/PHPCSStandards/PHPCSUtils | ||
*/ | ||
|
||
namespace PHPCSUtils\Tests\Utils\NamingConventions; | ||
|
||
use PHPCSUtils\Utils\NamingConventions; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* Tests for the \PHPCSUtils\Utils\NamingConventions::isValidIdentifierName() method. | ||
* | ||
* @covers \PHPCSUtils\Utils\NamingConventions::isValidIdentifierName | ||
* | ||
* @group namingconventions | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class IsValidIdentifierNameTest extends TestCase | ||
{ | ||
|
||
/** | ||
* Test correctly detecting whether an arbitrary string can be a valid PHP identifier name. | ||
* | ||
* @dataProvider dataIsValidIdentifierName | ||
* | ||
* @param string $input The input string. | ||
* @param array $expected The expected function output. | ||
* | ||
* @return void | ||
*/ | ||
public function testIsValidIdentifierName($input, $expected) | ||
{ | ||
$this->assertSame($expected, NamingConventions::isValidIdentifierName($input)); | ||
} | ||
|
||
/** | ||
* Data provider. | ||
* | ||
* @see testIsValidIdentifierName() For the array format. | ||
* | ||
* @return array | ||
*/ | ||
public function dataIsValidIdentifierName() | ||
{ | ||
return [ | ||
// Valid names. | ||
'a-z-only' => [ | ||
'valid_name', | ||
true, | ||
], | ||
'a-z-uppercase' => [ | ||
'VALID_NAME', | ||
true, | ||
], | ||
'a-z-camel-caps' => [ | ||
'Valid_Name', | ||
true, | ||
], | ||
'alphanum-mixed-case' => [ | ||
'VaLiD128NaMe', | ||
true, | ||
], | ||
'underscore-prefix' => [ | ||
'_valid_name', | ||
true, | ||
], | ||
'double-underscore-prefix' => [ | ||
'__valid_name', | ||
true, | ||
], | ||
'extended-ascii-lowercase' => [ | ||
'пасха', | ||
true, | ||
], | ||
'extended-ascii-mixed-case' => [ | ||
'Пасха', | ||
true, | ||
], | ||
'extended-ascii-non-letter' => [ | ||
'¢£¥ƒ¿½¼«»±÷˜°²', | ||
true, | ||
], | ||
'emoji-name-1' => [ | ||
'💩💩💩', | ||
true, | ||
], | ||
'emoji-name-2' => [ | ||
'😎', | ||
true, | ||
], | ||
|
||
// Invalid names. | ||
'not-a-string' => [ | ||
12345, | ||
false, | ||
], | ||
'empty-string' => [ | ||
'', | ||
false, | ||
], | ||
'name-with-whitespace' => [ | ||
'aa bb', | ||
false, | ||
], | ||
'starts-with-number' => [ | ||
'2beornot2be', | ||
false, | ||
], | ||
'name-with-quotes-in-it' => [ | ||
"aa'1'", | ||
false, | ||
], | ||
'name-with-dash' => [ | ||
'some-thing', | ||
false, | ||
], | ||
'name-with-punctuation-chars' => [ | ||
'!@#$%&*(){}[]', | ||
false, | ||
], | ||
]; | ||
} | ||
} |