Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of disable/enable/ignore directives #123

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
31 changes: 4 additions & 27 deletions src/Files/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ public function addFixableWarning(
protected function addMessage($error, $message, $line, $column, $code, $data, $severity, $fixable)
{
// Check if this line is ignoring all message codes.
if (isset($this->tokenizer->ignoredLines[$line]['.all']) === true) {
if (isset($this->tokenizer->ignoredLines[$line]) === true && $this->tokenizer->ignoredLines[$line]->isAll() === true) {
return false;
}

Expand Down Expand Up @@ -894,32 +894,9 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s
];
}//end if

if (isset($this->tokenizer->ignoredLines[$line]) === true) {
// Check if this line is ignoring this specific message.
$ignored = false;
foreach ($checkCodes as $checkCode) {
if (isset($this->tokenizer->ignoredLines[$line][$checkCode]) === true) {
$ignored = true;
break;
}
}

// If it is ignored, make sure it's not whitelisted.
if ($ignored === true
&& isset($this->tokenizer->ignoredLines[$line]['.except']) === true
) {
foreach ($checkCodes as $checkCode) {
if (isset($this->tokenizer->ignoredLines[$line]['.except'][$checkCode]) === true) {
$ignored = false;
break;
}
}
}

if ($ignored === true) {
return false;
}
}//end if
if (isset($this->tokenizer->ignoredLines[$line]) === true && $this->tokenizer->ignoredLines[$line]->check($sniffCode) === true) {
return false;
}

$includeAll = true;
if ($this->configCache['cache'] === false
Expand Down
107 changes: 36 additions & 71 deletions src/Tokenizers/Tokenizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use PHP_CodeSniffer\Exceptions\TokenizerException;
use PHP_CodeSniffer\Util;
use PHP_CodeSniffer\Util\IgnoreList;

abstract class Tokenizer
{
Expand Down Expand Up @@ -173,6 +174,7 @@ private function createPositionMap()
$lineNumber = 1;
$eolLen = strlen($this->eolChar);
$ignoring = null;
$ignoreAll = IgnoreList::ignoringAll();
$inTests = defined('PHP_CODESNIFFER_IN_TESTS');

$checkEncoding = false;
Expand Down Expand Up @@ -277,15 +279,15 @@ private function createPositionMap()
if ($ignoring === null
&& strpos($commentText, '@codingStandardsIgnoreStart') !== false
) {
$ignoring = ['.all' => true];
$ignoring = $ignoreAll;
if ($ownLine === true) {
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
}
} else if ($ignoring !== null
&& strpos($commentText, '@codingStandardsIgnoreEnd') !== false
) {
if ($ownLine === true) {
$this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreAll;
} else {
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
}
Expand All @@ -294,7 +296,7 @@ private function createPositionMap()
} else if ($ignoring === null
&& strpos($commentText, '@codingStandardsIgnoreLine') !== false
) {
$ignoring = ['.all' => true];
$ignoring = $ignoreAll;
if ($ownLine === true) {
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoring;
$this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoring;
Expand Down Expand Up @@ -393,7 +395,7 @@ private function createPositionMap()
if (substr($commentTextLower, 0, 9) === 'phpcs:set') {
// Ignore standards for complete lines that change sniff settings.
if ($lineHasOtherTokens === false) {
$this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreAll;
}

// Need to maintain case here, to get the correct sniff code.
Expand All @@ -416,42 +418,28 @@ private function createPositionMap()
} else if (substr($commentTextLower, 0, 13) === 'phpcs:disable') {
if ($lineHasOtherContent === false) {
// Completely ignore the comment line.
$this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
}

if ($ignoring === null) {
$ignoring = [];
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreAll;
}

$disabledSniffs = [];

$additionalText = substr($commentText, 14);
if (empty($additionalText) === true) {
$ignoring = ['.all' => true];
$ignoring = $ignoreAll;
} else {
if ($ignoring === null) {
$ignoring = IgnoreList::ignoringNone();
} else {
$ignoring = clone $ignoring;
}

$parts = explode(',', $additionalText);
foreach ($parts as $sniffCode) {
$sniffCode = trim($sniffCode);
$disabledSniffs[$sniffCode] = true;
$ignoring[$sniffCode] = true;

// This newly disabled sniff might be disabling an existing
// enabled exception that we are tracking.
if (isset($ignoring['.except']) === true) {
foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
if ($ignoredSniffCode === $sniffCode
|| strpos($ignoredSniffCode, $sniffCode.'.') === 0
) {
unset($ignoring['.except'][$ignoredSniffCode]);
}
}

if (empty($ignoring['.except']) === true) {
unset($ignoring['.except']);
}
}
}//end foreach
}//end if
$ignoring->set($sniffCode, true);
}
}

$this->tokens[$i]['code'] = T_PHPCS_DISABLE;
$this->tokens[$i]['type'] = 'T_PHPCS_DISABLE';
Expand All @@ -464,49 +452,22 @@ private function createPositionMap()
if (empty($additionalText) === true) {
$ignoring = null;
} else {
$parts = explode(',', $additionalText);
$ignoring = clone $ignoring;
$parts = explode(',', $additionalText);
foreach ($parts as $sniffCode) {
$sniffCode = trim($sniffCode);
$enabledSniffs[$sniffCode] = true;
$ignoring->set($sniffCode, false);
}

// This new enabled sniff might remove previously disabled
// sniffs if it is actually a standard or category of sniffs.
foreach (array_keys($ignoring) as $ignoredSniffCode) {
if ($ignoredSniffCode === $sniffCode
|| strpos($ignoredSniffCode, $sniffCode.'.') === 0
) {
unset($ignoring[$ignoredSniffCode]);
}
}

// This new enabled sniff might be able to clear up
// previously enabled sniffs if it is actually a standard or
// category of sniffs.
if (isset($ignoring['.except']) === true) {
foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) {
if ($ignoredSniffCode === $sniffCode
|| strpos($ignoredSniffCode, $sniffCode.'.') === 0
) {
unset($ignoring['.except'][$ignoredSniffCode]);
}
}
}
}//end foreach

if (empty($ignoring) === true) {
if ($ignoring->isEmpty() === true) {
$ignoring = null;
} else {
if (isset($ignoring['.except']) === true) {
$ignoring['.except'] += $enabledSniffs;
} else {
$ignoring['.except'] = $enabledSniffs;
}
}
}//end if
}

if ($lineHasOtherContent === false) {
// Completely ignore the comment line.
$this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreAll;
} else {
// The comment is on the same line as the code it is ignoring,
// so respect the new ignore rules.
Expand All @@ -523,31 +484,35 @@ private function createPositionMap()

$additionalText = substr($commentText, 13);
if (empty($additionalText) === true) {
$ignoreRules = ['.all' => true];
$ignoreRules = ['.all' => true];
$lineIgnoring = $ignoreAll;
} else {
$parts = explode(',', $additionalText);
if ($ignoring === null) {
$lineIgnoring = IgnoreList::ignoringNone();
} else {
$lineIgnoring = clone $ignoring;
}

foreach ($parts as $sniffCode) {
$ignoreRules[trim($sniffCode)] = true;
$lineIgnoring->set($sniffCode, true);
}
}

$this->tokens[$i]['code'] = T_PHPCS_IGNORE;
$this->tokens[$i]['type'] = 'T_PHPCS_IGNORE';
$this->tokens[$i]['sniffCodes'] = $ignoreRules;

if ($ignoring !== null) {
$ignoreRules += $ignoring;
}

if ($lineHasOtherContent === false) {
// Completely ignore the comment line, and set the following
// line to include the ignore rules we've set.
$this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true];
$this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoreRules;
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreAll;
$this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $lineIgnoring;
} else {
// The comment is on the same line as the code it is ignoring,
// so respect the ignore rules it set.
$this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules;
$this->ignoredLines[$this->tokens[$i]['line']] = $lineIgnoring;
}
}//end if
}//end if
Expand Down
Loading