From cc709c2c8e07b2a840f02dd35908183110c585f9 Mon Sep 17 00:00:00 2001 From: Daniel Espendiller Date: Sat, 24 Jun 2023 09:22:47 +0200 Subject: [PATCH] fix Twig "for in" completion of variables --- .../templating/TwigPattern.java | 25 +++++++++++++------ .../templating/util/TwigTypeResolveUtil.java | 2 +- .../templating/util/TwigUtil.java | 2 +- .../tests/templating/TwigPatternTest.java | 15 +++++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigPattern.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigPattern.java index 17e191972..27f26f3a5 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigPattern.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigPattern.java @@ -1180,18 +1180,16 @@ public boolean accepts(@NotNull PsiElement psiElement, ProcessingContext process .withLanguage(TwigLanguage.INSTANCE); } + /** + * @TODO: check related features introduce by PhpStorm for Twig changes in 2020 + */ public static PsiElementPattern.Capture captureVariableOrField() { return PlatformPatterns.psiElement().withElementType(TokenSet.create(TwigElementTypes.VARIABLE_REFERENCE, TwigElementTypes.FIELD_REFERENCE)); } - public static ElementPattern getForTagInVariablePattern() { - - // {% for key, user in "users" %} - // {% for user in "users" %} - // {% for user in "users"|slice(0, 10) %} - - //noinspection unchecked + public static ElementPattern getForTagInVariableReferencePattern() { + // {% for user in test.test %} return captureVariableOrField().afterLeafSkipping( PlatformPatterns.or( PlatformPatterns.psiElement(PsiWhiteSpace.class), @@ -1202,6 +1200,18 @@ public static ElementPattern getForTagInVariablePattern() { .withLanguage(TwigLanguage.INSTANCE); } + public static ElementPattern getForTagInVariablePattern() { + // {% for key, user in "users" %} + // {% for user in "users" %} + // {% for user in "users"|slice(0, 10) %} + return PlatformPatterns.psiElement().afterLeafSkipping( + PlatformPatterns.or( + PlatformPatterns.psiElement(PsiWhiteSpace.class), + PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE) + ), + PlatformPatterns.psiElement(TwigTokenTypes.IN).withLanguage(TwigLanguage.INSTANCE)); + } + public static ElementPattern getIfVariablePattern() { // {% if "var" %} @@ -1367,6 +1377,7 @@ public static ElementPattern getVariableTypePattern() { //noinspection unchecked return PlatformPatterns.or( getForTagInVariablePattern(), + getForTagInVariableReferencePattern(), getIfVariablePattern(), getIfConditionVariablePattern(), getSetVariablePattern() diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java index c3780d628..c64e5ee4a 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java @@ -371,7 +371,7 @@ private static void collectForArrayScopeVariables(@NotNull PsiElement psiElement // {% for user in "users" %} PsiElement forTag = twigCompositeElement.getFirstChild(); - PsiElement inVariable = PsiElementUtils.getChildrenOfType(forTag, TwigPattern.getForTagInVariablePattern()); + PsiElement inVariable = PsiElementUtils.getChildrenOfType(forTag, TwigPattern.getForTagInVariableReferencePattern()); inVariable = inVariable instanceof TwigVariableReference ? inVariable : PsiTreeUtil.getChildOfType(inVariable, TwigVariableReference.class); if(inVariable == null) { return; diff --git a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java index ad141160b..df91e7841 100644 --- a/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java +++ b/src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigUtil.java @@ -2715,7 +2715,7 @@ private static void visitTemplateVariables(@NotNull PsiElement scope, @NotNull C if(firstChild.getNode().getElementType() == TwigElementTypes.FOR_TAG) { PsiElement afterIn = PsiElementUtils.getNextSiblingOfType( firstChild.getFirstChild(), - TwigPattern.getForTagInVariablePattern() + TwigPattern.getForTagInVariableReferencePattern() ); visitTemplateVariablesConsumer(afterIn, consumer); diff --git a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/TwigPatternTest.java b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/TwigPatternTest.java index e2aafaa9a..d83ecaf8f 100644 --- a/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/TwigPatternTest.java +++ b/src/test/java/fr/adrienbrault/idea/symfony2plugin/tests/templating/TwigPatternTest.java @@ -1,5 +1,6 @@ package fr.adrienbrault.idea.symfony2plugin.tests.templating; +import com.intellij.psi.PsiElement; import com.jetbrains.twig.TwigFileType; import fr.adrienbrault.idea.symfony2plugin.templating.TwigPattern; import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase; @@ -442,4 +443,18 @@ public void testGetTranslationPattern() { assertTrue(TwigPattern.getTranslationKeyPattern("trans").accepts(findElementAt(TwigFileType.INSTANCE, "{{ 'foo'|trans }}"))); assertTrue(TwigPattern.getTranslationKeyPattern("trans").accepts(findElementAt(TwigFileType.INSTANCE, "{{ 'foo'|trans('foobar') }}"))); } + + public void testGetForTagInVariablePattern() { + PsiElement elementAt = findElementAt(TwigFileType.INSTANCE, "{% for user in %}"); + assertTrue(TwigPattern.getForTagInVariablePattern().accepts(elementAt)); + + PsiElement elementAt2 = findElementAt(TwigFileType.INSTANCE, "{% for user in test %}"); + assertTrue(TwigPattern.getForTagInVariablePattern().accepts(elementAt2)); + + PsiElement elementAt3 = findElementAt(TwigFileType.INSTANCE, "{% for key, user in %}"); + assertTrue(TwigPattern.getForTagInVariablePattern().accepts(elementAt3)); + + PsiElement elementAt4 = findElementAt(TwigFileType.INSTANCE, "{% for key, user in |test('test') %}"); + assertTrue(TwigPattern.getForTagInVariablePattern().accepts(elementAt4)); + } }