23
23
import java .util .Arrays ;
24
24
import java .util .Collections ;
25
25
import java .util .List ;
26
+ import java .util .Map ;
26
27
import java .util .Set ;
27
28
import java .util .stream .Collectors ;
28
29
import java .util .stream .Stream ;
41
42
import org .springframework .ide .vscode .boot .index .cache .IndexCacheKey ;
42
43
import org .springframework .ide .vscode .boot .java .beans .BeanUtils ;
43
44
import org .springframework .ide .vscode .boot .java .beans .BeansIndexer ;
45
+ import org .springframework .ide .vscode .boot .java .beans .CachedBean ;
44
46
import org .springframework .ide .vscode .commons .java .IClasspathUtil ;
45
47
import org .springframework .ide .vscode .commons .java .IJavaProject ;
46
48
import org .springframework .ide .vscode .commons .protocol .java .Classpath ;
49
+ import org .springframework .ide .vscode .commons .protocol .spring .Bean ;
50
+ import org .springframework .ide .vscode .commons .protocol .spring .DefaultValues ;
51
+ import org .springframework .ide .vscode .commons .protocol .spring .SpringIndexElement ;
47
52
import org .springframework .ide .vscode .commons .util .text .LanguageId ;
48
53
import org .springframework .ide .vscode .commons .util .text .Region ;
49
54
import org .springframework .ide .vscode .commons .util .text .TextDocument ;
@@ -61,6 +66,9 @@ public class SpringFactoriesIndexer implements SpringIndexer {
61
66
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
62
67
private static final String GENERATION = "GEN-12" ;
63
68
69
+ private static final String SYMBOL_KEY = "symbols" ;
70
+ private static final String BEANS_KEY = "beans" ;
71
+
64
72
private static final String FILE_PATTERN = "**/META-INF/spring/*.factories" ;
65
73
66
74
private static final PathMatcher FILE_GLOB_PATTERN = FileSystems .getDefault ().getPathMatcher ("glob:" + FILE_PATTERN );
@@ -99,12 +107,12 @@ public boolean isInterestedIn(String resource) {
99
107
@ Override
100
108
public List <WorkspaceSymbol > computeSymbols (IJavaProject project , String docURI , String content )
101
109
throws Exception {
102
- return computeSymbols (docURI , content );
110
+ return computeSymbols (docURI , content ). symbols ;
103
111
}
104
112
105
113
@ Override
106
114
public List <DocumentSymbol > computeDocumentSymbols (IJavaProject project , String docURI , String content ) throws Exception {
107
- return computeSymbols (docURI , content ).stream ()
115
+ return computeSymbols (docURI , content ).symbols . stream ()
108
116
.map (workspaceSymbol -> convertToDocumentSymbol (workspaceSymbol ))
109
117
.toList ();
110
118
}
@@ -124,8 +132,10 @@ else if (location.isRight()) {
124
132
return new DocumentSymbol (workspaceSymbol .getName (), workspaceSymbol .getKind (), range , range );
125
133
}
126
134
127
- private List < WorkspaceSymbol > computeSymbols (String docURI , String content ) {
135
+ private ComputeResult computeSymbols (String docURI , String content ) {
128
136
ImmutableList .Builder <WorkspaceSymbol > symbols = ImmutableList .builder ();
137
+ ImmutableList .Builder <Bean > beans = ImmutableList .builder ();
138
+
129
139
PropertiesAst ast = new AntlrParser ().parse (content ).ast ;
130
140
if (ast != null ) {
131
141
for (KeyValuePair pair : ast .getPropertyValuePairs ()) {
@@ -141,18 +151,26 @@ private List<WorkspaceSymbol> computeSymbols(String docURI, String content) {
141
151
String simpleName = getSimpleName (fqName );
142
152
String beanId = BeanUtils .getBeanNameFromType (simpleName );
143
153
Range range = doc .toRange (new Region (pair .getOffset (), pair .getLength ()));
144
- symbols .add (new WorkspaceSymbol (
154
+ Location location = new Location (docURI , range );
155
+
156
+ WorkspaceSymbol symbol = new WorkspaceSymbol (
145
157
BeansIndexer .beanLabel (false , beanId , fqName , Paths .get (URI .create (docURI )).getFileName ().toString ()),
146
158
SymbolKind .Interface ,
147
- Either .forLeft (new Location (docURI , range ))));
159
+ Either .forLeft (location ));
160
+
161
+ symbols .add (symbol );
162
+
163
+ Bean bean = new Bean (beanId , fqName , location , DefaultValues .EMPTY_INJECTION_POINTS , Collections .emptySet (), DefaultValues .EMPTY_ANNOTATIONS , false , symbol .getName ());
164
+ beans .add (bean );
165
+
148
166
} catch (Exception e ) {
149
167
log .error ("" , e );
150
168
}
151
169
}
152
170
}
153
171
}
154
172
}
155
- return symbols .build ();
173
+ return new ComputeResult ( symbols .build (), beans . build () );
156
174
}
157
175
158
176
private static String getSimpleName (String fqName ) {
@@ -163,22 +181,6 @@ private static String getSimpleName(String fqName) {
163
181
return fqName ;
164
182
}
165
183
166
- private IndexCacheKey getCacheKey (IJavaProject project ) {
167
- String filesIndentifier = getFiles (project ).stream ()
168
- .filter (f -> Files .isRegularFile (f ))
169
- .map (f -> {
170
- try {
171
- return f .toAbsolutePath ().toString () + "#" + Files .getLastModifiedTime (f ).toMillis ();
172
- } catch (IOException e ) {
173
- log .error ("" , e );
174
- return f .toAbsolutePath ().toString () + "#0" ;
175
- }
176
- })
177
- .collect (Collectors .joining ("," ));
178
- return new IndexCacheKey (project .getElementName (), "factories" , "" , DigestUtils .md5Hex (GENERATION + "-" + filesIndentifier ).toUpperCase ());
179
- }
180
-
181
-
182
184
@ Override
183
185
public void initializeProject (IJavaProject project , boolean clean ) throws Exception {
184
186
long startTime = System .currentTimeMillis ();
@@ -187,27 +189,39 @@ public void initializeProject(IJavaProject project, boolean clean) throws Except
187
189
188
190
log .info ("scan factories files for symbols for project: " + project .getElementName () + " - no. of files: " + files .size ());
189
191
190
- IndexCacheKey cacheKey = getCacheKey (project );
192
+ IndexCacheKey symbolsCacheKey = getCacheKey (project , SYMBOL_KEY );
193
+ IndexCacheKey beansCacheKey = getCacheKey (project , BEANS_KEY );
191
194
192
- CachedSymbol [] symbols = this .cache .retrieveSymbols (cacheKey , filesStr , CachedSymbol .class );
193
- if (symbols == null || clean ) {
195
+ CachedSymbol [] symbols = this .cache .retrieveSymbols (symbolsCacheKey , filesStr , CachedSymbol .class );
196
+ CachedBean [] beans = this .cache .retrieveSymbols (beansCacheKey , filesStr , CachedBean .class );
197
+
198
+ if (symbols == null || beans == null || clean ) {
194
199
List <CachedSymbol > generatedSymbols = new ArrayList <CachedSymbol >();
200
+ List <CachedBean > generatedBeans = new ArrayList <CachedBean >();
195
201
196
202
for (Path file : files ) {
197
- generatedSymbols .addAll (scanFile (file ));
203
+ ScanResult scanResult = scanFile (file );
204
+
205
+ if (scanResult != null ) {
206
+ generatedSymbols .addAll (scanResult .symbols );
207
+ generatedBeans .addAll (scanResult .beans );
208
+ }
198
209
}
199
210
200
- this .cache .store (cacheKey , filesStr , generatedSymbols , null , CachedSymbol .class );
211
+ this .cache .store (symbolsCacheKey , filesStr , generatedSymbols , null , CachedSymbol .class );
212
+ this .cache .store (beansCacheKey , filesStr , generatedBeans , null , CachedBean .class );
201
213
202
214
symbols = (CachedSymbol []) generatedSymbols .toArray (new CachedSymbol [generatedSymbols .size ()]);
215
+ beans = (CachedBean []) generatedBeans .toArray (new CachedBean [generatedBeans .size ()]);
203
216
}
204
217
else {
205
218
log .info ("scan factories files used cached data: " + project .getElementName () + " - no. of cached symbols retrieved: " + symbols .length );
206
219
}
207
220
208
- if (symbols != null ) {
221
+ if (symbols != null && beans != null ) {
209
222
WorkspaceSymbol [] enhancedSymbols = Arrays .stream (symbols ).map (cachedSymbol -> cachedSymbol .getEnhancedSymbol ()).toArray (WorkspaceSymbol []::new );
210
- symbolHandler .addSymbols (project , enhancedSymbols , null , null );
223
+ Map <String , List <SpringIndexElement >> beansByDoc = Arrays .stream (beans ).filter (cachedBean -> cachedBean .getBean () != null ).collect (Collectors .groupingBy (CachedBean ::getDocURI , Collectors .mapping (CachedBean ::getBean , Collectors .toList ())));
224
+ symbolHandler .addSymbols (project , enhancedSymbols , beansByDoc , null );
211
225
}
212
226
213
227
long endTime = System .currentTimeMillis ();
@@ -216,50 +230,13 @@ public void initializeProject(IJavaProject project, boolean clean) throws Except
216
230
217
231
}
218
232
219
- private List <CachedSymbol > scanFile (Path file ) {
220
- try {
221
- String content = Files .readString (file );
222
- ImmutableList .Builder <CachedSymbol > builder = ImmutableList .builder ();
223
- long lastModified = Files .getLastModifiedTime (file ).toMillis ();
224
- String docUri = file .toUri ().toASCIIString ();
225
- for (WorkspaceSymbol s : computeSymbols (docUri , content )) {
226
- builder .add (new CachedSymbol (docUri , lastModified , s ));
227
- }
228
- return builder .build ();
229
- } catch (IOException e ) {
230
- log .error ("" , e );
231
- return Collections .emptyList ();
232
- }
233
- }
234
-
235
- private List <Path > getFiles (IJavaProject project ) {
236
- try {
237
- return project .getClasspath ().getClasspathEntries ().stream ()
238
- .filter (Classpath ::isProjectSource )
239
- .map (cpe -> new File (cpe .getPath ()).toPath ())
240
- .map (p -> p .resolve ("META-INF" ).resolve ("spring" ))
241
- .filter (Files ::isDirectory )
242
- .flatMap (d -> {
243
- try {
244
- return Files .list (d );
245
- } catch (IOException e ) {
246
- // ignore
247
- return Stream .empty ();
248
- }
249
- })
250
- .filter (p -> p .toString ().endsWith (".factories" ))
251
- .collect (Collectors .toList ());
252
- } catch (Exception e ) {
253
- log .error ("" , e );
254
- return Collections .emptyList ();
255
- }
256
-
257
- }
258
-
259
233
@ Override
260
234
public void removeProject (IJavaProject project ) throws Exception {
261
- IndexCacheKey cacheKey = getCacheKey (project );
262
- this .cache .remove (cacheKey );
235
+ IndexCacheKey symbolsCacheKey = getCacheKey (project , SYMBOL_KEY );
236
+ IndexCacheKey beansCacheKey = getCacheKey (project , BEANS_KEY );
237
+
238
+ this .cache .remove (symbolsCacheKey );
239
+ this .cache .remove (beansCacheKey );
263
240
}
264
241
265
242
@ Override
@@ -269,30 +246,53 @@ public void updateFile(IJavaProject project, DocumentDescriptor updatedDoc, Stri
269
246
List <Path > outputFolders = IClasspathUtil .getOutputFolders (project .getClasspath ()).map (f -> f .toPath ()).collect (Collectors .toList ());
270
247
String docURI = updatedDoc .getDocURI ();
271
248
Path path = Paths .get (URI .create (docURI ));
249
+
272
250
if (!outputFolders .stream ().anyMatch (out -> path .startsWith (out ))) {
273
- List <CachedSymbol > generatedSymbols = scanFile (path );
251
+
252
+ ScanResult scanResult = scanFile (path );
253
+
254
+ List <CachedSymbol > generatedSymbols = Collections .emptyList ();
255
+ List <CachedBean > generatedBeans = Collections .emptyList ();
256
+
257
+ if (scanResult != null ) {
258
+ generatedSymbols = scanResult .symbols ;
259
+ generatedBeans = scanResult .beans ;
260
+ }
261
+
262
+ IndexCacheKey symbolsCacheKey = getCacheKey (project , SYMBOL_KEY );
263
+ IndexCacheKey beansCacheKey = getCacheKey (project , BEANS_KEY );
274
264
275
- IndexCacheKey cacheKey = getCacheKey (project );
276
265
String file = new File (new URI (docURI )).getAbsolutePath ();
277
- this .cache .update (cacheKey , file , updatedDoc .getLastModified (), generatedSymbols , null , CachedSymbol .class );
266
+ this .cache .update (symbolsCacheKey , file , updatedDoc .getLastModified (), generatedSymbols , null , CachedSymbol .class );
267
+ this .cache .update (beansCacheKey , file , updatedDoc .getLastModified (), generatedBeans , null , CachedBean .class );
278
268
279
269
WorkspaceSymbol [] symbols = generatedSymbols .stream ().map (cachedSymbol -> cachedSymbol .getEnhancedSymbol ()).toArray (WorkspaceSymbol []::new );
280
- symbolHandler .addSymbols (project , docURI , symbols , null , null );
270
+ List <SpringIndexElement > beans = generatedBeans .stream ().filter (cachedBean -> cachedBean .getBean () != null ).map (cachedBean -> cachedBean .getBean ()).toList ();
271
+ symbolHandler .addSymbols (project , docURI , symbols , beans , null );
281
272
}
282
273
}
283
274
284
275
@ Override
285
276
public void updateFiles (IJavaProject project , DocumentDescriptor [] updatedDocs ) throws Exception {
286
- IndexCacheKey key = getCacheKey (project );
277
+ IndexCacheKey symbolsCacheKey = getCacheKey (project , SYMBOL_KEY );
278
+ IndexCacheKey beansCacheKey = getCacheKey (project , BEANS_KEY );
279
+
287
280
List <Path > outputFolders = IClasspathUtil .getOutputFolders (project .getClasspath ()).map (f -> f .toPath ()).collect (Collectors .toList ());
281
+
288
282
for (DocumentDescriptor d : updatedDocs ) {
289
283
Path path = Paths .get (URI .create (d .getDocURI ()));
284
+
290
285
if (!outputFolders .stream ().anyMatch (out -> path .startsWith (out ))) {
286
+
291
287
if (Files .isRegularFile (path )) {
288
+
292
289
updateFile (project , d , Files .readString (path ));
290
+
293
291
} else {
294
292
String file = new File (new URI (d .getDocURI ())).getAbsolutePath ();
295
- cache .removeFile (key , file , CachedSymbol .class );
293
+
294
+ cache .removeFile (symbolsCacheKey , file , CachedSymbol .class );
295
+ cache .removeFile (beansCacheKey , file , CachedBean .class );
296
296
}
297
297
}
298
298
}
@@ -308,8 +308,82 @@ public void removeFiles(IJavaProject project, String[] docURIs) throws Exception
308
308
}
309
309
}).toArray (String []::new );
310
310
311
- IndexCacheKey key = getCacheKey (project );
312
- cache .removeFiles (key , files , CachedSymbol .class );
311
+ IndexCacheKey symbolsCacheKey = getCacheKey (project , SYMBOL_KEY );
312
+ IndexCacheKey beansCacheKey = getCacheKey (project , SYMBOL_KEY );
313
+
314
+ cache .removeFiles (symbolsCacheKey , files , CachedSymbol .class );
315
+ cache .removeFiles (beansCacheKey , files , CachedBean .class );
316
+ }
317
+
318
+ private ScanResult scanFile (Path file ) {
319
+ try {
320
+
321
+ String content = Files .readString (file );
322
+
323
+ ImmutableList .Builder <CachedSymbol > symbols = ImmutableList .builder ();
324
+ ImmutableList .Builder <CachedBean > beans = ImmutableList .builder ();
325
+
326
+ long lastModified = Files .getLastModifiedTime (file ).toMillis ();
327
+ String docUri = file .toUri ().toASCIIString ();
328
+
329
+ ComputeResult result = computeSymbols (docUri , content );
330
+
331
+ for (WorkspaceSymbol symbol : result .symbols ) {
332
+ symbols .add (new CachedSymbol (docUri , lastModified , symbol ));
333
+ }
334
+
335
+ for (Bean bean : result .beans ) {
336
+ beans .add (new CachedBean (docUri , bean ));
337
+ }
338
+
339
+ return new ScanResult (symbols .build (), beans .build ());
340
+
341
+ } catch (IOException e ) {
342
+ log .error ("" , e );
343
+ return null ;
344
+ }
345
+ }
346
+
347
+ private List <Path > getFiles (IJavaProject project ) {
348
+ try {
349
+ return project .getClasspath ().getClasspathEntries ().stream ()
350
+ .filter (Classpath ::isProjectSource )
351
+ .map (cpe -> new File (cpe .getPath ()).toPath ())
352
+ .map (p -> p .resolve ("META-INF" ).resolve ("spring" ))
353
+ .filter (Files ::isDirectory )
354
+ .flatMap (d -> {
355
+ try {
356
+ return Files .list (d );
357
+ } catch (IOException e ) {
358
+ // ignore
359
+ return Stream .empty ();
360
+ }
361
+ })
362
+ .filter (p -> p .toString ().endsWith (".factories" ))
363
+ .collect (Collectors .toList ());
364
+ } catch (Exception e ) {
365
+ log .error ("" , e );
366
+ return Collections .emptyList ();
367
+ }
368
+
313
369
}
314
370
371
+ private IndexCacheKey getCacheKey (IJavaProject project , String elementType ) {
372
+ String filesIndentifier = getFiles (project ).stream ()
373
+ .filter (f -> Files .isRegularFile (f ))
374
+ .map (f -> {
375
+ try {
376
+ return f .toAbsolutePath ().toString () + "#" + Files .getLastModifiedTime (f ).toMillis ();
377
+ } catch (IOException e ) {
378
+ log .error ("" , e );
379
+ return f .toAbsolutePath ().toString () + "#0" ;
380
+ }
381
+ })
382
+ .collect (Collectors .joining ("," ));
383
+ return new IndexCacheKey (project .getElementName (), "factories" , elementType , DigestUtils .md5Hex (GENERATION + "-" + filesIndentifier ).toUpperCase ());
384
+ }
385
+
386
+ private static record ScanResult (List <CachedSymbol > symbols , List <CachedBean > beans ) {}
387
+ private static record ComputeResult (List <WorkspaceSymbol > symbols , List <Bean > beans ) {}
388
+
315
389
}
0 commit comments