diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java index b1834517c..07786aaa9 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/ast/YamlParser.java @@ -11,6 +11,10 @@ package org.springframework.ide.vscode.commons.yaml.ast; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.text.IDocument; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.nodes.Node; @@ -27,9 +31,64 @@ public class YamlParser implements YamlASTProvider { @Override public YamlFileAST getAST(IDocument doc) throws Exception { CharSequenceReader reader = new CharSequenceReader(); - reader.setInput(doc.get()); + reader.setInput(atTokenTransformHack(doc.get())); Iterable nodes = new Yaml().composeAll(reader); return new YamlFileAST(doc, ImmutableList.copyOf(nodes)); } + Pattern AT_TOKEN = Pattern.compile("^.*?(\\@[a-zA-z0-9_\\-\\.]*\\@).*?$", Pattern.MULTILINE); + + static class StringCopier { + private int offset = 0; + private String input; + private StringBuilder output; + + public StringCopier(String input) { + this.input = input; + this.output = new StringBuilder(); + } + + public void copyUpto(int upto) { + if (upto>offset) { + output.append(input.substring(offset, upto)); + offset = upto; + } + } + + public void replace(int len) { + if (len>=3) { + offset+=len; + len-=2; + output.append('"'); + for (int i = 0; i < len; i++) { + output.append('@'); + } + output.append('"'); + } else { + copyUpto(offset+len); + } + } + } + + private CharSequence atTokenTransformHack(String input) { + Matcher matcher = AT_TOKEN.matcher(input); + StringCopier transformed = new StringCopier(input); + while (matcher.find()) { + int lineStart = matcher.start(); + + int tokenStart = matcher.start(1); + int tokenEnd = matcher.end(1); + + String pre = input.substring(lineStart, tokenStart); + if (!pre.contains("\"")) { + transformed.copyUpto(tokenStart); + transformed.replace(tokenEnd-tokenStart); + } + } + transformed.copyUpto(input.length()); + String out = transformed.output.toString(); + Assert.isTrue(out.length()==input.length()); + return out; + } + } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java index 846014033..ba41d8d22 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java @@ -90,6 +90,23 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest { //////////////////////////////////////////////////////////////////////////////////////// + @Test public void GH_190_tolerate_placeholders_without_quotes() throws Exception { + //See: https://github.com/spring-projects/sts4/issues/190 + data("info.build", "java.util.Map", null, null); + Editor editor = harness.newEditor( + "info:\n" + + " build:\n" + + " artifact: @project.artifactId@\n" + + " name: @project.name@\n" + + " description: @project.description@\n" + + " version: @project.version@\n" + + "bad: problem" + ); + editor.assertProblems( + "bad|Unknown" + ); + } + @Test public void GH_449_inheritedPropertiesInListValues() throws Exception { //See: https://github.com/spring-projects/sts4/issues/449 MavenJavaProject p = createPredefinedMavenProject("gh_449");