Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 122 additions & 46 deletions coder_sniffer/Drupal/Sniffs/WhiteSpace/ScopeIndentSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public function register()
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void|int
* @return int
*/
public function process(File $phpcsFile, $stackPtr)
{
Expand All @@ -146,13 +146,14 @@ public function process(File $phpcsFile, $stackPtr)
}
}

$lastOpenTag = $stackPtr;
$lastCloseTag = null;
$openScopes = [];
$adjustments = [];
$setIndents = [];
$disableExactEnd = 0;
$tokenIndent = 0;
$lastOpenTag = $stackPtr;
$lastCloseTag = null;
$openScopes = [];
$adjustments = [];
$setIndents = [];
$disableExactStack = [];
$disableExactEnd = 0;
$tokenIndent = 0;

$tokens = $phpcsFile->getTokens();
$first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr);
Expand Down Expand Up @@ -232,6 +233,7 @@ public function process(File $phpcsFile, $stackPtr)
if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS
&& isset($tokens[$i]['parenthesis_closer']) === true
) {
$disableExactStack[$tokens[$i]['parenthesis_closer']] = $tokens[$i]['parenthesis_closer'];
$disableExactEnd = max($disableExactEnd, $tokens[$i]['parenthesis_closer']);
if ($this->debug === true) {
$line = $tokens[$i]['line'];
Expand Down Expand Up @@ -337,7 +339,14 @@ public function process(File $phpcsFile, $stackPtr)
echo "\t* open tag is inside condition; using open tag *".PHP_EOL;
}

$checkIndent = ($tokens[$lastOpenTag]['column'] - 1);
$first = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $lastOpenTag, true);
if ($this->debug === true) {
$line = $tokens[$first]['line'];
$type = $tokens[$first]['type'];
echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
}

$checkIndent = ($tokens[$first]['column'] - 1);
if (isset($adjustments[$condition]) === true) {
$checkIndent += $adjustments[$condition];
}
Expand Down Expand Up @@ -483,12 +492,7 @@ public function process(File $phpcsFile, $stackPtr)

$arrayOpener = $tokens[$arrayCloser]['bracket_opener'];
if ($tokens[$arrayCloser]['line'] !== $tokens[$arrayOpener]['line']) {
$first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $arrayOpener, true);
$checkIndent = ($tokens[$first]['column'] - 1);
if (isset($adjustments[$first]) === true) {
$checkIndent += $adjustments[$first];
}

$first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $arrayOpener, true);
$exact = false;

if ($this->debug === true) {
Expand Down Expand Up @@ -524,6 +528,11 @@ public function process(File $phpcsFile, $stackPtr)
$first = $phpcsFile->findNext(T_WHITESPACE, ($first + 1), null, true);
}

$checkIndent = ($tokens[$first]['column'] - 1);
if (isset($adjustments[$first]) === true) {
$checkIndent += $adjustments[$first];
}

if (isset($tokens[$first]['scope_closer']) === true
&& $tokens[$first]['scope_closer'] === $first
) {
Expand Down Expand Up @@ -609,11 +618,11 @@ public function process(File $phpcsFile, $stackPtr)

// Scope closers reset the required indent to the same level as the opening condition.
if (($checkToken !== null
&& isset($openScopes[$checkToken]) === true
&& (isset($openScopes[$checkToken]) === true
|| (isset($tokens[$checkToken]['scope_condition']) === true
&& isset($tokens[$checkToken]['scope_closer']) === true
&& $tokens[$checkToken]['scope_closer'] === $checkToken
&& $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['scope_opener']]['line']))
&& $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['scope_opener']]['line'])))
|| ($checkToken === null
&& isset($openScopes[$i]) === true)
) {
Expand Down Expand Up @@ -796,6 +805,19 @@ public function process(File $phpcsFile, $stackPtr)
) {
$exact = true;

if ($disableExactEnd > $checkToken) {
foreach ($disableExactStack as $disableExactStackEnd) {
if ($disableExactStackEnd < $checkToken) {
continue;
}

if ($tokens[$checkToken]['conditions'] === $tokens[$disableExactStackEnd]['conditions']) {
$exact = false;
break;
}
}
}

$lastOpener = null;
if (empty($openScopes) === false) {
end($openScopes);
Expand Down Expand Up @@ -844,16 +866,34 @@ public function process(File $phpcsFile, $stackPtr)
&& $tokens[($checkToken + 1)]['code'] !== T_DOUBLE_COLON
) {
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($checkToken + 1), null, true);
if ($next === false || $tokens[$next]['code'] !== T_CLOSURE) {
if ($this->debug === true) {
$line = $tokens[$checkToken]['line'];
$type = $tokens[$checkToken]['type'];
echo "\t* method prefix ($type) found on line $line; indent set to exact *".PHP_EOL;
if ($next === false
|| ($tokens[$next]['code'] !== T_CLOSURE
&& $tokens[$next]['code'] !== T_VARIABLE
&& $tokens[$next]['code'] !== T_FN)
) {
$isMethodPrefix = true;
if (isset($tokens[$checkToken]['nested_parenthesis']) === true) {
$parenthesis = array_keys($tokens[$checkToken]['nested_parenthesis']);
$deepestOpen = array_pop($parenthesis);
if (isset($tokens[$deepestOpen]['parenthesis_owner']) === true
&& $tokens[$tokens[$deepestOpen]['parenthesis_owner']]['code'] === T_FUNCTION
) {
// This is constructor property promotion and not a method prefix.
$isMethodPrefix = false;
}
}

$exact = true;
}
}
if ($isMethodPrefix === true) {
if ($this->debug === true) {
$line = $tokens[$checkToken]['line'];
$type = $tokens[$checkToken]['type'];
echo "\t* method prefix ($type) found on line $line; indent set to exact *".PHP_EOL;
}

$exact = true;
}
}//end if
}//end if

// JS property indentation has to be exact or else if will break
// things like function and object indentation.
Expand Down Expand Up @@ -890,8 +930,6 @@ public function process(File $phpcsFile, $stackPtr)
}
}
}

$checkIndent = (int) (ceil($checkIndent / $this->indent) * $this->indent);
}//end if

// Close tags needs to be indented to exact column positions.
Expand All @@ -911,7 +949,8 @@ public function process(File $phpcsFile, $stackPtr)
// Don't perform strict checking on chained method calls since they
// are often covered by custom rules.
if ($checkToken !== null
&& $tokens[$checkToken]['code'] === T_OBJECT_OPERATOR
&& ($tokens[$checkToken]['code'] === T_OBJECT_OPERATOR
|| $tokens[$checkToken]['code'] === T_NULLSAFE_OBJECT_OPERATOR)
&& $exact === true
) {
$exact = false;
Expand Down Expand Up @@ -988,18 +1027,38 @@ public function process(File $phpcsFile, $stackPtr)
}

if ($this->tabIndent === true) {
$error .= '%s tabs, found %s';
$data = [
floor($checkIndent / $this->tabWidth),
floor($tokenIndent / $this->tabWidth),
];
$expectedTabs = floor($checkIndent / $this->tabWidth);
$foundTabs = floor($tokenIndent / $this->tabWidth);
$foundSpaces = ($tokenIndent - ($foundTabs * $this->tabWidth));
if ($foundSpaces > 0) {
if ($foundTabs > 0) {
$error .= '%s tabs, found %s tabs and %s spaces';
$data = [
$expectedTabs,
$foundTabs,
$foundSpaces,
];
} else {
$error .= '%s tabs, found %s spaces';
$data = [
$expectedTabs,
$foundSpaces,
];
}
} else {
$error .= '%s tabs, found %s';
$data = [
$expectedTabs,
$foundTabs,
];
}//end if
} else {
$error .= '%s spaces, found %s';
$data = [
$checkIndent,
$tokenIndent,
];
}
}//end if

if ($this->debug === true) {
$line = $tokens[$checkToken]['line'];
Expand Down Expand Up @@ -1030,15 +1089,17 @@ public function process(File $phpcsFile, $stackPtr)

// Don't check indents exactly between arrays as they tend to have custom rules.
if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
$disableExactStack[$tokens[$i]['bracket_closer']] = $tokens[$i]['bracket_closer'];
$disableExactEnd = max($disableExactEnd, $tokens[$i]['bracket_closer']);
if ($this->debug === true) {
$line = $tokens[$i]['line'];
$type = $tokens[$disableExactEnd]['type'];
$line = $tokens[$i]['line'];
$type = $tokens[$disableExactEnd]['type'];
$endLine = $tokens[$disableExactEnd]['line'];
echo "Opening short array bracket found on line $line".PHP_EOL;
if ($disableExactEnd === $tokens[$i]['bracket_closer']) {
echo "\t=> disabling exact indent checking until $disableExactEnd ($type)".PHP_EOL;
echo "\t=> disabling exact indent checking until $disableExactEnd ($type) on line $endLine".PHP_EOL;
} else {
echo "\t=> continuing to disable exact indent checking until $disableExactEnd ($type)".PHP_EOL;
echo "\t=> continuing to disable exact indent checking until $disableExactEnd ($type) on line $endLine".PHP_EOL;
}
}
}
Expand All @@ -1050,7 +1111,6 @@ public function process(File $phpcsFile, $stackPtr)
) {
if ($this->debug === true) {
$line = $tokens[$i]['line'];
$type = $tokens[$disableExactEnd]['type'];
echo "Here/nowdoc found on line $line".PHP_EOL;
}

Expand All @@ -1074,8 +1134,11 @@ public function process(File $phpcsFile, $stackPtr)
if ($tokens[$i]['code'] === T_CONSTANT_ENCAPSED_STRING
|| $tokens[$i]['code'] === T_DOUBLE_QUOTED_STRING
) {
$i = $phpcsFile->findNext($tokens[$i]['code'], ($i + 1), null, true);
$i--;
$nextNonTextString = $phpcsFile->findNext($tokens[$i]['code'], ($i + 1), null, true);
if ($nextNonTextString !== false) {
$i = ($nextNonTextString - 1);
}

continue;
}

Expand Down Expand Up @@ -1162,7 +1225,7 @@ public function process(File $phpcsFile, $stackPtr)
if ($this->debug === true) {
$type = str_replace('_', ' ', strtolower(substr($tokens[$i]['type'], 2)));
$line = $tokens[$i]['line'];
echo "* ignoring single-line $type on line $line".PHP_EOL;
echo "* ignoring single-line $type on line $line *".PHP_EOL;
}

$i = $closer;
Expand Down Expand Up @@ -1232,14 +1295,24 @@ public function process(File $phpcsFile, $stackPtr)
if ($this->debug === true) {
$line = $tokens[$i]['line'];
$type = $tokens[$i]['type'];
echo "* ignoring single-line $type on line $line".PHP_EOL;
echo "* ignoring single-line $type on line $line *".PHP_EOL;
}

$i = $closer;
continue;
}

$condition = $tokens[$tokens[$i]['scope_condition']]['code'];
if ($condition === T_FN) {
if ($this->debug === true) {
$line = $tokens[$tokens[$i]['scope_condition']]['line'];
echo "* ignoring arrow function on line $line *".PHP_EOL;
}

$i = $closer;
continue;
}

if (isset(Tokens::$scopeOpeners[$condition]) === true
&& in_array($condition, $this->nonIndentingScopes, true) === false
) {
Expand Down Expand Up @@ -1279,7 +1352,7 @@ public function process(File $phpcsFile, $stackPtr)
if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
if ($this->debug === true) {
$line = $tokens[$i]['line'];
echo "* ignoring single-line JS object on line $line".PHP_EOL;
echo "* ignoring single-line JS object on line $line *".PHP_EOL;
}

$i = $closer;
Expand Down Expand Up @@ -1309,11 +1382,14 @@ public function process(File $phpcsFile, $stackPtr)
continue;
}//end if

// Closing an anon class or function.
// Closing an anon class, closure, or match.
// Each may be returned, which can confuse control structures that
// use return as a closer, like CASE statements.
if (isset($tokens[$i]['scope_condition']) === true
&& $tokens[$i]['scope_closer'] === $i
&& ($tokens[$tokens[$i]['scope_condition']]['code'] === T_CLOSURE
|| $tokens[$tokens[$i]['scope_condition']]['code'] === T_ANON_CLASS)
|| $tokens[$tokens[$i]['scope_condition']]['code'] === T_ANON_CLASS
|| $tokens[$tokens[$i]['scope_condition']]['code'] === T_MATCH)
) {
if ($this->debug === true) {
$type = str_replace('_', ' ', strtolower(substr($tokens[$tokens[$i]['scope_condition']]['type'], 2)));
Expand Down
18 changes: 18 additions & 0 deletions tests/Drupal/good/good.php
Original file line number Diff line number Diff line change
Expand Up @@ -1887,3 +1887,21 @@ public function foo() {
'#empty' => $this->t('No strings available.'),
'#attributes' => ['class' => ['locale-translate-edit-table']],
];

/**
* Implements hook_cron().
*/
#[Hook('cron')]
class CronHook {

public function __construct(
private readonly EntityTypeManagerInterface $entityTypeManager,
private readonly StreamWrapperManagerInterface $streamWrapperManager,
private readonly ConfigFactoryInterface $configFactory,
private readonly FileUsageInterface $fileUsage,
private readonly TimeInterface $time,
#[Autowire('@logger.channel.file')]
private readonly LoggerInterface $logger,
) {}

}
Loading