34
34
import java .nio .file .attribute .BasicFileAttributes ;
35
35
import java .util .*;
36
36
import java .util .function .Supplier ;
37
+ import java .util .regex .PatternSyntaxException ;
37
38
import java .util .stream .Collectors ;
38
39
import java .util .stream .Stream ;
39
40
40
41
/**
41
42
* @author Daniel Espendiller <daniel@espendiller.net>
42
43
*/
43
44
public class FileResourceUtil {
45
+ /**
46
+ * chars that trigger a glob resolving on symfony
47
+ * extracted from: \Symfony\Component\Config\Loader\FileLoader::import
48
+ */
49
+ private static final String [] GLOB_DETECTION_CHARS = {"*" , "?" , "{" , "[" };
44
50
45
51
/**
46
52
* Search for files refers to given file
@@ -79,19 +85,56 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
79
85
return CachedValueProvider .Result .create (Boolean .FALSE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
80
86
}
81
87
82
- Set <String > collect = FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project )
83
- .stream ()
84
- .filter (s -> !s .startsWith ("@" ))
85
- .collect (Collectors .toSet ());
88
+ Set <String > resources = new HashSet <>(FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project ));
86
89
87
- for (String s : collect ) {
88
- for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , s , GlobalSearchScope .allScope (project ))) {
90
+ for (String resource : resources ) {
91
+ for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , resource , GlobalSearchScope .allScope (project ))) {
89
92
VirtualFile directory = containingFile .getParent ();
90
93
if (directory == null ) {
91
94
continue ;
92
95
}
93
96
94
- VirtualFile relativeFile = VfsUtil .findRelativeFile (directory , s .replace ("\\ " , "/" ).split ("/" ));
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 ("/" ));
95
138
if (relativeFile != null ) {
96
139
String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
97
140
if (relativePath != null ) {
@@ -111,24 +154,61 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
111
154
*/
112
155
@ NotNull
113
156
public static Collection <Pair <VirtualFile , String >> getFileResources (@ NotNull Project project , @ NotNull VirtualFile virtualFile ) {
114
- Set <String > collect = FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project )
115
- .stream ()
116
- .filter (s -> !s .startsWith ("@" ))
117
- .collect (Collectors .toSet ());
157
+ Set <String > resources = new HashSet <>(FileBasedIndex .getInstance ().getAllKeys (FileResourcesIndex .KEY , project ));
118
158
119
159
Collection <Pair <VirtualFile , String >> files = new ArrayList <>();
120
- for (String s : collect ) {
121
- for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , s , GlobalSearchScope .allScope (project ))) {
160
+ for (String resource : resources ) {
161
+ for (VirtualFile containingFile : FileBasedIndex .getInstance ().getContainingFiles (FileResourcesIndex .KEY , resource , GlobalSearchScope .allScope (project ))) {
122
162
VirtualFile directory = containingFile .getParent ();
123
163
if (directory == null ) {
124
164
continue ;
125
165
}
126
166
127
- VirtualFile relativeFile = VfsUtil .findRelativeFile (directory , s .replace ("\\ " , "/" ).split ("/" ));
167
+ String resourceResolved = resource ;
168
+
169
+ if (resource .startsWith ("@" )) {
170
+ String replace = resource .replace ("\\ " , "/" );
171
+ int i = replace .indexOf ("/" );
172
+ if (i > 2 ) {
173
+ String substring = resource .substring (1 , i );
174
+ Collection <SymfonyBundle > bundle = new SymfonyBundleUtil (project ).getBundle (substring );
175
+
176
+ for (SymfonyBundle symfonyBundle : bundle ) {
177
+ PsiDirectory directory1 = symfonyBundle .getDirectory ();
178
+ if (directory1 == null ) {
179
+ continue ;
180
+ }
181
+
182
+ String substring1 = resource .substring (i );
183
+ String path = directory1 .getVirtualFile ().getPath ();
184
+ resourceResolved = path + substring1 ;
185
+
186
+ break ;
187
+ }
188
+ }
189
+ }
190
+
191
+ if (Arrays .stream (GLOB_DETECTION_CHARS ).anyMatch (resource ::contains )) {
192
+ String path = directory .getPath ();
193
+
194
+ // nested types not support by java glob implementation so just catch the exception: "../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,Service/{IspConfiguration,DataCollection}}"
195
+ try {
196
+ String s1 = Paths .get (path + File .separatorChar + StringUtils .stripStart (resourceResolved , "\\ /" )).normalize ().toString ();
197
+ String syntaxAndPattern = "glob:" + s1 ;
198
+ if (FileSystems .getDefault ().getPathMatcher (syntaxAndPattern ).matches (Paths .get (virtualFile .getPath ()))) {
199
+ files .add (Pair .create (containingFile , resource ));
200
+ }
201
+ } catch (PatternSyntaxException | InvalidPathException ignored ) {
202
+ }
203
+
204
+ continue ;
205
+ }
206
+
207
+ VirtualFile relativeFile = VfsUtil .findRelativeFile (directory , resourceResolved .replace ("\\ " , "/" ).split ("/" ));
128
208
if (relativeFile != null ) {
129
209
String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
130
210
if (relativePath != null ) {
131
- files .add (Pair .create (containingFile , s ));
211
+ files .add (Pair .create (containingFile , resource ));
132
212
}
133
213
}
134
214
}
0 commit comments