3
3
import com .intellij .codeInsight .daemon .RelatedItemLineMarkerInfo ;
4
4
import com .intellij .codeInsight .daemon .RelatedItemLineMarkerProvider ;
5
5
import com .intellij .codeInsight .navigation .NavigationGutterIconBuilder ;
6
+ import com .intellij .openapi .vfs .VirtualFile ;
6
7
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 ;
7
15
import com .jetbrains .php .PhpIcons ;
8
16
import com .jetbrains .php .lang .psi .elements .Method ;
9
17
import com .jetbrains .twig .TwigFile ;
18
+ import com .jetbrains .twig .TwigFileType ;
10
19
import fr .adrienbrault .idea .symfony2plugin .Symfony2Icons ;
11
20
import fr .adrienbrault .idea .symfony2plugin .Symfony2ProjectComponent ;
12
21
import fr .adrienbrault .idea .symfony2plugin .TwigHelper ;
22
+ import fr .adrienbrault .idea .symfony2plugin .stubs .indexes .TwigExtendsStubIndex ;
13
23
import fr .adrienbrault .idea .symfony2plugin .templating .util .TwigUtil ;
14
24
import org .jetbrains .annotations .NotNull ;
15
25
16
- import java .util .Collection ;
26
+ import java .util .* ;
17
27
18
28
public class TwigControllerLineMarkerProvider extends RelatedItemLineMarkerProvider {
19
29
@@ -30,12 +40,13 @@ protected void collectNavigationMarkers(@NotNull PsiElement psiElement, Collecti
30
40
31
41
if (TwigHelper .getBlockTagPattern ().accepts (psiElement )) {
32
42
this .attachBlockImplementations (psiElement , result );
43
+ this .attachBlockImplements (psiElement , result );
33
44
}
34
45
35
46
}
36
47
37
48
private void attachController (TwigFile psiElement , Collection <? super RelatedItemLineMarkerInfo > result ) {
38
- Method method = TwigUtil .findTwigFileController (( TwigFile ) psiElement );
49
+ Method method = TwigUtil .findTwigFileController (psiElement );
39
50
if (method == null ) {
40
51
return ;
41
52
}
@@ -47,6 +58,47 @@ private void attachController(TwigFile psiElement, Collection<? super RelatedIte
47
58
result .add (builder .createLineMarkerInfo (psiElement ));
48
59
}
49
60
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
+
50
102
private void attachBlockImplementations (PsiElement psiElement , Collection <? super RelatedItemLineMarkerInfo > result ) {
51
103
52
104
PsiElement [] blocks = TwigTemplateGoToDeclarationHandler .getBlockGoTo (psiElement );
@@ -62,4 +114,44 @@ private void attachBlockImplementations(PsiElement psiElement, Collection<? supe
62
114
63
115
}
64
116
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
+
65
157
}
0 commit comments