Try to shorten labels for boot property completions

See: https://github.com/spring-projects/sts4/issues/361
This commit is contained in:
Kris De Volder
2019-09-05 15:12:57 -07:00
parent 297aea926e
commit f7276a5683
8 changed files with 105 additions and 71 deletions

View File

@@ -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 "";
}
};
}
}

View File

@@ -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<dataLen && patternPos<patternLen) {
// int pChar = pattern.charAt(patternPos++);
// int highlightPos = data.indexOf(pChar, dataPos);
// if (dataPos<highlightPos) {
// result.append(data.substring(dataPos, highlightPos), plainStyle);
// }
// result.append(data.charAt(highlightPos), highlightStyle);
// dataPos = highlightPos+1;
// }
// if (dataPos<dataLen) {
// result.append(data.substring(dataPos), plainStyle);
// }
// } else { //no pattern to highlight
// result.append(data, plainStyle);
// }
// }
// protected abstract boolean isDeprecated();
// protected abstract String getHighlightPattern();
// protected abstract String getBaseDisplayString();
// @Override
// public String getAdditionalProposalInfo() {
// HoverInfo hoverInfo = getAdditionalProposalInfo(new NullProgressMonitor());
// if (hoverInfo!=null) {
// return hoverInfo.getHtml();
// }
// return null;
// }
// @Override
// public abstract HoverInfo getAdditionalProposalInfo(IProgressMonitor monitor);
// @Override
// public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
// return null;
// }
//
// @Override
// public int getPrefixCompletionStart(IDocument document, int completionOffset) {
// return completionOffset;
// }
@Override
public String toString() {
return getLabel();

View File

@@ -8,12 +8,9 @@
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.completion;
package org.springframework.ide.vscode.commons.languageserver.completion;
import org.eclipse.lsp4j.CompletionItemKind;
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.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.util.Renderable;
/**
@@ -24,6 +21,7 @@ import org.springframework.ide.vscode.commons.util.Renderable;
* @author Kris De Volder
*/
public abstract class TransformedCompletion extends ScoreableProposal {
protected final ICompletionProposal original;
private DocumentEdits transformedEdit = null;
@@ -35,7 +33,9 @@ public abstract class TransformedCompletion extends ScoreableProposal {
protected String tranformLabel(String originalLabel) {
return originalLabel;
}
protected abstract DocumentEdits transformEdit(DocumentEdits textEdit);
protected DocumentEdits transformEdit(DocumentEdits textEdit) {
return textEdit;
}
@Override
public synchronized DocumentEdits getTextEdit() {

View File

@@ -20,6 +20,7 @@ import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import com.google.common.base.Strings;
@@ -77,6 +78,22 @@ public class StringUtil {
return "";
}
public static String commonPrefix(Stream<CharSequence> strings) {
CharSequence prefix = null;
for (CharSequence string : (Iterable<CharSequence>)strings::iterator) {
if (prefix==null) {
prefix = string;
} else {
int end = 0;
while (end<prefix.length() && end<string.length() && string.charAt(end)==prefix.charAt(end)) {
end++;
}
prefix = prefix.subSequence(0, end);
}
}
return prefix.toString();
}
public static String camelCaseToHyphens(String value) {
Matcher matcher = CAMEL_CASE_PATTERN.matcher(value);
StringBuffer result = new StringBuffer();

View File

@@ -26,6 +26,7 @@ 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.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
import org.springframework.ide.vscode.commons.languageserver.util.PlaceHolderString;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;

View File

@@ -26,6 +26,7 @@ import org.springframework.ide.vscode.commons.languageserver.completion.Document
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.Unicodes;

View File

@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,12 +42,15 @@ import org.springframework.ide.vscode.boot.properties.reconcile.PropertyNavigato
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.completion.LazyProposalApplier;
import org.springframework.ide.vscode.commons.languageserver.completion.TransformedCompletion;
import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.CollectionUtil;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
import org.springframework.ide.vscode.commons.util.Streams;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
@@ -359,10 +363,23 @@ public class PropertiesCompletionProposalsCalculator {
log.error("{}", e);
}
});
return proposals;
return elideCommonPrefix(prefix, proposals);
}
}
return Collections.emptyList();
}
private Collection<ICompletionProposal> elideCommonPrefix(String basePrefix, ArrayList<ICompletionProposal> 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;
}
}

View File

@@ -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 {