|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * \Drupal\Sniffs\CSS\ClassDefinitionNameSpacingSniff. |
| 4 | + * |
| 5 | + * @category PHP |
| 6 | + * @package PHP_CodeSniffer |
| 7 | + * @link http://pear.php.net/package/PHP_CodeSniffer |
| 8 | + */ |
| 9 | + |
| 10 | +namespace Drupal\Sniffs\CSS; |
| 11 | + |
| 12 | +use PHP_CodeSniffer\Files\File; |
| 13 | +use PHP_CodeSniffer\Sniffs\DeprecatedSniff; |
| 14 | +use PHP_CodeSniffer\Sniffs\Sniff; |
| 15 | +use PHP_CodeSniffer\Util\Tokens; |
| 16 | + |
| 17 | +/** |
| 18 | + * Ensure there are no blank lines between the names of classes/IDs. Copied from |
| 19 | + * \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ClassDefinitionNameSpacingSniff |
| 20 | + * because we also check for comma separated selectors on their own line. |
| 21 | + * |
| 22 | + * @deprecated in Coder 8.3.30 and will be removed in Coder 9.0.0. Checking CSS |
| 23 | + * coding standards is not supported anymore, use Stylelint instead with the |
| 24 | + * Drupal core .stylelintrc.json configuration file. |
| 25 | + * @see https://git.drupalcode.org/project/drupal/-/blob/11.x/core/.stylelintrc.json |
| 26 | + * |
| 27 | + * @category PHP |
| 28 | + * @package PHP_CodeSniffer |
| 29 | + * @link http://pear.php.net/package/PHP_CodeSniffer |
| 30 | + */ |
| 31 | +class ClassDefinitionNameSpacingSniff implements Sniff, DeprecatedSniff |
| 32 | +{ |
| 33 | + |
| 34 | + /** |
| 35 | + * A list of tokenizers this sniff supports. |
| 36 | + * |
| 37 | + * @var array<string> |
| 38 | + */ |
| 39 | + public $supportedTokenizers = ['CSS']; |
| 40 | + |
| 41 | + |
| 42 | + /** |
| 43 | + * Returns the token types that this sniff is interested in. |
| 44 | + * |
| 45 | + * @return array<int, int|string> |
| 46 | + */ |
| 47 | + public function register() |
| 48 | + { |
| 49 | + return [T_OPEN_CURLY_BRACKET]; |
| 50 | + |
| 51 | + }//end register() |
| 52 | + |
| 53 | + |
| 54 | + /** |
| 55 | + * Processes the tokens that this sniff is interested in. |
| 56 | + * |
| 57 | + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. |
| 58 | + * @param int $stackPtr The position in the stack where |
| 59 | + * the token was found. |
| 60 | + * |
| 61 | + * @return void |
| 62 | + */ |
| 63 | + public function process(File $phpcsFile, $stackPtr) |
| 64 | + { |
| 65 | + $tokens = $phpcsFile->getTokens(); |
| 66 | + |
| 67 | + // Do not check nested style definitions as, for example, in @media style rules. |
| 68 | + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); |
| 69 | + if ($nested !== false) { |
| 70 | + return; |
| 71 | + } |
| 72 | + |
| 73 | + // Find the first blank line before this opening brace, unless we get |
| 74 | + // to another style definition, comment or the start of the file. |
| 75 | + $endTokens = [ |
| 76 | + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, |
| 77 | + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, |
| 78 | + T_OPEN_TAG => T_OPEN_TAG, |
| 79 | + ]; |
| 80 | + $endTokens += Tokens::$commentTokens; |
| 81 | + |
| 82 | + $foundContent = false; |
| 83 | + $currentLine = $tokens[$stackPtr]['line']; |
| 84 | + for ($i = ($stackPtr - 1); $i >= 0; $i--) { |
| 85 | + if (isset($endTokens[$tokens[$i]['code']]) === true) { |
| 86 | + break; |
| 87 | + } |
| 88 | + |
| 89 | + // A comma must be followed by a new line character. |
| 90 | + if ($tokens[$i]['code'] === T_COMMA |
| 91 | + && strpos($tokens[($i + 1)]['content'], $phpcsFile->eolChar) === false |
| 92 | + ) { |
| 93 | + $error = 'Multiple selectors should each be on a single line'; |
| 94 | + $fix = $phpcsFile->addFixableError($error, ($i + 1), 'MultipleSelectors'); |
| 95 | + if ($fix === true) { |
| 96 | + $phpcsFile->fixer->addNewline($i); |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + // Selectors must be on the same line. |
| 101 | + if ($tokens[$i]['code'] === T_WHITESPACE |
| 102 | + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false |
| 103 | + && isset($endTokens[$tokens[($i - 1)]['code']]) === false |
| 104 | + && in_array($tokens[($i - 1)]['code'], [T_WHITESPACE, T_COMMA]) === false |
| 105 | + ) { |
| 106 | + $error = 'Selectors must be on a single line'; |
| 107 | + // cspell:ignore SeletorSingleLine |
| 108 | + $fix = $phpcsFile->addFixableError($error, $i, 'SeletorSingleLine'); |
| 109 | + if ($fix === true) { |
| 110 | + $phpcsFile->fixer->replaceToken($i, str_replace($phpcsFile->eolChar, ' ', $tokens[$i]['content'])); |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + if ($tokens[$i]['line'] === $currentLine) { |
| 115 | + if ($tokens[$i]['code'] !== T_WHITESPACE) { |
| 116 | + $foundContent = true; |
| 117 | + } |
| 118 | + |
| 119 | + continue; |
| 120 | + } |
| 121 | + |
| 122 | + // We changed lines. |
| 123 | + if ($foundContent === false) { |
| 124 | + // Before we throw an error, make sure we are not looking |
| 125 | + // at a gap before the style definition. |
| 126 | + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i, null, true); |
| 127 | + if ($prev !== false |
| 128 | + && isset($endTokens[$tokens[$prev]['code']]) === false |
| 129 | + ) { |
| 130 | + $error = 'Blank lines are not allowed between class names'; |
| 131 | + $fix = $phpcsFile->addFixableError($error, ($i + 1), 'BlankLinesFound'); |
| 132 | + if ($fix === true) { |
| 133 | + $phpcsFile->fixer->replaceToken(($i + 1), ''); |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + break; |
| 138 | + } |
| 139 | + |
| 140 | + $foundContent = false; |
| 141 | + $currentLine = $tokens[$i]['line']; |
| 142 | + }//end for |
| 143 | + |
| 144 | + }//end process() |
| 145 | + |
| 146 | + |
| 147 | + /** |
| 148 | + * {@inheritdoc} |
| 149 | + * |
| 150 | + * @return string |
| 151 | + */ |
| 152 | + public function getDeprecationVersion(): string |
| 153 | + { |
| 154 | + return 'Coder 8.3.30'; |
| 155 | + |
| 156 | + }//end getDeprecationVersion() |
| 157 | + |
| 158 | + |
| 159 | + /** |
| 160 | + * {@inheritdoc} |
| 161 | + * |
| 162 | + * @return string |
| 163 | + */ |
| 164 | + public function getRemovalVersion(): string |
| 165 | + { |
| 166 | + return 'Coder 9.0.0'; |
| 167 | + |
| 168 | + }//end getRemovalVersion() |
| 169 | + |
| 170 | + |
| 171 | + /** |
| 172 | + * {@inheritdoc} |
| 173 | + * |
| 174 | + * @return string |
| 175 | + */ |
| 176 | + public function getDeprecationMessage(): string |
| 177 | + { |
| 178 | + return 'Checking CSS coding standards is not supported anymore, use Stylelint instead with the Drupal core .stylelintrc.json configuration file. https://git.drupalcode.org/project/drupal/-/blob/11.x/core/.stylelintrc.json'; |
| 179 | + |
| 180 | + }//end getDeprecationMessage() |
| 181 | + |
| 182 | + |
| 183 | +}//end class |
0 commit comments