<commit_before><?php declare(strict_types = 1);

namespace SlevomatCodingStandard\Sniffs\Commenting;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
use SlevomatCodingStandard\Helpers\CommentHelper;
use SlevomatCodingStandard\Helpers\FixerHelper;
use SlevomatCodingStandard\Helpers\IndentationHelper;
use SlevomatCodingStandard\Helpers\TokenHelper;
use function array_key_exists;
use function array_merge;
use function in_array;
use function strlen;
use function substr;
use const T_CLOSE_CURLY_BRACKET;
use const T_CLOSURE;
use const T_DOC_COMMENT_OPEN_TAG;
use const T_ELSE;
use const T_ELSEIF;
use const T_OPEN_CURLY_BRACKET;
use const T_WHITESPACE;

class DisallowCommentAfterCodeSniff implements Sniff
{

	public const CODE_DISALLOWED_COMMENT_AFTER_CODE = 'DisallowedCommentAfterCode';

	/**
	 * @return array<int, (int|string)>
	 */
	public function register(): array
	{
		/** @phpstan-var array<int, (int|string)> */
		return array_merge(TokenHelper::$inlineCommentTokenCodes, [T_DOC_COMMENT_OPEN_TAG]);
	}

	/**
	 * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
	 * @param int $commentPointer
	 */
	public function process(File $phpcsFile, $commentPointer): void
	{
		$firstNonWhitespacePointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $commentPointer);

		if ($firstNonWhitespacePointerOnLine === $commentPointer) {
			return;
		}

		$tokens = $phpcsFile->getTokens();

		$commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $commentPointer);
		$nextNonWhitespacePointer = TokenHelper::findNextNonWhitespace($phpcsFile, $commentEndPointer + 1);

		if (
			$nextNonWhitespacePointer !== null
			&& $commentEndPointer !== null
			&& $tokens[$nextNonWhitespacePointer]['line'] === $tokens[$commentEndPointer]['line']

		) {
			return;
		}

		$fix = $phpcsFile->addFixableError('Comment after code is disallowed.', $commentPointer, self::CODE_DISALLOWED_COMMENT_AFTER_CODE);
		if (!$fix) {
			return;
		}

		$commentContent = TokenHelper::getContent($phpcsFile, $commentPointer, $commentEndPointer);
		$commentHasNewLineAtTheEnd = substr($commentContent, -strlen($phpcsFile->eolChar)) === $phpcsFile->eolChar;

		if (!$commentHasNewLineAtTheEnd) {
			$commentContent .= $phpcsFile->eolChar;
		}

		$firstNonWhiteSpacePointerBeforeComment = TokenHelper::findPreviousNonWhitespace($phpcsFile, $commentPointer - 1);

		$newLineAfterComment = $commentHasNewLineAtTheEnd
			? $commentEndPointer
			: TokenHelper::findNextContent($phpcsFile, T_WHITESPACE, $phpcsFile->eolChar, $commentEndPointer + 1);

		$indentation = IndentationHelper::getIndentation($phpcsFile, $firstNonWhitespacePointerOnLine);
		$firstPointerOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $firstNonWhitespacePointerOnLine);

		$phpcsFile->fixer->beginChangeset();

		if (
			$tokens[$firstNonWhiteSpacePointerBeforeComment]['code'] === T_OPEN_CURLY_BRACKET
			&& array_key_exists('scope_condition', $tokens[$firstNonWhiteSpacePointerBeforeComment])
			&& in_array(
				$tokens[$tokens[$firstNonWhiteSpacePointerBeforeComment]['scope_condition']]['code'],
				[T_ELSEIF, T_ELSE, T_CLOSURE],
				true
			)
		) {
			$phpcsFile->fixer->addContent(
				$firstNonWhiteSpacePointerBeforeComment,<commit_msg>Cleanup<commit_after><?php declare(strict_types = 1);

namespace SlevomatCodingStandard\Sniffs\Commenting;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
use SlevomatCodingStandard\Helpers\CommentHelper;
use SlevomatCodingStandard\Helpers\FixerHelper;
use SlevomatCodingStandard\Helpers\IndentationHelper;
use SlevomatCodingStandard\Helpers\TokenHelper;
use function array_key_exists;
use function array_merge;
use function in_array;
use function strlen;
use function substr;
use const T_CLOSE_CURLY_BRACKET;
use const T_CLOSURE;
use const T_DOC_COMMENT_OPEN_TAG;
use const T_ELSE;
use const T_ELSEIF;
use const T_OPEN_CURLY_BRACKET;
use const T_WHITESPACE;

class DisallowCommentAfterCodeSniff implements Sniff
{

	public const CODE_DISALLOWED_COMMENT_AFTER_CODE = 'DisallowedCommentAfterCode';

	/**
	 * @return array<int, (int|string)>
	 */
	public function register(): array
	{
		/** @phpstan-var array<int, (int|string)> */
		return array_merge(TokenHelper::$inlineCommentTokenCodes, [T_DOC_COMMENT_OPEN_TAG]);
	}

	/**
	 * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
	 * @param int $commentPointer
	 */
	public function process(File $phpcsFile, $commentPointer): void
	{
		$firstNonWhitespacePointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $commentPointer);

		if ($firstNonWhitespacePointerOnLine === $commentPointer) {
			return;
		}

		$tokens = $phpcsFile->getTokens();

		$commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $commentPointer);
		$nextNonWhitespacePointer = TokenHelper::findNextNonWhitespace($phpcsFile, $commentEndPointer + 1);

		if (
			$nextNonWhitespacePointer !== null
			&& $commentEndPointer !== null
			&& $tokens[$nextNonWhitespacePointer]['line'] === $tokens[$commentEndPointer]['line']

		) {
			return;
		}

		$fix = $phpcsFile->addFixableError('Comment after code is disallowed.', $commentPointer, self::CODE_DISALLOWED_COMMENT_AFTER_CODE);
		if (!$fix) {
			return;
		}

		$commentContent = TokenHelper::getContent($phpcsFile, $commentPointer, $commentEndPointer);
		$commentHasNewLineAtTheEnd = substr($commentContent, -strlen($phpcsFile->eolChar)) === $phpcsFile->eolChar;

		if (!$commentHasNewLineAtTheEnd) {
			$commentContent .= $phpcsFile->eolChar;
		}

		$firstNonWhiteSpacePointerBeforeComment = TokenHelper::findPreviousNonWhitespace($phpcsFile, $commentPointer - 1);

		$newLineAfterComment = $commentHasNewLineAtTheEnd
			? $commentEndPointer
			: TokenHelper::findLastTokenOnLine($phpcsFile, $commentEndPointer);

		$indentation = IndentationHelper::getIndentation($phpcsFile, $firstNonWhitespacePointerOnLine);
		$firstPointerOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $firstNonWhitespacePointerOnLine);

		$phpcsFile->fixer->beginChangeset();

		if (
			$tokens[$firstNonWhiteSpacePointerBeforeComment]['code'] === T_OPEN_CURLY_BRACKET
			&& array_key_exists('scope_condition', $tokens[$firstNonWhiteSpacePointerBeforeComment])
			&& in_array(
				$tokens[$tokens[$firstNonWhiteSpacePointerBeforeComment]['scope_condition']]['code'],
				[T_ELSEIF, T_ELSE, T_CLOSURE],
				true
			)
		) {
			$phpcsFile->fixer->addContent(
				$firstNonWhiteSpacePointerBeforeComment,
{'fraction_non_alphanumeric': 0.1142336320826371, 'fraction_numerical': 0.0010633449794926325, 'mean_word_length': 7.148514851485149, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1920625', 'n_tokens_mistral': 2302, 'n_tokens_neox': 2127, 'n_words': 328}