Skip to content

Commit 9e58fa8

Browse files
committed
Add support for detecting AsTwig* attributes in SymfonyImplicitUsageProvider
1 parent 96e8654 commit 9e58fa8

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/codeInsight/SymfonyImplicitUsageProvider.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public boolean isImplicitUsage(@NotNull PsiElement element) {
3232
if (element instanceof Method method && method.getAccess() == PhpModifier.Access.PUBLIC) {
3333
return isMethodARoute(method)
3434
|| isSubscribedEvent(method)
35-
|| isAsEventListenerMethodPhpAttribute(method);
35+
|| isAsEventListenerMethodPhpAttribute(method)
36+
|| hasTwigAttribute(method);
3637
} else if (element instanceof PhpClass phpClass) {
3738
return isRouteClass(phpClass)
3839
|| isCommandAndService(phpClass)
@@ -229,4 +230,10 @@ private boolean isAsEventListenerMethodPhpAttribute(@NotNull Method method) {
229230

230231
return false;
231232
}
233+
234+
private boolean hasTwigAttribute(@NotNull Method method) {
235+
return !method.getAttributes("\\Twig\\Attribute\\AsTwigFilter").isEmpty()
236+
|| !method.getAttributes("\\Twig\\Attribute\\AsTwigFunction").isEmpty()
237+
|| !method.getAttributes("\\Twig\\Attribute\\AsTwigTest").isEmpty();
238+
}
232239
}

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/codeInsight/SymfonyImplicitUsageProviderTest.java

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,79 @@ public void testTwigExtensionRegisteredAsServiceWithFunctionMethodImplementedIsM
395395
assertFalse(new SymfonyImplicitUsageProvider().isImplicitUsage(firstClassFromFile2));
396396
}
397397

398+
public void testTwigExtensionMethodsWithAttributesAreMarkedAsUsed() {
399+
PsiFile psiFile = myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
400+
"\n" +
401+
"namespace App\\Twig;\n" +
402+
"\n" +
403+
"use Twig\\Attribute\\AsTwigFunction;\n" +
404+
"use Twig\\Attribute\\AsTwigFilter;\n" +
405+
"use Twig\\Attribute\\AsTwigTest;\n" +
406+
"\n" +
407+
"class MyTwigExtension\n" +
408+
"{\n" +
409+
" #[AsTwigFunction('my_function')]\n" +
410+
" public function myFunction(): string\n" +
411+
" {\n" +
412+
" return 'Hello';\n" +
413+
" }\n" +
414+
"\n" +
415+
" #[AsTwigFilter('my_filter')]\n" +
416+
" public function myFilter(): string\n" +
417+
" {\n" +
418+
" return 'Filtered';\n" +
419+
" }\n" +
420+
"\n" +
421+
" #[AsTwigTest('my_test')]\n" +
422+
" public function myTest(): bool\n" +
423+
" {\n" +
424+
" return true;\n" +
425+
" }\n" +
426+
"\n" +
427+
" public function unusedMethod(): string\n" +
428+
" {\n" +
429+
" return 'Not used';\n" +
430+
" }\n" +
431+
"}"
432+
);
433+
434+
PhpClass phpClass = PhpElementsUtil.getFirstClassFromFile((PhpFile) psiFile.getContainingFile());
435+
436+
// Methods with Twig attributes should be marked as used
437+
assertTrue(new SymfonyImplicitUsageProvider().isImplicitUsage(phpClass.findOwnMethodByName("myFunction")));
438+
assertTrue(new SymfonyImplicitUsageProvider().isImplicitUsage(phpClass.findOwnMethodByName("myFilter")));
439+
assertTrue(new SymfonyImplicitUsageProvider().isImplicitUsage(phpClass.findOwnMethodByName("myTest")));
440+
441+
// Method without attributes should not be marked as used
442+
assertFalse(new SymfonyImplicitUsageProvider().isImplicitUsage(phpClass.findOwnMethodByName("unusedMethod")));
443+
}
444+
445+
446+
public void testTwigExtensionMethodWithMultipleAttributes() {
447+
PsiFile psiFile = myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
448+
"\n" +
449+
"namespace App\\Twig;\n" +
450+
"\n" +
451+
"use Twig\\Attribute\\AsTwigFunction;\n" +
452+
"use Twig\\Attribute\\AsTwigFilter;\n" +
453+
"\n" +
454+
"class MyTwigExtension\n" +
455+
"{\n" +
456+
" #[AsTwigFunction('callable_method')]\n" +
457+
" #[AsTwigFilter('callable_filter')]\n" +
458+
" public function callableMethod(): string\n" +
459+
" {\n" +
460+
" return 'Callable';\n" +
461+
" }\n" +
462+
"}"
463+
);
464+
465+
PhpClass phpClass = PhpElementsUtil.getFirstClassFromFile((PhpFile) psiFile.getContainingFile());
466+
467+
// Method with multiple attributes should be marked as used
468+
assertTrue(new SymfonyImplicitUsageProvider().isImplicitUsage(phpClass.findOwnMethodByName("callableMethod")));
469+
}
470+
398471
private PhpClass createPhpControllerClassWithRouteContent(@NotNull String content) {
399472
return createPhpControllerClassWithRouteContent("\\App\\Controller\\FooController", content);
400473
}

0 commit comments

Comments
 (0)