diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java index b5f1199e4..f3717fdaf 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java @@ -312,7 +312,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent Map providers = new HashMap<>(); - providers.put(Annotations.VALUE, new ValuePropertyReferencesProvider(server)); + providers.put(Annotations.VALUE, new ValuePropertyReferencesProvider(projectFinder)); providers.put(Annotations.QUALIFIER, new QualifierReferencesProvider(index, symbolIndex)); providers.put(Annotations.NAMED_JAKARTA, new NamedReferencesProvider(index, symbolIndex)); providers.put(Annotations.NAMED_JAVAX, new NamedReferencesProvider(index, symbolIndex)); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java index b110b8c12..c39af1805 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValuePropertyReferencesProvider.java @@ -18,7 +18,6 @@ import java.net.URI; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -37,14 +36,14 @@ import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; -import org.eclipse.lsp4j.WorkspaceFolder; import org.eclipse.lsp4j.jsonrpc.CancelChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.handlers.ReferenceProvider; import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents; +import org.springframework.ide.vscode.commons.java.IClasspathUtil; import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; +import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.util.text.TextDocument; import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider; import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST; @@ -65,10 +64,10 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { private static final Logger log = LoggerFactory.getLogger(ValuePropertyReferencesProvider.class); - private SimpleLanguageServer languageServer; + private final JavaProjectFinder projectFinder; - public ValuePropertyReferencesProvider(SimpleLanguageServer server) { - this.languageServer = server; + public ValuePropertyReferencesProvider(JavaProjectFinder projectFinder) { + this.projectFinder = projectFinder; } @Override @@ -105,7 +104,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { if (range != null) { String propertyKey = value.substring(range.getStart(), range.getEnd()); if (propertyKey != null && propertyKey.length() > 0) { - return findReferencesFromPropertyFiles(languageServer.getWorkspaceRoots(), propertyKey); + return findReferencesFromPropertyFiles(propertyKey); } } } @@ -116,27 +115,29 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { return null; } - public List findReferencesFromPropertyFiles(Collection workspaceRoots, String propertyKey) { - - for (WorkspaceFolder workspaceFolder : workspaceRoots) { - try { - Path workspaceRoot = Paths.get(new URI(workspaceFolder.getUri())); - try (Stream walk = Files.walk(workspaceRoot)) { - List locations = walk - .filter(path -> isPropertiesFile(path)) - .filter(path -> path.toFile().isFile()) - .map(path -> findReferences(path, propertyKey)) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - return locations; - } - } catch (Exception e) { - e.printStackTrace(); - } + public List findReferencesFromPropertyFiles(String propertyKey) { + Collection allProjects = this.projectFinder.all(); + + try { + return allProjects + .stream() + .flatMap(project -> IClasspathUtil.getSourceFolders(project.getClasspath())) + .flatMap(sourceFolder -> { + try { + return Files.walk(sourceFolder.toPath()); + } catch (IOException e) { + return Stream.empty(); + } + }) + .filter(path -> ValuePropertyReferencesProvider.isPropertiesFile(path)) + .filter(path -> path.toFile().isFile()) + .map(path -> findReferences(path, propertyKey)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + catch (Exception e) { + return null; } - - return null; } public static boolean isPropertiesFile(Path path) { @@ -154,7 +155,7 @@ public class ValuePropertyReferencesProvider implements ReferenceProvider { return false; } - private List findReferences(Path path, String propertyKey) { + public List findReferences(Path path, String propertyKey) { String filePath = path.toString(); if (filePath.endsWith(BootPropertiesLanguageServerComponents.PROPERTIES)) { return findReferencesInPropertiesFile(path.toFile(), propertyKey); diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/ValuePropertyReferenceFinderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/ValuePropertyReferenceFinderTest.java index e94c99205..0cbc5960e 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/ValuePropertyReferenceFinderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/references/test/ValuePropertyReferenceFinderTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2018 Pivotal, Inc. + * Copyright (c) 2017, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,8 +16,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import java.io.File; import java.net.URI; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collection; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -42,8 +40,6 @@ import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness; import org.springframework.ide.vscode.project.harness.ProjectsHarness; import org.springframework.test.context.junit.jupiter.SpringExtension; -import com.google.common.collect.ImmutableList; - /** * @author Martin Lippert */ @@ -58,6 +54,7 @@ public class ValuePropertyReferenceFinderTest { private File directory; private String tempJavaDocUri; + private Path resourceDir; @BeforeEach public void setup() throws Exception { @@ -69,6 +66,7 @@ public class ValuePropertyReferenceFinderTest { projectFinder.find(new TextDocumentIdentifier(projectDir)).get(); tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString(); + resourceDir = directory.toPath().resolve("src/main/resources/"); CompletableFuture initProject = indexer.waitOperation(); initProject.get(5, TimeUnit.SECONDS); @@ -76,16 +74,16 @@ public class ValuePropertyReferenceFinderTest { @Test void testFindReferenceAtBeginningPropFile() throws Exception { - ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); + ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(projectFinder); - Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI()); - List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); + Path file = resourceDir.resolve("simple-case/application.properties"); + List locations = provider.findReferences(file, "test.property"); assertNotNull(locations); assertEquals(1, locations.size()); Location location = locations.get(0); - URI docURI = Paths.get(root.toString(), "application.properties").toUri(); + URI docURI = file.toUri(); assertEquals(docURI.toString(), location.getUri()); assertEquals(0, location.getRange().getStart().getLine()); assertEquals(0, location.getRange().getStart().getCharacter()); @@ -93,28 +91,18 @@ public class ValuePropertyReferenceFinderTest { assertEquals(13, location.getRange().getEnd().getCharacter()); } - private Collection wsFolder(Path directory) { - if (directory != null) { - WorkspaceFolder folder = new WorkspaceFolder(); - folder.setName(directory.getFileName().toString()); - folder.setUri(directory.toUri().toString()); - return ImmutableList.of(folder); - } - return ImmutableList.of(); - } - @Test void testFindReferenceAtBeginningYMLFile() throws Exception { - ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); + ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(projectFinder); - Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-yml/").toURI()); - List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "test.property"); + Path file = resourceDir.resolve("simple-yml/application.yml"); + List locations = provider.findReferences(file, "test.property"); assertNotNull(locations); assertEquals(1, locations.size()); Location location = locations.get(0); - URI docURI = Paths.get(root.toString(), "application.yml").toUri(); + URI docURI = file.toUri(); assertEquals(docURI.toString(), location.getUri()); assertEquals(3, location.getRange().getStart().getLine()); assertEquals(2, location.getRange().getStart().getCharacter()); @@ -122,50 +110,41 @@ public class ValuePropertyReferenceFinderTest { assertEquals(10, location.getRange().getEnd().getCharacter()); } - @Test - void testFindReferenceWithinTheDocument() throws Exception { - ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); - - Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI()); - List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "server.port"); - - assertNotNull(locations); - assertEquals(1, locations.size()); - Location location = locations.get(0); - - URI docURI = Paths.get(root.toString(), "application.properties").toUri(); - assertEquals(docURI.toString(), location.getUri()); - assertEquals(2, location.getRange().getStart().getLine()); - assertEquals(0, location.getRange().getStart().getCharacter()); - assertEquals(2, location.getRange().getEnd().getLine()); - assertEquals(11, location.getRange().getEnd().getCharacter()); - } - @Test void testFindReferenceWithinMultipleFiles() throws Exception { - ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); + ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(projectFinder); - Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/multiple-files/").toURI()); - List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); + List locations = provider.findReferencesFromPropertyFiles("appl1.prop"); assertNotNull(locations); - assertEquals(3, locations.size()); + assertEquals(4, locations.size()); - Location location = getLocation(locations, Paths.get(root.toString(), "application-dev.properties").toUri()); + Path file1 = resourceDir.resolve("mixed-multiple-files/application-dev.properties"); + Location location = getLocation(locations, file1.toUri()); assertNotNull(location); assertEquals(1, location.getRange().getStart().getLine()); assertEquals(0, location.getRange().getStart().getCharacter()); assertEquals(1, location.getRange().getEnd().getLine()); assertEquals(10, location.getRange().getEnd().getCharacter()); - location = getLocation(locations, Paths.get(root.toString(), "application.properties").toUri()); + Path file2 = resourceDir.resolve("mixed-multiple-files/application.yml"); + location = getLocation(locations, file2.toUri()); + assertNotNull(location); + assertEquals(3, location.getRange().getStart().getLine()); + assertEquals(2, location.getRange().getStart().getCharacter()); + assertEquals(3, location.getRange().getEnd().getLine()); + assertEquals(6, location.getRange().getEnd().getCharacter()); + + Path file3 = resourceDir.resolve("another-prop-folder/application.properties"); + location = getLocation(locations, file3.toUri()); assertNotNull(location); assertEquals(1, location.getRange().getStart().getLine()); assertEquals(0, location.getRange().getStart().getCharacter()); assertEquals(1, location.getRange().getEnd().getLine()); assertEquals(10, location.getRange().getEnd().getCharacter()); - location = getLocation(locations, Paths.get(root.toString(), "prod-application.properties").toUri()); + Path file4 = resourceDir.resolve("another-prop-folder/prod-application.properties"); + location = getLocation(locations, file4.toUri()); assertNotNull(location); assertEquals(1, location.getRange().getStart().getLine()); assertEquals(0, location.getRange().getStart().getCharacter()); @@ -183,31 +162,6 @@ public class ValuePropertyReferenceFinderTest { return null; } - @Test - void testFindReferenceWithinMultipleMixedFiles() throws Exception { - ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null); - - Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/mixed-multiple-files/").toURI()); - List locations = provider.findReferencesFromPropertyFiles(wsFolder(root), "appl1.prop"); - - assertNotNull(locations); - assertEquals(2, locations.size()); - - Location location = getLocation(locations, Paths.get(root.toString(), "application-dev.properties").toUri()); - assertNotNull(location); - assertEquals(1, location.getRange().getStart().getLine()); - assertEquals(0, location.getRange().getStart().getCharacter()); - assertEquals(1, location.getRange().getEnd().getLine()); - assertEquals(10, location.getRange().getEnd().getCharacter()); - - location = getLocation(locations, Paths.get(root.toString(), "application.yml").toUri()); - assertNotNull(locations); - assertEquals(3, location.getRange().getStart().getLine()); - assertEquals(2, location.getRange().getStart().getCharacter()); - assertEquals(3, location.getRange().getEnd().getLine()); - assertEquals(6, location.getRange().getEnd().getCharacter()); - } - @Test void testFindReferencesToPropertyFromValueAnnotation() throws Exception { harness.getServer().getWorkspaceService().setWorkspaceFolders(List.of(new WorkspaceFolder(directory.toURI().toString()))); diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application.properties b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/another-prop-folder/application.properties similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application.properties rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/another-prop-folder/application.properties diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/prod-application.properties b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/another-prop-folder/prod-application.properties similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/prod-application.properties rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/another-prop-folder/prod-application.properties diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/application-dev.properties b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/application-dev.properties similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/application-dev.properties rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/application-dev.properties diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/application.yml b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/application.yml similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/application.yml rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/application.yml diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/no-props.yml b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/no-props.yml similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/no-props.yml rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/no-props.yml diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/non-app-props.properties b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/non-app-props.properties similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/mixed-multiple-files/non-app-props.properties rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/mixed-multiple-files/non-app-props.properties diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/simple-case/application.properties b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/simple-case/application.properties similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/simple-case/application.properties rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/simple-case/application.properties diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/simple-yml/application.yml b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/simple-yml/application.yml similarity index 100% rename from headless-services/spring-boot-language-server/src/test/resources/test-property-files/simple-yml/application.yml rename to headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-indexing/src/main/resources/simple-yml/application.yml diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application-dev.properties b/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application-dev.properties deleted file mode 100644 index 9937ca7e6..000000000 --- a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application-dev.properties +++ /dev/null @@ -1,2 +0,0 @@ -something.else=true -appl1.prop=test diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application.non-properties b/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application.non-properties deleted file mode 100644 index 9937ca7e6..000000000 --- a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/application.non-properties +++ /dev/null @@ -1,2 +0,0 @@ -something.else=true -appl1.prop=test diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/non-app-props.properties b/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/non-app-props.properties deleted file mode 100644 index 9937ca7e6..000000000 --- a/headless-services/spring-boot-language-server/src/test/resources/test-property-files/multiple-files/non-app-props.properties +++ /dev/null @@ -1,2 +0,0 @@ -something.else=true -appl1.prop=test