diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/quickfix/QuickfixResolveParams.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/quickfix/QuickfixResolveParams.java
index 10ef8711f..b0ede4654 100644
--- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/quickfix/QuickfixResolveParams.java
+++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/quickfix/QuickfixResolveParams.java
@@ -16,6 +16,15 @@ public class QuickfixResolveParams {
private Object params;
+ public QuickfixResolveParams(String type, Object params) {
+ super();
+ this.type = type;
+ this.params = params;
+ }
+
+ public QuickfixResolveParams() {
+ }
+
public String getType() {
return type;
}
diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/CollectionUtil.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/CollectionUtil.java
index c9137ec50..6266d2199 100644
--- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/CollectionUtil.java
+++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/CollectionUtil.java
@@ -18,6 +18,21 @@ import java.util.Collection;
*/
public class CollectionUtil {
+ /**
+ * Get some element of the collection (will be the first one
+ * found by its iterator, or null if the collection is empty).
+ *
+ * Note that unless the collection is ordered, or has at most
+ * one element, then it may be unpredictable which element
+ * you will get.
+ */
+ public static E getAny(Collection elements) {
+ for (E e : elements) {
+ return e;
+ }
+ return null;
+ }
+
public static boolean hasElements(Collection c) {
return c!=null && !c.isEmpty();
}
diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/YamlSchemaProblems.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/YamlSchemaProblems.java
index 3e719e77c..1ecd8979e 100644
--- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/YamlSchemaProblems.java
+++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/reconcile/YamlSchemaProblems.java
@@ -22,6 +22,7 @@ import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemTy
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
+import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
@@ -140,6 +141,9 @@ public class YamlSchemaProblems {
.map(YamlPathSegment::encode)
.collect(Collectors.toList());
+ String fixTitle = missingProps.size()==1
+ ? "Add property '"+CollectionUtil.getAny(missingProps)+"'"
+ : "Add properties: "+missingProps;
QuickfixData fix = new QuickfixData(
quickfixType,
new MissingPropertiesData(
@@ -147,7 +151,7 @@ public class YamlSchemaProblems {
segments,
ImmutableList.copyOf(missingProps)
),
- "Add properties: "+missingProps
+ fixTitle
);
return missingProperty(msg, dc.getDocument(), parent, map)
diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/CodeAction.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/CodeAction.java
new file mode 100644
index 000000000..2ca1f2483
--- /dev/null
+++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/CodeAction.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.languageserver.testharness;
+
+import org.eclipse.lsp4j.Command;
+
+/**
+ * Wrapper for the test harness to refer to and manipulate a
+ * CodeAction.
+ */
+public class CodeAction {
+
+ private final Command command;
+ private LanguageServerHarness harness;
+
+ public CodeAction(LanguageServerHarness harness, Command command) {
+ super();
+ this.harness = harness;
+
+ this.command = command;
+ }
+
+ @Override
+ public String toString() {
+ return command.toString();
+ }
+
+ public String getLabel() {
+ return command.getTitle();
+ }
+
+ public void perform() throws Exception {
+ harness.perform(command);
+ }
+
+}
diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java
index a50bbe0db..78edaad4b 100644
--- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java
+++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/Editor.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import javax.swing.text.BadLocationException;
@@ -42,6 +43,7 @@ import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.junit.Assert;
+import org.springframework.ide.vscode.commons.util.CollectionUtil;
import com.google.common.collect.ImmutableList;
@@ -627,4 +629,22 @@ public class Editor {
return languageId;
}
+ public List getCodeActions(Diagnostic problem) throws Exception {
+ return harness.getCodeActions(document, problem);
+ }
+
+ public CodeAction assertCodeAction(Diagnostic problem) throws Exception {
+ List actions = getCodeActions(problem);
+ assertEquals("Number of codeActions", 1, actions.size());
+ return actions.get(0);
+ }
+
+ public String getUri() {
+ return document.getUri();
+ }
+
+ public void assertRawText(String expectedText) throws Exception {
+ assertEquals(expectedText, getRawText());
+ }
+
}
diff --git a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
index 71afd265f..302c1055c 100644
--- a/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
+++ b/headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java
@@ -18,17 +18,23 @@ import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.assertj.core.api.Condition;
import org.eclipse.lsp4j.ClientCapabilities;
+import org.eclipse.lsp4j.CodeActionContext;
+import org.eclipse.lsp4j.CodeActionParams;
+import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.Diagnostic;
@@ -50,13 +56,25 @@ import org.eclipse.lsp4j.TextDocumentItem;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.eclipse.lsp4j.TextDocumentSyncOptions;
+import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
+import org.eclipse.lsp4j.WorkspaceEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageClientAware;
import org.springframework.ide.vscode.commons.languageserver.LanguageIds;
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
+import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
+import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits.TextReplace;
+import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixResolveParams;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
+import org.springframework.ide.vscode.commons.util.Assert;
+import org.springframework.ide.vscode.commons.util.text.IDocument;
+import org.springframework.ide.vscode.commons.util.text.IRegion;
+import org.springframework.ide.vscode.commons.util.text.TextDocument;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
public class LanguageServerHarness {
@@ -73,6 +91,7 @@ public class LanguageServerHarness {
private Map documents = new HashMap<>();
private Map diagnostics = new HashMap<>();
+ private List activeEditors = new ArrayList<>();
public LanguageServerHarness(Callable extends SimpleLanguageServer> factory, String defaultLanguageId) {
@@ -340,11 +359,13 @@ public class LanguageServerHarness {
}
public Editor newEditor(String contents) throws Exception {
- return new Editor(this, contents, getDefaultLanguageId());
+ return newEditor(getDefaultLanguageId(), contents);
}
- public Editor newEditor(String languageId, String contents) throws Exception {
- return new Editor(this, contents, languageId);
+ public synchronized Editor newEditor(String languageId, String contents) throws Exception {
+ Editor editor = new Editor(this, contents, languageId);
+ activeEditors.add(editor);
+ return editor;
}
public synchronized TextDocumentInfo createWorkingCopy(String contents, String languageId) throws Exception {
@@ -406,4 +427,71 @@ public class LanguageServerHarness {
return server.getTextDocumentService().definition(params).get();
}
+ public List getCodeActions(TextDocumentInfo doc, Diagnostic problem) throws Exception {
+ CodeActionContext context = new CodeActionContext(ImmutableList.of(problem));
+ List extends Command> actions =
+ server.getTextDocumentService().codeAction(new CodeActionParams(doc.getId(), problem.getRange(), context)).get();
+ return actions.stream()
+ .map((command) -> new CodeAction(this, command))
+ .collect(Collectors.toList());
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ public void perform(Command command) throws Exception {
+ switch (command.getCommand()) {
+ case "sts.quickfix":
+ List