10
10
import com .intellij .psi .PsiDirectory ;
11
11
import com .intellij .psi .PsiElement ;
12
12
import com .intellij .psi .PsiFile ;
13
- import com .intellij .psi .PsiManager ;
14
13
import com .intellij .psi .search .GlobalSearchScope ;
15
14
import com .intellij .psi .util .CachedValueProvider ;
16
15
import com .intellij .psi .util .CachedValuesManager ;
17
16
import com .intellij .util .PlatformIcons ;
18
17
import com .intellij .util .indexing .FileBasedIndex ;
19
18
import com .jetbrains .php .PhpIcons ;
20
19
import fr .adrienbrault .idea .symfony2plugin .stubs .cache .FileIndexCaches ;
20
+ import fr .adrienbrault .idea .symfony2plugin .stubs .dict .FileResource ;
21
+ import fr .adrienbrault .idea .symfony2plugin .stubs .dict .FileResourceContextTypeEnum ;
21
22
import fr .adrienbrault .idea .symfony2plugin .stubs .indexes .FileResourcesIndex ;
22
23
import fr .adrienbrault .idea .symfony2plugin .util .FileResourceVisitorUtil ;
23
24
import fr .adrienbrault .idea .symfony2plugin .util .PhpIndexUtil ;
33
34
import java .nio .file .*;
34
35
import java .nio .file .attribute .BasicFileAttributes ;
35
36
import java .util .*;
37
+ import java .util .function .Function ;
36
38
import java .util .function .Supplier ;
37
39
import java .util .regex .PatternSyntaxException ;
38
40
import java .util .stream .Collectors ;
@@ -48,31 +50,6 @@ public class FileResourceUtil {
48
50
*/
49
51
private static final String [] GLOB_DETECTION_CHARS = {"*" , "?" , "{" , "[" };
50
52
51
- /**
52
- * Search for files refers to given file
53
- */
54
- @ NotNull
55
- public static Collection <VirtualFile > getFileResourceRefers (@ NotNull Project project , @ NotNull VirtualFile virtualFile ) {
56
- String bundleLocateName = getBundleLocateName (project , virtualFile );
57
- if (bundleLocateName == null ) {
58
- return Collections .emptyList ();
59
- }
60
-
61
- return getFileResourceRefers (project , bundleLocateName );
62
- }
63
-
64
- /**
65
- * Search for files refers to given file
66
- */
67
- @ NotNull
68
- private static Collection <VirtualFile > getFileResourceRefers (@ NotNull Project project , @ NotNull String bundleLocateName ) {
69
- return FileBasedIndex .getInstance ().getContainingFiles (
70
- FileResourcesIndex .KEY ,
71
- bundleLocateName ,
72
- GlobalSearchScope .allScope (project )
73
- );
74
- }
75
-
76
53
/**
77
54
* Search for files refers to given file
78
55
*/
@@ -85,66 +62,14 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
85
62
return CachedValueProvider .Result .create (Boolean .FALSE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
86
63
}
87
64
88
- Set < String > resources = new HashSet <>( FileBasedIndex . getInstance (). getAllKeys ( FileResourcesIndex . KEY , project )) ;
65
+ final Boolean [] aFalse = { Boolean . FALSE } ;
89
66
90
- for (String resource : resources ) {
91
- for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , resource , GlobalSearchScope .allScope (project ))) {
92
- VirtualFile directory = containingFile .getParent ();
93
- if (directory == null ) {
94
- continue ;
95
- }
96
-
97
- String resourceResolved = resource ;
98
-
99
- if (resource .startsWith ("@" )) {
100
- String replace = resource .replace ("\\ " , "/" );
101
- int i = replace .indexOf ("/" );
102
- if (i > 2 ) {
103
- String substring = resource .substring (1 , i );
104
- Collection <SymfonyBundle > bundle = new SymfonyBundleUtil (project ).getBundle (substring );
105
-
106
- for (SymfonyBundle symfonyBundle : bundle ) {
107
- PsiDirectory directory1 = symfonyBundle .getDirectory ();
108
- if (directory1 == null ) {
109
- continue ;
110
- }
111
-
112
- String substring1 = resource .substring (i );
113
- String path = directory1 .getVirtualFile ().getPath ();
114
- resourceResolved = path + substring1 ;
115
-
116
- break ;
117
- }
118
- }
119
- }
120
-
121
- if (Arrays .stream (GLOB_DETECTION_CHARS ).anyMatch (resource ::contains )) {
122
- String path = directory .getPath ();
123
-
124
- // nested types not support by java glob implementation so just catch the exception: "../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,Service/{IspConfiguration,DataCollection}}"
125
- try {
126
- String s1 = Paths .get (path + File .separatorChar + StringUtils .stripStart (resourceResolved , "\\ /" )).normalize ().toString ();
127
- String syntaxAndPattern = "glob:" + s1 ;
128
- if (FileSystems .getDefault ().getPathMatcher (syntaxAndPattern ).matches (Paths .get (virtualFile .getPath ()))) {
129
- return CachedValueProvider .Result .create (Boolean .TRUE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
130
- }
131
- } catch (PatternSyntaxException | InvalidPathException ignored ) {
132
- }
133
-
134
- continue ;
135
- }
136
-
137
- VirtualFile relativeFile = VfsUtil .findRelativeFile (directory , resourceResolved .replace ("\\ " , "/" ).split ("/" ));
138
- if (relativeFile != null ) {
139
- String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
140
- if (relativePath != null ) {
141
- return CachedValueProvider .Result .create (Boolean .TRUE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
142
- }
143
- }
144
- }
145
- }
67
+ visitFileResources (project , virtualFile , pair -> {
68
+ aFalse [0 ] = Boolean .TRUE ;
69
+ return true ;
70
+ });
146
71
147
- return CachedValueProvider .Result .create (Boolean . FALSE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
72
+ return CachedValueProvider .Result .create (aFalse [ 0 ] , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
148
73
}
149
74
);
150
75
}
@@ -154,11 +79,32 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
154
79
*/
155
80
@ NotNull
156
81
public static Collection <Pair <VirtualFile , String >> getFileResources (@ NotNull Project project , @ NotNull VirtualFile virtualFile ) {
157
- Set <String > resources = new HashSet <>(FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project ));
158
-
159
82
Collection <Pair <VirtualFile , String >> files = new ArrayList <>();
160
- for (String resource : resources ) {
161
- for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , resource , GlobalSearchScope .allScope (project ))) {
83
+
84
+ visitFileResources (project , virtualFile , pair -> {
85
+ files .add (Pair .create (pair .getFirst (), pair .getSecond ()));
86
+ return false ;
87
+ });
88
+
89
+ return files ;
90
+ }
91
+
92
+ /**
93
+ * Search for files refers to given file
94
+ */
95
+ public static void visitFileResources (@ NotNull Project project , @ NotNull VirtualFile virtualFile , @ NotNull Function <Pair <VirtualFile , String >, Boolean > consumer ) {
96
+ Set <VirtualFile > files = new HashSet <>();
97
+ for (String resource : FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project )) {
98
+ files .addAll (FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , resource , GlobalSearchScope .allScope (project )));
99
+ }
100
+
101
+ for (VirtualFile containingFile : files ) {
102
+ for (FileResource fileResourceContext : FileBasedIndex .getInstance ().getFileData (FileResourcesIndex .KEY , containingFile , project ).values ()) {
103
+ String resource = fileResourceContext .getResource ();
104
+ if (resource == null ) {
105
+ continue ;
106
+ }
107
+
162
108
VirtualFile directory = containingFile .getParent ();
163
109
if (directory == null ) {
164
110
continue ;
@@ -169,7 +115,14 @@ public static Collection<Pair<VirtualFile, String>> getFileResources(@NotNull Pr
169
115
if (resource .startsWith ("@" )) {
170
116
String replace = resource .replace ("\\ " , "/" );
171
117
int i = replace .indexOf ("/" );
172
- if (i > 2 ) {
118
+
119
+ boolean resolved = false ;
120
+
121
+ if (i > 2 || i == -1 ) {
122
+ if (i == -1 ) {
123
+ i = resource .length ();
124
+ }
125
+
173
126
String substring = resource .substring (1 , i );
174
127
Collection <SymfonyBundle > bundle = new SymfonyBundleUtil (project ).getBundle (substring );
175
128
@@ -179,15 +132,22 @@ public static Collection<Pair<VirtualFile, String>> getFileResources(@NotNull Pr
179
132
continue ;
180
133
}
181
134
182
- String substring1 = resource .substring (i );
183
- String path = directory1 .getVirtualFile ().getPath ();
184
- resourceResolved = path + substring1 ;
135
+ resourceResolved = resource .substring (replace .contains ("/" ) ? i + 1 : replace .length ());
136
+ directory = directory1 .getVirtualFile ();
137
+
138
+ resolved = true ;
185
139
186
140
break ;
187
141
}
188
142
}
143
+
144
+ if (!resolved ) {
145
+ continue ;
146
+ }
189
147
}
190
148
149
+ // '../src/{Entity}'
150
+ // '../src/*Controller.php'
191
151
if (Arrays .stream (GLOB_DETECTION_CHARS ).anyMatch (resource ::contains )) {
192
152
String path = directory .getPath ();
193
153
@@ -196,62 +156,41 @@ public static Collection<Pair<VirtualFile, String>> getFileResources(@NotNull Pr
196
156
String s1 = Paths .get (path + File .separatorChar + StringUtils .stripStart (resourceResolved , "\\ /" )).normalize ().toString ();
197
157
String syntaxAndPattern = "glob:" + s1 ;
198
158
if (FileSystems .getDefault ().getPathMatcher (syntaxAndPattern ).matches (Paths .get (virtualFile .getPath ()))) {
199
- files .add (Pair .create (containingFile , resource ));
159
+ if (consumer .apply (new Pair <>(containingFile , resource ))) {
160
+ return ;
161
+ }
200
162
}
201
163
} catch (PatternSyntaxException | InvalidPathException ignored ) {
202
164
}
203
165
204
166
continue ;
205
167
}
206
168
169
+ // '../src/FooController.php'
207
170
VirtualFile relativeFile = VfsUtil .findRelativeFile (directory , resourceResolved .replace ("\\ " , "/" ).split ("/" ));
208
- if (relativeFile != null ) {
209
- String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
210
- if (relativePath != null ) {
211
- files .add (Pair .create (containingFile , resource ));
171
+ if (relativeFile != null && relativeFile .equals (virtualFile )) {
172
+ if (consumer .apply (new Pair <>(containingFile , resource ))) {
173
+ return ;
212
174
}
213
175
}
214
- }
215
- }
216
176
217
- return files ;
218
- }
219
-
220
- @ Nullable
221
- public static String getBundleLocateName (@ NotNull Project project , @ NotNull VirtualFile virtualFile ) {
222
- SymfonyBundle containingBundle = new SymfonyBundleUtil (project ).getContainingBundle (virtualFile );
223
- if (containingBundle == null ) {
224
- return null ;
225
- }
226
-
227
- String relativePath = containingBundle .getRelativePath (virtualFile );
228
- if (relativePath == null ) {
229
- return null ;
230
- }
231
-
232
- return "@" + containingBundle .getName () + "/" + relativePath ;
233
- }
234
-
235
- /**
236
- * Search for line definition of "@FooBundle/foo.xml"
237
- */
238
- @ NotNull
239
- private static Collection <PsiElement > getBundleLocateStringDefinitions (@ NotNull Project project , final @ NotNull String bundleFileName ) {
240
- final Collection <PsiElement > psiElements = new HashSet <>();
241
- for (VirtualFile refVirtualFile : getFileResourceRefers (project , bundleFileName )) {
242
- PsiFile psiFile = PsiManager .getInstance (project ).findFile (refVirtualFile );
243
- if (psiFile == null ) {
244
- continue ;
245
- }
177
+ // '..src/Controller'
178
+ if (fileResourceContext .getContextType () == FileResourceContextTypeEnum .ROUTE ) {
179
+ if (StringUtils .isNotBlank (resourceResolved )) {
180
+ directory = VfsUtil .findRelativeFile (directory , resourceResolved .replace ("\\ " , "/" ).split ("/" ));
181
+ if (directory == null ) {
182
+ continue ;
183
+ }
184
+ }
246
185
247
- FileResourceVisitorUtil .visitFile (psiFile , consumer -> {
248
- if (bundleFileName .equals (consumer .getResource ())) {
249
- psiElements .add (consumer .getPsiElement ());
186
+ if (VfsUtil .isAncestor (directory , virtualFile , false )) {
187
+ if (consumer .apply (new Pair <>(containingFile , resource ))) {
188
+ return ;
189
+ }
190
+ }
250
191
}
251
- });
192
+ }
252
193
}
253
-
254
- return psiElements ;
255
194
}
256
195
257
196
@ Nullable
@@ -263,15 +202,6 @@ public static RelatedItemLineMarkerInfo<PsiElement> getFileImplementsLineMarker(
263
202
return null ;
264
203
}
265
204
266
- String bundleLocateName = FileResourceUtil .getBundleLocateName (project , virtualFile );
267
- if (bundleLocateName != null && FileResourceUtil .getFileResourceRefers (project , bundleLocateName ).size () > 0 ) {
268
- NavigationGutterIconBuilder <PsiElement > builder = NavigationGutterIconBuilder .create (PhpIcons .IMPLEMENTS )
269
- .setTargets (NotNullLazyValue .lazy (new FileResourceBundleNotNullLazyValue (project , bundleLocateName )))
270
- .setTooltipText ("Navigate to resource" );
271
-
272
- return builder .createLineMarkerInfo (psiFile );
273
- }
274
-
275
205
if (hasFileResources (project , psiFile )) {
276
206
NavigationGutterIconBuilder <PsiElement > builder = NavigationGutterIconBuilder .create (PhpIcons .IMPLEMENTS )
277
207
.setTargets (NotNullLazyValue .lazy (new FileResourceNotNullLazyValue (project , virtualFile )))
@@ -288,69 +218,22 @@ public static RelatedItemLineMarkerInfo<PsiElement> getFileImplementsLineMarker(
288
218
*/
289
219
@ Nullable
290
220
public static RelatedItemLineMarkerInfo <PsiElement > getFileImplementsLineMarkerInFolderScope (@ NotNull PsiFile psiFile ) {
291
- VirtualFile virtualFile = psiFile .getVirtualFile ();
292
- if (virtualFile == null ) {
293
- return null ;
294
- }
295
-
296
- final Project project = psiFile .getProject ();
297
- String bundleLocateName = FileResourceUtil .getBundleLocateName (project , virtualFile );
298
- if (bundleLocateName == null ) {
221
+ if (!hasFileResources (psiFile .getProject (), psiFile )) {
299
222
return null ;
300
223
}
301
224
302
- Set <String > names = new HashSet <>();
303
- names .add (bundleLocateName );
304
-
305
- // strip filename
306
- int i = bundleLocateName .lastIndexOf ("/" );
307
- if (i > 0 ) {
308
- names .add (bundleLocateName .substring (0 , i ));
309
- }
310
-
311
- int targets = 0 ;
312
- for (String name : names ) {
313
- targets += FileResourceUtil .getFileResourceRefers (project , name ).size ();
314
- }
315
-
316
- if (targets == 0 ) {
225
+ VirtualFile virtualFile = psiFile .getVirtualFile ();
226
+ if (virtualFile == null ) {
317
227
return null ;
318
228
}
319
229
320
230
NavigationGutterIconBuilder <PsiElement > builder = NavigationGutterIconBuilder .create (PlatformIcons .ANNOTATION_TYPE_ICON )
321
- .setTargets (NotNullLazyValue .lazy (new FileResourceBundleNotNullLazyValue ( project , names )))
231
+ .setTargets (NotNullLazyValue .lazy (new FileResourceNotNullLazyValue ( psiFile . getProject (), virtualFile )))
322
232
.setTooltipText ("Symfony: <a href=\" https://symfony.com/doc/current/routing.html#creating-routes-as-annotations\" >Annotation Routing</a>" );
323
233
324
234
return builder .createLineMarkerInfo (psiFile );
325
235
}
326
236
327
- private static class FileResourceBundleNotNullLazyValue implements Supplier <Collection <? extends PsiElement >> {
328
-
329
- private final Collection <String > resources ;
330
- private final Project project ;
331
-
332
- public FileResourceBundleNotNullLazyValue (@ NotNull Project project , @ NotNull Collection <String > resource ) {
333
- this .resources = resource ;
334
- this .project = project ;
335
- }
336
-
337
- public FileResourceBundleNotNullLazyValue (@ NotNull Project project , @ NotNull String resource ) {
338
- this .resources = Collections .singleton (resource );
339
- this .project = project ;
340
- }
341
-
342
- @ Override
343
- public Collection <? extends PsiElement > get () {
344
- Collection <PsiElement > psiElements = new HashSet <>();
345
-
346
- for (String resource : this .resources ) {
347
- psiElements .addAll (getBundleLocateStringDefinitions (project , resource ));
348
- }
349
-
350
- return psiElements ;
351
- }
352
- }
353
-
354
237
/**
355
238
* Gives targets to files on Bundle locate syntax. "@FooBundle/.../foo.yml"
356
239
*/
@@ -474,7 +357,7 @@ private static class FileResourceNotNullLazyValue implements Supplier<Collection
474
357
private final Project project ;
475
358
private final VirtualFile virtualFile ;
476
359
477
- public FileResourceNotNullLazyValue (Project project , VirtualFile virtualFile ) {
360
+ public FileResourceNotNullLazyValue (@ NotNull Project project , @ NotNull VirtualFile virtualFile ) {
478
361
this .project = project ;
479
362
this .virtualFile = virtualFile ;
480
363
}
0 commit comments