Skip to content

Commit 025a1e0

Browse files
authored
Merge pull request #851 from Automattic/feature/constants-constantstring-sniff-review
2 parents ff75da7 + 68260d2 commit 025a1e0

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

WordPressVIPMinimum/Sniffs/Constants/ConstantStringSniff.php

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,51 +11,43 @@
1111

1212
use PHP_CodeSniffer\Util\Tokens;
1313
use PHPCSUtils\Utils\PassedParameters;
14-
use WordPressVIPMinimum\Sniffs\Sniff;
14+
use WordPressCS\WordPress\AbstractFunctionParameterSniff;
1515

1616
/**
1717
* Sniff for properly using constant name when checking whether a constant is defined.
1818
*/
19-
class ConstantStringSniff extends Sniff {
19+
class ConstantStringSniff extends AbstractFunctionParameterSniff {
2020

2121
/**
22-
* Returns an array of tokens this test wants to listen for.
22+
* The group name for this group of functions.
2323
*
24-
* @return array<int|string>
24+
* @var string
2525
*/
26-
public function register() {
27-
return [
28-
T_STRING,
29-
];
30-
}
26+
protected $group_name = 'constant_functions';
27+
28+
/**
29+
* Functions this sniff is looking for.
30+
*
31+
* @var array<string, bool> Key is the function name, value irrelevant.
32+
*/
33+
protected $target_functions = [
34+
'define' => true,
35+
'defined' => true,
36+
];
3137

3238
/**
33-
* Process this test when one of its tokens is encountered.
39+
* Process the parameters of a matched function.
3440
*
35-
* @param int $stackPtr The position of the current token in the stack passed in $tokens.
41+
* @param int $stackPtr The position of the current token in the stack.
42+
* @param string $group_name The name of the group which was matched.
43+
* @param string $matched_content The token content (function name) which was matched
44+
* in lowercase.
45+
* @param array $parameters Array with information about the parameters.
3646
*
3747
* @return void
3848
*/
39-
public function process_token( $stackPtr ) {
40-
41-
if ( in_array( $this->tokens[ $stackPtr ]['content'], [ 'define', 'defined' ], true ) === false ) {
42-
return;
43-
}
44-
45-
// Find the next non-empty token.
46-
$nextToken = $this->phpcsFile->findNext( Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true );
47-
48-
if ( $this->tokens[ $nextToken ]['code'] !== T_OPEN_PARENTHESIS ) {
49-
// Not a function call.
50-
return;
51-
}
52-
53-
if ( isset( $this->tokens[ $nextToken ]['parenthesis_closer'] ) === false ) {
54-
// Not a function call.
55-
return;
56-
}
57-
58-
$param = PassedParameters::getParameter( $this->phpcsFile, $stackPtr, 1, 'constant_name' );
49+
public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) {
50+
$param = PassedParameters::getParameterFromStack( $parameters, 1, 'constant_name' );
5951
if ( $param === false ) {
6052
// Target parameter not found.
6153
return;
@@ -72,7 +64,7 @@ public function process_token( $stackPtr ) {
7264

7365
$tstring_token = $this->phpcsFile->findNext( T_STRING, $param['start'], $param['end'] + 1 );
7466

75-
$message = 'Constant name, as a string, should be used along with `%s()`.';
67+
$message = 'The `%s()` function expects to be passed the constant name as a text string.';
7668
$data = [ $this->tokens[ $stackPtr ]['content'] ];
7769
$this->phpcsFile->addError( $message, $tstring_token, 'NotCheckingConstantName', $data );
7870
}

WordPressVIPMinimum/Tests/Constants/ConstantStringUnitTest.inc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,38 @@ if ( ! defined($generator->get()) { // OK.
3131

3232
$defined = defined(); // OK, ignore.
3333
$defined = defined( /*comment*/ ); // OK, ignore.
34+
35+
// Safeguard that calls to namespaced functions or methods are not confused with the global functions.
36+
if ( ! Not\defined( WPCOM_VIP ) ) { // Okay.
37+
$obj->define( WPCOM_VIP, true ); // Okay.
38+
}
39+
40+
if ( ! \Fully\Qualified\defined( WPCOM_VIP ) ) { // Okay.
41+
namespace\define( WPCOM_VIP, true ); // Okay.
42+
}
43+
44+
// Safeguard that fully qualified function calls are handled correctly.
45+
if ( ! \defined( 'WPCOM_VIP' ) ) { // Okay.
46+
\define( 'WPCOM_VIP', true, ); // Okay.
47+
}
48+
49+
if ( ! \defined( WPCOM_VIP, ) ) { // Error.
50+
\define( WPCOM_VIP, true ); // Error.
51+
}
52+
53+
// Safeguard correct handling of case-insensitivity of function names.
54+
if ( ! DEFINED( WPCOM_VIP ) ) { // Error.
55+
Define( WPCOM_VIP, true ); // Error.
56+
}
57+
58+
// Safeguard correct handling of function calls using PHP 8.0+ named parameters.
59+
\defined( constant_nam: WPCOM_VIP ); // Okay, well not really, typo in param name, but that's not the concern of the sniff.
60+
define(value: true, constant_name: 'WPCOM_VIP', ); // Okay.
61+
define(case_insensitive: true, constant_name: WPCOM_VIP ); // Error.
62+
63+
// Looks like a function call, but is a PHP 8.0+ class instantiation via an attribute.
64+
#[Define('name', 'value')]
65+
function foo() {}
66+
67+
define(...$params); // PHP 5.6 argument unpacking will be ignored.
68+
add_action('my_action', define(...)); // PHP 8.1 first class callable will be ignored.

WordPressVIPMinimum/Tests/Constants/ConstantStringUnitTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ class ConstantStringUnitTest extends AbstractSniffUnitTest {
2323
*/
2424
public function getErrorList() {
2525
return [
26-
7 => 1,
27-
8 => 1,
26+
7 => 1,
27+
8 => 1,
28+
49 => 1,
29+
50 => 1,
30+
54 => 1,
31+
55 => 1,
32+
61 => 1,
2833
];
2934
}
3035

0 commit comments

Comments
 (0)