Fix error message in CA on services when not logged in
This commit is contained in:
@@ -24,7 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
/**
|
||||
* Provides existing Cloud Foundry client params, like target and credentials,
|
||||
* from the CLI config.json in the file system.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
@@ -39,7 +39,7 @@ public class CfCliParamsProvider implements ClientParamsProvider {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.
|
||||
* ClientParamsProvider#getParams()
|
||||
*/
|
||||
|
||||
@@ -30,5 +30,6 @@ public interface ICompletionProposal {
|
||||
|
||||
String getDetail();
|
||||
Renderable getDocumentation();
|
||||
default String getFilterText() { return getLabel(); }
|
||||
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
|
||||
item.setLabel(completion.getLabel());
|
||||
item.setKind(completion.getKind());
|
||||
item.setSortText(sortkeys.next());
|
||||
item.setFilterText(completion.getLabel());
|
||||
item.setFilterText(completion.getFilterText());
|
||||
item.setDetail(completion.getDetail());
|
||||
item.setDocumentation(toMarkdown(completion.getDocumentation()));
|
||||
adaptEdits(item, doc, completion.getTextEdit());
|
||||
|
||||
@@ -24,16 +24,13 @@ public interface CompletionFactory {
|
||||
|
||||
ICompletionProposal beanProperty(IDocument doc, String contextProperty, YType contextType, String query, YTypedProperty p, double score, DocumentEdits edits, YTypeUtil typeUtil);
|
||||
ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a completion with an EMPTY value and a display message indicating some error condition. The purpose of this is
|
||||
* to show the user a completion with some meaningful information on why completion values were not fetched.
|
||||
*
|
||||
* @param message the error message to display to the user in the completion
|
||||
* @param query
|
||||
* @param type
|
||||
* @param edits
|
||||
* @return non-null proposal
|
||||
* Create a fake completion proposal that represents an error message. Such a proposal, when applied does nothing. Its main purpose is to
|
||||
* show a (possibly lengthy) error message to the user.
|
||||
* <p>
|
||||
* If the error message is long you can include a ": " to divide the string into a 'short message' and a longer explanation. The longer explanation
|
||||
* will be chopped-off from the message and displayed as a 'doc string'.
|
||||
*/
|
||||
ICompletionProposal errorMessage(String message, String query, YType type, DocumentEdits edits, YTypeUtil typeUtil);
|
||||
ICompletionProposal errorMessage(String query, String message);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Document
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyInfoTemplates;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
@@ -23,7 +24,7 @@ import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
|
||||
|
||||
public class DefaultCompletionFactory implements CompletionFactory {
|
||||
|
||||
|
||||
private static final int ERROR_COMPLETION_SCORE = -10000000;
|
||||
|
||||
public static class BeanPropertyProposal extends ScoreableProposal {
|
||||
@@ -48,7 +49,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
this.edits = edits;
|
||||
this.typeUtil = typeUtil;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getBaseScore() {
|
||||
return baseScore;
|
||||
@@ -79,7 +80,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
return YPropertyInfoTemplates.createCompletionDocumentation(contextProperty, contextType, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ValueProposal extends ScoreableProposal {
|
||||
|
||||
private String value;
|
||||
@@ -119,7 +120,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
public DocumentEdits getTextEdit() {
|
||||
return edits;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ValueProposal("+value+")";
|
||||
@@ -135,38 +136,42 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ErrorProposal extends ScoreableProposal {
|
||||
private final String label;
|
||||
private DocumentEdits edits;
|
||||
private YTypeUtil typeUtil;
|
||||
private YType type;
|
||||
|
||||
public ErrorProposal(String label, YType type, DocumentEdits edits, YTypeUtil typeUtil) {
|
||||
this.label = label;
|
||||
this.edits = edits;
|
||||
this.typeUtil = typeUtil;
|
||||
this.type = type;
|
||||
public static final class ErrorProposal extends ScoreableProposal {
|
||||
private final String longMessage;
|
||||
private String shortMessage;
|
||||
private String filterText;
|
||||
|
||||
public ErrorProposal(String query, String longMessage) {
|
||||
this.filterText = query;
|
||||
int split = longMessage.indexOf(": ");
|
||||
if (split>0) {
|
||||
this.shortMessage = longMessage.substring(0, split);
|
||||
this.longMessage = longMessage.substring(split+2);
|
||||
} else {
|
||||
this.longMessage = longMessage;
|
||||
this.shortMessage = longMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentEdits getTextEdit() {
|
||||
return edits;
|
||||
return new DocumentEdits(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
return shortMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionItemKind getKind() {
|
||||
return CompletionItemKind.Value;
|
||||
return CompletionItemKind.Text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
return null;
|
||||
return Renderables.text(longMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -181,7 +186,12 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
return typeUtil.niceTypeName(type);
|
||||
return "Error";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterText() {
|
||||
return filterText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,8 +206,7 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICompletionProposal errorMessage(String message, String query, YType type, DocumentEdits edits, YTypeUtil typeUtil) {
|
||||
final String label = message;
|
||||
return new ErrorProposal(label, type, edits, typeUtil);
|
||||
public ICompletionProposal errorMessage(String query, String longMessage) {
|
||||
return new ErrorProposal(query, longMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,8 +158,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
try {
|
||||
values = typeUtil.getHintValues(type, getSchemaContext());
|
||||
} catch (Exception e) {
|
||||
DocumentEdits edits = new DocumentEdits(doc.getDocument());
|
||||
return ImmutableList.of(completionFactory().errorMessage(getMessage(e), query, type, edits, typeUtil));
|
||||
return ImmutableList.of(completionFactory().errorMessage(query, getMessage(e)));
|
||||
}
|
||||
if (values!=null) {
|
||||
ArrayList<ICompletionProposal> completions = new ArrayList<>();
|
||||
|
||||
@@ -444,7 +444,7 @@ public class Editor {
|
||||
assertEquals(expectedHover, hover.getContents().toString());
|
||||
}
|
||||
|
||||
public void assertCompletionDetails(String expectLabel, String expectDetail, String expectDocSnippet) throws Exception {
|
||||
public CompletionItem assertCompletionDetails(String expectLabel, String expectDetail, String expectDocSnippet) throws Exception {
|
||||
CompletionItem it = harness.resolveCompletionItem(assertCompletionWithLabel(expectLabel));
|
||||
if (expectDetail!=null) {
|
||||
assertEquals(expectDetail, it.getDetail());
|
||||
@@ -452,6 +452,7 @@ public class Editor {
|
||||
if (expectDocSnippet!=null) {
|
||||
assertContains(expectDocSnippet, it.getDocumentation());
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
protected CompletionItem assertCompletionWithLabel(String expectLabel) throws Exception {
|
||||
|
||||
@@ -11,8 +11,11 @@
|
||||
|
||||
package org.springframework.ide.vscode.languageserver.testharness;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class TestAsserts {
|
||||
|
||||
public static void assertContains(String needle, String haystack) {
|
||||
@@ -26,4 +29,14 @@ public class TestAsserts {
|
||||
fail("Found: "+needle+"\n in \n"+haystack);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T assertOneElement(Collection<T> collection) {
|
||||
assertEquals("Wrong number of elements in "+ collection, 1, collection.size());
|
||||
for (T t : collection) {
|
||||
return t;
|
||||
}
|
||||
throw new AssertionError("No elements found");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
|
||||
@Override
|
||||
public Collection<YValueHint> call() throws Exception {
|
||||
|
||||
|
||||
try {
|
||||
List<CFTarget> targets = targetCache.getOrCreate();
|
||||
|
||||
|
||||
// Do NOT wrap the results in another list. Allow null values to return
|
||||
// as the reconcile framework expects null if hints failed to be resolved
|
||||
return getHints(targets);
|
||||
@@ -59,7 +59,7 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
// Do not log the no-targets exception as it may be encountered
|
||||
// frequently
|
||||
// if a user does not have a CF client installed
|
||||
throw new ValueParseException(ExceptionUtil.getMessageNoAppendedInformation(noTargetsError));
|
||||
throw new ValueParseException("No Cloudfoundry Targets: "+ExceptionUtil.getMessageNoAppendedInformation(noTargetsError));
|
||||
} else {
|
||||
// Log any other error
|
||||
logger.log(Level.SEVERE, ExceptionUtil.getMessage(e), e);
|
||||
@@ -77,7 +77,7 @@ public abstract class AbstractCFHintsProvider implements Callable<Collection<YVa
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return non-null list of hints. Return empty if no hints available
|
||||
*/
|
||||
abstract protected Collection<YValueHint> getHints(List<CFTarget> targets) throws Exception;
|
||||
|
||||
@@ -15,7 +15,9 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItem;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.DiagnosticSeverity;
|
||||
import org.junit.Before;
|
||||
@@ -27,9 +29,13 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFCredentials;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
|
||||
import org.springframework.ide.vscode.commons.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.Editor;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class ManifestYamlEditorTest {
|
||||
@@ -844,6 +850,57 @@ public class ManifestYamlEditorTest {
|
||||
assertEquals(DiagnosticSeverity.Warning, problem.getSeverity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servicesContentAssistShowErrorMessageWhenNotLoggedIn() throws Exception {
|
||||
reset(cloudfoundry.paramsProvider);
|
||||
|
||||
String exceptionMessage = "Please login to cf";
|
||||
|
||||
when(cloudfoundry.paramsProvider.getParams()).thenThrow(new NoTargetsException(exceptionMessage));
|
||||
|
||||
String textBefore =
|
||||
"applications:\n" +
|
||||
"- name: foo\n" +
|
||||
" services:\n" +
|
||||
" - <*>";
|
||||
Editor editor = harness.newEditor(
|
||||
textBefore
|
||||
);
|
||||
|
||||
//Applying the single completion should do nothing in the editor:
|
||||
editor.assertCompletions(textBefore);
|
||||
|
||||
//The message from the exception should appear in the 'doc string':
|
||||
editor.assertCompletionDetails("No Cloudfoundry Targets", "Error", exceptionMessage);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servicesContentAssistShowErrorMessageWhenNotLoggedIn_nonEmptyQueryString() throws Exception {
|
||||
reset(cloudfoundry.paramsProvider);
|
||||
|
||||
String exceptionMessage = "Please login to cf";
|
||||
|
||||
when(cloudfoundry.paramsProvider.getParams()).thenThrow(new NoTargetsException(exceptionMessage));
|
||||
|
||||
String textBefore =
|
||||
"applications:\n" +
|
||||
"- name: foo\n" +
|
||||
" services:\n" +
|
||||
" - something<*>";
|
||||
Editor editor = harness.newEditor(
|
||||
textBefore
|
||||
);
|
||||
|
||||
//Applying the single completion should do nothing in the editor:
|
||||
editor.assertCompletions(textBefore);
|
||||
|
||||
//The message from the exception should appear in the 'doc string':
|
||||
CompletionItem completion = editor.assertCompletionDetails("No Cloudfoundry Targets", "Error", exceptionMessage);
|
||||
//query string should match the 'filter text' otherwise vscode will filter the item and it will be gone!
|
||||
assertEquals("something", completion.getFilterText());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void assertCompletions(String textBefore, String... textAfter) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user