Skip to content

Commit a6f91ff

Browse files
committed
add twig block implements (children) marker Haehnchen#75
1 parent f611c8c commit a6f91ff

File tree

1 file changed

+94
-2
lines changed

1 file changed

+94
-2
lines changed

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

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,27 @@
33
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
44
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
55
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
6+
import com.intellij.openapi.vfs.VirtualFile;
67
import com.intellij.psi.PsiElement;
8+
import com.intellij.psi.PsiFile;
9+
import com.intellij.psi.PsiManager;
10+
import com.intellij.psi.search.GlobalSearchScope;
11+
import com.intellij.psi.util.PsiElementFilter;
12+
import com.intellij.psi.util.PsiTreeUtil;
13+
import com.intellij.util.Processor;
14+
import com.intellij.util.indexing.FileBasedIndexImpl;
715
import com.jetbrains.php.PhpIcons;
816
import com.jetbrains.php.lang.psi.elements.Method;
917
import com.jetbrains.twig.TwigFile;
18+
import com.jetbrains.twig.TwigFileType;
1019
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
1120
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1221
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
22+
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigExtendsStubIndex;
1323
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
1424
import org.jetbrains.annotations.NotNull;
1525

16-
import java.util.Collection;
26+
import java.util.*;
1727

1828
public class TwigControllerLineMarkerProvider extends RelatedItemLineMarkerProvider {
1929

@@ -30,12 +40,13 @@ protected void collectNavigationMarkers(@NotNull PsiElement psiElement, Collecti
3040

3141
if (TwigHelper.getBlockTagPattern().accepts(psiElement)) {
3242
this.attachBlockImplementations(psiElement, result);
43+
this.attachBlockImplements(psiElement, result);
3344
}
3445

3546
}
3647

3748
private void attachController(TwigFile psiElement, Collection<? super RelatedItemLineMarkerInfo> result) {
38-
Method method = TwigUtil.findTwigFileController((TwigFile) psiElement);
49+
Method method = TwigUtil.findTwigFileController(psiElement);
3950
if(method == null) {
4051
return;
4152
}
@@ -47,6 +58,47 @@ private void attachController(TwigFile psiElement, Collection<? super RelatedIte
4758
result.add(builder.createLineMarkerInfo(psiElement));
4859
}
4960

61+
private void attachBlockImplements(final PsiElement psiElement, Collection<? super RelatedItemLineMarkerInfo> result) {
62+
63+
Map<String, PsiFile> files = TwigHelper.getTemplateFilesByName(psiElement.getProject(), true, true);
64+
PsiFile psiFile = psiElement.getContainingFile();
65+
if(psiFile == null) {
66+
return;
67+
}
68+
69+
List<PsiFile> twigChild = new ArrayList<PsiFile>();
70+
getTwigChildList(files, psiFile, twigChild, 8);
71+
72+
if(twigChild.size() == 0) {
73+
return;
74+
}
75+
76+
final String blockName = psiElement.getText();
77+
78+
List<PsiElement> blockTargets = new ArrayList<PsiElement>();
79+
for(PsiFile psiFile1: twigChild) {
80+
81+
blockTargets.addAll(Arrays.asList(PsiTreeUtil.collectElements(psiFile1, new PsiElementFilter() {
82+
@Override
83+
public boolean isAccepted(PsiElement psiElement) {
84+
return TwigHelper.getBlockTagPattern().accepts(psiElement) && blockName.equals(psiElement.getText());
85+
}
86+
})));
87+
88+
}
89+
90+
if(blockTargets.size() == 0) {
91+
return;
92+
}
93+
94+
NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.IMPLEMENTS).
95+
setTargets(blockTargets).
96+
setTooltipText("Navigate to block");
97+
98+
result.add(builder.createLineMarkerInfo(psiElement));
99+
100+
}
101+
50102
private void attachBlockImplementations(PsiElement psiElement, Collection<? super RelatedItemLineMarkerInfo> result) {
51103

52104
PsiElement[] blocks = TwigTemplateGoToDeclarationHandler.getBlockGoTo(psiElement);
@@ -62,4 +114,44 @@ private void attachBlockImplementations(PsiElement psiElement, Collection<? supe
62114

63115
}
64116

117+
118+
private static void getTwigChildList(Map<String, PsiFile> files, final PsiFile psiFile, final List<PsiFile> twigChild, int depth) {
119+
120+
if(depth <= 0) {
121+
return;
122+
}
123+
124+
// use set here, we have multiple shortcut on one file, but only one is required
125+
final HashSet<VirtualFile> virtualFiles = new LinkedHashSet<VirtualFile>();
126+
127+
for(Map.Entry<String, PsiFile> entry: files.entrySet()) {
128+
129+
// getFilesWithKey dont support keyset with > 1 items (bug?), so we cant merge calls
130+
if(entry.getValue().equals(psiFile)) {
131+
String key = entry.getKey();
132+
FileBasedIndexImpl.getInstance().getFilesWithKey(TwigExtendsStubIndex.KEY, new HashSet<String>(Arrays.asList(key)), new Processor<VirtualFile>() {
133+
@Override
134+
public boolean process(VirtualFile virtualFile) {
135+
virtualFiles.add(virtualFile);
136+
return true;
137+
}
138+
}, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(psiFile.getProject()), TwigFileType.INSTANCE));
139+
140+
}
141+
142+
}
143+
144+
// finally resolve virtual file to twig files
145+
for(VirtualFile virtualFile: virtualFiles) {
146+
147+
PsiFile resolvedPsiFile = PsiManager.getInstance(psiFile.getProject()).findFile(virtualFile);
148+
if(resolvedPsiFile != null) {
149+
twigChild.add(resolvedPsiFile);
150+
getTwigChildList(files, resolvedPsiFile, twigChild, depth--);
151+
}
152+
153+
}
154+
155+
}
156+
65157
}

0 commit comments

Comments
 (0)