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 aae74ee3b..8cfe7a421 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 @@ -17,7 +17,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.lsp4j.TextEdit; -import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.IDocument; @@ -45,6 +46,8 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; * @author Kris De Volder */ public class DocumentEdits implements ProposalApplier { + + private static final Logger log = LoggerFactory.getLogger(DocumentEdits.class); private static final Pattern NON_WS_CHAR = Pattern.compile("\\S"); @@ -511,4 +514,20 @@ public class DocumentEdits implements ProposalApplier { final public boolean hasSnippets() { return hasSnippets; } + + public void dropPrefix(String prefix) { + try { + if (edits.size() == 2 && edits.get(0) instanceof Deletion && edits.get(1) instanceof Insertion) { + Deletion del = (Deletion) edits.get(0); + Insertion ins = (Insertion) edits.get(1); + String replacedText = doc.textBetween(del.start, del.end); + if (ins.offset>=del.start && ins.offset <=del.end && replacedText.startsWith(prefix)) { + del.start+=prefix.length(); + ins.text = ins.text.substring(prefix.length()); + } + } + } catch (BadLocationException e) { + log.error("", e); + } + } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java index 134292231..1881cf1d0 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ICompletionProposal.java @@ -39,14 +39,20 @@ public interface ICompletionProposal { default boolean isDeprecated() { return false; } - default TransformedCompletion dropLabelPrefix(int numberOfDroppedChars) { + default TransformedCompletion dropLabelPrefix(int _numberOfDroppedChars) { + String orgLabel = getLabel(); + int numberOfDroppedChars = Math.min(orgLabel.length(), _numberOfDroppedChars); + String prefix = getLabel().substring(0, numberOfDroppedChars); return new TransformedCompletion(this) { @Override protected String tranformLabel(String originalLabel) { - if (originalLabel.length()>=numberOfDroppedChars) { - return originalLabel.substring(numberOfDroppedChars); - } - return ""; + return originalLabel.substring(numberOfDroppedChars); + } + + @Override + protected DocumentEdits transformEdit(DocumentEdits textEdit) { + textEdit.dropPrefix(prefix); + return textEdit; } }; } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java index 9ab60820d..e4757940a 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationPropertiesEditorTest.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType.PROP_DUPLICATE_KEY; @@ -25,6 +26,7 @@ import java.util.List; import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.TextEdit; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -112,7 +114,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "spring.data.jpa.very.long.foobar.more=<*>" ); - editor.assertCompletionLabels( + List completions = editor.assertCompletionLabels( "long.barbar", "long.barfoo", "long.foobar", @@ -120,11 +122,15 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "long.barfoo.more", "long.foobar.more" ); + for (CompletionItem c : completions) { + TextEdit edit = c.getTextEdit(); + assertEquals("bar", editor.getText(edit.getRange())); + } editor = newEditor( "spring.data.jpa.vr<*>" ); - editor.assertCompletionLabels( + completions = editor.assertCompletionLabels( "very.long.barbar", "very.long.barfoo", "very.long.foobar", @@ -134,6 +140,38 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { "very.long.foobar.more", "very.long.foofoo.more" ); + for (CompletionItem c : completions) { + TextEdit edit = c.getTextEdit(); + assertEquals("vr", editor.getText(edit.getRange())); + } + + editor = newEditor( + "spring.data.jpa.very.<*>" + ); + editor.assertCompletions( + "spring.data.jpa.very.long.barbar=<*>", + "spring.data.jpa.very.long.barbar.more=<*>", + "spring.data.jpa.very.long.barfoo=<*>", + "spring.data.jpa.very.long.barfoo.more=<*>", + "spring.data.jpa.very.long.foobar=<*>", + "spring.data.jpa.very.long.foobar.more=<*>", + "spring.data.jpa.very.long.foofoo=<*>", + "spring.data.jpa.very.long.foofoo.more=<*>" + ); + completions = editor.assertCompletionLabels( + "long.barbar", + "long.barbar.more", + "long.barfoo", + "long.barfoo.more", + "long.foobar", + "long.foobar.more", + "long.foofoo", + "long.foofoo.more" + ); + for (CompletionItem c : completions) { + TextEdit edit = c.getTextEdit(); + assertEquals("", editor.getText(edit.getRange())); + } } diff --git a/vscode-extensions/vscode-spring-boot/lib/Main.ts b/vscode-extensions/vscode-spring-boot/lib/Main.ts index ff83022ec..063368bb7 100644 --- a/vscode-extensions/vscode-spring-boot/lib/Main.ts +++ b/vscode-extensions/vscode-spring-boot/lib/Main.ts @@ -18,7 +18,7 @@ export function activate(context: VSCode.ExtensionContext): Thenable {