Skip to content

Commit

Permalink
GH-1354: taking all application*.properties files into account for ad…
Browse files Browse the repository at this point in the history
…hoc property index
  • Loading branch information
martinlippert committed Sep 20, 2024
1 parent 342e746 commit 7fa81e8
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,8 @@ private List<? extends Location> provideReferences(String value, int offset, int
return null;
}

public List<? extends Location> findReferencesFromPropertyFiles(
Collection<WorkspaceFolder> workspaceRoots,
String propertyKey
) {
public List<? extends Location> findReferencesFromPropertyFiles(Collection<WorkspaceFolder> workspaceRoots, String propertyKey) {

for (WorkspaceFolder workspaceFolder : workspaceRoots) {
try {
Path workspaceRoot = Paths.get(new URI(workspaceFolder.getUri()));
Expand All @@ -141,7 +139,7 @@ public List<? extends Location> findReferencesFromPropertyFiles(
return null;
}

static boolean isPropertiesFile(Path path) {
public static boolean isPropertiesFile(Path path) {
String fileName = path.getFileName().toString();

if (fileName.endsWith(BootPropertiesLanguageServerComponents.PROPERTIES)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 Pivotal, Inc.
* Copyright (c) 2018, 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
Expand All @@ -15,14 +15,19 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;

import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.value.ValuePropertyReferencesProvider;
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.java.JavaProjectFinder;
Expand Down Expand Up @@ -64,8 +69,9 @@ public AdHocSpringPropertyIndexProvider(JavaProjectFinder projectFinder, Project
}
if (fileObserver!=null) {
fileObserver.onAnyChange(ImmutableList.of(
"**/application.properties",
"**/application.yml"
"**/application*.properties",
"**/application*.yaml",
"**/application*.yml"
), changed -> {
log.debug("Files changed: {}", (Object[])changed);

Expand All @@ -83,7 +89,7 @@ public AdHocSpringPropertyIndexProvider(JavaProjectFinder projectFinder, Project

});
}
if (documents!=null) {
if (documents != null) {
documents.onDidSave(saveEvent -> {
LanguageId language = saveEvent.getDocument().getLanguageId();
if (language.equals(LanguageId.BOOT_PROPERTIES) || language.equals(LanguageId.BOOT_PROPERTIES_YAML)) {
Expand All @@ -95,13 +101,12 @@ public AdHocSpringPropertyIndexProvider(JavaProjectFinder projectFinder, Project

@Override
public FuzzyMap<PropertyInfo> getIndex(IJavaProject jp) {
if (jp!=null) {
if (jp != null) {
try {
return indexes.get(jp, () -> {
SimplePropertyIndex index = new SimplePropertyIndex();
IClasspathUtil.getSourceFolders(jp.getClasspath()).forEach(sourceFolder -> {
processFile(this::parseProperties, new File(sourceFolder, "application.properties"), index);
processFile(this::parseYaml, new File(sourceFolder, "application.yml"), index);
getIndexFromSourceFolder(sourceFolder, index);
});
return index;
});
Expand All @@ -112,9 +117,28 @@ public FuzzyMap<PropertyInfo> getIndex(IJavaProject jp) {
return SpringPropertyIndex.EMPTY_INDEX.getProperties();
}

private void getIndexFromSourceFolder(File sourceFolder, SimplePropertyIndex index) {
try (Stream<Path> walk = Files.walk(sourceFolder.toPath())) {
walk
.filter(path -> ValuePropertyReferencesProvider.isPropertiesFile(path))
.filter(path -> path.toFile().isFile())
.forEach(path -> {
String fileName = path.getFileName().toString();
if (fileName.endsWith(BootPropertiesLanguageServerComponents.PROPERTIES)) {
processFile(this::parseProperties, path.toFile(), index);
}
else if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
processFile(this::parseYaml, path.toFile(), index);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

private void processFile(Function<File, Properties> parserFunction, File file, SimplePropertyIndex index) {
Properties props = parserFunction.apply(file);
if (props!=null) {
if (props != null) {
for (Object p : props.keySet()) {
if (p instanceof String) {
String filename = file.getName();
Expand Down Expand Up @@ -157,22 +181,25 @@ private Properties parseYaml(File yamlFile) {

private void flattenProperties(String prefix, Node node, Properties props) {
switch (node.getNodeId()) {

case mapping:
if (!prefix.isEmpty()) {
prefix = prefix +".";
prefix = prefix + ".";
}
MappingNode mapping = (MappingNode)node;
for (NodeTuple tup : mapping.getValue()) {
String key = NodeUtil.asScalar(tup.getKeyNode());
if (key!=null) {
flattenProperties(prefix+key, tup.getValueNode(), props);
if (key != null) {
flattenProperties(prefix + key, tup.getValueNode(), props);
}
}
break;

case scalar:
//End of the line.
props.put(prefix, NodeUtil.asScalar(node));
break;

default:
if (!prefix.isEmpty()) {
props.put(prefix, "<object>");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2018, 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
Expand All @@ -10,15 +10,14 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.value.test;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.File;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.springframework.ide.vscode.boot.java.value.test.MockProjects.MockProject;
import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocumentSaveChange;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
Expand All @@ -45,6 +44,38 @@ void parseProperties() throws Exception {
);
}

@Test
void parsePropertiesInSubFolder() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/test/application.properties",
"some-adhoc-foo=somefoo\n" +
"some-adhoc-bar=somebar\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);

assertProperties(indexer.getIndex(project),
//alphabetic order
"some-adhoc-bar",
"some-adhoc-foo"
);
}

@Test
void parsePropertiesFromPropertyFileVariants() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application-dev.properties",
"dev-some-adhoc-foo=somefoo\n" +
"dev-some-adhoc-bar=somebar\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);

assertProperties(indexer.getIndex(project),
//alphabetic order
"dev-some-adhoc-bar",
"dev-some-adhoc-foo"
);
}

@Test
void parseYamlWithList() throws Exception {
//Note: the LoggerNameProvider implementation relies on this behavior
Expand All @@ -64,7 +95,7 @@ void parseYamlWithList() throws Exception {
}

@Test
void parseYaml() throws Exception {
void parseYml() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application.yml",
"from-yaml:\n" +
Expand All @@ -81,6 +112,24 @@ void parseYaml() throws Exception {
);
}

@Test
void parseYaml() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application.yaml",
"from-yaml:\n" +
" adhoc:\n" +
" foo: somefoo\n" +
" bar: somebar\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);

assertProperties(indexer.getIndex(project),
//alphabetic order
"from-yaml.adhoc.bar",
"from-yaml.adhoc.foo"
);
}

@Test
void respondsToClasspathChanges() throws Exception {
MockProject project = projects.create("test-project");
Expand Down

0 comments on commit 7fa81e8

Please sign in to comment.