diff --git a/src/Reflection/Nette/HtmlClassReflectionExtension.php b/src/Reflection/Nette/HtmlClassReflectionExtension.php
index 1f6d391..c71a789 100644
--- a/src/Reflection/Nette/HtmlClassReflectionExtension.php
+++ b/src/Reflection/Nette/HtmlClassReflectionExtension.php
@@ -7,13 +7,15 @@
use PHPStan\Reflection\MethodsClassReflectionExtension;
use PHPStan\Reflection\PropertiesClassReflectionExtension;
use PHPStan\Reflection\PropertyReflection;
+use function in_array;
class HtmlClassReflectionExtension implements MethodsClassReflectionExtension, PropertiesClassReflectionExtension
{
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
{
- return $classReflection->is('Nette\Utils\Html');
+ // The static factories declared in the stub, which would otherwise be taken for attribute setters
+ return $classReflection->is('Nette\Utils\Html') && !in_array($methodName, ['text', 'html'], true);
}
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
diff --git a/stubs/Utils/Html.stub b/stubs/Utils/Html.stub
index 1ee2b50..6018297 100644
--- a/stubs/Utils/Html.stub
+++ b/stubs/Utils/Html.stub
@@ -5,6 +5,8 @@ namespace Nette\Utils;
/**
* @implements \IteratorAggregate
* @implements \ArrayAccess
+ * @method static static text(mixed $text)
+ * @method static static html(mixed $html)
*/
class Html implements \ArrayAccess, \IteratorAggregate
{
diff --git a/tests/Reflection/Nette/HtmlClassReflectionExtensionTest.php b/tests/Reflection/Nette/HtmlClassReflectionExtensionTest.php
index 6dc1978..96f0af1 100644
--- a/tests/Reflection/Nette/HtmlClassReflectionExtensionTest.php
+++ b/tests/Reflection/Nette/HtmlClassReflectionExtensionTest.php
@@ -28,10 +28,22 @@ public function dataHasMethod(): array
return [
[
Html::class,
+ 'href',
true,
],
+ [
+ Html::class,
+ 'text',
+ false,
+ ],
+ [
+ Html::class,
+ 'html',
+ false,
+ ],
[
stdClass::class,
+ 'href',
false,
],
];
@@ -40,10 +52,10 @@ public function dataHasMethod(): array
/**
* @dataProvider dataHasMethod
*/
- public function testHasMethod(string $className, bool $result): void
+ public function testHasMethod(string $className, string $methodName, bool $result): void
{
$classReflection = $this->reflectionProvider->getClass($className);
- self::assertSame($result, $this->extension->hasMethod($classReflection, 'href'));
+ self::assertSame($result, $this->extension->hasMethod($classReflection, $methodName));
}
public function testGetMethod(): void
diff --git a/tests/Rule/Nette/HtmlStaticFactoriesTest.php b/tests/Rule/Nette/HtmlStaticFactoriesTest.php
new file mode 100644
index 0000000..311f1d9
--- /dev/null
+++ b/tests/Rule/Nette/HtmlStaticFactoriesTest.php
@@ -0,0 +1,32 @@
+
+ */
+class HtmlStaticFactoriesTest extends RuleTestCase
+{
+
+ protected function getRule(): Rule
+ {
+ return self::getContainer()->getByType(CallStaticMethodsRule::class); // @phpstan-ignore phpstanApi.classConstant
+ }
+
+ public function testRule(): void
+ {
+ $this->analyse([__DIR__ . '/data/html-static-factories.php'], []);
+ }
+
+ public static function getAdditionalConfigFiles(): array
+ {
+ return [
+ __DIR__ . '/../../../extension.neon',
+ ];
+ }
+
+}
diff --git a/tests/Rule/Nette/data/html-static-factories.php b/tests/Rule/Nette/data/html-static-factories.php
new file mode 100644
index 0000000..e4d0863
--- /dev/null
+++ b/tests/Rule/Nette/data/html-static-factories.php
@@ -0,0 +1,12 @@
+html');
+ return $text->addHtml($html);
+}