/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer * @return \SlevomatCodingStandard\Helpers\UseStatement[] canonicalName(string) => useStatement(\SlevomatCodingStandard\Helpers\UseStatement) */ public static function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $names = []; foreach (self::getUseStatementPointers($phpcsFile, $openTagPointer) as $usePointer) { $name = self::getNameAsReferencedInClassFromUse($phpcsFile, $usePointer); $useStatement = new UseStatement($name, self::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer), $usePointer); $names[$useStatement->getCanonicalNameAsReferencedInFile()] = $useStatement; } return $names; }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer */ public function process(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $unusedNames = UseStatementHelper::getUseStatements($phpcsFile, $openTagPointer); $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer, $this->searchAnnotations); foreach ($referencedNames as $referencedName) { $name = $referencedName->getNameAsReferencedInFile(); $pointer = $referencedName->getPointer(); $nameParts = NamespaceHelper::getNameParts($name); $nameAsReferencedInFile = $nameParts[0]; $normalizedNameAsReferencedInFile = UseStatement::normalizedNameAsReferencedInFile($nameAsReferencedInFile); if (!NamespaceHelper::isFullyQualifiedName($name) && isset($unusedNames[$normalizedNameAsReferencedInFile])) { if ($unusedNames[$normalizedNameAsReferencedInFile]->getNameAsReferencedInFile() !== $nameAsReferencedInFile) { $phpcsFile->addError(sprintf('Case of reference name %s and use statement %s do not match', $nameAsReferencedInFile, $unusedNames[$normalizedNameAsReferencedInFile]->getNameAsReferencedInFile()), $pointer, self::CODE_MISMATCHING_CASE); } unset($unusedNames[$normalizedNameAsReferencedInFile]); } } foreach ($unusedNames as $value) { $fullName = $value->getFullyQualifiedTypeName(); if ($value->getNameAsReferencedInFile() !== $fullName) { if ($value->getNameAsReferencedInFile() !== NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($fullName)) { $fullName .= sprintf(' (as %s)', $value->getNameAsReferencedInFile()); } } $fix = $phpcsFile->addFixableError(sprintf('Type %s is not used in this file', $fullName), $value->getPointer(), self::CODE_UNUSED_USE); if ($fix) { $phpcsFile->fixer->beginChangeset(); $endPointer = $phpcsFile->findNext(T_SEMICOLON, $value->getPointer()) + 1; for ($i = $value->getPointer(); $i <= $endPointer; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } $phpcsFile->fixer->endChangeset(); } } }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer */ public function process(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer); $useStatements = UseStatementHelper::getUseStatements($phpcsFile, $openTagPointer); foreach ($referencedNames as $referencedName) { $pointer = $referencedName->getPointer(); $name = $referencedName->getNameAsReferencedInFile(); $normalizedName = UseStatement::normalizedNameAsReferencedInFile($name); if (isset($useStatements[$normalizedName]) && $referencedName->hasSameUseStatementType($useStatements[$normalizedName])) { $useStatement = $useStatements[$normalizedName]; if (in_array($useStatement->getFullyQualifiedTypeName(), $this->getIgnoredNames(), true) || !StringHelper::endsWith($useStatement->getFullyQualifiedTypeName(), 'Exception') && $useStatement->getFullyQualifiedTypeName() !== 'Throwable' && (!StringHelper::endsWith($useStatement->getFullyQualifiedTypeName(), 'Error') || NamespaceHelper::hasNamespace($useStatement->getFullyQualifiedTypeName())) && !in_array($useStatement->getFullyQualifiedTypeName(), $this->getSpecialExceptionNames(), true)) { continue; } } else { $fileNamespace = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $pointer); $canonicalName = $name; if (!NamespaceHelper::isFullyQualifiedName($name) && $fileNamespace !== null) { $canonicalName = sprintf('%s%s%s', $fileNamespace, NamespaceHelper::NAMESPACE_SEPARATOR, $name); } if (in_array($canonicalName, $this->getIgnoredNames(), true) || !StringHelper::endsWith($name, 'Exception') && $name !== 'Throwable' && (!StringHelper::endsWith($canonicalName, 'Error') || NamespaceHelper::hasNamespace($canonicalName)) && !in_array($canonicalName, $this->getSpecialExceptionNames(), true)) { continue; } } if (!NamespaceHelper::isFullyQualifiedName($name)) { $phpcsFile->addError(sprintf('Exception %s should be referenced via a fully qualified name', $name), $pointer, self::CODE_NON_FULLY_QUALIFIED_EXCEPTION); } } }
/** * @param \SlevomatCodingStandard\Helpers\UseStatement $a * @param \SlevomatCodingStandard\Helpers\UseStatement $b * @return integer */ private function compareUseStatements(UseStatement $a, UseStatement $b) { if (!$a->hasSameType($b)) { return $a->compareByType($b); } $aName = $a->getFullyQualifiedTypeName(); $bName = $b->getFullyQualifiedTypeName(); $i = 0; for (; $i < min(strlen($aName), strlen($bName)); $i++) { if ($this->isSpecialCharacter($aName[$i]) && !$this->isSpecialCharacter($bName[$i])) { return -1; } elseif (!$this->isSpecialCharacter($aName[$i]) && $this->isSpecialCharacter($bName[$i])) { return 1; } if (is_numeric($aName[$i]) && is_numeric($bName[$i])) { break; } $cmp = strcasecmp($aName[$i], $bName[$i]); if ($cmp !== 0 || $aName[$i] !== $bName[$i] && strtolower($aName[$i]) === strtolower($bName[$i])) { return $cmp; } } return strnatcasecmp(substr($aName, $i), substr($bName, $i)); }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param integer $openTagPointer * @return \SlevomatCodingStandard\Helpers\UseStatement[] canonicalName(string) => useStatement(\SlevomatCodingStandard\Helpers\UseStatement) */ public static function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $openTagPointer) { $names = []; $tokens = $phpcsFile->getTokens(); foreach (self::getUseStatementPointers($phpcsFile, $openTagPointer) as $usePointer) { $nextTokenFromUsePointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); $type = UseStatement::TYPE_DEFAULT; if ($tokens[$nextTokenFromUsePointer]['code'] === T_STRING) { if ($tokens[$nextTokenFromUsePointer]['content'] === 'const') { $type = UseStatement::TYPE_CONSTANT; } elseif ($tokens[$nextTokenFromUsePointer]['content'] === 'function') { $type = UseStatement::TYPE_FUNCTION; } } $name = self::getNameAsReferencedInClassFromUse($phpcsFile, $usePointer); $useStatement = new UseStatement($name, self::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer), $usePointer, $type); $names[$useStatement->getCanonicalNameAsReferencedInFile()] = $useStatement; } return $names; }