Quick Fix for unknown properties in application.yml

See https://github.com/spring-projects/sts4/issues/442
This commit is contained in:
Kris De Volder
2020-04-06 17:18:00 -07:00
parent 99a33547c4
commit 3d4c72318c
3 changed files with 81 additions and 3 deletions

View File

@@ -813,6 +813,19 @@ public class Editor {
assertEquals(expectLabel, ca.getLabel());
return ca;
}
public void assertQuickfixes(Diagnostic problem, String... expectedLabels) throws Exception {
List<CodeAction> actions = getCodeActions(problem);
StringBuilder expecteds = new StringBuilder();
for (String l : expectedLabels) {
expecteds.append(l+"\n");
}
StringBuilder actuals = new StringBuilder();
for (CodeAction a : actions) {
actuals.append(a.getLabel()+"\n");
}
assertEquals(expecteds.toString(), actuals.toString());
}
public void assertText(String expected) {
assertEquals(expected, getText());
@@ -966,4 +979,5 @@ public class Editor {
this.selectionStart = this.selectionEnd = doc.toOffset(position);
}
}

View File

@@ -17,6 +17,7 @@ import static org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYaml
import static org.springframework.ide.vscode.commons.yaml.ast.NodeUtil.asScalar;
import static org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST.getChildren;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -55,6 +56,7 @@ import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.Kind;
import org.springframework.ide.vscode.commons.yaml.ast.NodeRef.TupleValueRef;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlASTReconciler;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
@@ -353,9 +355,11 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
if (fixType != null) {
switch (fixType.getId()) {
case CommonQuickfixes.MISSING_PROPERTY_APP_QF_ID:
p.addQuickfix(new QuickfixData<>(fixType,
new MissingPropertyData(new TextDocumentIdentifier(docUri), name),
"Create metadata for `" + name +"`"));
for (String missingProp : getUnknownProperties(name, entry.getValueNode(), new ArrayList<>())) {
p.addQuickfix(new QuickfixData<>(fixType,
new MissingPropertyData(new TextDocumentIdentifier(docUri), name),
"Create metadata for `" + missingProp +"`"));
}
break;
}
}
@@ -364,6 +368,22 @@ public class ApplicationYamlASTReconciler implements YamlASTReconciler {
problems.accept(p);
}
private List<String> getUnknownProperties(String name, Node valueNode, List<String> unknownProps) {
if (valueNode instanceof MappingNode) {
MappingNode map = (MappingNode) valueNode;
for (NodeTuple entry : map.getValue()) {
String key = NodeUtil.asScalar(entry.getKeyNode());
if (key!=null) {
key = StringUtil.camelCaseToHyphens(key);
getUnknownProperties(name+"."+key, entry.getValueNode(), unknownProps);
}
}
} else {
unknownProps.add(name);
}
return unknownProps;
}
private String extendForQuickfix(String name, Node node) {
if (node!=null) {
TupleValueRef child = getFirstTupleValue(getChildren(node));

View File

@@ -3020,6 +3020,50 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
assertCompletionDetailsWithDeprecation("foo:\n nam<*>", "alt-name", "String", null, Boolean.TRUE);
}
@Test public void missingPropertyQuickfix() throws Exception {
IJavaProject p = createPredefinedMavenProject("empty-boot-2.1.0-app");
useProject(p);
{
Editor editor = newEditor(
"myapp:\n" +
" orders:\n" +
" pages: 10"
);
Diagnostic problem = editor.assertProblems("myapp|Unknown").get(0);
editor.assertQuickfixes(problem, "Create metadata for `myapp.orders.pages`");
}
{
Editor editor = newEditor(
"myapp:\n" +
" orders:\n" +
" pageSize: 10"
);
Diagnostic problem = editor.assertProblems("myapp|Unknown").get(0);
editor.assertQuickfixes(problem, "Create metadata for `myapp.orders.page-size`");
}
{
Editor editor = newEditor(
"myapp:\n" +
" orders:\n" +
" pageSize: 10\n" +
" start: 0\n"
);
Diagnostic problem = editor.assertProblems("myapp|Unknown").get(0);
editor.assertQuickfixes(problem,
"Create metadata for `myapp.orders.page-size`",
"Create metadata for `myapp.orders.start`"
);
}
//TODO: a test case that verifies codeAction.perform has expected result.
// Carefull though, if you do add this you must make sure to cleanup any side-effects the quickfix does
// to files in the project.
}
@Test public void testDeprecatedPropertyQuickfixSimple() throws Exception {
//A simple case for starters. The path edits aren't too complicated since there's
//just the one property in the file and only the last part of the 'path' changes.