Skip to content

Commit 9ae678c

Browse files
committed
index usages of twig files inside "Template" php attribute
1 parent 88d09cd commit 9ae678c

File tree

2 files changed

+111
-17
lines changed

2 files changed

+111
-17
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/PhpMethodVariableResolveUtil.java

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import fr.adrienbrault.idea.symfony2plugin.templating.variable.dict.PsiVariable;
1616
import fr.adrienbrault.idea.symfony2plugin.util.AnnotationBackportUtil;
1717
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
18+
import fr.adrienbrault.idea.symfony2plugin.util.PhpPsiAttributesUtil;
1819
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
1920
import kotlin.Triple;
2021
import org.apache.commons.lang.StringUtils;
@@ -244,6 +245,10 @@ public static void visitRenderTemplateFunctions(@NotNull Method method, @NotNull
244245
psiElementVisitor.visitPhpDocTag(phpDocTag);
245246
}
246247

248+
for (PhpAttributesList phpAttributesList : PsiTreeUtil.getChildrenOfTypeAsList(method, PhpAttributesList.class)) {
249+
psiElementVisitor.visitPhpAttribute(phpAttributesList);
250+
}
251+
247252
method.accept(psiElementVisitor);
248253
}
249254

@@ -271,10 +276,36 @@ public void visitElement(@NotNull PsiElement element) {
271276
visitMethodReference((MethodReference) element);
272277
} else if(element instanceof PhpDocTag) {
273278
visitPhpDocTag((PhpDocTag) element);
279+
} else if(element instanceof PhpAttributesList) {
280+
visitPhpAttribute((PhpAttributesList) element);
274281
}
275282
super.visitElement(element);
276283
}
277284

285+
private void visitPhpAttribute(@NotNull PhpAttributesList phpAttributesList) {
286+
Collection<@NotNull PhpAttribute> attributes = phpAttributesList.getAttributes(TwigUtil.TEMPLATE_ANNOTATION_CLASS);
287+
for (PhpAttribute attribute : attributes) {
288+
if (attribute.getArguments().isEmpty()) {
289+
// #[@Template()]
290+
PsiElement parent = phpAttributesList.getParent();
291+
if (parent instanceof Method) {
292+
visitMethodForGuessing((Method) parent);
293+
}
294+
} else {
295+
// [@Template("foobar.html.twig")]
296+
// #[@Template(template: "foobar.html.twig")]
297+
String template = PhpPsiAttributesUtil.getAttributeValueByNameAsStringWithDefaultParameterFallback(attribute, "template");
298+
if (StringUtils.isNotBlank(template)) {
299+
PsiElement parent = phpAttributesList.getParent();
300+
if (parent instanceof Method) {
301+
addTemplateWithScope(template, (Method) parent, null);
302+
303+
}
304+
}
305+
}
306+
}
307+
}
308+
278309
private void visitMethodReference(@NotNull MethodReference methodReference) {
279310
String methodName = methodReference.getName();
280311
if (methodName == null) {
@@ -409,23 +440,7 @@ private void visitPhpDocTag(@NotNull PhpDocTag phpDocTag) {
409440
// App\Controller\MyNiceController::myAction => my_nice/my.html.twig
410441
Method methodScope = AnnotationBackportUtil.getMethodScope(phpDocTag);
411442
if(methodScope != null) {
412-
PhpClass phpClass = methodScope.getContainingClass();
413-
if (phpClass != null) {
414-
// App\Controller\ "MyNice" Controller
415-
Matcher matcher = Pattern.compile("Controller\\\\(.+)Controller$", Pattern.MULTILINE).matcher(StringUtils.stripStart(phpClass.getFQN(), "\\"));
416-
if(matcher.find()){
417-
String group = underscore(matcher.group(1).replace("\\", "/"));
418-
String name = methodScope.getName();
419-
420-
// __invoke is using controller as template name
421-
if (name.equals("__invoke")) {
422-
addTemplateWithScope(group + ".html.twig", methodScope, null);
423-
} else {
424-
String action = name.endsWith("Action") ? name.substring(0, name.length() - "Action".length()) : name;
425-
addTemplateWithScope(group + "/" + underscore(action) + ".html.twig", methodScope, null);
426-
}
427-
}
428-
}
443+
visitMethodForGuessing(methodScope);
429444
}
430445
} else if(template.endsWith(".twig")) {
431446
Method methodScope = AnnotationBackportUtil.getMethodScope(phpDocTag);
@@ -435,6 +450,26 @@ private void visitPhpDocTag(@NotNull PhpDocTag phpDocTag) {
435450
}
436451
}
437452

453+
private void visitMethodForGuessing(@NotNull Method methodScope) {
454+
PhpClass phpClass = methodScope.getContainingClass();
455+
if (phpClass != null) {
456+
// App\Controller\ "MyNice" Controller
457+
Matcher matcher = Pattern.compile("Controller\\\\(.+)Controller$", Pattern.MULTILINE).matcher(StringUtils.stripStart(phpClass.getFQN(), "\\"));
458+
if(matcher.find()){
459+
String group = underscore(matcher.group(1).replace("\\", "/"));
460+
String name = methodScope.getName();
461+
462+
// __invoke is using controller as template name
463+
if (name.equals("__invoke")) {
464+
addTemplateWithScope(group + ".html.twig", methodScope, null);
465+
} else {
466+
String action = name.endsWith("Action") ? name.substring(0, name.length() - "Action".length()) : name;
467+
addTemplateWithScope(group + "/" + underscore(action) + ".html.twig", methodScope, null);
468+
}
469+
}
470+
}
471+
}
472+
438473
private void addTemplateWithScope(@NotNull String contents, @NotNull PhpNamedElement scope, @Nullable FunctionReference functionReference) {
439474
String s = TwigUtil.normalizeTemplateName(contents);
440475
consumer.accept(new Triple<>(s, scope, functionReference));

src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/stubs/indexes/PhpTwigTemplateUsageStubIndexTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,65 @@ public void testEmptyTemplateAnnotationIndexUsingTemplateGuesser() {
130130
);
131131
}
132132

133+
134+
public void testThatDefaultTemplatePropertyPhpAttributeIsIndexed() {
135+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
136+
"use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template;" +
137+
"class Foobar\n" +
138+
"{" +
139+
"#[Template(\"foo-php-attribute-default.html.twig\")]\n" +
140+
"public function foobar() {}" +
141+
"}\n"
142+
);
143+
144+
assertIndexContains(
145+
PhpTwigTemplateUsageStubIndex.KEY,
146+
"foo-php-attribute-default.html.twig"
147+
);
148+
149+
assertIndexContainsKeyWithValue(PhpTwigTemplateUsageStubIndex.KEY, "foo-php-attribute-default.html.twig", value ->
150+
"foo-php-attribute-default.html.twig".equals(value.getTemplate()) && value.getScopes().contains("Foobar.foobar")
151+
);
152+
}
153+
154+
public void testThatDefaultTemplatePropertyPhpAttributeTemplateIsIndexed() {
155+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
156+
"use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template;" +
157+
"class Foobar\n" +
158+
"{" +
159+
"#[Template(template: \"foo-php-attribute-template.html.twig\")]\n" +
160+
"public function foobar() {}" +
161+
"}\n"
162+
);
163+
164+
assertIndexContains(
165+
PhpTwigTemplateUsageStubIndex.KEY,
166+
"foo-php-attribute-template.html.twig"
167+
);
168+
169+
assertIndexContainsKeyWithValue(PhpTwigTemplateUsageStubIndex.KEY, "foo-php-attribute-template.html.twig", value ->
170+
"foo-php-attribute-template.html.twig".equals(value.getTemplate()) && value.getScopes().contains("Foobar.foobar")
171+
);
172+
}
173+
174+
public void testEmptyTemplatePhpAttributeIndexUsingTemplateGuesser() {
175+
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
176+
"namespace App\\Controller;" +
177+
"" +
178+
"use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template;" +
179+
"class MyNiceFoobarController\n" +
180+
"{" +
181+
"#[Template()]\n" +
182+
"public function foobarWhatAction() {}" +
183+
"}\n"
184+
);
185+
186+
assertIndexContains(
187+
PhpTwigTemplateUsageStubIndex.KEY,
188+
"my_nice_foobar/foobar_what.html.twig"
189+
);
190+
}
191+
133192
public void testEmptyTemplateAnnotationIndexUsingInvokeTemplateGuesser() {
134193
myFixture.configureByText(PhpFileType.INSTANCE, "<?php\n" +
135194
"namespace App\\Controller;" +

0 commit comments

Comments
 (0)