diff --git a/SlevomatCodingStandard/Helpers/UseStatement.php b/SlevomatCodingStandard/Helpers/UseStatement.php index 41d380b03..fc4c6477a 100644 --- a/SlevomatCodingStandard/Helpers/UseStatement.php +++ b/SlevomatCodingStandard/Helpers/UseStatement.php @@ -85,6 +85,11 @@ public function getPointer(): int return $this->usePointer; } + public function getType(): string + { + return $this->type; + } + public function isConstant(): bool { return $this->type === self::TYPE_CONSTANT; @@ -100,13 +105,13 @@ public function hasSameType(self $that): bool return $this->type === $that->type; } - public function getTypeName(): ?string + public static function getTypeName(string $type): ?string { - if ($this->isConstant()) { + if ($type === self::TYPE_CONSTANT) { return 'const'; } - if ($this->isFunction()) { + if ($type === self::TYPE_FUNCTION) { return 'function'; } diff --git a/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php index 7c4df4601..bc0dda227 100644 --- a/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php +++ b/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -87,7 +87,7 @@ private function fixAlphabeticalOrder( $phpcsFile->fixer->addContent($firstUseStatement->getPointer(), implode($phpcsFile->eolChar, array_map(function (UseStatement $useStatement): string { $unqualifiedName = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($useStatement->getFullyQualifiedTypeName()); - $useTypeName = $useStatement->getTypeName(); + $useTypeName = UseStatement::getTypeName($useStatement->getType()); $useTypeFormatted = $useTypeName !== null ? sprintf('%s ', $useTypeName) : ''; if ($unqualifiedName === $useStatement->getNameAsReferencedInFile()) { diff --git a/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php b/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php index 50f13f6a7..8d11811dd 100644 --- a/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php +++ b/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php @@ -9,6 +9,7 @@ use SlevomatCodingStandard\Helpers\SniffSettingsHelper; use SlevomatCodingStandard\Helpers\StringHelper; use SlevomatCodingStandard\Helpers\TokenHelper; +use SlevomatCodingStandard\Helpers\UseStatement; use SlevomatCodingStandard\Helpers\UseStatementHelper; class ReferenceUsedNamesOnlySniff implements \PHP_CodeSniffer\Sniffs\Sniff @@ -218,7 +219,9 @@ function (ReferencedName $referencedName): string { $canBeFixed = true; foreach ($useStatements as $useStatement) { - if ($useStatement->getFullyQualifiedTypeName() !== $canonicalName + if ( + $useStatement->getType() === $referencedName->getType() + && $useStatement->getFullyQualifiedTypeName() !== $canonicalName && ($useStatement->getCanonicalNameAsReferencedInFile() === $canonicalNameToReference || array_key_exists($canonicalNameToReference, $definedClassesIndex)) ) { $canBeFixed = false; @@ -251,7 +254,7 @@ function (ReferencedName $referencedName): string { $alreadyUsed = false; foreach ($useStatements as $useStatement) { - if ($useStatement->getFullyQualifiedTypeName() === $canonicalName) { + if ($useStatement->getType() === $referencedName->getType() && $useStatement->getFullyQualifiedTypeName() === $canonicalName) { $nameToReference = $useStatement->getNameAsReferencedInFile(); $alreadyUsed = true; break; @@ -261,8 +264,11 @@ function (ReferencedName $referencedName): string { $phpcsFile->fixer->addContent($referencedName->getStartPointer(), $nameToReference); if (!$alreadyUsed) { + $useTypeName = UseStatement::getTypeName($referencedName->getType()); + $useTypeFormatted = $useTypeName !== null ? sprintf('%s ', $useTypeName) : ''; + $phpcsFile->fixer->addNewline($useStatementPlacePointer); - $phpcsFile->fixer->addContent($useStatementPlacePointer, sprintf('use %s;', $canonicalName)); + $phpcsFile->fixer->addContent($useStatementPlacePointer, sprintf('use %s%s;', $useTypeFormatted, $canonicalName)); } $phpcsFile->fixer->endChangeset(); diff --git a/tests/Sniffs/Namespaces/ReferenceUsedNamesOnlySniffTest.php b/tests/Sniffs/Namespaces/ReferenceUsedNamesOnlySniffTest.php index 6b0263be6..189f3b2a8 100644 --- a/tests/Sniffs/Namespaces/ReferenceUsedNamesOnlySniffTest.php +++ b/tests/Sniffs/Namespaces/ReferenceUsedNamesOnlySniffTest.php @@ -65,7 +65,7 @@ public function testCreatingNewObjectViaFullyQualifiedName(array $ignoredNames): * @dataProvider dataIgnoredNamesForIrrelevantTests * @param string[] $ignoredNames */ - public function testReferencingConstantViaFullyQualifiedName(array $ignoredNames): void + public function testReferencingClassConstantViaFullyQualifiedName(array $ignoredNames): void { $report = $this->checkFile(__DIR__ . '/data/shouldBeInUseStatement.php', [ 'ignoredNames' => $ignoredNames, @@ -78,6 +78,28 @@ public function testReferencingConstantViaFullyQualifiedName(array $ignoredNames ); } + public function testReferencingConstantViaFullyQualifiedName(): void + { + $report = $this->checkFile(__DIR__ . '/data/shouldBeInUseStatement.php'); + $this->assertSniffError( + $report, + 16, + ReferenceUsedNamesOnlySniff::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME, + '\Boo\FOO' + ); + } + + public function testReferencingFunctionViaFullyQualifiedName(): void + { + $report = $this->checkFile(__DIR__ . '/data/shouldBeInUseStatement.php'); + $this->assertSniffError( + $report, + 17, + ReferenceUsedNamesOnlySniff::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME, + '\Boo\foo' + ); + } + /** * @dataProvider dataIgnoredNamesForIrrelevantTests * @param string[] $ignoredNames diff --git a/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.fixed.php b/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.fixed.php index a5f04eeaf..30e88532b 100644 --- a/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.fixed.php +++ b/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.fixed.php @@ -7,6 +7,8 @@ use Some\ConstantClass; use Foo\SomeError; use Nette\ObjectPrototype; +use function Boo\foo; +use const Boo\FOO; class Bar extends \ObjectPrototype implements Iterator { @@ -19,6 +21,8 @@ public function bar() new \Some\CommonException(); new \Exception(); new ObjectPrototype(); + foo(); + FOO; } public function foo(DoctrineColumn $doctrineColumn): ObjectPrototype diff --git a/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.php b/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.php index 94d0e456a..3417e7bda 100644 --- a/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.php +++ b/tests/Sniffs/Namespaces/data/fixableReferenceViaFullyQualifiedName.php @@ -15,6 +15,8 @@ public function bar() new \Some\CommonException(); new \Exception(); new \Nette\ObjectPrototype(); + \Boo\foo(); + \Boo\FOO; } public function foo(\Doctrine\ORM\Mapping\Column $doctrineColumn): \Nette\ObjectPrototype diff --git a/tests/Sniffs/Namespaces/data/shouldBeInUseStatement.php b/tests/Sniffs/Namespaces/data/shouldBeInUseStatement.php index 8af27ed27..9205d6763 100644 --- a/tests/Sniffs/Namespaces/data/shouldBeInUseStatement.php +++ b/tests/Sniffs/Namespaces/data/shouldBeInUseStatement.php @@ -13,6 +13,8 @@ public function bar() new \Some\CommonException(); new \Exception(); new \Nette\ObjectPrototype(); + \Boo\FOO; + \Boo\foo(); } }