Skip to content

Commit

Permalink
Fix class detection in double-quoted strings and heredoc
Browse files Browse the repository at this point in the history
  • Loading branch information
c01l authored and kukulich committed Mar 9, 2024
1 parent d82a671 commit 74b296b
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 0 deletions.
29 changes: 29 additions & 0 deletions SlevomatCodingStandard/Helpers/ReferencedNameHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
use const T_HEREDOC;
use const T_IMPLEMENTS;
use const T_INSTANCEOF;
use const T_NAME_FULLY_QUALIFIED;
use const T_NAME_QUALIFIED;
use const T_NAME_RELATIVE;
use const T_NAMESPACE;
use const T_NEW;
use const T_NS_SEPARATOR;
Expand All @@ -51,6 +54,7 @@
use const T_TYPE_UNION;
use const T_USE;
use const T_VARIABLE;
use const T_WHITESPACE;

/**
* @internal
Expand Down Expand Up @@ -494,6 +498,31 @@ private static function getReferencedNamesFromString(string $content): array
}

$referencedNames[] = $referencedName;
} elseif (is_array($token) && $token[0] === T_NEW) {
$referencedName = '';
$tmpPosition = $position + 1;
while (true) {
if (!is_array($subTokens[$tmpPosition])) {
break;
}
if ($subTokens[$tmpPosition][0] === T_WHITESPACE) {
$tmpPosition++;
continue;
}
if (!in_array(
$subTokens[$tmpPosition][0],
[T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED, T_NAME_RELATIVE],
true
)) {
break;
}

$referencedName .= $subTokens[$tmpPosition][1];
$tmpPosition++;
}
if ($referencedName !== '') {
$referencedNames[] = $referencedName;
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/Helpers/ReferencedNameHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ public function testGetAllReferencedNames(): void
['EnumType', false, false],
['UrlGeneratorInterface', false, false],
['ClassInHeredoc', false, false],
['\Some\OtherClassInHeredoc', false, false],
['ClassInDoubleQuote', false, false],
['\Some\OtherClassInDoubleQuote', false, false],
['object', true, false],
['DateTime', false, false],
['DateTimeImmutable', false, false],
Expand Down
2 changes: 2 additions & 0 deletions tests/Helpers/data/lotsOfReferencedNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,12 @@ public function generateRoute($router): string

<<<XML
<string>Hello world and {$this->wrap(ClassInHeredoc::EXAMPLE)}</string>
{$_(new \Some\OtherClassInHeredoc())}
XML;

"foo {$db->quote(ClassInDoubleQuote::SOME_CONSTANT)}";
"foo $db->quote(FakeClassInDoubleQuote::SOME_CONSTANT)";
"{$_(new \Some\OtherClassInDoubleQuote ?? "")}";

$script .= "// @see \Foo\Bar::func()
\$hasDefaultValue = $hasDefaultValue;
Expand Down
4 changes: 4 additions & 0 deletions tests/Sniffs/Namespaces/UnusedUsesSniffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public function testUnusedUse(): void
self::assertNoSniffError($report, 30);
self::assertNoSniffError($report, 31);

// Used class inside a string or heredoc
self::assertNoSniffError($report, 31);
self::assertNoSniffError($report, 32);

self::assertNoSniffError($report, 91);
}

Expand Down
7 changes: 7 additions & 0 deletions tests/Sniffs/Namespaces/data/unusedUses.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
use ClassWithStaticVariable;
use ClassWithConstant;
use function Psl\Type\null;
use InstantiableClass1;
use InstantiableClass2;

class TestClass implements FirstInterface, SecondInterface
{
Expand Down Expand Up @@ -60,6 +62,11 @@ enum_type: EnumClass::VALUE(),

echo "test {$wrapper->escape(ClassWithConstant::FOO)}";

echo "{$_(new InstantiableClass1())}";
echo <<<DOC
{$_(new InstantiableClass2())}
DOC;

return new NewObject();
}

Expand Down

0 comments on commit 74b296b

Please sign in to comment.