/** * @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 \PHP_CodeSniffer_File $phpcsFile * @param integer $usePointer */ public function process(PHP_CodeSniffer_File $phpcsFile, $usePointer) { if (UseStatementHelper::isAnonymousFunctionUse($phpcsFile, $usePointer) || UseStatementHelper::isTraitUse($phpcsFile, $usePointer)) { return; } $namespaceName = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $usePointer); if ($namespaceName === null) { $namespaceName = ''; } $usedTypeName = UseStatementHelper::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer); if (!StringHelper::startsWith($usedTypeName, $namespaceName)) { return; } $asPointer = $this->findAsPointer($phpcsFile, $usePointer); if ($asPointer !== null) { return; } $usedTypeNameRest = substr($usedTypeName, strlen($namespaceName)); if (!NamespaceHelper::isFullyQualifiedName($usedTypeNameRest) && $namespaceName !== '') { return; } if (!NamespaceHelper::hasNamespace($usedTypeNameRest)) { $fix = $phpcsFile->addFixableError(sprintf('Use %s is from the same namespace – that is prohibited', $usedTypeName), $usePointer, self::CODE_USE_FROM_SAME_NAMESPACE); if ($fix) { $phpcsFile->fixer->beginChangeset(); $endPointer = $phpcsFile->findNext(T_SEMICOLON, $usePointer) + 1; for ($i = $usePointer; $i <= $endPointer; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } $phpcsFile->fixer->endChangeset(); } } }
/** * @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 $usePointer */ public function process(PHP_CodeSniffer_File $phpcsFile, $usePointer) { if (UseStatementHelper::isAnonymousFunctionUse($phpcsFile, $usePointer) || UseStatementHelper::isTraitUse($phpcsFile, $usePointer)) { return; } $className = UseStatementHelper::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer); if ($this->allowUseFromRootNamespace && !NamespaceHelper::isQualifiedName($className)) { return; } foreach ($this->getNamespacesRequiredToUse() as $namespace) { if (NamespaceHelper::isTypeInNamespace($className, $namespace)) { return; } } $phpcsFile->addError(sprintf('Type %s should not be used, but referenced via a fully qualified name', $className), $usePointer, self::CODE_NON_FULLY_QUALIFIED); }
/** * @param \PHP_CodeSniffer_File $phpcsFile * @param \SlevomatCodingStandard\Helpers\UseStatement[] $useStatements */ private function fixAlphabeticalOrder(PHP_CodeSniffer_File $phpcsFile, array $useStatements) { $firstUseStatement = reset($useStatements); $lastUseStatement = end($useStatements); $lastSemicolonPointer = $phpcsFile->findNext(T_SEMICOLON, $lastUseStatement->getPointer()); $phpcsFile->fixer->beginChangeset(); for ($i = $firstUseStatement->getPointer(); $i <= $lastSemicolonPointer; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } uasort($useStatements, function (UseStatement $a, UseStatement $b) { return $this->compareUseStatements($a, $b); }); $phpcsFile->fixer->addContent($firstUseStatement->getPointer(), implode(PHP_EOL, array_map(function (UseStatement $useStatement) { $unqualifiedName = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($useStatement->getFullyQualifiedTypeName()); if ($unqualifiedName === $useStatement->getNameAsReferencedInFile()) { return sprintf('use %s;', $useStatement->getFullyQualifiedTypeName()); } return sprintf('use %s as %s;', $useStatement->getFullyQualifiedTypeName(), $useStatement->getNameAsReferencedInFile()); }, $useStatements))); $phpcsFile->fixer->endChangeset(); }
/** * @param string $name * @return boolean */ private function isClassRequiredToBeUsed($name) { if ($this->namespacesRequiredToUse === null) { return true; } foreach ($this->getNamespacesRequiredToUse() as $namespace) { if (NamespaceHelper::isTypeInNamespace($name, $namespace)) { return true; } } return false; }