From 9e0513663c68d72718b7237bfe28a4cf48977519 Mon Sep 17 00:00:00 2001 From: Kris De Volder Date: Wed, 26 Apr 2017 11:11:40 -0700 Subject: [PATCH] Improve content assist for services (auto inserting dashes) --- .../completion/DocumentEdits.java | 7 +++ .../yaml/completion/YTypeAssistContext.java | 49 ++++++++++++++----- .../manifest/yaml/ManifestYamlEditorTest.java | 48 ++++++++++++++++++ 3 files changed, 91 insertions(+), 13 deletions(-) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java index 002cdca22..54e19550c 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java @@ -437,4 +437,11 @@ public class DocumentEdits implements ProposalApplier { } } + public Integer getFirstEditStart() { + for (Edit edit : edits) { + return edit.getStart(); + } + return null; + } + } 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 fcc966a4f..29d6ac520 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 @@ -43,6 +43,9 @@ import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode; import org.springframework.ide.vscode.commons.yaml.util.YamlIndentUtil; +import org.springframework.ide.vscode.commons.yaml.completion.DefaultCompletionFactory.ValueProposal; + +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import static org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal.*; @@ -56,8 +59,8 @@ public class YTypeAssistContext extends AbstractYamlAssistContext { final private YamlAssistContext parent; /** - * Create a 'relaxed' {@link YTypeAssistContext} that pretends the type expectedin this context - * is something else than what the schema sugests. + * Create a 'relaxed' {@link YTypeAssistContext} that pretends the type expected in this context + * is actually something else than the schema sugests. */ public YTypeAssistContext(YTypeAssistContext relaxationTarget, YType relaxedType) { super(relaxationTarget.getDocument(), relaxationTarget.documentSelector, relaxationTarget.contextPath); @@ -316,7 +319,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext { @Override public Collection getCompletions(YamlDocument doc, SNode node, int offset) throws Exception { Collection basicCompletions = super.getCompletions(doc, node, offset); - return addDashes(basicCompletions); + return addDashes(basicCompletions, doc, node); } }; } @@ -327,7 +330,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext { return super.relax(); } - private Collection addDashes(Collection basicCompletions) { + private Collection addDashes(Collection basicCompletions, YamlDocument doc, SNode node) { if (!basicCompletions.isEmpty()) { List dashedCompletions = new ArrayList<>(basicCompletions.size()); for (ICompletionProposal c : basicCompletions) { @@ -335,17 +338,37 @@ public class YTypeAssistContext extends AbstractYamlAssistContext { new TransformedCompletion(c) { @Override protected DocumentEdits transformEdit(DocumentEdits textEdit) { - textEdit.transformFirstNonWhitespaceEdit((Integer offset, String insertText) -> { - if (offset > 2) { - String prefix = insertText.substring(offset-2, offset); - if (" ".equals(prefix)) { - //special case don't add the "- " in front, but replace the inserted spaces instead. - return insertText.substring(0, offset-2)+"- "+insertText.substring(offset); + if (needNewline(textEdit)) { + textEdit.indentFirstEdit("\n"+Strings.repeat(" ", node.getIndent())+"- "); + } else { + textEdit.transformFirstNonWhitespaceEdit((Integer offset, String insertText) -> { + if (offset > 2) { + String prefix = insertText.substring(offset-2, offset); + if (" ".equals(prefix)) { + //special case don't add the "- " in front, but replace the inserted spaces instead. + return insertText.substring(0, offset-2)+"- "+insertText.substring(offset); + } + } + return insertText.substring(0, offset) + "- "+insertText.substring(offset); + }); + } + return textEdit; + } + + private boolean needNewline(DocumentEdits textEdit) { + //value proposals which are inserted right after a key will not automatically include a newline, as + // its not required for them. So we should add it along with the dash. + try { + if (original instanceof ValueProposal) { + Integer insertAt = textEdit.getFirstEditStart(); + if (insertAt!=null) { + return !"".equals(doc.getLineTextBefore(insertAt).trim()); } } - return insertText.substring(0, offset) + "- "+insertText.substring(offset); - }); - return textEdit; + } catch (Exception e) { + Log.log(e); + } + return false; } @Override 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 42da0ee68..0bf8046ad 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 @@ -13,6 +13,7 @@ package org.springframework.ide.vscode.manifest.yaml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; @@ -1140,6 +1141,53 @@ public class ManifestYamlEditorTest { editor.assertProblems(); } + @Test public void dashedContentAssistForServices() throws Exception { + Editor editor; + CFServiceInstance service = mock(CFServiceInstance.class); + when(cloudfoundry.client.getServices()).thenReturn(ImmutableList.of(service)); + when(service.getName()).thenReturn("my-service"); + when(service.getPlan()).thenReturn("cheap-plan"); + + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " services: <*>\n" + ); + editor.assertCompletionLabels("- my-service - cheap-plan"); + editor.assertCompletions( + "applications:\n" + + "- name: foo\n" + + " services: \n" + + " - my-service<*>\n" + ); + + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " services: ser<*>\n" + ); + editor.assertCompletions( + "applications:\n" + + "- name: foo\n" + + " services: \n" + + " - my-service<*>\n" + ); + + editor = harness.newEditor( + "applications:\n" + + "- name: foo\n" + + " services: \n" + + " - blah\n" + + " <*>\n" + ); + editor.assertCompletionWithLabel((s) -> s.startsWith("- "), + "applications:\n" + + "- name: foo\n" + + " services: \n" + + " - blah\n" + + " - my-service<*>\n" + ); + } //////////////////////////////////////////////////////////////////////////////