Skip to content

Commit 5e2e5f7

Browse files
authored
Merge pull request #1557 from slapoguzov/203-support
Support for PHPStorm 2020.3 version
2 parents 38b3225 + 7e272da commit 5e2e5f7

File tree

10 files changed

+165
-148
lines changed

10 files changed

+165
-148
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ before_install:
2323
- "export ORG_GRADLE_PROJECT_annotationPluginVersion=${ANNOTATION_PLUGIN_VERSION}"
2424

2525
env:
26-
- PHPSTORM_ENV="skip incomplete" IDEA_VERSION="IU-2020.2" PHP_PLUGIN_VERSION="202.6397.115" TWIG_PLUGIN_VERSION="202.6397.21" TOOLBOX_PLUGIN_VERSION="0.4.6" ANNOTATION_PLUGIN_VERSION="5.3" DQL_PLUGIN_VERSION="202.6397.59"
26+
- PHPSTORM_ENV="skip incomplete" IDEA_VERSION="IU-203.6682.78-EAP-SNAPSHOT" PHP_PLUGIN_VERSION="203.6682.78" TWIG_PLUGIN_VERSION="203.6682.75" TOOLBOX_PLUGIN_VERSION="0.4.6" ANNOTATION_PLUGIN_VERSION="5.3" DQL_PLUGIN_VERSION="203.5981.155"
2727

2828
script:
2929
- "./gradlew check verifyPlugin buildPlugin"

gradle.properties

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
ideaVersion = IU-2020.2
2-
phpPluginVersion = 202.6397.115
3-
twigPluginVersion = 202.6397.21
4-
dqlPluginVersion = 202.6397.59
1+
ideaVersion = IU-203.6682.78-EAP-SNAPSHOT
2+
phpPluginVersion = 203.6682.78
3+
twigPluginVersion = 203.6682.75
4+
dqlPluginVersion = 203.5981.155
55
toolboxPluginVersion = 0.4.6
66
annotationPluginVersion = 5.3

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigPattern.java

Lines changed: 38 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
import com.intellij.psi.PsiErrorElement;
1010
import com.intellij.psi.PsiWhiteSpace;
1111
import com.intellij.psi.tree.IElementType;
12+
import com.intellij.psi.tree.TokenSet;
1213
import com.intellij.util.ProcessingContext;
1314
import com.jetbrains.twig.TwigLanguage;
1415
import com.jetbrains.twig.TwigTokenTypes;
15-
import com.jetbrains.twig.elements.TwigBlockTag;
16-
import com.jetbrains.twig.elements.TwigCompositeElement;
17-
import com.jetbrains.twig.elements.TwigElementTypes;
16+
import com.jetbrains.twig.elements.*;
1817
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigTypeResolveUtil;
1918
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
2019
import org.jetbrains.annotations.NotNull;
@@ -414,16 +413,18 @@ public static ElementPattern<PsiElement> getAfterIsTokenWithOneIdentifierLeafPat
414413
//noinspection unchecked
415414
return PlatformPatterns
416415
.psiElement()
417-
.afterLeafSkipping(
418-
PlatformPatterns.or(
419-
PlatformPatterns.psiElement(PsiWhiteSpace.class),
420-
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
421-
),
422-
PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER).afterLeafSkipping(PlatformPatterns.psiElement(PsiWhiteSpace.class), PlatformPatterns.or(
423-
PlatformPatterns.psiElement(TwigTokenTypes.IS),
424-
PlatformPatterns.psiElement(TwigTokenTypes.NOT)
416+
.withParent(PlatformPatterns
417+
.psiElement()
418+
.afterLeafSkipping(
419+
PlatformPatterns.or(
420+
PlatformPatterns.psiElement(PsiWhiteSpace.class),
421+
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
422+
),
423+
PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER).afterLeafSkipping(PlatformPatterns.psiElement(PsiWhiteSpace.class), PlatformPatterns.or(
424+
PlatformPatterns.psiElement(TwigTokenTypes.IS),
425+
PlatformPatterns.psiElement(TwigTokenTypes.NOT)
426+
))
425427
))
426-
)
427428
.withLanguage(TwigLanguage.INSTANCE);
428429
}
429430

@@ -445,41 +446,10 @@ public static ElementPattern<PsiElement> getAfterIsTokenTextPattern() {
445446
* {% if 'foo.bar' <carpet> %}
446447
*/
447448
public static ElementPattern<PsiElement> getAfterOperatorPattern() {
448-
// @TODO: make it some nicer. can wrap it with whitespace
449-
450-
//noinspection unchecked
451-
ElementPattern<PsiElement> or = PlatformPatterns.or(
452-
PlatformPatterns.psiElement(PsiWhiteSpace.class),
453-
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE),
454-
PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER),
455-
PlatformPatterns.psiElement(TwigTokenTypes.SINGLE_QUOTE),
456-
PlatformPatterns.psiElement(TwigTokenTypes.STRING_TEXT),
457-
PlatformPatterns.psiElement(TwigTokenTypes.DOT),
458-
PlatformPatterns.psiElement(TwigTokenTypes.DOUBLE_QUOTE),
459-
PlatformPatterns.psiElement(TwigTokenTypes.LBRACE),
460-
PlatformPatterns.psiElement(TwigTokenTypes.RBRACE),
461-
PlatformPatterns.psiElement(TwigTokenTypes.LBRACE_SQ),
462-
PlatformPatterns.psiElement(TwigTokenTypes.RBRACE_SQ),
463-
PlatformPatterns.psiElement(TwigTokenTypes.NUMBER),
464-
PlatformPatterns.psiElement(TwigTokenTypes.FILTER)
465-
);
466-
467-
//noinspection unchecked
468-
ElementPattern<PsiElement> anIf = PlatformPatterns.or(
469-
PlatformPatterns.psiElement(TwigTokenTypes.TAG_NAME).withText("if"),
470-
PlatformPatterns.psiElement(TwigTokenTypes.AND),
471-
PlatformPatterns.psiElement(TwigTokenTypes.OR)
472-
);
473-
474449
return PlatformPatterns
475450
.psiElement(TwigTokenTypes.IDENTIFIER)
476-
.afterLeaf(PlatformPatterns.not(
477-
PlatformPatterns.psiElement(TwigTokenTypes.DOT)
478-
))
479-
.withParent(
480-
PlatformPatterns.psiElement(TwigElementTypes.IF_TAG)
481-
)
482-
.afterLeafSkipping(or, anIf)
451+
.inside(PlatformPatterns.psiElement(TwigElementTypes.IF_TAG))
452+
.andNot(PlatformPatterns.psiElement().inside(PlatformPatterns.psiElement(TwigElementTypes.FIELD_REFERENCE)))
483453
.withLanguage(TwigLanguage.INSTANCE);
484454
}
485455

@@ -555,7 +525,12 @@ public static ElementPattern<PsiElement> getEmbedPattern() {
555525
}
556526

557527
static ElementPattern<PsiElement> getPrintBlockFunctionPattern() {
558-
return PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER).withParent(getFunctionCallScopePattern()).withLanguage(TwigLanguage.INSTANCE);
528+
return PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER)
529+
.inside(PlatformPatterns.or(
530+
PlatformPatterns.psiElement(TwigPsiReference.class),
531+
PlatformPatterns.psiElement(TwigElementTypes.FUNCTION_CALL)))
532+
.inside(getFunctionCallScopePattern())
533+
.withLanguage(TwigLanguage.INSTANCE);
559534
}
560535

561536
public static ElementPattern<PsiElement> getFunctionPattern(@NotNull String ...functionName) {
@@ -601,25 +576,16 @@ private static ElementPattern<PsiElement> getFunctionCallScopePattern() {
601576
*/
602577
public static ElementPattern<PsiElement> getCompletablePattern() {
603578
//noinspection unchecked
604-
return PlatformPatterns.psiElement()
579+
return PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER)
580+
.inside(PlatformPatterns.psiElement(TwigElementTypes.VARIABLE_REFERENCE))
605581
.andNot(
582+
PlatformPatterns.psiElement().inside(PlatformPatterns.psiElement(TwigElementTypes.FIELD_REFERENCE))
583+
).inside(
606584
PlatformPatterns.or(
607-
PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(TwigTokenTypes.DOT)),
608-
PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(TwigTokenTypes.SINGLE_QUOTE)),
609-
PlatformPatterns.psiElement().afterLeaf(PlatformPatterns.psiElement(TwigTokenTypes.DOUBLE_QUOTE))
585+
PlatformPatterns.psiElement(TwigElementTypes.PRINT_BLOCK),
586+
PlatformPatterns.psiElement(TwigElementTypes.SET_TAG)
610587
)
611588
)
612-
.afterLeafSkipping(
613-
PlatformPatterns.or(
614-
PlatformPatterns.psiElement(TwigTokenTypes.LBRACE),
615-
PlatformPatterns.psiElement(PsiWhiteSpace.class)
616-
),
617-
PlatformPatterns.psiElement()
618-
)
619-
.withParent(PlatformPatterns.or(
620-
PlatformPatterns.psiElement(TwigElementTypes.PRINT_BLOCK),
621-
PlatformPatterns.psiElement(TwigElementTypes.SET_TAG)
622-
))
623589
.withLanguage(TwigLanguage.INSTANCE);
624590
}
625591

@@ -873,9 +839,7 @@ public static ElementPattern<PsiElement> getParentFunctionPattern() {
873839
public static ElementPattern<PsiElement> getTypeCompletionPattern() {
874840
return PlatformPatterns
875841
.psiElement(TwigTokenTypes.IDENTIFIER)
876-
.afterLeaf(
877-
PlatformPatterns.psiElement(TwigTokenTypes.DOT)
878-
)
842+
.withParent(PlatformPatterns.psiElement(TwigElementTypes.FIELD_REFERENCE))
879843
.withLanguage(TwigLanguage.INSTANCE);
880844
}
881845

@@ -1080,9 +1044,7 @@ public static ElementPattern<PsiElement> getForTagVariablePattern() {
10801044
// {% for "user" %}
10811045

10821046
//noinspection unchecked
1083-
return PlatformPatterns
1084-
.psiElement(TwigTokenTypes.IDENTIFIER)
1085-
.beforeLeafSkipping(
1047+
return captureVariableOrField().beforeLeafSkipping(
10861048
PlatformPatterns.or(
10871049
PlatformPatterns.psiElement(PsiWhiteSpace.class),
10881050
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
@@ -1129,16 +1091,19 @@ public boolean accepts(@NotNull PsiElement psiElement, ProcessingContext process
11291091
.withLanguage(TwigLanguage.INSTANCE);
11301092
}
11311093

1094+
public static PsiElementPattern.Capture<PsiElement> captureVariableOrField() {
1095+
return PlatformPatterns.psiElement().withElementType(TokenSet.create(TwigElementTypes.VARIABLE_REFERENCE,
1096+
TwigElementTypes.FIELD_REFERENCE));
1097+
}
1098+
11321099
public static ElementPattern<PsiElement> getForTagInVariablePattern() {
11331100

11341101
// {% for key, user in "users" %}
11351102
// {% for user in "users" %}
11361103
// {% for user in "users"|slice(0, 10) %}
11371104

11381105
//noinspection unchecked
1139-
return PlatformPatterns
1140-
.psiElement(TwigTokenTypes.IDENTIFIER)
1141-
.afterLeafSkipping(
1106+
return captureVariableOrField().afterLeafSkipping(
11421107
PlatformPatterns.or(
11431108
PlatformPatterns.psiElement(PsiWhiteSpace.class),
11441109
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
@@ -1153,9 +1118,7 @@ public static ElementPattern<PsiElement> getIfVariablePattern() {
11531118
// {% if "var" %}
11541119

11551120
//noinspection unchecked
1156-
return PlatformPatterns
1157-
.psiElement(TwigTokenTypes.IDENTIFIER)
1158-
.afterLeafSkipping(
1121+
return captureVariableOrField().afterLeafSkipping(
11591122
PlatformPatterns.or(
11601123
PlatformPatterns.psiElement(PsiWhiteSpace.class),
11611124
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
@@ -1177,9 +1140,7 @@ public static ElementPattern<PsiElement> getIfConditionVariablePattern() {
11771140
// and so on
11781141

11791142
//noinspection unchecked
1180-
return PlatformPatterns
1181-
.psiElement(TwigTokenTypes.IDENTIFIER)
1182-
.afterLeafSkipping(
1143+
return captureVariableOrField().afterLeafSkipping(
11831144
PlatformPatterns.or(
11841145
PlatformPatterns.psiElement(PsiWhiteSpace.class),
11851146
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)
@@ -1246,9 +1207,7 @@ public static ElementPattern<PsiElement> getSetVariablePattern() {
12461207
// {% set count1 = "var" %}
12471208

12481209
//noinspection unchecked
1249-
return PlatformPatterns
1250-
.psiElement(TwigTokenTypes.IDENTIFIER)
1251-
.afterLeafSkipping(
1210+
return captureVariableOrField().afterLeafSkipping(
12521211
PlatformPatterns.or(
12531212
PlatformPatterns.psiElement(PsiWhiteSpace.class),
12541213
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE)

src/main/java/fr/adrienbrault/idea/symfony2plugin/templating/TwigTemplateGoToDeclarationHandler.java

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import com.intellij.psi.PsiElement;
1111
import com.intellij.psi.PsiManager;
1212
import com.intellij.psi.PsiWhiteSpace;
13-
import com.intellij.psi.util.PsiTreeUtil;
13+
import com.intellij.psi.tree.IElementType;
1414
import com.intellij.util.containers.ContainerUtil;
1515
import com.jetbrains.php.PhpIndex;
1616
import com.jetbrains.php.lang.psi.elements.Field;
@@ -19,7 +19,8 @@
1919
import com.jetbrains.twig.TwigTokenTypes;
2020
import com.jetbrains.twig.elements.TwigBlockTag;
2121
import com.jetbrains.twig.elements.TwigElementTypes;
22-
import com.jetbrains.twig.elements.TwigTagWithFileReference;
22+
import com.jetbrains.twig.elements.TwigPsiReference;
23+
import com.jetbrains.twig.elements.TwigVariableReference;
2324
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
2425
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
2526
import fr.adrienbrault.idea.symfony2plugin.templating.dict.TwigExtension;
@@ -127,17 +128,6 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int offset,
127128
targets.addAll(this.getMacros(psiElement));
128129
}
129130

130-
// {% set foo %}
131-
// {% set foo = bar %}
132-
if (PlatformPatterns
133-
.psiElement(TwigTokenTypes.IDENTIFIER)
134-
.withParent(
135-
PlatformPatterns.psiElement(TwigElementTypes.PRINT_BLOCK)
136-
).withLanguage(TwigLanguage.INSTANCE).accepts(psiElement)) {
137-
138-
targets.addAll(getSets(psiElement));
139-
}
140-
141131
// {{ foo.fo<caret>o }}
142132
if (TwigPattern.getTypeCompletionPattern().accepts(psiElement)
143133
|| TwigPattern.getPrintBlockFunctionPattern().accepts(psiElement)
@@ -185,8 +175,9 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int offset,
185175
@NotNull
186176
private Collection<PsiElement> getAfterIsToken(@NotNull PsiElement psiElement) {
187177
// find text after if statement
178+
PsiElement actualElement = psiElement.getParent() instanceof TwigVariableReference ? psiElement.getParent() : psiElement;
188179
String text = StringUtils.trim(
189-
PhpElementsUtil.getPrevSiblingAsTextUntil(psiElement, TwigPattern.getAfterIsTokenTextPattern(), false) + psiElement.getText()
180+
PhpElementsUtil.getPrevSiblingAsTextUntil(actualElement, TwigPattern.getAfterIsTokenTextPattern(), false) + actualElement.getText()
190181
);
191182

192183
if(StringUtils.isBlank(text)) {
@@ -202,12 +193,13 @@ private Collection<PsiElement> getAfterIsToken(@NotNull PsiElement psiElement) {
202193
PsiElement whitespace = psiElement.getNextSibling();
203194
if(whitespace instanceof PsiWhiteSpace) {
204195
PsiElement nextSibling = whitespace.getNextSibling();
205-
if(nextSibling != null && nextSibling.getNode().getElementType() == TwigTokenTypes.IDENTIFIER) {
206-
String identifier = nextSibling.getText();
207-
if(StringUtils.isNotBlank(identifier)) {
208-
items.add(text + " " + identifier);
196+
IElementType elementType = nextSibling == null ? null : nextSibling.getNode().getElementType();
197+
if (elementType == TwigTokenTypes.IDENTIFIER || elementType == TwigElementTypes.VARIABLE_REFERENCE) {
198+
String identifier = nextSibling.getText();
199+
if (StringUtils.isNotBlank(identifier)) {
200+
items.add(text + " " + identifier);
201+
}
209202
}
210-
}
211203
}
212204

213205
Collection<PsiElement> psiElements = new ArrayList<>();
@@ -416,7 +408,10 @@ private Collection<PsiElement> getSeeDocTagTargets(@NotNull PsiElement psiElemen
416408
@NotNull
417409
public static Collection<PsiElement> getTypeGoto(@NotNull PsiElement psiElement) {
418410
Collection<PsiElement> targetPsiElements = new HashSet<>();
419-
411+
if (psiElement.getParent() instanceof TwigPsiReference) {
412+
PsiElement defaultResult = ((TwigPsiReference) psiElement.getParent()).resolve();
413+
if (defaultResult != null && defaultResult != psiElement.getParent()) return Collections.singleton(defaultResult);
414+
}
420415
// class, class.method, class.method.method
421416
// click on first item is our class name
422417
Collection<String> beforeLeaf = TwigTypeResolveUtil.formatPsiTypeName(psiElement);
@@ -466,23 +461,6 @@ private Collection<PsiElement> getFunctions(@NotNull PsiElement psiElement) {
466461
return Arrays.asList(PhpElementsUtil.getPsiElementsBySignature(psiElement.getProject(), functions.get(funcName).getSignature()));
467462
}
468463

469-
@NotNull
470-
private Collection<PsiElement> getSets(@NotNull PsiElement psiElement) {
471-
String funcName = psiElement.getText();
472-
for(String twigSet: TwigUtil.getSetDeclaration(psiElement.getContainingFile())) {
473-
if(twigSet.equals(funcName)) {
474-
// @TODO: drop regex
475-
return Arrays.asList(PsiTreeUtil.collectElements(psiElement.getContainingFile(), psiElement1 ->
476-
PlatformPatterns.psiElement(TwigTagWithFileReference.class)
477-
.accepts(psiElement1) && psiElement1.getText()
478-
.matches("\\{%\\s?set\\s?" + Pattern.quote(funcName) + "\\s?.*"))
479-
);
480-
}
481-
}
482-
483-
return Collections.emptyList();
484-
}
485-
486464
@NotNull
487465
private Collection<PsiElement> getMacros(@NotNull PsiElement psiElement) {
488466
String funcName = psiElement.getText();
@@ -493,7 +471,7 @@ private Collection<PsiElement> getMacros(@NotNull PsiElement psiElement) {
493471
PsiElement prevSibling = psiElement.getPrevSibling();
494472
if(prevSibling != null && prevSibling.getNode().getElementType() == TwigTokenTypes.DOT) {
495473
PsiElement identifier = prevSibling.getPrevSibling();
496-
if(identifier == null || identifier.getNode().getElementType() != TwigTokenTypes.IDENTIFIER) {
474+
if(identifier == null || identifier.getNode().getElementType() != TwigElementTypes.VARIABLE_REFERENCE) {
497475
return Collections.emptyList();
498476
}
499477

@@ -524,7 +502,8 @@ private Collection<PsiElement> getControllerNameGoto(@NotNull PsiElement psiElem
524502
@NotNull
525503
private Collection<PsiElement> getParentGoto(@NotNull PsiElement psiElement) {
526504
// find printblock
527-
PsiElement printBlock = psiElement.getParent();
505+
PsiElement functionCall = psiElement.getParent();
506+
PsiElement printBlock = functionCall != null ? functionCall.getParent() : null;
528507
if(printBlock == null || !PlatformPatterns.psiElement(TwigElementTypes.PRINT_BLOCK).accepts(printBlock)) {
529508
return Collections.emptyList();
530509
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.jetbrains.twig.TwigTokenTypes;
2020
import com.jetbrains.twig.elements.TwigCompositeElement;
2121
import com.jetbrains.twig.elements.TwigElementTypes;
22+
import com.jetbrains.twig.elements.TwigVariableReference;
2223
import fr.adrienbrault.idea.symfony2plugin.templating.TwigPattern;
2324
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollector;
2425
import fr.adrienbrault.idea.symfony2plugin.templating.variable.TwigFileVariableCollectorParameter;
@@ -39,6 +40,8 @@
3940
import java.util.regex.Pattern;
4041
import java.util.stream.Collectors;
4142

43+
import static fr.adrienbrault.idea.symfony2plugin.templating.TwigPattern.captureVariableOrField;
44+
4245
/**
4346
* @author Daniel Espendiller <daniel@espendiller.net>
4447
*/
@@ -369,6 +372,7 @@ private static void collectForArrayScopeVariables(@NotNull PsiElement psiElement
369372
// {% for user in "users" %}
370373
PsiElement forTag = twigCompositeElement.getFirstChild();
371374
PsiElement inVariable = PsiElementUtils.getChildrenOfType(forTag, TwigPattern.getForTagInVariablePattern());
375+
inVariable = inVariable instanceof TwigVariableReference ? inVariable : PsiTreeUtil.getChildOfType(inVariable, TwigVariableReference.class);
372376
if(inVariable == null) {
373377
return;
374378
}
@@ -629,7 +633,7 @@ private static Collection<String> getForTagIdentifierAsString(PsiElement forTag)
629633
}
630634

631635
// find next IDENTIFIER, eg skip whitespaces
632-
PsiElement psiIdentifier = PsiElementUtils.getNextSiblingOfType(psiIn, PlatformPatterns.psiElement(TwigTokenTypes.IDENTIFIER));
636+
PsiElement psiIdentifier = PsiElementUtils.getNextSiblingOfType(psiIn, captureVariableOrField());
633637
if(psiIdentifier == null) {
634638
return Collections.emptyList();
635639
}

0 commit comments

Comments
 (0)