From 2cdf0af492286fc3737bac098d96283197b5e411 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Mon, 24 Apr 2017 17:15:09 -0700 Subject: [PATCH] Add target description to domains CA hints --- .../client/cftarget/CFTarget.java | 11 ++- .../yaml/completion/CompletionFactory.java | 11 ++- .../completion/DefaultCompletionFactory.java | 25 +++--- .../yaml/completion/YTypeAssistContext.java | 6 +- .../commons/yaml/schema/BasicYValueHint.java | 12 +++ .../commons/yaml/schema/YValueHint.java | 8 ++ .../languageserver/testharness/Editor.java | 6 +- .../yaml/ManifestYamlCFDomainsProvider.java | 4 +- .../manifest/yaml/ManifestYmlSchema.java | 15 ++-- .../manifest/yaml/ManifestYamlEditorTest.java | 80 +++++-------------- .../manifest/yaml/MockCloudfoundry.java | 2 +- 11 files changed, 91 insertions(+), 89 deletions(-) diff --git a/headless-services/commons/commons-cf/src/main/java/org/springframework/ide/vscode/commons/cloudfoundry/client/cftarget/CFTarget.java b/headless-services/commons/commons-cf/src/main/java/org/springframework/ide/vscode/commons/cloudfoundry/client/cftarget/CFTarget.java index f2087ddf4..c53a2feee 100644 --- a/headless-services/commons/commons-cf/src/main/java/org/springframework/ide/vscode/commons/cloudfoundry/client/cftarget/CFTarget.java +++ b/headless-services/commons/commons-cf/src/main/java/org/springframework/ide/vscode/commons/cloudfoundry/client/cftarget/CFTarget.java @@ -24,7 +24,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; /** - * + * * Wrapper around a {@link ClientRequests} that may contain cached information * like buildpacks * @@ -115,12 +115,12 @@ public class CFTarget { public List getServices() throws Exception { /* services don't use keys, as they get wiped clean on each refresh * . That said, the cache doesn't allow a null key, so use the target name as the "key" - * + * */ String key = getName(); return this.servicesCache.get(key); } - + public List getDomains() throws Exception { String key = getName(); return this.domainCache.get(key); @@ -138,4 +138,9 @@ public class CFTarget { public String toString() { return "CFClientTarget [params=" + params + ", targetName=" + targetName + "]"; } + + public String getLabel() { +// %o : %s - [%a] + return params.getOrgName() + " : " + params.getSpaceName() + " ["+params.getApiUrl()+"]"; + } } diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/CompletionFactory.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/CompletionFactory.java index 7979aac84..c8326d17b 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/CompletionFactory.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/CompletionFactory.java @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.commons.yaml.completion; import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits; import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal; +import org.springframework.ide.vscode.commons.util.Renderable; import org.springframework.ide.vscode.commons.util.text.IDocument; import org.springframework.ide.vscode.commons.yaml.schema.YType; import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil; @@ -22,8 +23,14 @@ public interface CompletionFactory { CompletionFactory DEFAULT = new DefaultCompletionFactory(); - 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); + 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, Renderable doc, + double score, DocumentEdits edits, YTypeUtil typeUtil + ); /** * Create a fake completion proposal that represents an error message. Such a proposal, when applied does nothing. Its main purpose is to diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/DefaultCompletionFactory.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/DefaultCompletionFactory.java index edbd158ee..aa494b63e 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/DefaultCompletionFactory.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/DefaultCompletionFactory.java @@ -29,10 +29,10 @@ public class DefaultCompletionFactory implements CompletionFactory { public static class BeanPropertyProposal extends ScoreableProposal { - private IDocument doc; +// private IDocument doc; private String contextProperty; private YType contextType; - private String query; +// private String query; private YTypedProperty p; private double baseScore; private DocumentEdits edits; @@ -40,10 +40,10 @@ public class DefaultCompletionFactory implements CompletionFactory { public BeanPropertyProposal(IDocument doc, String contextProperty, YType contextType, String query, YTypedProperty p, double score, DocumentEdits edits, YTypeUtil typeUtil) { super(); - this.doc = doc; + // this.doc = doc; this.contextProperty = contextProperty; this.contextType = contextType; - this.query = query; + // this.query = query; this.p = p; this.baseScore = score; this.edits = edits; @@ -84,18 +84,20 @@ public class DefaultCompletionFactory implements CompletionFactory { public class ValueProposal extends ScoreableProposal { private String value; - private String query; + //private String query; private String label; private YType type; private double baseScore; private DocumentEdits edits; private YTypeUtil typeUtil; + private Renderable docs; - public ValueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil) { + public ValueProposal(String value, String query, String label, YType type, Renderable docs, double score, DocumentEdits edits, YTypeUtil typeUtil) { this.value = value; - this.query = query; + //this.query = query; this.label = label; this.type = type; + this.docs = docs; this.baseScore = score; this.edits = edits; this.typeUtil = typeUtil; @@ -133,7 +135,7 @@ public class DefaultCompletionFactory implements CompletionFactory { @Override public Renderable getDocumentation() { - return null; + return docs; } } @@ -201,8 +203,11 @@ public class DefaultCompletionFactory implements CompletionFactory { } @Override - public ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil) { - return new ValueProposal(value, query, label, type, score, edits, typeUtil); + public ICompletionProposal valueProposal( + String value, String query, String label, YType type, Renderable doc, + double score, DocumentEdits edits, YTypeUtil typeUtil + ) { + return new ValueProposal(value, query, label, type, doc, score, edits, typeUtil); } @Override diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/YTypeAssistContext.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/YTypeAssistContext.java index 6178a67fe..b783c70bc 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/YTypeAssistContext.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/YTypeAssistContext.java @@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits; import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal; import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion; -import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.CollectionUtil; import org.springframework.ide.vscode.commons.util.ExceptionUtil; import org.springframework.ide.vscode.commons.util.FuzzyMatcher; @@ -183,7 +182,10 @@ public class YTypeAssistContext extends AbstractYamlAssistContext { if (extraInsertion!=null) { edits.insert(offset, indenter.applyIndentation(extraInsertion, referenceIndent)); } - completions.add(completionFactory().valueProposal(value.getValue(), query, value.getLabel(), type, score, edits, typeUtil)); + completions.add(completionFactory().valueProposal( + value.getValue(), query, value.getLabel(), type, + value.getDocumentation(), score, edits, typeUtil + )); } } return completions; diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/BasicYValueHint.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/BasicYValueHint.java index 2b06d0e98..5d56460cf 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/BasicYValueHint.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/BasicYValueHint.java @@ -11,6 +11,7 @@ package org.springframework.ide.vscode.commons.yaml.schema; import org.springframework.ide.vscode.commons.util.Assert; +import org.springframework.ide.vscode.commons.util.Renderable; import com.google.common.base.Supplier; @@ -19,6 +20,7 @@ public class BasicYValueHint implements YValueHint { private final String value; private String label; private Supplier extraInsertion = null; + private Renderable documentation; public BasicYValueHint(String value, String label) { this.value = value; @@ -93,4 +95,14 @@ public class BasicYValueHint implements YValueHint { this.extraInsertion = insertions; return this; } + + public BasicYValueHint setDocumentation(Renderable docs) { + this.documentation = docs; + return this; + } + + @Override + public Renderable getDocumentation() { + return documentation; + } } diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YValueHint.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YValueHint.java index d0cf87420..5437e2a2f 100644 --- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YValueHint.java +++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/schema/YValueHint.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.springframework.ide.vscode.commons.yaml.schema; +import org.springframework.ide.vscode.commons.util.Renderable; + public interface YValueHint { String getValue(); String getLabel(); @@ -21,4 +23,10 @@ public interface YValueHint { * the line where the value itself is being inserted. */ String getExtraInsertion(); + + /** + * An optional documentation string (i.e. shown in javadoc side hover in Eclipse style + * or in the line below a completion item in vscode style. + */ + Renderable getDocumentation(); } \ No newline at end of file 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 a92def36f..e6300f907 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 @@ -289,7 +289,7 @@ public class Editor { return Collections.emptyList(); } - public void assertCompletions(String... expectTextAfter) throws Exception { + public List assertCompletions(String... expectTextAfter) throws Exception { StringBuilder expect = new StringBuilder(); StringBuilder actual = new StringBuilder(); for (String after : expectTextAfter) { @@ -297,13 +297,15 @@ public class Editor { expect.append("\n-------------------\n"); } - for (CompletionItem completion : getCompletions()) { + List completions = getCompletions(); + for (CompletionItem completion : completions) { Editor editor = this.clone(); editor.apply(completion); actual.append(editor.getText()); actual.append("\n-------------------\n"); } assertEquals(expect.toString(), actual.toString()); + return completions; } public void assertCompletionLabels(String... expectedLabels) throws Exception { diff --git a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlCFDomainsProvider.java b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlCFDomainsProvider.java index 4617dbcf9..32f9dc326 100644 --- a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlCFDomainsProvider.java +++ b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlCFDomainsProvider.java @@ -17,6 +17,7 @@ import java.util.List; import org.springframework.ide.vscode.commons.cloudfoundry.client.CFDomain; import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget; import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache; +import org.springframework.ide.vscode.commons.util.Renderables; import org.springframework.ide.vscode.commons.yaml.schema.BasicYValueHint; import org.springframework.ide.vscode.commons.yaml.schema.YValueHint; @@ -39,7 +40,8 @@ public class ManifestYamlCFDomainsProvider extends AbstractCFHintsProvider { for (CFDomain domain : domains) { String name = domain.getName(); String label = getLabel(cfTarget, domain); - YValueHint hint = new BasicYValueHint(name, label); + YValueHint hint = new BasicYValueHint(name, label) + .setDocumentation(Renderables.text(cfTarget.getLabel())); if (!hints.contains(hint)) { hints.add(hint); } diff --git a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java index 4bb908d37..70f4277d6 100644 --- a/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java +++ b/headless-services/manifest-yaml-language-server/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYmlSchema.java @@ -71,22 +71,17 @@ public class ManifestYmlSchema implements YamlSchema { } YAtomicType t_domain = f.yatomic("Domain"); - YAtomicType t_domains_string = f.yatomic("Domains"); if (domainsProvider != null) { t_domain.addHintProvider(domainsProvider); - t_domains_string.addHintProvider(domainsProvider); } - YType t_domains = f.yseq(t_domains_string); - - YAtomicType t_service_string = f.yatomic("Service"); + YAtomicType t_service = f.yatomic("Service"); if (servicesProvider != null) { - t_service_string.addHintProvider(servicesProvider); - t_service_string.parseWith(new CFServicesValueParser(t_service_string.toString(), + t_service.addHintProvider(servicesProvider); + t_service.parseWith(new CFServicesValueParser(t_service.toString(), YTypeFactory.valuesFromHintProvider(servicesProvider))); } - YType t_services = f.yseq(t_service_string); YAtomicType t_boolean = f.yenum("boolean", "true", "false"); YAtomicType t_ne_string = f.yatomic("String"); @@ -128,7 +123,7 @@ public class ManifestYmlSchema implements YamlSchema { f.yprop("command", t_string), f.yprop("disk_quota", t_memory), f.yprop("domain", t_domain), - f.yprop("domains", t_domains), + f.yprop("domains", f.yseq(t_domain)), f.yprop("env", t_env), f.yprop("host", t_string), f.yprop("hosts", t_strings), @@ -140,7 +135,7 @@ public class ManifestYmlSchema implements YamlSchema { f.yprop("path", t_path), f.yprop("random-route", t_boolean), f.yprop("routes", f.yseq(route)), - f.yprop("services", t_services), + f.yprop("services", f.yseq(t_service)), f.yprop("stack", t_string), f.yprop("timeout", t_pos_integer), f.yprop("health-check-type", t_health_check_type), diff --git a/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java b/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java index 10dbaf28a..8fd2e9df0 100644 --- a/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java +++ b/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java @@ -17,6 +17,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import java.io.IOException; +import java.util.List; import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.Diagnostic; @@ -985,22 +986,6 @@ public class ManifestYamlEditorTest { assertEquals("something", completion.getFilterText()); } - @Test - public void serviceContentAssistEmptyServices() throws Exception { - ClientRequests cfClient = cloudfoundry.client; - when(cfClient.getServices()).thenReturn(ImmutableList.of()); - assertDoesNotContainCompletions("services:\n" + " - <*>", "mysql"); - } - - @Test - public void serviceContentAssistDoesNotContainServices() throws Exception { - ClientRequests cfClient = cloudfoundry.client; - CFServiceInstance service = Mockito.mock(CFServiceInstance.class); - when(service.getName()).thenReturn("mysql"); - when(cfClient.getServices()).thenReturn(ImmutableList.of(service)); - assertDoesNotContainCompletions("services:\n" + " - <*>", "wrongsql"); - } - @Test public void serviceContentAssist() throws Exception { ClientRequests cfClient = cloudfoundry.client; @@ -1008,7 +993,13 @@ public class ManifestYamlEditorTest { when(service.getName()).thenReturn("mysql"); when(cfClient.getServices()).thenReturn(ImmutableList.of(service)); - assertContainsCompletions("services:\n" + " - <*>", "mysql"); + assertCompletions( + "services:\n" + + " - <*>" + , // ==> + "services:\n" + + " - mysql<*>" + ); } @Test @@ -1018,16 +1009,7 @@ public class ManifestYamlEditorTest { when(buildPack.getName()).thenReturn("java_buildpack"); when(cfClient.getBuildpacks()).thenReturn(ImmutableList.of(buildPack)); - assertContainsCompletions("buildpack: <*>", "buildpack: java_buildpack<*>"); - } - - @Test - public void buildpackContentAssistDoesNotContainCompletion() throws Exception { - ClientRequests cfClient = cloudfoundry.client; - CFBuildpack buildPack = Mockito.mock(CFBuildpack.class); - when(buildPack.getName()).thenReturn("java_buildpack"); - when(cfClient.getBuildpacks()).thenReturn(ImmutableList.of(buildPack)); - assertDoesNotContainCompletions("buildpack: <*>", "buildpack: wrong_buildpack<*>"); + assertCompletions("buildpack: <*>", "buildpack: java_buildpack<*>"); } @Test @@ -1037,35 +1019,27 @@ public class ManifestYamlEditorTest { when(domain.getName()).thenReturn("cfapps.io"); when(cfClient.getDomains()).thenReturn(ImmutableList.of(domain)); - assertContainsCompletions("domain: <*>", "domain: cfapps.io<*>"); - } - - @Test - public void domainContentAssistDoesNotContainCompletion() throws Exception { - ClientRequests cfClient = cloudfoundry.client; - CFDomain domain = Mockito.mock(CFDomain.class); - when(domain.getName()).thenReturn("cfapps.io"); - when(cfClient.getDomains()).thenReturn(ImmutableList.of(domain)); - assertDoesNotContainCompletions("domain: <*>", "domain: wrong.cfapps.io<*>"); + CompletionItem completion = assertCompletions("domain: <*>", "domain: cfapps.io<*>").get(0); + assertEquals("an-org : a-space [test.io]", completion.getDocumentation()); } @Test public void domainsContentAssist() throws Exception { ClientRequests cfClient = cloudfoundry.client; + CFDomain domain = Mockito.mock(CFDomain.class); when(domain.getName()).thenReturn("cfapps.io"); when(cfClient.getDomains()).thenReturn(ImmutableList.of(domain)); - assertContainsCompletions("domains:\n" + " - <*>", "cfapps.io"); - } + CompletionItem completion = assertCompletions( + "domains:\n" + + "- <*>" + , // ===> + "domains:\n" + + "- cfapps.io<*>" + ).get(0); - @Test - public void domainsContentAssistWrongDomain() throws Exception { - ClientRequests cfClient = cloudfoundry.client; - CFDomain domain = Mockito.mock(CFDomain.class); - when(domain.getName()).thenReturn("cfapps.io"); - when(cfClient.getDomains()).thenReturn(ImmutableList.of(domain)); - assertDoesNotContainCompletions("domains:\n" + " - <*>", "wrong.cfapps.io"); + assertEquals("an-org : a-space [test.io]", completion.getDocumentation()); } @Test @@ -1164,19 +1138,9 @@ public class ManifestYamlEditorTest { ////////////////////////////////////////////////////////////////////////////// - private void assertCompletions(String textBefore, String... textAfter) throws Exception { + private List assertCompletions(String textBefore, String... textAfter) throws Exception { Editor editor = harness.newEditor(textBefore); - editor.assertCompletions(textAfter); - } - - private void assertDoesNotContainCompletions(String textBefore, String... notToBeFound) throws Exception { - Editor editor = harness.newEditor(textBefore); - editor.assertDoesNotContainCompletions(notToBeFound); - } - - private void assertContainsCompletions(String textBefore, String... textAfter) throws Exception { - Editor editor = harness.newEditor(textBefore); - editor.assertContainsCompletions(textAfter); + return editor.assertCompletions(textAfter); } } diff --git a/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/MockCloudfoundry.java b/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/MockCloudfoundry.java index cc8f42ff8..f68efccc9 100644 --- a/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/MockCloudfoundry.java +++ b/headless-services/manifest-yaml-language-server/src/test/java/org/springframework/ide/vscode/manifest/yaml/MockCloudfoundry.java @@ -27,7 +27,7 @@ import com.google.common.collect.ImmutableList; public class MockCloudfoundry { public final CFClientParams DEFAULT_PARAMS = new CFClientParams("test.io", "testuser", - CFCredentials.fromRefreshToken("refreshtoken"), false); + CFCredentials.fromRefreshToken("refreshtoken"), "an-org", "a-space", false); public final CloudFoundryClientFactory factory = mock(CloudFoundryClientFactory.class); public final ClientRequests client = mock(ClientRequests.class);