Skip to content

Commit d43a932

Browse files
committed
GH-1650: parse yml property files as well when scanning for web config information
1 parent a4e0f05 commit d43a932

File tree

3 files changed

+97
-5
lines changed

3 files changed

+97
-5
lines changed

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebConfigCodeLensProvider.java

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
package org.springframework.ide.vscode.boot.java.requestmapping;
1212

1313
import java.io.File;
14+
import java.io.FileInputStream;
1415
import java.io.IOException;
16+
import java.io.InputStreamReader;
17+
import java.io.Reader;
1518
import java.nio.charset.Charset;
1619
import java.nio.file.Path;
20+
import java.util.ArrayList;
1721
import java.util.HashMap;
1822
import java.util.List;
1923
import java.util.Map;
@@ -48,9 +52,18 @@
4852
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
4953
import org.springframework.ide.vscode.commons.util.BadLocationException;
5054
import org.springframework.ide.vscode.commons.util.text.TextDocument;
55+
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
5156
import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
5257
import org.springframework.ide.vscode.java.properties.parser.ParseResults;
5358
import org.springframework.ide.vscode.java.properties.parser.Parser;
59+
import org.yaml.snakeyaml.LoaderOptions;
60+
import org.yaml.snakeyaml.Yaml;
61+
import org.yaml.snakeyaml.constructor.SafeConstructor;
62+
import org.yaml.snakeyaml.nodes.MappingNode;
63+
import org.yaml.snakeyaml.nodes.Node;
64+
import org.yaml.snakeyaml.nodes.NodeTuple;
65+
import org.yaml.snakeyaml.nodes.ScalarNode;
66+
import org.yaml.snakeyaml.nodes.SequenceNode;
5467

5568
public class WebConfigCodeLensProvider implements CodeLensProvider {
5669

@@ -215,9 +228,63 @@ private Stream<PropertyKeyValue> getPropertiesFromPropertiesFile(File file) {
215228
}
216229

217230
private Stream<PropertyKeyValue> getPropertiesFromYamlFile(File file) {
231+
if (file.isFile()) {
232+
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
233+
234+
try (Reader reader = new InputStreamReader(new FileInputStream(file), "UTF8")) {
235+
236+
List<PropertyKeyValue> result = new ArrayList<>();
237+
for (Node node : yaml.composeAll(reader)) {
238+
flattenProperties("", node, result);
239+
}
240+
241+
return result.stream();
242+
} catch (Exception e ) {
243+
//ignore failed attempt to read bad file
244+
}
245+
}
218246
return Stream.empty();
247+
}
248+
249+
private void flattenProperties(String prefix, Node node, List<PropertyKeyValue> props) {
250+
switch (node.getNodeId()) {
219251

220-
// TODO !!!
252+
case mapping:
253+
if (!prefix.isEmpty()) {
254+
prefix = prefix + ".";
255+
}
256+
MappingNode mapping = (MappingNode)node;
257+
for (NodeTuple tup : mapping.getValue()) {
258+
String key = NodeUtil.asScalar(tup.getKeyNode());
259+
if (key != null) {
260+
flattenProperties(prefix + key, tup.getValueNode(), props);
261+
}
262+
}
263+
break;
264+
265+
case scalar:
266+
//End of the line.
267+
props.add(new PropertyKeyValue(prefix, NodeUtil.asScalar(node)));
268+
break;
269+
270+
case sequence:
271+
SequenceNode sequenceNode = (SequenceNode) node;
272+
List<String> values = sequenceNode.getValue().stream()
273+
.filter(valueNode -> valueNode instanceof ScalarNode)
274+
.map(scalarNode -> NodeUtil.asScalar(scalarNode))
275+
.toList();
276+
277+
props.add(new PropertyKeyValue(prefix, String.join(", ", values)));
278+
279+
break;
280+
281+
default:
282+
if (!prefix.isEmpty()) {
283+
props.add(new PropertyKeyValue(prefix, "<object>"));
284+
}
285+
286+
break;
287+
}
221288
}
222289

223290
record PropertyKeyValue (String key, String value) {}

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/WebConfigCodeLensProviderTest.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.requestmapping.test;
1212

13-
import static org.junit.Assert.assertEquals;
1413
import static org.junit.Assert.assertTrue;
1514

1615
import java.nio.charset.StandardCharsets;
@@ -71,18 +70,35 @@ public void setup() throws Exception {
7170
}
7271

7372
@Test
74-
void codeLensOverMethod() throws Exception {
73+
void codeLensOverMethodFromWebConfig() throws Exception {
7574
Path filePath = Paths.get(testProject.getLocationUri())
7675
.resolve("src/main/java/org/test/versions/MappingClassWithMultipleVersions.java");
7776
Editor editor = harness.newEditor(LanguageId.JAVA, new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8), filePath.toUri().toASCIIString());
7877

7978
List<CodeLens> cls = editor.getCodeLenses("MappingClassWithMultipleVersions", 1);
80-
assertEquals(2, cls.size());
81-
8279
assertTrue(contains(cls, "Web Config - Path Prefix: /{version} - Versioning via Request Header: X-API-Version, Path Segment: 0 - Supported Versions: 1.1, 1.2"));
80+
}
81+
82+
@Test
83+
void codeLensOverMethodFromProperties() throws Exception {
84+
Path filePath = Paths.get(testProject.getLocationUri())
85+
.resolve("src/main/java/org/test/versions/MappingClassWithMultipleVersions.java");
86+
Editor editor = harness.newEditor(LanguageId.JAVA, new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8), filePath.toUri().toASCIIString());
87+
88+
List<CodeLens> cls = editor.getCodeLenses("MappingClassWithMultipleVersions", 1);
8389
assertTrue(contains(cls, "Properties Config - Versioning via Request Header: X-API-Version - Supported Versions: 1"));
8490
}
8591

92+
@Test
93+
void codeLensOverMethodFromPropertiesYaml() throws Exception {
94+
Path filePath = Paths.get(testProject.getLocationUri())
95+
.resolve("src/main/java/org/test/versions/MappingClassWithMultipleVersions.java");
96+
Editor editor = harness.newEditor(LanguageId.JAVA, new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8), filePath.toUri().toASCIIString());
97+
98+
List<CodeLens> cls = editor.getCodeLenses("MappingClassWithMultipleVersions", 1);
99+
assertTrue(contains(cls, "Properties Config - Versioning via Path Segment: 3, Request Header: X-API-HEADER-VIA-YML - Supported Versions: 2, 3"));
100+
}
101+
86102
private boolean contains(List<CodeLens> cls, String title) {
87103
return cls.stream().filter(cl -> cl.getCommand().getTitle().equals(title)).findAny().isPresent();
88104
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
spring:
2+
mvc:
3+
apiversion:
4+
use:
5+
path-segment: 3
6+
header: X-API-HEADER-VIA-YML
7+
supported:
8+
- 2
9+
- 3

0 commit comments

Comments
 (0)