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 3774189e3..131ef4453 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 @@ -38,5 +38,16 @@ public interface ICompletionProposal { default ICompletionProposal deemphasize(double howmuch) { return this; } default boolean isDeprecated() { return false; } - + + default ICompletionProposal dropLabelPrefix(int numberOfDroppedChars) { + return new TransformedCompletion(this) { + @Override + protected String tranformLabel(String originalLabel) { + if (originalLabel.length()>=numberOfDroppedChars) { + return originalLabel.substring(numberOfDroppedChars); + } + return ""; + } + }; + } } diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java index f955f2bf3..36e29082f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java @@ -68,70 +68,6 @@ public abstract class ScoreableProposal implements ICompletionProposal { return deemphasizedBy > 0; } -// @Override -// public boolean isAutoInsertable() { -// return !isDeemphasized(); -// } - -// public StyledString getStyledDisplayString() { -// StyledString result = new StyledString(); -// highlightPattern(getHighlightPattern(), getBaseDisplayString(), result); -// return result; -// } - -// private void highlightPattern(String pattern, String data, StyledString result) { -// Styler highlightStyle = CompletionFactory.HIGHLIGHT; -// Styler plainStyle = isDeemphasized()?CompletionFactory.DEEMPHASIZE:CompletionFactory.NULL_STYLER; -// if (isDeprecated()) { -// highlightStyle = CompletionFactory.compose(highlightStyle, CompletionFactory.DEPRECATE); -// plainStyle = CompletionFactory.compose(plainStyle, CompletionFactory.DEPRECATE); -// } -// if (StringUtils.hasText(pattern)) { -// int dataPos = 0; int dataLen = data.length(); -// int patternPos = 0; int patternLen = pattern.length(); -// -// while (dataPos strings) { + CharSequence prefix = null; + for (CharSequence string : (Iterable)strings::iterator) { + if (prefix==null) { + prefix = string; + } else { + int end = 0; + while (end elideCommonPrefix(String basePrefix, ArrayList proposals) { + String prefix = StringUtil.commonPrefix(Stream.concat(Stream.of(basePrefix), proposals.stream().map(ICompletionProposal::getLabel))); + int lastDot = prefix.lastIndexOf('.'); + if (lastDot>=0) { + for (int i = 0; i < proposals.size(); i++) { + ICompletionProposal p = proposals.get(i); + proposals.set(i, p.dropLabelPrefix(lastDot+1)); + } + } + return proposals; + } + + } 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 7c86b4ef8..9ab60820d 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 @@ -85,6 +85,57 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest { ); editor.assertProblems("no-bool|boolean"); } + + @Test public void abbreviateLongPrefixCompletions() throws Exception { + //See: https://github.com/spring-projects/sts4/issues/361 + Editor editor; + + data("spring.data.jpa.very.long.foobar", "java.lang.String", null, null); + data("spring.data.jpa.very.long.barbar", "java.lang.String", null, null); + data("spring.data.jpa.very.long.foofoo", "java.lang.String", null, null); + data("spring.data.jpa.very.long.barfoo", "java.lang.String", null, null); + data("spring.data.jpa.very.long.foobar.more", "java.lang.String", null, null); + data("spring.data.jpa.very.long.barbar.more", "java.lang.String", null, null); + data("spring.data.jpa.very.long.foofoo.more", "java.lang.String", null, null); + data("spring.data.jpa.very.long.barfoo.more", "java.lang.String", null, null); + + + editor = newEditor( + "spring.data.jpa.very.bar<*>" + ); + editor.assertCompletions( + "spring.data.jpa.very.long.barbar=<*>", + "spring.data.jpa.very.long.barfoo=<*>", + "spring.data.jpa.very.long.foobar=<*>", + "spring.data.jpa.very.long.barbar.more=<*>", + "spring.data.jpa.very.long.barfoo.more=<*>", + "spring.data.jpa.very.long.foobar.more=<*>" + ); + + editor.assertCompletionLabels( + "long.barbar", + "long.barfoo", + "long.foobar", + "long.barbar.more", + "long.barfoo.more", + "long.foobar.more" + ); + + editor = newEditor( + "spring.data.jpa.vr<*>" + ); + editor.assertCompletionLabels( + "very.long.barbar", + "very.long.barfoo", + "very.long.foobar", + "very.long.foofoo", + "very.long.barbar.more", + "very.long.barfoo.more", + "very.long.foobar.more", + "very.long.foofoo.more" + ); + + } @Test public void testReconcileCatchesParseError() throws Exception {