Skip to content

Commit

Permalink
Add a sniff that checks if double arrows use only 1 space THEME-3651
Browse files Browse the repository at this point in the history
  • Loading branch information
KamilBaczkowski committed Oct 17, 2023
1 parent f4df8e7 commit 061a839
Showing 1 changed file with 202 additions and 0 deletions.
202 changes: 202 additions & 0 deletions WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
<?php
/**
* WordPress Coding Standard.
*
* @package WPCS\WordPressCodingStandards
* @link https://github.com/WordPress/WordPress-Coding-Standards
* @license https://opensource.org/licenses/MIT MIT
*/

namespace WordPressCS\WordPress\Sniffs\Arrays;

use PHPCSUtils\Tokens\Collections;
use PHPCSUtils\Utils\Arrays;
use PHPCSUtils\Utils\PassedParameters;
use WordPressCS\WordPress\Sniff;

/**
* Enforces alignment of the double arrow assignment operator to be exactly one space.
*/
final class ArrayDoubleArrowSpacingSniff extends Sniff {
public function register() {

Check failure on line 21 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 21 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Missing doc comment for function register()

Check failure on line 21 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 21 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Missing doc comment for function register()
return Collections::arrayOpenTokensBC();

Check failure on line 22 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 22 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed
}

Check failure on line 23 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 23 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

/**
* Processes this test, when one of its tokens is encountered.
*
* @since 0.14.0
*
* @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 ) {

Check failure on line 35 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 35 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed
if ( isset( Collections::shortArrayListOpenTokensBC()[ $this->tokens[ $stackPtr ]['code'] ] )
&& Arrays::isShortArray( $this->phpcsFile, $stackPtr ) === false
) {
// Short list, not short array.
return;
}

/*
* Determine the array opener & closer.
*/
$array_open_close = Arrays::getOpenClose( $this->phpcsFile, $stackPtr );
if ( false === $array_open_close ) {
// Array open/close could not be determined.
return;
}

$opener = $array_open_close['opener'];
$closer = $array_open_close['closer'];

$array_items = PassedParameters::getParameters( $this->phpcsFile, $stackPtr );
if ( empty( $array_items ) ) {
return;
}

// Pass off to either the single line or multi-line array analysis.
if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) {
return $this->process_single_line_array( $stackPtr, $array_items, $opener, $closer );
} else {
return $this->process_multi_line_array( $stackPtr, $array_items, $opener, $closer );
}
}

Check failure on line 66 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 66 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

/**
* Process a single-line array.
*
* While the WP standard does not allow single line multi-item associative arrays,
* this sniff should function independently of that.
*
* The `WordPress.WhiteSpace.OperatorSpacing` sniff already covers checking that
* there is a space between the array key and the double arrow, but doesn't
* enforce it to be exactly one space for single line arrays.
* That is what this method covers.
*
* @since 0.14.0
*
* @param int $stackPtr The position of the current token in the stack.
* @param array $items Info array containing information on each array item.
* @param int $opener The position of the array opener.
* @param int $closer The position of the array closer.
*
* @return int|void Integer stack pointer to skip forward or void to continue
* normal file processing.
*/
protected function process_single_line_array( $stackPtr, $items, $opener, $closer ) {
/*
* For single line arrays, we don't care about what level the arrow is from.
* Just find and fix them all.
*/
$next_arrow = $this->phpcsFile->findNext(
\T_DOUBLE_ARROW,
( $opener + 1 ),
$closer
);

while ( false !== $next_arrow ) {
if ( \T_WHITESPACE === $this->tokens[ ( $next_arrow - 1 ) ]['code'] ) {
$space_length = $this->tokens[ ( $next_arrow - 1 ) ]['length'];
if ( 1 !== $space_length ) {
$error = 'Expected 1 space between "%s" and double arrow; %s found';
$data = array(
$this->tokens[ ( $next_arrow - 2 ) ]['content'],
$space_length,
);

$fix = $this->phpcsFile->addFixableWarning( $error, $next_arrow, 'SpaceBeforeDoubleArrow', $data );
if ( true === $fix ) {
$this->phpcsFile->fixer->replaceToken( ( $next_arrow - 1 ), ' ' );
}
}
}

// Find the position of the next double arrow.
$next_arrow = $this->phpcsFile->findNext(
\T_DOUBLE_ARROW,
( $next_arrow + 1 ),
$closer
);
}

// Ignore any child-arrays as the double arrows in these will already have been handled.
return ( $closer + 1 );
}

/**

Check failure on line 129 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Doc comment for parameter "$stackPtf" missing

Check failure on line 129 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Doc comment for parameter "$stackPtf" missing
* Process a multi-line array.
*
* @since 0.14.0
*
* @param int $stackPtr The position of the current token in the stack.

Check failure on line 134 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Doc comment for parameter $stackPtr does not match actual variable name $stackPtf

Check failure on line 134 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Doc comment for parameter $stackPtr does not match actual variable name $stackPtf
* @param array $items Info array containing information on each array item.
* @param int $opener The position of the array opener.
* @param int $closer The position of the array closer.
*
* @return void
*/
protected function process_multi_line_array( $stackPtf, $items, $opener, $closer ) {

Check failure on line 141 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / PHPStan

PHPDoc tag @param references unknown parameter: $stackPtr

Check failure on line 141 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 141 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / PHPStan

PHPDoc tag @param references unknown parameter: $stackPtr

Check failure on line 141 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed
foreach ( $items as $key => $item ) {

Check failure on line 142 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed

Check failure on line 142 in WordPress/Sniffs/Arrays/ArrayDoubleArrowSpacingSniff.php

View workflow job for this annotation

GitHub Actions / Run code sniffs

Tabs must be used to indent lines; spaces are not allowed
$double_arrow = Arrays::getDoubleArrowPtr( $this->phpcsFile, $item['start'], $item['end'] );

if ( false === $double_arrow ) {
unset( $items[ $key ] );
continue;
}

// Find the end of the array key.
$last_index_token = $this->phpcsFile->findPrevious(
\T_WHITESPACE,
( $double_arrow - 1 ),
$item['start'],
true
);

$item['operatorPtr'] = $double_arrow;
$item['last_index_token'] = $last_index_token;

$key_end_column = $this->tokens[ $last_index_token ]['column'] + $this->tokens[ $last_index_token ]['length'];
$double_arrow_start = $this->tokens[ $double_arrow ]['column'];
$result = $double_arrow_start - $key_end_column;

if ( $result === 1 ) {
continue;
}

if ( \T_WHITESPACE !== $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['code'] ) {
$before = 0;
} elseif ( $this->tokens[ $item['last_index_token'] ]['line'] !== $this->tokens[ $item['operatorPtr'] ]['line'] ) {
$before = 'newline';
} else {
$before = $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['length'];
}

$fix = $this->phpcsFile->addFixableWarning(
'Expected 1 space between "%s" and double arrow; %s found.',
$item['operatorPtr'],
'TooManySpaces',
array(
$this->tokens[ $item['last_index_token'] ]['content'],
$before,
)
);

if ( true === $fix ) {
$this->phpcsFile->fixer->beginChangeset();

// Remove whitespace tokens between the end of the index and the arrow, if any.
for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) {
$this->phpcsFile->fixer->replaceToken( $i, '' );
}

// Add the correct whitespace.
$this->phpcsFile->fixer->addContent( $item['last_index_token'], ' ' );

$this->phpcsFile->fixer->endChangeset();
}
}
}
}

0 comments on commit 061a839

Please sign in to comment.