Skip to content

Commit c726920

Browse files
committed
File::getDeclarationName(): stop accepting tokens for non-named structures
The `File::getDeclarationName()` method - for historic reasons - accepted the `T_CLOSURE` and `T_ANON_CLASS` tokens, even though these structures will never have a name, and returned `null` for those tokens. This commit changes the `File::getDeclarationName()` method to no longer accept those tokens and throw an exception if they are passed to the method instead. As a secondary change, when the name of a valid structure cannot be determined, the method will now no longer return `null`, but will return an empty string. This normalizes the return type of the method to always return a string (or throw an exception). Includes updated unit tests to match. Related to squizlabs/PHP_CodeSniffer 3766 --- All PHPCS native sniffs using the `File::getDeclarationName()` method have been reviewed and where necessary fixed to allow for this change. Also note that in some cases, the sniff already contained sufficient protection and in other case, the fact that the method will no longer return `null`, meant that the sniff code could be simplified. List of sniffs reviewed: - `AbstractScopeSniff` - `Generic.Classes.DuplicateClassName` - `Generic.CodeAnalysis.UnusedFunctionParameter` - `Generic.CodeAnalysis.UselessOverridingMethod` - `Generic.NamingConventions.AbstractClassNamePrefix` - `Generic.NamingConventions.CamelCapsFunctionName` - `Generic.NamingConventions.ConstructorName` - `Generic.NamingConventions.InterfaceNameSuffix` - `Generic.NamingConventions.TraitNameSuffix` - `PEAR.Commenting.ClassComment` - `PEAR.Commenting.FunctionComment` - `PEAR.Functions.FunctionDeclaration` - `PEAR.NamingConventions.ValidFunctionName` - `PSR1.Methods.CamelCapsMethodName` - `PSR2.Methods.MethodDeclaration` - `Squiz.Classes.ClassFileName` - `Squiz.Classes.SelfMemberReference` - `Squiz.Commenting.ClassComment` - `Squiz.Commenting.ClosingDeclarationComment` - `Squiz.Commenting.FunctionComment` - `Squiz.Functions.GlobalFunction` - `Squiz.NamingConventions.ValidFunctionName` - `Squiz.Scope.MethodScope` :point_right: The changes to the PEAR/FunctionDeclaration sniff will be easier to review while ignoring whitespace.
1 parent 40dd4b5 commit c726920

19 files changed

+95
-114
lines changed

src/Files/File.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,20 +1204,15 @@ public function getFilename()
12041204
* @param int $stackPtr The position of the declaration token which
12051205
* declared the class, interface, trait, or function.
12061206
*
1207-
* @return string|null The name of the class, interface, trait, or function;
1208-
* or NULL if the function or class is anonymous.
1207+
* @return string The name of the class, interface, trait, or function or an empty string
1208+
* if the name could not be determined (live coding).
12091209
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified token is not of type
1210-
* T_FUNCTION, T_CLASS, T_ANON_CLASS,
1211-
* T_CLOSURE, T_TRAIT, T_ENUM, or T_INTERFACE.
1210+
* T_FUNCTION, T_CLASS, T_TRAIT, T_ENUM, or T_INTERFACE.
12121211
*/
12131212
public function getDeclarationName($stackPtr)
12141213
{
12151214
$tokenCode = $this->tokens[$stackPtr]['code'];
12161215

1217-
if ($tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) {
1218-
return null;
1219-
}
1220-
12211216
if ($tokenCode !== T_FUNCTION
12221217
&& $tokenCode !== T_CLASS
12231218
&& $tokenCode !== T_INTERFACE
@@ -1236,7 +1231,7 @@ public function getDeclarationName($stackPtr)
12361231
$stopPoint = $this->tokens[$stackPtr]['scope_opener'];
12371232
}
12381233

1239-
$content = null;
1234+
$content = '';
12401235
for ($i = $stackPtr; $i < $stopPoint; $i++) {
12411236
if ($this->tokens[$i]['code'] === T_STRING) {
12421237
$content = $this->tokens[$i]['content'];

src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,10 @@ public function process(File $phpcsFile, $stackPtr)
9999
$classPtr = $phpcsFile->getCondition($stackPtr, T_CLASS);
100100
if ($classPtr !== false) {
101101
// Check for magic methods and ignore these as the method signature cannot be changed.
102-
$methodName = $phpcsFile->getDeclarationName($stackPtr);
103-
if (empty($methodName) === false) {
104-
$methodNameLc = strtolower($methodName);
105-
if (isset($this->magicMethods[$methodNameLc]) === true) {
106-
return;
107-
}
102+
$methodName = $phpcsFile->getDeclarationName($stackPtr);
103+
$methodNameLc = strtolower($methodName);
104+
if (isset($this->magicMethods[$methodNameLc]) === true) {
105+
return;
108106
}
109107

110108
// Check for extends/implements and adjust the error code when found.

src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function process(File $phpcsFile, $stackPtr)
4444
}
4545

4646
$className = $phpcsFile->getDeclarationName($stackPtr);
47-
if ($className === null) {
47+
if ($className === '') {
4848
// Live coding or parse error.
4949
return;
5050
}

src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
112112
}
113113

114114
$methodName = $phpcsFile->getDeclarationName($stackPtr);
115-
if ($methodName === null) {
115+
if ($methodName === '') {
116116
// Live coding or parse error. Bow out.
117117
return;
118118
}
119119

120-
$className = $phpcsFile->getDeclarationName($currScope);
121-
if (isset($className) === false) {
122-
$className = '[Anonymous Class]';
120+
$className = '[Anonymous Class]';
121+
if ($tokens[$currScope]['code'] !== T_ANON_CLASS) {
122+
$className = $phpcsFile->getDeclarationName($currScope);
123123
}
124124

125125
$errorData = [$className.'::'.$methodName];
@@ -187,7 +187,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
187187
protected function processTokenOutsideScope(File $phpcsFile, $stackPtr)
188188
{
189189
$functionName = $phpcsFile->getDeclarationName($stackPtr);
190-
if ($functionName === null) {
190+
if ($functionName === '') {
191191
// Live coding or parse error. Bow out.
192192
return;
193193
}

src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,9 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
6767
return;
6868
}
6969

70-
$className = $phpcsFile->getDeclarationName($currScope);
71-
if (empty($className) === false) {
72-
// Not an anonymous class.
73-
$className = strtolower($className);
70+
$className = '[Anonymous Class]';
71+
if ($tokens[$currScope]['code'] !== T_ANON_CLASS) {
72+
$className = strtolower($phpcsFile->getDeclarationName($currScope));
7473
}
7574

7675
if ($className !== $this->currentClass) {
@@ -79,7 +78,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
7978
}
8079

8180
$methodName = $phpcsFile->getDeclarationName($stackPtr);
82-
if ($methodName === null) {
81+
if ($methodName === '') {
8382
// Live coding or parse error. Bow out.
8483
return;
8584
}
@@ -170,7 +169,7 @@ protected function loadFunctionNamesInScope(File $phpcsFile, $currScope)
170169
}
171170

172171
$methodName = $phpcsFile->getDeclarationName($i);
173-
if ($methodName === null) {
172+
if ($methodName === '') {
174173
// Live coding or parse error. Ignore.
175174
continue;
176175
}

src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function register()
3939
public function process(File $phpcsFile, $stackPtr)
4040
{
4141
$interfaceName = $phpcsFile->getDeclarationName($stackPtr);
42-
if ($interfaceName === null) {
42+
if ($interfaceName === '') {
4343
// Live coding or parse error. Bow out.
4444
return;
4545
}

src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function register()
3939
public function process(File $phpcsFile, $stackPtr)
4040
{
4141
$traitName = $phpcsFile->getDeclarationName($stackPtr);
42-
if ($traitName === null) {
42+
if ($traitName === '') {
4343
// Live coding or parse error. Bow out.
4444
return;
4545
}

src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -94,47 +94,49 @@ public function process(File $phpcsFile, $stackPtr)
9494
// and the opening parenthesis.
9595
// Unfinished closures are tokenized as T_FUNCTION however, and can be excluded
9696
// by checking if the function has a name.
97-
$methodProps = $phpcsFile->getMethodProperties($stackPtr);
98-
$methodName = $phpcsFile->getDeclarationName($stackPtr);
99-
if ($tokens[$stackPtr]['code'] === T_FUNCTION && $methodName !== null) {
100-
if ($tokens[($openBracket - 1)]['content'] === $phpcsFile->eolChar) {
101-
$spaces = 'newline';
102-
} else if ($tokens[($openBracket - 1)]['code'] === T_WHITESPACE) {
103-
$spaces = $tokens[($openBracket - 1)]['length'];
104-
} else {
105-
$spaces = 0;
106-
}
107-
108-
if ($spaces !== 0) {
109-
$error = 'Expected 0 spaces before opening parenthesis; %s found';
110-
$data = [$spaces];
111-
$fix = $phpcsFile->addFixableError($error, $openBracket, 'SpaceBeforeOpenParen', $data);
112-
if ($fix === true) {
113-
$phpcsFile->fixer->replaceToken(($openBracket - 1), '');
97+
if ($tokens[$stackPtr]['code'] === T_FUNCTION) {
98+
$methodProps = $phpcsFile->getMethodProperties($stackPtr);
99+
$methodName = $phpcsFile->getDeclarationName($stackPtr);
100+
if ($methodName !== '') {
101+
if ($tokens[($openBracket - 1)]['content'] === $phpcsFile->eolChar) {
102+
$spaces = 'newline';
103+
} else if ($tokens[($openBracket - 1)]['code'] === T_WHITESPACE) {
104+
$spaces = $tokens[($openBracket - 1)]['length'];
105+
} else {
106+
$spaces = 0;
114107
}
115-
}
116108

117-
// Must be no space before semicolon in abstract/interface methods.
118-
if ($methodProps['has_body'] === false) {
119-
$end = $phpcsFile->findNext(T_SEMICOLON, $closeBracket);
120-
if ($end !== false) {
121-
if ($tokens[($end - 1)]['content'] === $phpcsFile->eolChar) {
122-
$spaces = 'newline';
123-
} else if ($tokens[($end - 1)]['code'] === T_WHITESPACE) {
124-
$spaces = $tokens[($end - 1)]['length'];
125-
} else {
126-
$spaces = 0;
109+
if ($spaces !== 0) {
110+
$error = 'Expected 0 spaces before opening parenthesis; %s found';
111+
$data = [$spaces];
112+
$fix = $phpcsFile->addFixableError($error, $openBracket, 'SpaceBeforeOpenParen', $data);
113+
if ($fix === true) {
114+
$phpcsFile->fixer->replaceToken(($openBracket - 1), '');
127115
}
116+
}
128117

129-
if ($spaces !== 0) {
130-
$error = 'Expected 0 spaces before semicolon; %s found';
131-
$data = [$spaces];
132-
$fix = $phpcsFile->addFixableError($error, $end, 'SpaceBeforeSemicolon', $data);
133-
if ($fix === true) {
134-
$phpcsFile->fixer->replaceToken(($end - 1), '');
118+
// Must be no space before semicolon in abstract/interface methods.
119+
if ($methodProps['has_body'] === false) {
120+
$end = $phpcsFile->findNext(T_SEMICOLON, $closeBracket);
121+
if ($end !== false) {
122+
if ($tokens[($end - 1)]['content'] === $phpcsFile->eolChar) {
123+
$spaces = 'newline';
124+
} else if ($tokens[($end - 1)]['code'] === T_WHITESPACE) {
125+
$spaces = $tokens[($end - 1)]['length'];
126+
} else {
127+
$spaces = 0;
128+
}
129+
130+
if ($spaces !== 0) {
131+
$error = 'Expected 0 spaces before semicolon; %s found';
132+
$data = [$spaces];
133+
$fix = $phpcsFile->addFixableError($error, $end, 'SpaceBeforeSemicolon', $data);
134+
if ($fix === true) {
135+
$phpcsFile->fixer->replaceToken(($end - 1), '');
136+
}
135137
}
136138
}
137-
}
139+
}//end if
138140
}//end if
139141
}//end if
140142

src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
8383
}
8484

8585
$methodName = $phpcsFile->getDeclarationName($stackPtr);
86-
if ($methodName === null) {
86+
if ($methodName === '') {
8787
// Ignore live coding.
8888
return;
8989
}
9090

91-
$className = $phpcsFile->getDeclarationName($currScope);
92-
if (isset($className) === false) {
93-
$className = '[Anonymous Class]';
91+
$className = '[Anonymous Class]';
92+
if ($tokens[$currScope]['code'] !== T_ANON_CLASS) {
93+
$className = $phpcsFile->getDeclarationName($currScope);
9494
}
9595

9696
$errorData = [$className.'::'.$methodName];
@@ -181,11 +181,6 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
181181
protected function processTokenOutsideScope(File $phpcsFile, $stackPtr)
182182
{
183183
$functionName = $phpcsFile->getDeclarationName($stackPtr);
184-
if ($functionName === null) {
185-
// Ignore live coding.
186-
return;
187-
}
188-
189184
if (ltrim($functionName, '_') === '') {
190185
// Ignore special functions.
191186
return;

src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
4040
}
4141

4242
$methodName = $phpcsFile->getDeclarationName($stackPtr);
43-
if ($methodName === null) {
43+
if ($methodName === '') {
4444
// Ignore live coding.
4545
return;
4646
}
@@ -58,9 +58,9 @@ protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScop
5858
$testName = ltrim($methodName, '_');
5959
if ($testName !== '' && Common::isCamelCaps($testName, false, true, false) === false) {
6060
$error = 'Method name "%s" is not in camel caps format';
61-
$className = $phpcsFile->getDeclarationName($currScope);
62-
if (isset($className) === false) {
63-
$className = '[Anonymous Class]';
61+
$className = '[Anonymous Class]';
62+
if ($tokens[$currScope]['code'] !== T_ANON_CLASS) {
63+
$className = $phpcsFile->getDeclarationName($currScope);
6464
}
6565

6666
$errorData = [$className.'::'.$methodName];

0 commit comments

Comments
 (0)