diff --git a/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/ICompletionProvider.java b/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/ICompletionProvider.java index d9c7ed611..bcb3da0b9 100644 --- a/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/ICompletionProvider.java +++ b/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/ICompletionProvider.java @@ -53,7 +53,7 @@ import java.nio.file.Path; */ public interface ICompletionProvider { - int MIN_MATCH_RATIO = CompletionsKt.MIN_MATCH_RATIO; + int MIN_MATCH_RATIO = CompletionsKt.DEFAULT_MIN_MATCH_RATIO; default boolean canComplete(Path file) { return file != null && Files.exists(file) && !Files.isDirectory(file); @@ -68,7 +68,14 @@ public interface ICompletionProvider { } default MatchLevel matchLevel(CharSequence candidate, CharSequence partial) { - return CompletionItem.matchLevel(candidate.toString(), partial.toString()); + var matchRatio = CompletionsKt.DEFAULT_MIN_MATCH_RATIO; + if (this instanceof AbstractServiceProvider) { + matchRatio = ((AbstractServiceProvider) this).getSettings().completionFuzzyMatchMinRatio(); + } + + if (matchRatio < 0 || matchRatio > 100) matchRatio = CompletionsKt.DEFAULT_MIN_MATCH_RATIO; + + return CompletionItem.matchLevel(candidate.toString(), partial.toString(), matchRatio); } /** diff --git a/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/IServerSettings.java b/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/IServerSettings.java index 7d019a948..de31f7c50 100644 --- a/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/IServerSettings.java +++ b/lsp/api/src/main/java/com/itsaky/androidide/lsp/api/IServerSettings.java @@ -17,6 +17,8 @@ package com.itsaky.androidide.lsp.api; +import com.itsaky.androidide.lsp.models.CompletionsKt; + /** * Settings contain preferences for the language server. Clients can use settings to enable/disable * specific features of a server. @@ -83,4 +85,13 @@ public interface IServerSettings { * @return {@code true} if enabled, {@code false} otherwise. */ boolean shouldMatchAllLowerCase(); + + /** + * The minimum match ratio that is needed for the completions to be considered as 'matched'. + * + * @return The match ratio. Betweeen 0 and 100. + */ + default int completionFuzzyMatchMinRatio() { + return CompletionsKt.DEFAULT_MIN_MATCH_RATIO; + } } diff --git a/lsp/models/src/main/java/com/itsaky/androidide/lsp/models/Completions.kt b/lsp/models/src/main/java/com/itsaky/androidide/lsp/models/Completions.kt index 54c19745c..934708919 100644 --- a/lsp/models/src/main/java/com/itsaky/androidide/lsp/models/Completions.kt +++ b/lsp/models/src/main/java/com/itsaky/androidide/lsp/models/Completions.kt @@ -36,7 +36,7 @@ import io.github.rosemoe.sora.text.Content import io.github.rosemoe.sora.widget.CodeEditor import java.nio.file.Path -const val MIN_MATCH_RATIO = 45 +const val DEFAULT_MIN_MATCH_RATIO = 59 data class CompletionParams(var position: Position, var file: Path) { var content: CharSequence? = null @@ -162,7 +162,8 @@ open class CompletionItem( private val LOG = ILogger.newInstance("CompletionItem") @JvmStatic - fun matchLevel(candidate: String, partial: String): MatchLevel { + @JvmOverloads + fun matchLevel(candidate: String, partial: String, minMatchRatio: Int = DEFAULT_MIN_MATCH_RATIO): MatchLevel { if (candidate.startsWith(partial)) { return if (candidate.length == partial.length) { CASE_SENSITIVE_EQUAL @@ -182,7 +183,7 @@ open class CompletionItem( } val ratio = FuzzySearch.ratio(candidate, partial) - if (ratio > MIN_MATCH_RATIO) { + if (ratio > minMatchRatio) { return PARTIAL_MATCH } diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/models/XMLServerSettings.java b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/models/XMLServerSettings.java index 3402cc3fc..58ed1b35e 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/models/XMLServerSettings.java +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/models/XMLServerSettings.java @@ -33,4 +33,9 @@ public class XMLServerSettings extends PrefBasedServerSettings { return instance; } + + @Override + public int completionFuzzyMatchMinRatio() { + return 50; + } } diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/XmlCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/XmlCompletionProvider.kt index cc594b031..f5f3c267e 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/XmlCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/XmlCompletionProvider.kt @@ -126,9 +126,9 @@ class XmlCompletionProvider(settings: IServerSettings) : private fun createLayoutCompleter(type: NodeType): IXmlCompletionProvider? { return when (type) { - TAG -> LayoutTagCompletionProvider() - ATTRIBUTE -> LayoutAttributeCompletionProvider() - ATTRIBUTE_VALUE -> AttrValueCompletionProvider() + TAG -> LayoutTagCompletionProvider(this) + ATTRIBUTE -> LayoutAttributeCompletionProvider(this) + ATTRIBUTE_VALUE -> AttrValueCompletionProvider(this) else -> null } } diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/AttributeCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/AttributeCompletionProvider.kt index 9b91dbce9..3936c5a47 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/AttributeCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/AttributeCompletionProvider.kt @@ -18,6 +18,7 @@ package com.itsaky.androidide.lsp.xml.providers.completion import com.android.aaptcompiler.ResourcePathData +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE import java.nio.file.Path @@ -27,7 +28,7 @@ import java.nio.file.Path * * @author Akash Yadav */ -abstract class AttributeCompletionProvider : IXmlCompletionProvider() { +abstract class AttributeCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) { override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean { return super.canProvideCompletions(pathData, type) && type == ATTRIBUTE diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/IXmlCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/IXmlCompletionProvider.kt index 4accc53d8..d51e24c24 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/IXmlCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/IXmlCompletionProvider.kt @@ -21,6 +21,7 @@ import com.android.aaptcompiler.Reference import com.android.aaptcompiler.ResourcePathData import com.android.aaptcompiler.ResourceTable import com.itsaky.androidide.lookup.Lookup +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.models.Command import com.itsaky.androidide.lsp.models.CompletionData import com.itsaky.androidide.lsp.models.CompletionItem @@ -42,7 +43,7 @@ import org.eclipse.lemminx.dom.DOMDocument * * @author Akash Yadav */ -abstract class IXmlCompletionProvider { +abstract class IXmlCompletionProvider(private val provider: ICompletionProvider) { protected val log = ILogger.newInstance("XmlCompletionProvider") @@ -50,6 +51,10 @@ abstract class IXmlCompletionProvider { const val NAMESPACE_PREFIX = "http://schemas.android.com/apk/res/" const val NAMESPACE_AUTO = "http://schemas.android.com/apk/res-auto" } + + protected open fun matchLevel(candidate: CharSequence, partial: CharSequence) : MatchLevel { + return provider.matchLevel(candidate, partial) + } /** * Whether this completion provide can provide completions for the given [pathData]. diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/TagCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/TagCompletionProvider.kt index a7964ca7a..9e20b1fd2 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/TagCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/TagCompletionProvider.kt @@ -18,6 +18,7 @@ package com.itsaky.androidide.lsp.xml.providers.completion import com.android.aaptcompiler.ResourcePathData +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.TAG @@ -26,7 +27,7 @@ import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.TAG * * @author Akash Yadav */ -abstract class TagCompletionProvider : IXmlCompletionProvider() { +abstract class TagCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) { override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean { return super.canProvideCompletions(pathData, type) && type == TAG diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/common/AttrValueCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/common/AttrValueCompletionProvider.kt index c93fd4f3b..aa04bb3e7 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/common/AttrValueCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/common/AttrValueCompletionProvider.kt @@ -36,8 +36,8 @@ import com.android.aaptcompiler.ResourceGroup import com.android.aaptcompiler.ResourcePathData import com.android.aaptcompiler.ResourceTable import com.itsaky.androidide.aapt.findEntries +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.models.CompletionItem -import com.itsaky.androidide.lsp.models.CompletionItem.Companion.matchLevel import com.itsaky.androidide.lsp.models.CompletionParams import com.itsaky.androidide.lsp.models.CompletionResult import com.itsaky.androidide.lsp.models.CompletionResult.Companion.EMPTY @@ -52,7 +52,7 @@ import org.eclipse.lemminx.dom.DOMDocument * * @author Akash Yadav */ -class AttrValueCompletionProvider : IXmlCompletionProvider() { +class AttrValueCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) { override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean { return super.canProvideCompletions(pathData, type) && type == ATTRIBUTE_VALUE diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutAttributeCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutAttributeCompletionProvider.kt index a80d2fca7..ce97eb01a 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutAttributeCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutAttributeCompletionProvider.kt @@ -24,8 +24,8 @@ import com.android.aaptcompiler.ResourcePathData import com.android.aaptcompiler.ResourceTablePackage import com.android.aaptcompiler.Styleable import com.itsaky.androidide.lookup.Lookup +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.models.CompletionItem -import com.itsaky.androidide.lsp.models.CompletionItem.Companion.matchLevel import com.itsaky.androidide.lsp.models.CompletionParams import com.itsaky.androidide.lsp.models.CompletionResult import com.itsaky.androidide.lsp.models.MatchLevel.NO_MATCH @@ -41,7 +41,8 @@ import org.eclipse.lemminx.dom.DOMNode * * @author Akash Yadav */ -class LayoutAttributeCompletionProvider : AttributeCompletionProvider() { +class LayoutAttributeCompletionProvider(provider: ICompletionProvider) : + AttributeCompletionProvider(provider) { override fun doComplete( params: CompletionParams, diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutCompletionProvider.kt index 4133afc6f..af1c4a375 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutCompletionProvider.kt @@ -19,6 +19,7 @@ package com.itsaky.androidide.lsp.xml.providers.completion.layout import com.android.aaptcompiler.AaptResourceType.LAYOUT import com.android.aaptcompiler.ResourcePathData +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.xml.providers.completion.IXmlCompletionProvider import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType @@ -27,7 +28,7 @@ import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType * * @author Akash Yadav */ -abstract class LayoutCompletionProvider : IXmlCompletionProvider() { +abstract class LayoutCompletionProvider(provider: ICompletionProvider) : IXmlCompletionProvider(provider) { override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean { return super.canProvideCompletions(pathData, type) && pathData.type == LAYOUT diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutTagCompletionProvider.kt b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutTagCompletionProvider.kt index 332933e06..e83f9840d 100644 --- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutTagCompletionProvider.kt +++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/providers/completion/layout/LayoutTagCompletionProvider.kt @@ -19,8 +19,8 @@ package com.itsaky.androidide.lsp.xml.providers.completion.layout import com.android.aaptcompiler.ResourcePathData import com.itsaky.androidide.lookup.Lookup +import com.itsaky.androidide.lsp.api.ICompletionProvider import com.itsaky.androidide.lsp.models.CompletionItem -import com.itsaky.androidide.lsp.models.CompletionItem.Companion.matchLevel import com.itsaky.androidide.lsp.models.CompletionParams import com.itsaky.androidide.lsp.models.CompletionResult import com.itsaky.androidide.lsp.models.MatchLevel @@ -29,15 +29,16 @@ import com.itsaky.androidide.lsp.xml.providers.completion.TagCompletionProvider import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.TAG import com.itsaky.androidide.xml.widgets.WidgetTable -import org.eclipse.lemminx.dom.DOMDocument import kotlin.math.max +import org.eclipse.lemminx.dom.DOMDocument /** * [TagCompletionProvider] implementation for providing completing tags in an XML layout file. * * @author Akash Yadav */ -class LayoutTagCompletionProvider : LayoutCompletionProvider() { +class LayoutTagCompletionProvider(provider: ICompletionProvider) : + LayoutCompletionProvider(provider) { override fun canProvideCompletions(pathData: ResourcePathData, type: NodeType): Boolean { return super.canProvideCompletions(pathData, type) && type == TAG diff --git a/tests/test-home/.androidide/init/model.jar b/tests/test-home/.androidide/init/model.jar index 44f474e14..ccf67e48f 100644 Binary files a/tests/test-home/.androidide/init/model.jar and b/tests/test-home/.androidide/init/model.jar differ