/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $anyPointer any pointer type where the search begins from (backwards) * @return string|null */ public static function findCurrentNamespaceName(PHP_CodeSniffer_File $phpcsFile, $anyPointer) { $namespacePointer = $phpcsFile->findPrevious(T_NAMESPACE, $anyPointer); if ($namespacePointer === false) { return null; } $namespaceNameStartPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $namespacePointer + 1); $namespaceNameEndPointer = TokenHelper::findNextExcluding($phpcsFile, TokenHelper::$nameTokenCodes, $namespaceNameStartPointer + 1); return TokenHelper::getContent($phpcsFile, $namespaceNameStartPointer, $namespaceNameEndPointer); }
/** * @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 $keywordPointer * @param integer $nameStartPointer * @return integer Referenced name end pointer (exclusive) */ private function checkReferencedName(PHP_CodeSniffer_File $phpcsFile, $keywordPointer, $nameStartPointer) { $tokens = $phpcsFile->getTokens(); $nameStartToken = $tokens[$nameStartPointer]; $endPointer = ReferencedNameHelper::findReferencedNameEndPointer($phpcsFile, $nameStartPointer); if ($nameStartToken['code'] !== T_NS_SEPARATOR) { $name = TokenHelper::getContent($phpcsFile, $nameStartPointer, $endPointer); $keyword = $tokens[$keywordPointer]['content']; $phpcsFile->addError(sprintf('Type %s in %s statement should be referenced via a fully qualified name', $name, $keyword), $keywordPointer, self::getErrorCode($keyword)); } return $endPointer; }
/** * @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) { $implementsOrExtendsPointer = TokenHelper::findPreviousExcluding($phpcsFile, array_merge([T_COMMA], TokenHelper::$nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), $previousTokenBeforeStartPointer - 1); if ($tokens[$implementsOrExtendsPointer]['code'] !== T_IMPLEMENTS && $tokens[$implementsOrExtendsPointer]['code'] !== T_EXTENDS) { $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 * @param boolean $searchAnnotations * @return \SlevomatCodingStandard\Helpers\ReferencedName[] referenced names */ private static function createAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer, $searchAnnotations) { $beginSearchAtPointer = $openTagPointer + 1; $tokens = $phpcsFile->getTokens(); $phpDocTypes = [T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG]; $searchTypes = array_merge([T_RETURN_TYPE], TokenHelper::$nameTokenCodes); if ($searchAnnotations) { $searchTypes = array_merge($phpDocTypes, $searchTypes); } $types = []; $matchTypesInAnnotation = function ($annotation, $nameStartPointer) use(&$types) { $annotation = trim($annotation, '@ '); if (preg_match('#([a-zA-Z0-9_|\\[\\]\\\\]+)#', $annotation, $matches) > 0) { $referencedNames = array_filter(array_map(function ($name) { return trim($name, '[]'); }, explode('|', $matches[1])), function ($match) { return !in_array($match, ['null', 'self', 'static', 'mixed', 'array', 'string', 'int', 'integer', 'bool', 'boolean'], true); }); foreach ($referencedNames as $name) { $types[] = new ReferencedName($name, $nameStartPointer); } } }; while (true) { $nameStartPointer = $phpcsFile->findNext($searchTypes, $beginSearchAtPointer); if ($nameStartPointer === false) { break; } $nameStartToken = $tokens[$nameStartPointer]; if (in_array($nameStartToken['code'], $phpDocTypes, true)) { if ($nameStartToken['code'] === T_DOC_COMMENT_TAG) { if (!StringHelper::startsWith($nameStartToken['content'], '@var') && !StringHelper::startsWith($nameStartToken['content'], '@param') && !StringHelper::startsWith($nameStartToken['content'], '@return') && !StringHelper::startsWith($nameStartToken['content'], '@throws') && !StringHelper::startsWith($nameStartToken['content'], '@see') && !StringHelper::startsWith($nameStartToken['content'], '@link') && !StringHelper::startsWith($nameStartToken['content'], '@inherit')) { $matchTypesInAnnotation($nameStartToken['content'], $nameStartPointer); } } elseif ($nameStartToken['code'] === T_DOC_COMMENT_STRING) { $matchTypesInAnnotation($nameStartToken['content'], $nameStartPointer); } $beginSearchAtPointer = $nameStartPointer + 1; continue; } $nameEndPointer = self::findReferencedNameEndPointer($phpcsFile, $nameStartPointer); if ($nameEndPointer === null) { $beginSearchAtPointer = TokenHelper::findNextExcluding($phpcsFile, array_merge([T_WHITESPACE, T_RETURN_TYPE], TokenHelper::$nameTokenCodes), $nameStartPointer); continue; } $types[] = new ReferencedName(TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer), $nameStartPointer); $beginSearchAtPointer = $nameEndPointer + 1; } return $types; }