*/ public function register() { return [\T_STRING_CONCAT]; } /** * Processes this test, when one of its tokens is encountered. * * @since 1.2.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return int|void Integer stack pointer to skip forward or void to continue * normal file processing. */ public function process(File $phpcsFile, $stackPtr) { /* * Validate the setting. */ if ($this->allowOnly !== self::POSITION_END) { // Use the default. $this->allowOnly = self::POSITION_START; } $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); if ($nextNonEmpty === false) { // Parse error/live coding. return; } $tokens = $phpcsFile->getTokens(); if ($tokens[$prevNonEmpty]['line'] === $tokens[$nextNonEmpty]['line']) { // Not multi-line concatenation. Not our target. return; } $position = self::POSITION_STANDALONE; if ($tokens[$prevNonEmpty]['line'] === $tokens[$stackPtr]['line']) { $position = self::POSITION_END; } elseif ($tokens[$nextNonEmpty]['line'] === $tokens[$stackPtr]['line']) { $position = self::POSITION_START; } // Record metric. $phpcsFile->recordMetric($stackPtr, self::METRIC_NAME, $position); if ($this->allowOnly === $position) { // All okay. return; } $fix = $phpcsFile->addFixableError( 'The concatenation operator for multi-line concatenations should always be at the %s of a line.', $stackPtr, 'Incorrect', [$this->allowOnly] ); if ($fix === true) { if ($this->allowOnly === self::POSITION_END) { $phpcsFile->fixer->beginChangeset(); // Move the concat operator. $phpcsFile->fixer->replaceToken($stackPtr, ''); $phpcsFile->fixer->addContent($prevNonEmpty, ' .'); if ($position === self::POSITION_START && $tokens[($stackPtr + 1)]['code'] === \T_WHITESPACE ) { // Remove trailing space. $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); } elseif ($position === self::POSITION_STANDALONE) { // Remove potential indentation space. if ($tokens[($stackPtr - 1)]['code'] === \T_WHITESPACE) { $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); } // Remove new line. if ($tokens[($stackPtr + 1)]['code'] === \T_WHITESPACE) { $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); } } $phpcsFile->fixer->endChangeset(); return; } // Fixer for allowOnly === self::POSITION_START. $phpcsFile->fixer->beginChangeset(); // Move the concat operator. $phpcsFile->fixer->replaceToken($stackPtr, ''); $phpcsFile->fixer->addContentBefore($nextNonEmpty, '. '); if ($position === self::POSITION_END && $tokens[($stackPtr - 1)]['code'] === \T_WHITESPACE ) { // Remove trailing space. $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); } elseif ($position === self::POSITION_STANDALONE) { // Remove potential indentation space. if ($tokens[($stackPtr - 1)]['code'] === \T_WHITESPACE) { $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); } // Remove new line. if ($tokens[($stackPtr + 1)]['code'] === \T_WHITESPACE) { $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); } } $phpcsFile->fixer->endChangeset(); } } }