Fix #135: Use 'match lower case' preference in XML completion provider

This commit is contained in:
Akash Yadav
2022-03-21 18:55:06 +05:30
parent f083bfea9c
commit cf72d25614
5 changed files with 50 additions and 17 deletions
@@ -37,10 +37,9 @@ public class StringUtils {
char char2 = partialName.charAt(i);
// Match by keeping the first character of the partial name and candidate as is
// The make all the characters lower case
// Then make all the characters lower case
// So if the first character is upper case, we could assume that the user is expecting a
// class
// name
// class name
// Otherwise a variable name
if (allLower || i != 0) {
char1 = Character.toLowerCase(char1);
@@ -21,6 +21,7 @@ import static com.itsaky.lsp.java.utils.EditHelper.repeatSpaces;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.lsp.api.AbstractServiceProvider;
import com.itsaky.lsp.api.ICompletionProvider;
@@ -59,6 +60,7 @@ import com.sun.source.tree.SwitchTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
@@ -75,6 +77,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
@@ -161,7 +164,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
public CompletionProvider(CompilerProvider compiler, IServerSettings settings) {
super();
applySettings(settings);
super.applySettings(settings);
this.compiler = compiler;
}
@@ -18,6 +18,7 @@
package com.itsaky.lsp.xml;
import androidx.annotation.NonNull;
import com.itsaky.lsp.api.ICompletionProvider;
import com.itsaky.lsp.api.IDocumentHandler;
import com.itsaky.lsp.api.ILanguageClient;
@@ -38,13 +39,15 @@ import com.itsaky.lsp.models.SignatureHelp;
import com.itsaky.lsp.models.SignatureHelpParams;
import com.itsaky.lsp.util.NoCompletionsProvider;
import com.itsaky.lsp.util.NoDocumentHandler;
import com.itsaky.lsp.xml.models.DefaultXMLServerSettings;
import com.itsaky.lsp.xml.models.XMLServerSettings;
import com.itsaky.lsp.xml.providers.CompletionProvider;
import com.itsaky.sdk.SDKInfo;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import org.jetbrains.annotations.Nullable;
/**
* Language server implementation for XML files.
@@ -71,8 +74,9 @@ public class XMLLanguageServer implements ILanguageServer {
@NonNull
public IServerSettings getSettings() {
if (settings == null) {
settings = new DefaultXMLServerSettings();
settings = XMLServerSettings.getInstance();
}
return settings;
}
@@ -17,9 +17,20 @@
package com.itsaky.lsp.xml.models;
import com.itsaky.lsp.util.DefaultServerSettings;
import com.itsaky.lsp.util.PrefBasedServerSettings;
/**
* @author Akash Yadav
*/
public class DefaultXMLServerSettings extends DefaultServerSettings {}
public class XMLServerSettings extends PrefBasedServerSettings {
private static XMLServerSettings instance;
public static XMLServerSettings getInstance() {
if (instance == null) {
instance = new XMLServerSettings();
}
return instance;
}
}
@@ -34,7 +34,6 @@ import com.itsaky.lsp.models.CompletionItemKind;
import com.itsaky.lsp.models.CompletionParams;
import com.itsaky.lsp.models.CompletionResult;
import com.itsaky.lsp.models.InsertTextFormat;
import com.itsaky.lsp.util.StringUtils;
import com.itsaky.lsp.xml.R;
import com.itsaky.sdk.SDKInfo;
import com.itsaky.widgets.models.Widget;
@@ -70,6 +69,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
public CompletionProvider(SDKInfo sdkInfo, IServerSettings settings) {
Objects.requireNonNull(sdkInfo);
Objects.requireNonNull(settings);
super.applySettings(settings);
this.sdkInfo = sdkInfo;
}
@@ -173,7 +173,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
if (attr != null && attr.hasPossibleValues()) {
Set<String> values = attr.possibleValues;
for (String value : values) {
if (StringUtils.matchesPartialName(value, prefix, matchLower)) {
if (matchesPartialName(value, prefix, matchLower)) {
result.getItems().add(valueAsCompletion(value));
}
}
@@ -182,7 +182,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
} else {
for (Map.Entry<String, Attr> entry : attrs.getAttributes().entrySet()) {
Attr attr = entry.getValue();
if (StringUtils.matchesPartialName(attr.name, prefix, matchLower)) {
if (matchesPartialName(attr.name, prefix, matchLower)) {
result.getItems().add(attrAsCompletion(attr));
}
}
@@ -190,15 +190,15 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
// Shortcuts for automatically declaring namespaces
// These completions are proposed if you type 'androidNs', 'appNs' or 'toolsNs'
// Idea is shamelessly copied from Android Studio 😂
if (StringUtils.matchesPartialName("android", prefix, matchLower)) {
if (matchesPartialName("android", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("android", ANDROID_NS));
}
if (StringUtils.matchesPartialName("app", prefix, matchLower)) {
if (matchesPartialName("app", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("app", APP_NS));
}
if (StringUtils.matchesPartialName("tools", prefix, matchLower)) {
if (matchesPartialName("tools", prefix, matchLower)) {
result.getItems().add(createNamespaceCompletion("tools", TOOLS_NS));
}
}
@@ -211,8 +211,7 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
prefix = prefix.toLowerCase(Locale.ROOT);
for (var widget : this.sdkInfo.getWidgetInfo().getWidgets()) {
var name = widget.simpleName.toLowerCase(Locale.ROOT);
if (StringUtils.matchesPartialName(
name, prefix, getSettings().shouldMatchAllLowerCase())) {
if (matchesPartialName(name, prefix, getSettings().shouldMatchAllLowerCase())) {
result.getItems().add(widgetNameAsCompletion(widget, slash));
}
}
@@ -300,6 +299,23 @@ public class CompletionProvider extends AbstractServiceProvider implements IComp
return sb.toString();
}
private boolean matchesPartialName(String candidate, String partialName, boolean matchLower) {
if (candidate == null || partialName == null) {
return false;
}
if (candidate.length() < partialName.length()) {
return false;
}
if (matchLower) {
candidate = candidate.toLowerCase(Locale.ROOT);
partialName = partialName.toLowerCase(Locale.ROOT);
}
return candidate.startsWith(partialName);
}
private static class IsInValueScanner {
private final int cursorIndex;