3434import java .nio .file .attribute .BasicFileAttributes ;
3535import java .util .*;
3636import java .util .function .Supplier ;
37+ import java .util .regex .PatternSyntaxException ;
3738import java .util .stream .Collectors ;
3839import java .util .stream .Stream ;
3940
4041/**
4142 * @author Daniel Espendiller <daniel@espendiller.net>
4243 */
4344public 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 = {"*" , "?" , "{" , "[" };
4450
4551 /**
4652 * Search for files refers to given file
@@ -79,19 +85,56 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
7985 return CachedValueProvider .Result .create (Boolean .FALSE , FileIndexCaches .getModificationTrackerForIndexId (project , FileResourcesIndex .KEY ));
8086 }
8187
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 ));
8689
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 ))) {
8992 VirtualFile directory = containingFile .getParent ();
9093 if (directory == null ) {
9194 continue ;
9295 }
9396
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 ("/" ));
95138 if (relativeFile != null ) {
96139 String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
97140 if (relativePath != null ) {
@@ -111,24 +154,61 @@ public static boolean hasFileResources(@NotNull Project project, @NotNull PsiFil
111154 */
112155 @ NotNull
113156 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 ));
118158
119159 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 ))) {
122162 VirtualFile directory = containingFile .getParent ();
123163 if (directory == null ) {
124164 continue ;
125165 }
126166
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 ("/" ));
128208 if (relativeFile != null ) {
129209 String relativePath = VfsUtil .getRelativePath (virtualFile , relativeFile );
130210 if (relativePath != null ) {
131- files .add (Pair .create (containingFile , s ));
211+ files .add (Pair .create (containingFile , resource ));
132212 }
133213 }
134214 }
0 commit comments