Skip to content

Commit becfe9e

Browse files
committed
add twig "use" tag support in block name parser Haehnchen#266
1 parent 08f68a1 commit becfe9e

File tree

4 files changed

+84
-12
lines changed

4 files changed

+84
-12
lines changed

src/fr/adrienbrault/idea/symfony2plugin/TwigHelper.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,28 @@ public static ElementPattern<PsiElement> getTwigMacroNamePattern() {
771771
.withLanguage(TwigLanguage.INSTANCE);
772772
}
773773

774+
public static ElementPattern<PsiElement> getTwigTagUseNamePattern() {
775+
776+
// {% use '<foo>' %}
777+
778+
//noinspection unchecked
779+
return PlatformPatterns
780+
.psiElement(TwigTokenTypes.STRING_TEXT)
781+
.withParent(PlatformPatterns.psiElement(
782+
TwigElementTypes.TAG
783+
))
784+
.afterLeafSkipping(
785+
PlatformPatterns.or(
786+
PlatformPatterns.psiElement(PsiWhiteSpace.class),
787+
PlatformPatterns.psiElement(TwigTokenTypes.WHITE_SPACE),
788+
PlatformPatterns.psiElement(TwigTokenTypes.SINGLE_QUOTE),
789+
PlatformPatterns.psiElement(TwigTokenTypes.DOUBLE_QUOTE)
790+
),
791+
PlatformPatterns.psiElement(TwigTokenTypes.TAG_NAME).withText("use")
792+
)
793+
.withLanguage(TwigLanguage.INSTANCE);
794+
}
795+
774796
public static ElementPattern<PsiElement> getTwigMacroNameKnownPattern(String macroName) {
775797

776798
// {% macro <foo>(user) %}

src/fr/adrienbrault/idea/symfony2plugin/templating/BlockCompletionRegistrar.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public Collection<PsiElement> getPsiTargets(PsiElement element) {
5353
}
5454

5555
return Arrays.asList(
56-
TwigTemplateGoToDeclarationHandler.getBlockNameGoTo(element.getContainingFile(), blockName)
56+
TwigTemplateGoToDeclarationHandler.getBlockNameGoTo(element.getContainingFile(), blockName, true)
5757
);
5858

5959
}
@@ -64,7 +64,7 @@ public Collection<LookupElement> getLookupElements() {
6464
Collection<LookupElement> lookupElements = new ArrayList<LookupElement>();
6565

6666
Map<String, VirtualFile> twigFilesByName = TwigHelper.getTwigFilesByName(getElement().getProject());
67-
List<TwigBlock> blocks = new TwigBlockParser(twigFilesByName).walk(getElement().getContainingFile());
67+
List<TwigBlock> blocks = new TwigBlockParser(twigFilesByName).withSelfBlocks(true).walk(getElement().getContainingFile());
6868
List<String> uniqueList = new ArrayList<String>();
6969
for (TwigBlock block : blocks) {
7070
if(!uniqueList.contains(block.getName())) {

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,12 @@ public static PsiElement[] getBlockGoTo(PsiElement psiElement) {
154154
}
155155

156156
public static PsiElement[] getBlockNameGoTo(PsiFile psiFile, String blockName) {
157+
return getBlockNameGoTo(psiFile, blockName, false);
158+
}
159+
160+
public static PsiElement[] getBlockNameGoTo(PsiFile psiFile, String blockName, boolean withSelfBlocks) {
157161
Map<String, VirtualFile> twigFilesByName = TwigHelper.getTwigFilesByName(psiFile.getProject());
158-
List<TwigBlock> blocks = new TwigBlockParser(twigFilesByName).walk(psiFile);
162+
List<TwigBlock> blocks = new TwigBlockParser(twigFilesByName).withSelfBlocks(withSelfBlocks).walk(psiFile);
159163
List<PsiElement> psiElements = new ArrayList<PsiElement>();
160164
for (TwigBlock block : blocks) {
161165
if(block.getName().equals(blockName)) {

src/fr/adrienbrault/idea/symfony2plugin/templating/dict/TwigBlockParser.java

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
package fr.adrienbrault.idea.symfony2plugin.templating.dict;
22

33
import com.intellij.openapi.vfs.VirtualFile;
4+
import com.intellij.psi.PsiElement;
45
import com.intellij.psi.PsiFile;
56
import com.intellij.psi.PsiManager;
7+
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
8+
import com.intellij.psi.util.PsiTreeUtil;
69
import com.jetbrains.twig.TwigFile;
10+
import com.jetbrains.twig.elements.TwigCompositeElement;
11+
import com.jetbrains.twig.elements.TwigElementTypes;
712
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
13+
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
14+
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
15+
import org.apache.commons.lang.StringUtils;
816
import org.jetbrains.annotations.Nullable;
917

10-
import java.util.ArrayList;
11-
import java.util.List;
12-
import java.util.Map;
18+
import java.util.*;
1319
import java.util.regex.Matcher;
1420
import java.util.regex.Pattern;
1521

1622
public class TwigBlockParser {
1723

1824
public static String EXTENDS_TEMPLATE_NAME_PATTERN = "^[\\s+]*\\{%\\s+extends[\\s+]*['|\"](.*?)['|\"]";
1925

26+
private boolean withSelfBlock = false;
27+
2028
private Map<String, VirtualFile> twigFilesByName;
2129

2230
public TwigBlockParser(Map<String, VirtualFile> twigFilesByName) {
@@ -36,7 +44,8 @@ public List<TwigBlock> walk(@Nullable PsiFile file, String shortcutName, List<Tw
3644
// @TODO: we dont use psielements here, check if Pattern faster or not
3745

3846
// dont match on self file !?
39-
if(depth > 0) {
47+
if(depth > 0 || (withSelfBlock && depth == 0)) {
48+
// @TODO: migrate to psi elements
4049
Matcher matcherBlocks = Pattern.compile("\\{%[\\s+]*block[\\s+]*(.*?)[\\s+]*%}").matcher(file.getText());
4150
while(matcherBlocks.find()){
4251
current.add(new TwigBlock(matcherBlocks.group(1), shortcutName, file));
@@ -48,20 +57,57 @@ public List<TwigBlock> walk(@Nullable PsiFile file, String shortcutName, List<Tw
4857
return current;
4958
}
5059

60+
final Map<VirtualFile, String> virtualFiles = new HashMap<VirtualFile, String>();
61+
62+
// @TODO: migrate to psi elements
63+
// {% extends 'foo' %}
5164
// find extend in self
5265
Matcher matcher = Pattern.compile(EXTENDS_TEMPLATE_NAME_PATTERN).matcher(file.getText());
5366
while(matcher.find()){
5467
String templateName = TwigHelper.normalizeTemplateName(matcher.group(1));
5568
if(twigFilesByName.containsKey(templateName)) {
56-
VirtualFile virtualFile = twigFilesByName.get(templateName);
57-
PsiFile psiFile = PsiManager.getInstance(file.getProject()).findFile(virtualFile);
58-
if(psiFile instanceof TwigFile) {
59-
this.walk(psiFile, matcher.group(1), current, depth);
60-
}
69+
virtualFiles.put(twigFilesByName.get(templateName), templateName);
70+
}
71+
}
72+
73+
// {% use 'foo' %}
74+
for(TwigCompositeElement twigCompositeElement: PsiTreeUtil.getChildrenOfTypeAsList(file, TwigCompositeElement.class)) {
75+
if(twigCompositeElement.getNode().getElementType() == TwigElementTypes.TAG) {
76+
twigCompositeElement.acceptChildren(new PsiRecursiveElementWalkingVisitor() {
77+
@Override
78+
public void visitElement(PsiElement element) {
79+
80+
if(TwigHelper.getTwigTagUseNamePattern().accepts(element)) {
81+
82+
String templateName = PsiElementUtils.trimQuote(element.getText());
83+
if(StringUtils.isNotBlank(templateName)) {
84+
String templateNameNormalized = TwigHelper.normalizeTemplateName(TwigHelper.normalizeTemplateName(templateName));
85+
if(twigFilesByName.containsKey(templateNameNormalized)) {
86+
virtualFiles.put(twigFilesByName.get(templateName), templateNameNormalized);
87+
}
88+
}
89+
90+
}
91+
92+
super.visitElement(element);
93+
}
94+
});
95+
}
96+
}
97+
98+
for(Map.Entry<VirtualFile, String> entry : virtualFiles.entrySet()) {
99+
PsiFile psiFile = PsiManager.getInstance(file.getProject()).findFile(entry.getKey());
100+
if(psiFile instanceof TwigFile) {
101+
this.walk(psiFile, TwigUtil.getFoldingTemplateNameOrCurrent(entry.getValue()), current, depth);
61102
}
62103
}
63104

64105
return current;
65106
}
66107

108+
public TwigBlockParser withSelfBlocks(boolean withSelfBlock) {
109+
this.withSelfBlock = withSelfBlock;
110+
return this;
111+
}
112+
67113
}

0 commit comments

Comments
 (0)