public static findPreviousExcluding ( PHP_CodeSniffer_File $phpcsFile, integer[] | integer $types, integer $startPointer, integer | null $endPointer = null ) : integer | null | ||
$phpcsFile | PHP_CodeSniffer_File | |
$types | integer[] | integer | |
$startPointer | integer | search starts at this token, inclusive |
$endPointer | integer | null | search ends at this token, exclusive |
return | integer | null |
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $usePointer * @return string */ public static function getFullyQualifiedTypeNameFromUse(PHP_CodeSniffer_File $phpcsFile, $usePointer) { $nameEndPointer = $phpcsFile->findNext([T_SEMICOLON, T_AS, T_COMMA], $usePointer + 1); $tokens = $phpcsFile->getTokens(); if ($tokens[$nameEndPointer - 1]['code'] === T_WHITESPACE) { $nameEndPointer = TokenHelper::findPreviousExcluding($phpcsFile, [T_WHITESPACE], $nameEndPointer - 1) + 1; } $nameStartPointer = $phpcsFile->findNext(TokenHelper::$nameTokenCodes, $usePointer + 1, $nameEndPointer); $name = TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer); return NamespaceHelper::normalizeToCanonicalName($name); }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer * @return \SlevomatCodingStandard\Helpers\ReferencedName[] referenced names */ private static function createAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $beginSearchAtPointer = $openTagPointer + 1; $tokens = $phpcsFile->getTokens(); $searchTypes = array_merge([T_RETURN_TYPE], TokenHelper::$nameTokenCodes); $types = []; while (true) { $nameStartPointer = $phpcsFile->findNext($searchTypes, $beginSearchAtPointer); if ($nameStartPointer === false) { break; } $nameStartToken = $tokens[$nameStartPointer]; $nameEndPointer = self::findReferencedNameEndPointer($phpcsFile, $nameStartPointer); if ($nameEndPointer === null) { $beginSearchAtPointer = TokenHelper::findNextExcluding($phpcsFile, array_merge([T_WHITESPACE, T_RETURN_TYPE], TokenHelper::$nameTokenCodes), $nameStartPointer); continue; } $nextTokenAfterEndPointer = TokenHelper::findNextEffective($phpcsFile, $nameEndPointer); $previousTokenBeforeStartPointer = TokenHelper::findPreviousEffective($phpcsFile, $nameStartPointer - 1); $type = ReferencedName::TYPE_DEFAULT; if ($nextTokenAfterEndPointer !== null && $previousTokenBeforeStartPointer !== null) { if ($tokens[$nextTokenAfterEndPointer]['code'] === T_OPEN_PARENTHESIS) { if ($tokens[$previousTokenBeforeStartPointer]['code'] !== T_NEW) { $type = ReferencedName::TYPE_FUNCTION; } } elseif ($tokens[$nextTokenAfterEndPointer]['code'] !== T_VARIABLE) { if (!in_array($tokens[$previousTokenBeforeStartPointer]['code'], [T_EXTENDS, T_IMPLEMENTS, T_INSTANCEOF, T_USE, T_NEW, T_COLON], true) && !in_array($tokens[$nextTokenAfterEndPointer]['code'], [T_DOUBLE_COLON], true)) { if ($tokens[$previousTokenBeforeStartPointer]['code'] === T_COMMA) { $precedingTokenPointer = TokenHelper::findPreviousExcluding($phpcsFile, array_merge([T_COMMA], TokenHelper::$nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), $previousTokenBeforeStartPointer - 1); if (!in_array($tokens[$precedingTokenPointer]['code'], [T_IMPLEMENTS, T_EXTENDS, T_USE])) { $type = ReferencedName::TYPE_CONSTANT; } } elseif (PHP_VERSION_ID >= 70100 && ($tokens[$previousTokenBeforeStartPointer]['code'] === T_BITWISE_OR || $tokens[$previousTokenBeforeStartPointer]['code'] === T_OPEN_PARENTHESIS)) { $exclude = [T_BITWISE_OR, T_OPEN_PARENTHESIS]; $catchPointer = TokenHelper::findPreviousExcluding($phpcsFile, array_merge($exclude, TokenHelper::$nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), $previousTokenBeforeStartPointer - 1); $exclude = [T_BITWISE_OR]; $openParenthesisPointer = TokenHelper::findPreviousExcluding($phpcsFile, array_merge($exclude, TokenHelper::$nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), $previousTokenBeforeStartPointer); if ($tokens[$catchPointer]['code'] !== T_CATCH || $tokens[$openParenthesisPointer]['code'] !== T_OPEN_PARENTHESIS) { $type = ReferencedName::TYPE_CONSTANT; } } else { $type = ReferencedName::TYPE_CONSTANT; } } } } $types[] = new ReferencedName(TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer), $nameStartPointer, $type); $beginSearchAtPointer = $nameEndPointer + 1; } return $types; }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer */ public function process(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $tokens = $phpcsFile->getTokens(); $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer); foreach ($referencedNames as $referencedName) { $name = $referencedName->getNameAsReferencedInFile(); $pointer = $referencedName->getPointer(); $canonicalName = NamespaceHelper::normalizeToCanonicalName($name); if (NamespaceHelper::isFullyQualifiedName($name)) { $isExceptionByName = StringHelper::endsWith($name, 'Exception') || $name === '\\Throwable' || StringHelper::endsWith($name, 'Error') && !NamespaceHelper::hasNamespace($name) || in_array($canonicalName, $this->getSpecialExceptionNames(), true); $inIgnoredNames = in_array($canonicalName, $this->getIgnoredNames(), true); if ($this->isClassRequiredToBeUsed($name) && (!$this->allowFullyQualifiedExceptions || !$isExceptionByName || $inIgnoredNames)) { $previousKeywordPointer = TokenHelper::findPreviousExcluding($phpcsFile, array_merge(TokenHelper::$nameTokenCodes, [T_WHITESPACE, T_COMMA]), $pointer - 1); if (!in_array($tokens[$previousKeywordPointer]['code'], $this->getFullyQualifiedKeywords(), true)) { if (!NamespaceHelper::hasNamespace($name) && NamespaceHelper::findCurrentNamespaceName($phpcsFile, $pointer) === null) { $phpcsFile->addError(sprintf('Type %s should not be referenced via a fully qualified name, but via an unqualified name without the leading \\, because the file does not have a namespace and the type cannot be put in a use statement', $name), $pointer, self::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME_WITHOUT_NAMESPACE); } else { $phpcsFile->addError(sprintf('Type %s should not be referenced via a fully qualified name, but via a use statement', $name), $pointer, self::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME); } } } } elseif (!$this->allowPartialUses) { if (NamespaceHelper::isQualifiedName($name)) { $phpcsFile->addError(sprintf('Partial use statements are not allowed, but referencing %s found', $name), $pointer, self::CODE_PARTIAL_USE); } } } }
/** * @param PHP_CodeSniffer_File $phpcsFile * @param mixed[] $tokens * @param integer $privateTokenPointer * @return string[] */ private function getPhpDocTags(PHP_CodeSniffer_File $phpcsFile, array $tokens, $privateTokenPointer) { $phpDocTokenCloseTagPointer = TokenHelper::findPreviousExcluding($phpcsFile, T_WHITESPACE, $privateTokenPointer - 1); $phpDocTokenCloseTag = $tokens[$phpDocTokenCloseTagPointer]; if ($phpDocTokenCloseTag['code'] !== T_DOC_COMMENT_CLOSE_TAG) { return []; } $tags = []; $findPhpDocTagPointer = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, $phpDocTokenCloseTagPointer - 1) + 1; while (($phpDocTagTokenPointer = $phpcsFile->findNext([T_DOC_COMMENT_TAG], $findPhpDocTagPointer, $phpDocTokenCloseTagPointer)) !== false) { $phpDocTagToken = $tokens[$phpDocTagTokenPointer]; $tags[] = $phpDocTagToken['content']; $findPhpDocTagPointer++; } return $tags; }