<commit_before><?php

namespace PSR2R\Sniffs\Commenting;

use PSR2R\Tools\AbstractSniff;

/**
 * Makes sure doc block param types allow `|null`, `|array` etc, when those are used
 * as default values in the method signature.
 *
 * @author    <NAME>
 * @license   MIT
 */
class DocBlockParamAllowDefaultValueSniff extends AbstractSniff {

	/**
	 * @return array
	 */
	public function register() {
		return [
			T_FUNCTION,
		];
	}

	/**
	 * @param \PHP_CodeSniffer_File $phpCsFile
	 * @param int $stackPointer
	 *
	 * @return void
	 */
	public function process(\PHP_CodeSniffer_File $phpCsFile, $stackPointer) {
		$tokens = $phpCsFile->getTokens();

		$docBlockEndIndex = $this->findRelatedDocBlock($phpCsFile, $stackPointer);

		if (!$docBlockEndIndex) {
			return;
		}

		$methodSignature = $this->getMethodSignature($phpCsFile, $stackPointer);
		if (!$methodSignature) {
			return;
		}
		//TODO: check count of signature vs doc block param count

		$docBlockStartIndex = $tokens[$docBlockEndIndex]['comment_opener'];

		$paramCount = 0;
		for ($i = $docBlockStartIndex + 1; $i < $docBlockEndIndex; $i++) {
			if ($tokens[$i]['type'] !== 'T_DOC_COMMENT_TAG') {
				continue;
			}
			if (!in_array($tokens[$i]['content'], ['@param'])) {
				continue;
			}

			if (empty($methodSignature[$paramCount])) {
				$phpCsFile->addError('Param type does not have a matching signature in method', $i);
				continue;
			}
			$methodSignatureValue = $methodSignature[$paramCount];
			$paramCount++;

			$classNameIndex = $i + 2;

			if ($tokens[$classNameIndex]['type'] !== 'T_DOC_COMMENT_STRING') {
				$phpCsFile->addError('Missing type in param doc block', $i);
				continue;
			}

			$content = $tokens[$classNameIndex]['content'];

			$appendix = '';
			$spaceIndex = strpos($content, ' ');
			if ($spaceIndex) {
				$appendix = substr($content, $spaceIndex);
				$content = substr($content, 0, $spaceIndex);
			}
			if (empty($content)) {
				continue;
			}

			if (empty($methodSignatureValue['typehint']) && empty($methodSignatureValue['default'])) {
				continue;
			}

			$pieces = explode('|', $content);
			if ($methodSignatureValue['typehint']) {
				$typeIndex = $methodSignatureValue['typehint'];
				$type = $tokens[$typeIndex]['content'];
				if (!in_array($type, $pieces)) {
					$error = 'Possible doc block error: `' . $content . '` seems to be missing type `' . $type . '`.';
					$fix = $phpCsFile->addFixableError($error, $classNameIndex);
					if ($fix) {
						$pieces[] = $type;
						$content = implode('|', $pieces);
						$phpCsFile->fixer->replaceToken($classNameIndex, $content . $appendix);
					}
				}
			}
			if ($methodSignatureValue['default']) {<commit_msg>Skip for mixed type<commit_after><?php

namespace PSR2R\Sniffs\Commenting;

use PSR2R\Tools\AbstractSniff;

/**
 * Makes sure doc block param types allow `|null`, `|array` etc, when those are used
 * as default values in the method signature.
 *
 * @author    <NAME>
 * @license   MIT
 */
class DocBlockParamAllowDefaultValueSniff extends AbstractSniff {

	/**
	 * @return array
	 */
	public function register() {
		return [
			T_FUNCTION,
		];
	}

	/**
	 * @param \PHP_CodeSniffer_File $phpCsFile
	 * @param int $stackPointer
	 *
	 * @return void
	 */
	public function process(\PHP_CodeSniffer_File $phpCsFile, $stackPointer) {
		$tokens = $phpCsFile->getTokens();

		$docBlockEndIndex = $this->findRelatedDocBlock($phpCsFile, $stackPointer);

		if (!$docBlockEndIndex) {
			return;
		}

		$methodSignature = $this->getMethodSignature($phpCsFile, $stackPointer);
		if (!$methodSignature) {
			return;
		}
		//TODO: check count of signature vs doc block param count

		$docBlockStartIndex = $tokens[$docBlockEndIndex]['comment_opener'];

		$paramCount = 0;
		for ($i = $docBlockStartIndex + 1; $i < $docBlockEndIndex; $i++) {
			if ($tokens[$i]['type'] !== 'T_DOC_COMMENT_TAG') {
				continue;
			}
			if (!in_array($tokens[$i]['content'], ['@param'])) {
				continue;
			}

			if (empty($methodSignature[$paramCount])) {
				$phpCsFile->addError('Param type does not have a matching signature in method', $i);
				continue;
			}
			$methodSignatureValue = $methodSignature[$paramCount];
			$paramCount++;

			$classNameIndex = $i + 2;

			if ($tokens[$classNameIndex]['type'] !== 'T_DOC_COMMENT_STRING') {
				$phpCsFile->addError('Missing type in param doc block', $i);
				continue;
			}

			$content = $tokens[$classNameIndex]['content'];

			$appendix = '';
			$spaceIndex = strpos($content, ' ');
			if ($spaceIndex) {
				$appendix = substr($content, $spaceIndex);
				$content = substr($content, 0, $spaceIndex);
			}
			if (empty($content)) {
				continue;
			}

			if (empty($methodSignatureValue['typehint']) && empty($methodSignatureValue['default'])) {
				continue;
			}

			$pieces = explode('|', $content);
			// We skip for mixed
			if (in_array('mixed', $pieces, true)) {
				continue;
			}

			if ($methodSignatureValue['typehint']) {
				$typeIndex = $methodSignatureValue['typehint'];
				$type = $tokens[$typeIndex]['content'];
				if (!in_array($type, $pieces)) {
					$error = 'Possible doc block error: `' . $content . '` seems to be missing type `' . $type . '`.';
					$fix = $phpCsFile->addFixableError($error, $classNameIndex);
					if ($fix) {
						$pieces[] = $type;
						$content = implode('|', $pieces);
						$phpCsFile->fixer->replaceToken($classNameIndex, $content . $appendix);
					}
				}
			}
			if ($methodSignatureValue['default']) {
{'fraction_non_alphanumeric': 0.16773484709760117, 'fraction_numerical': 0.0021973997436366965, 'mean_word_length': 3.825088339222615, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, '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': '373667', 'n_tokens_mistral': 2114, 'n_tokens_neox': 1739, 'n_words': 388}