diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java index 5766197a7..27214398b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java @@ -207,9 +207,8 @@ public class SpringIndexerJava implements SpringIndexer { List generatedSymbols = new ArrayList(); AtomicReference docRef = new AtomicReference<>(); String file = UriUtil.toFileString(docURI); - Set changedTypes = new HashSet<>(); SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file, - lastModified, docRef, content, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>(), changedTypes); + lastModified, docRef, content, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>()); scanAST(context); @@ -223,7 +222,7 @@ public class SpringIndexerJava implements SpringIndexer { Set scannedFiles = new HashSet<>(); scannedFiles.add(file); fileScannedEvent(file); - scanAffectedFiles(project, changedTypes, scannedFiles); + scanAffectedFiles(project, context.getScannedTypes(), scannedFiles); } } @@ -261,12 +260,13 @@ public class SpringIndexerJava implements SpringIndexer { AtomicReference docRef = new AtomicReference<>(); SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath, - lastModified, docRef, null, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>(), scannedTypes); + lastModified, docRef, null, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>()); - dependencies.putAll(sourceFilePath, context.getDependencies()); - scanAST(context); + dependencies.putAll(sourceFilePath, context.getDependencies()); + scannedTypes.addAll(context.getScannedTypes()); + fileScannedEvent(sourceFilePath); } }; @@ -366,7 +366,7 @@ public class SpringIndexerJava implements SpringIndexer { AtomicReference docRef = new AtomicReference<>(); SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath, - lastModified, docRef, null, generatedSymbols, pass, nextPassFiles, null); + lastModified, docRef, null, generatedSymbols, pass, nextPassFiles); scanAST(context); } @@ -439,6 +439,7 @@ public class SpringIndexerJava implements SpringIndexer { return super.visit(node); } }); + dependencyTracker.update(context.getFile(), context.getDependencies());; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java index 0d2e4147c..74bf5621f 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java @@ -36,8 +36,9 @@ public class SpringIndexerJavaContext { private final List generatedSymbols; private final SCAN_PASS pass; private final List nextPassFiles; + private final Set dependencies = new HashSet<>(); - private final Set scannedTypes; + private final Set scannedTypes = new HashSet<>(); public SpringIndexerJavaContext( IJavaProject project, @@ -49,8 +50,7 @@ public class SpringIndexerJavaContext { String content, List generatedSymbols, SCAN_PASS pass, - List nextPassFiles, - Set scannedTypes + List nextPassFiles ) { super(); this.project = project; @@ -63,7 +63,6 @@ public class SpringIndexerJavaContext { this.generatedSymbols = generatedSymbols; this.pass = pass; this.nextPassFiles = nextPassFiles; - this.scannedTypes = scannedTypes; } public IJavaProject getProject() { @@ -111,7 +110,13 @@ public class SpringIndexerJavaContext { } public void addDependency(ITypeBinding dependsOn) { - dependencies.add(dependsOn.getKey()); + if (dependsOn != null && dependsOn.isFromSource()) { + String type = dependsOn.getKey(); + + if (type != null && !scannedTypes.contains(type)) { + dependencies.add(type); + } + } } public Set getScannedTypes() { @@ -119,8 +124,10 @@ public class SpringIndexerJavaContext { } public void addScannedType(ITypeBinding scannedType) { - if (this.scannedTypes != null && scannedType != null) { - scannedTypes.add(scannedType.getKey()); + if (scannedType != null) { + String type = scannedType.getKey(); + scannedTypes.add(type); + dependencies.remove(type); } } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java index c429b4331..750d92bc9 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingSymbolProviderTest.java @@ -103,6 +103,31 @@ public class RequestMappingSymbolProviderTest { fileScanListener.assertScannedUri(docUri, 1); } + @Test + public void testUpdateDocumentWithConstantFromDifferentClass() throws Exception { + String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClassWithConstantInDifferentClass.java").toUri().toString(); + String constantsUri = directory.toPath().resolve("src/main/java/org/test/Constants.java").toUri().toString(); + List symbols = indexer.getSymbols(docUri); + assertEquals(1, symbols.size()); + assertTrue(containsSymbol(symbols, "@/path/from/constant", docUri, 6, 1, 6, 48)); + + //Verify whether dependency tracker logics works properly for this example. + SpringIndexerJavaDependencyTracker dt = indexer.getJavaIndexer().getDependencyTracker(); + assertEquals(ImmutableSet.of("Lorg/test/Constants;"), dt.getAllDependencies().get(UriUtil.toFileString(docUri))); + + TestFileScanListener fileScanListener = new TestFileScanListener(); + indexer.getJavaIndexer().setFileScanListener(fileScanListener); + + CompletableFuture updateFuture = indexer.updateDocument(docUri, FileUtils.readFileToString(UriUtil.toFile(docUri)), "test triggered"); + updateFuture.get(5, TimeUnit.SECONDS); + + assertEquals(ImmutableSet.of("Lorg/test/Constants;"), dt.getAllDependencies().get(UriUtil.toFileString(docUri))); + + fileScanListener.assertScannedUris(docUri); + fileScanListener.assertScannedUri(constantsUri, 0); + fileScanListener.assertScannedUri(docUri, 1); + } + @Test public void testCyclicalRequestMappingDependency() throws Exception { //Cyclical dependency: @@ -138,6 +163,20 @@ public class RequestMappingSymbolProviderTest { List symbols = indexer.getSymbols(docUri); assertEquals(1, symbols.size()); assertTrue(containsSymbol(symbols, "@/request/mapping/path/from/same/class/constant", docUri, 8, 1, 8, 52)); + + SpringIndexerJavaDependencyTracker dt = indexer.getJavaIndexer().getDependencyTracker(); + assertEquals(ImmutableSet.of(), dt.getAllDependencies().get(UriUtil.toFileString(docUri))); + } + + @Test + public void testSimpleRequestMappingSymbolFromConstantInBinaryType() throws Exception { + String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClassWithConstantFromBinaryType.java").toUri().toString(); + List symbols = indexer.getSymbols(docUri); + assertEquals(1, symbols.size()); + assertTrue(containsSymbol(symbols, "@/(inferred)", docUri, 7, 1, 7, 53)); + + SpringIndexerJavaDependencyTracker dt = indexer.getJavaIndexer().getDependencyTracker(); + assertEquals(ImmutableSet.of(), dt.getAllDependencies().get(UriUtil.toFileString(docUri))); } @Test diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/SimpleMappingClassWithConstantFromBinaryType.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/SimpleMappingClassWithConstantFromBinaryType.java new file mode 100644 index 000000000..70e6da296 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-request-mapping-symbols/src/main/java/org/test/SimpleMappingClassWithConstantFromBinaryType.java @@ -0,0 +1,13 @@ +package org.test; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.beans.factory.support.AbstractBeanDefinition; + +public class SimpleMappingClassWithConstantFromBinaryType { + + @RequestMapping(AbstractBeanDefinition.INFER_METHOD) + public String hello() { + return "Hello"; + } + +}