diff --git a/vscode-extensions/vscode-boot-java/pom.xml b/vscode-extensions/vscode-boot-java/pom.xml
index de3f34aba..e3aa1fb4a 100644
--- a/vscode-extensions/vscode-boot-java/pom.xml
+++ b/vscode-extensions/vscode-boot-java/pom.xml
@@ -48,6 +48,11 @@
commons-language-server
${project.version}
+
+ org.springframework.ide.vscode
+ java-properties
+ ${project.version}
+
diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/references/ValuePropertyReferencesProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/references/ValuePropertyReferencesProvider.java
index cd1fe58bd..1457e685d 100644
--- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/references/ValuePropertyReferencesProvider.java
+++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/references/ValuePropertyReferencesProvider.java
@@ -10,8 +10,11 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.references;
+import java.io.File;
+import java.net.URI;
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;
@@ -19,14 +22,22 @@ import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.commons.io.FileUtils;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.lsp4j.Location;
+import org.eclipse.lsp4j.Position;
+import org.eclipse.lsp4j.Range;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
+import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
+import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
+import org.springframework.ide.vscode.java.properties.parser.ParseResults;
+import org.springframework.ide.vscode.java.properties.parser.Parser;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.KeyValuePair;
/**
* @author Martin Lippert
@@ -89,7 +100,7 @@ public class ValuePropertyReferencesProvider {
List locations = walk
.filter(path -> isPropertiesFile(path))
.filter(path -> path.toFile().isFile())
- .map(path -> findReferences(path))
+ .map(path -> findReferences(path, propertyKey))
.flatMap(Collection::stream)
.collect(Collectors.toList());
@@ -103,13 +114,20 @@ public class ValuePropertyReferencesProvider {
}
private boolean isPropertiesFile(Path path) {
- return path.toString().endsWith("application.properties");
+ Path fileName = path.getFileName();
+
+ if (fileName.toString().endsWith(".properties") || path.toString().endsWith(".yml")) {
+ return fileName.toString().contains("application");
+ }
+ else {
+ return false;
+ }
}
- private List findReferences(Path path) {
+ private List findReferences(Path path, String propertyKey) {
String filePath = path.toString();
if (filePath.endsWith(".properties")) {
- // do the real work
+ return findReferencesInPropertiesFile(filePath, propertyKey);
}
else if (filePath.endsWith(".yml")) {
// do the real work
@@ -117,6 +135,55 @@ public class ValuePropertyReferencesProvider {
return new ArrayList();
}
+ private List findReferencesInPropertiesFile(String filePath, String propertyKey) {
+ List foundLocations = new ArrayList<>();
+
+ try {
+ String fileContent = FileUtils.readFileToString(new File(filePath));
+
+ Parser parser = new AntlrParser();
+ ParseResults parseResults = parser.parse(fileContent);
+
+ if (parseResults != null && parseResults.ast != null) {
+ parseResults.ast.getNodes(KeyValuePair.class).forEach(pair -> {
+ if (pair.getKey() != null && pair.getKey().decode().equals(propertyKey)) {
+ URI docURI = Paths.get(filePath).toUri();
+ TextDocument doc = new TextDocument(docURI.toString(), null);
+ doc.setText(fileContent);
+
+ try {
+ int line = doc.getLineOfOffset(pair.getKey().getOffset());
+ int startInLine = pair.getKey().getOffset() - doc.getLineOffset(line);
+ int endInLine = startInLine + (pair.getKey().getLength());
+
+ Position start = new Position();
+ start.setLine(line);
+ start.setCharacter(startInLine);
+
+ Position end = new Position();
+ end.setLine(line);
+ end.setCharacter(endInLine);
+
+ Range range = new Range();
+ range.setStart(start);
+ range.setEnd(end);
+
+ Location location = new Location(docURI.toString(), range);
+ foundLocations.add(location);
+
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return foundLocations;
+ }
+
public LocalRange getPropertyRange(String value, int offset) {
int start = -1;
int end = -1;
diff --git a/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java b/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java
index a507b2fc8..5df4c925b 100644
--- a/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java
+++ b/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/boot/java/references/test/PropertyReferenceFinderTest.java
@@ -10,8 +10,10 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.references.test;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@@ -28,13 +30,79 @@ import org.springframework.ide.vscode.project.harness.ProjectsHarness;
public class PropertyReferenceFinderTest {
@Test
- public void testFindReferences() throws Exception {
+ public void testFindReferenceAtBeginning() throws Exception {
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI());
- CompletableFuture> locations = provider.findReferencesFromPropertyFiles(root, "test.property");
+ CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(root, "test.property");
- assertNotNull(locations);
+ assertNotNull(resultFuture);
+ List extends Location> locations = resultFuture.get();
+ assertEquals(1, locations.size());
+ Location location = locations.get(0);
+
+ URI docURI = Paths.get(root.toString(), "application.properties").toUri();
+ assertEquals(docURI.toString(), location.getUri());
+ assertEquals(0, location.getRange().getStart().getLine());
+ assertEquals(0, location.getRange().getStart().getCharacter());
+ assertEquals(0, location.getRange().getEnd().getLine());
+ assertEquals(13, location.getRange().getEnd().getCharacter());
+ }
+
+ @Test
+ public void testFindReferenceWithinTheDocument() throws Exception {
+ ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
+
+ Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI());
+ CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(root, "server.port");
+
+ assertNotNull(resultFuture);
+ List extends Location> locations = resultFuture.get();
+ 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
+ public void testFindReferenceWithinMultipleFiles() throws Exception {
+ ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
+
+ Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/multiple-files/").toURI());
+ CompletableFuture> resultFuture = provider.findReferencesFromPropertyFiles(root, "appl1.prop");
+
+ assertNotNull(resultFuture);
+ List extends Location> locations = resultFuture.get();
+ assertEquals(3, locations.size());
+
+ Location location = locations.get(0);
+ URI docURI = Paths.get(root.toString(), "application-dev.properties").toUri();
+ assertEquals(docURI.toString(), location.getUri());
+ 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 = locations.get(1);
+ docURI = Paths.get(root.toString(), "application.properties").toUri();
+ assertEquals(docURI.toString(), location.getUri());
+ 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 = locations.get(2);
+ docURI = Paths.get(root.toString(), "prod-application.properties").toUri();
+ assertEquals(docURI.toString(), location.getUri());
+ assertEquals(1, location.getRange().getStart().getLine());
+ assertEquals(0, location.getRange().getStart().getCharacter());
+ assertEquals(1, location.getRange().getEnd().getLine());
+ assertEquals(10, location.getRange().getEnd().getCharacter());
}
}
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application-dev.properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application-dev.properties
new file mode 100644
index 000000000..9937ca7e6
--- /dev/null
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application-dev.properties
@@ -0,0 +1,2 @@
+something.else=true
+appl1.prop=test
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.non-properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.non-properties
new file mode 100644
index 000000000..9937ca7e6
--- /dev/null
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.non-properties
@@ -0,0 +1,2 @@
+something.else=true
+appl1.prop=test
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.properties
new file mode 100644
index 000000000..9937ca7e6
--- /dev/null
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/application.properties
@@ -0,0 +1,2 @@
+something.else=true
+appl1.prop=test
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/non-app-props.properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/non-app-props.properties
new file mode 100644
index 000000000..9937ca7e6
--- /dev/null
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/non-app-props.properties
@@ -0,0 +1,2 @@
+something.else=true
+appl1.prop=test
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/prod-application.properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/prod-application.properties
new file mode 100644
index 000000000..9937ca7e6
--- /dev/null
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/multiple-files/prod-application.properties
@@ -0,0 +1,2 @@
+something.else=true
+appl1.prop=test
diff --git a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/simple-case/application.properties b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/simple-case/application.properties
index 72b67a7be..1c9ede71f 100644
--- a/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/simple-case/application.properties
+++ b/vscode-extensions/vscode-boot-java/src/test/resources/test-property-files/simple-case/application.properties
@@ -1 +1,5 @@
test.property=Hey there
+
+server.port=8080
+
+another.property=moretests
diff --git a/vscode-extensions/vscode-boot-properties/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/DemoEnumApplication.java b/vscode-extensions/vscode-boot-properties/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/DemoEnumApplication.java
index b484e936f..bd7ecf7de 100644
--- a/vscode-extensions/vscode-boot-properties/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/DemoEnumApplication.java
+++ b/vscode-extensions/vscode-boot-properties/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/DemoEnumApplication.java
@@ -3,6 +3,7 @@ package demo;
import java.util.Map.Entry;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -18,6 +19,7 @@ public class DemoEnumApplication implements CommandLineRunner {
@Autowired
+ @Value("${server.port}")
FooProperties foo;
@Override