mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Added: Long click java completion item for documentation
This commit is contained in:
@@ -28,17 +28,21 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.databinding.LayoutCompletionItemBinding
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.CLASS
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.CONSTRUCTOR
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.ENUM
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.FIELD
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.INTERFACE
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.METHOD
|
||||
import com.itsaky.androidide.lsp.models.MemberCompletionData
|
||||
import com.itsaky.androidide.lsp.models.MethodCompletionData
|
||||
import com.itsaky.androidide.resources.R.color
|
||||
import com.itsaky.androidide.resources.R.string.msg_api_info_deprecated
|
||||
import com.itsaky.androidide.resources.R.string.msg_api_info_removed
|
||||
import com.itsaky.androidide.resources.R.string.msg_api_info_since
|
||||
import com.itsaky.androidide.tasks.executeAsync
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.TypefaceUtils
|
||||
import com.itsaky.androidide.xml.versions.ApiVersions
|
||||
import com.itsaky.androidide.xml.versions.Info
|
||||
@@ -48,6 +52,9 @@ import io.github.rosemoe.sora.widget.component.EditorCompletionAdapter
|
||||
import com.itsaky.androidide.lsp.models.CompletionItem as LspCompletionItem
|
||||
|
||||
class CompletionListAdapter : EditorCompletionAdapter() {
|
||||
|
||||
private val log = ILogger.newInstance("CompletionListAdapter")
|
||||
|
||||
override fun attachValues(window: EditorAutoCompletion, items: List<CompletionItem>) {
|
||||
super.attachValues(window, items)
|
||||
}
|
||||
@@ -105,32 +112,34 @@ class CompletionListAdapter : EditorCompletionAdapter() {
|
||||
}
|
||||
|
||||
val data = item.data
|
||||
if (data?.className == null) {
|
||||
return@executeAsync null
|
||||
}
|
||||
|
||||
val versions =
|
||||
Lookup.DEFAULT.lookup(ApiVersions.COMPLETION_LOOKUP_KEY) ?: return@executeAsync null
|
||||
val className = data.className
|
||||
val className =
|
||||
when (data) {
|
||||
is ClassCompletionData -> data.className
|
||||
is MemberCompletionData -> data.classInfo.className
|
||||
else -> return@executeAsync null
|
||||
}
|
||||
val kind = item.kind
|
||||
|
||||
val clazz = versions.getClass(className) ?: return@executeAsync null
|
||||
var info: Info? = clazz
|
||||
|
||||
if (
|
||||
kind == METHOD && data.erasedParameterTypes.isNotEmpty() && data.memberName.isNotBlank()
|
||||
) {
|
||||
val method = clazz.getMethod(data.memberName, *data.erasedParameterTypes)
|
||||
if (method != null) {
|
||||
info = method
|
||||
}
|
||||
} else if (kind == FIELD && data.memberName.isNotBlank()) {
|
||||
val field = clazz.getField(data.memberName)
|
||||
if (field != null) {
|
||||
info = field
|
||||
if (data is MethodCompletionData) {
|
||||
if (
|
||||
kind == METHOD && data.erasedParameterTypes.isNotEmpty() && data.memberName.isNotBlank()
|
||||
) {
|
||||
val method = clazz.getMethod(data.memberName, *data.erasedParameterTypes.toTypedArray())
|
||||
if (method != null) {
|
||||
info = method
|
||||
}
|
||||
} else if (kind == FIELD && data.memberName.isNotBlank()) {
|
||||
val field = clazz.getField(data.memberName)
|
||||
if (field != null) {
|
||||
info = field
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sb = StringBuilder()
|
||||
if (info!!.since > 1) {
|
||||
sb.append(textView.context.getString(msg_api_info_since, info.since))
|
||||
@@ -177,7 +186,13 @@ class CompletionListAdapter : EditorCompletionAdapter() {
|
||||
// A field type
|
||||
type === FIELD) && data != null
|
||||
) {
|
||||
!TextUtils.isEmpty(data.className)
|
||||
val className =
|
||||
when (data) {
|
||||
is ClassCompletionData -> data.className
|
||||
is MemberCompletionData -> data.classInfo.className
|
||||
else -> null
|
||||
}
|
||||
!TextUtils.isEmpty(className)
|
||||
} else false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ class FileTreeFragment :
|
||||
): View {
|
||||
binding = LayoutEditorFileTreeBinding.inflate(inflater, container, false)
|
||||
binding?.root?.doOnApplyWindowInsets { view, insets, _, _ ->
|
||||
LOG.debug("onApplyWindowInsets")
|
||||
insets.getInsets(statusBars()).apply { view.updatePadding(top = top + SizeUtils.dp2px(8f)) }
|
||||
}
|
||||
return binding!!.root
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
|
||||
package com.itsaky.androidide.views.editor
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.widget.ListView
|
||||
import com.blankj.utilcode.util.ReflectUtils
|
||||
import com.itsaky.androidide.lsp.util.DocumentationReferenceProvider
|
||||
import com.itsaky.androidide.progress.ProgressManager
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import io.github.rosemoe.sora.lang.completion.CompletionItem
|
||||
@@ -26,7 +29,7 @@ import io.github.rosemoe.sora.lang.completion.CompletionPublisher
|
||||
import io.github.rosemoe.sora.widget.component.CompletionLayout
|
||||
import io.github.rosemoe.sora.widget.component.EditorAutoCompletion
|
||||
import io.github.rosemoe.sora.widget.component.EditorCompletionAdapter
|
||||
import java.util.concurrent.atomic.*
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
@@ -46,8 +49,24 @@ class EditorCompletionWindow(val editor: IDEEditor) : EditorAutoCompletion(edito
|
||||
|
||||
override fun setLayout(layout: CompletionLayout) {
|
||||
super.setLayout(layout)
|
||||
mListView = layout.completionList as ListView
|
||||
mListView!!.adapter = mAdapter
|
||||
(layout.completionList as? ListView)?.let {
|
||||
mListView = it
|
||||
it.adapter = mAdapter
|
||||
it.setOnItemLongClickListener { _, view, position, _ ->
|
||||
val data =
|
||||
(mItems[position] as? com.itsaky.androidide.lsp.models.CompletionItem)?.data
|
||||
?: return@setOnItemLongClickListener false
|
||||
val url =
|
||||
DocumentationReferenceProvider.getUrl(data) ?: return@setOnItemLongClickListener false
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
setData(Uri.parse(url))
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
view.context.startActivity(this)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun setAdapter(adapter: EditorCompletionAdapter) {
|
||||
@@ -58,7 +77,7 @@ class EditorCompletionWindow(val editor: IDEEditor) : EditorAutoCompletion(edito
|
||||
mListView!!.adapter = adapter
|
||||
}
|
||||
|
||||
override fun select(pos: Int) : Boolean {
|
||||
override fun select(pos: Int): Boolean {
|
||||
if (pos > mAdapter!!.count) {
|
||||
return false
|
||||
}
|
||||
@@ -70,7 +89,7 @@ class EditorCompletionWindow(val editor: IDEEditor) : EditorAutoCompletion(edito
|
||||
}
|
||||
}
|
||||
|
||||
override fun select() : Boolean {
|
||||
override fun select(): Boolean {
|
||||
return try {
|
||||
super.select()
|
||||
} catch (e: Throwable) {
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.util
|
||||
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.ICompletionData
|
||||
import com.itsaky.androidide.lsp.models.MemberCompletionData
|
||||
import com.itsaky.androidide.lsp.models.MethodCompletionData
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
|
||||
/**
|
||||
* Provides the documentation URL for classes, methods, fields, etc.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
object DocumentationReferenceProvider {
|
||||
|
||||
const val DOCS_BASE_URL = "https://developer.android.com/reference/"
|
||||
|
||||
/**
|
||||
* Package names whose documentation is most likely to be available on the Android Developers
|
||||
* website.
|
||||
*/
|
||||
private val availablePackages =
|
||||
setOf(
|
||||
"android", // Android APIs
|
||||
"androidx", // AndroidX libraries
|
||||
"com.google.android.material", // Material Components
|
||||
"java" // Java APIs
|
||||
)
|
||||
|
||||
/**
|
||||
* Get the documentation URL for given completion data.
|
||||
*
|
||||
* @return The URL or `null` if cannot be determined.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getUrl(data: ICompletionData): String? {
|
||||
val klass =
|
||||
when (data) {
|
||||
is ClassCompletionData -> data
|
||||
is MemberCompletionData -> data.classInfo
|
||||
else -> return null
|
||||
}
|
||||
val url = StringBuilder(DOCS_BASE_URL)
|
||||
val baseName =
|
||||
if (klass.isNested) {
|
||||
klass.topLevelClass
|
||||
} else klass.className
|
||||
|
||||
if (availablePackages.find { baseName.startsWith("$it.") } == null) {
|
||||
// This package is probably not listed on Android Developers documentation
|
||||
return null
|
||||
}
|
||||
|
||||
url.append(baseName.replace('.', '/'))
|
||||
|
||||
if (klass.isNested) {
|
||||
url.append('.')
|
||||
url.append(klass.nameWithoutTopLevel)
|
||||
}
|
||||
|
||||
if (data is MemberCompletionData) {
|
||||
url.append('#')
|
||||
url.append(data.memberName)
|
||||
}
|
||||
|
||||
if (data is MethodCompletionData) {
|
||||
url.append('(')
|
||||
url.append(data.parameterTypes.joinToString(separator = ", "))
|
||||
url.append(')')
|
||||
}
|
||||
log.debug(url)
|
||||
return url.toString()
|
||||
}
|
||||
|
||||
private val log = ILogger.newInstance("DocumentationReferenceProvider")
|
||||
}
|
||||
+3
-1
@@ -19,6 +19,7 @@ package com.itsaky.androidide.lsp.java.edits
|
||||
|
||||
import com.itsaky.androidide.lsp.java.compiler.JavaCompilerService
|
||||
import com.itsaky.androidide.lsp.java.utils.EditHelper
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.CompletionItem
|
||||
import com.itsaky.androidide.lsp.util.RewriteHelper
|
||||
import io.github.rosemoe.sora.widget.CodeEditor
|
||||
@@ -38,7 +39,8 @@ class ClassImportEditHandler(val imports: Set<String>, file: Path) : IJavaEditHa
|
||||
editor: CodeEditor,
|
||||
completionItem: CompletionItem
|
||||
) {
|
||||
val className = completionItem.data!!.className
|
||||
val data = completionItem.data as? ClassCompletionData ?: return
|
||||
val className = data.className
|
||||
val edits = EditHelper.addImportIfNeeded(compiler, file, imports, className)
|
||||
RewriteHelper.performEdits(edits, editor)
|
||||
}
|
||||
|
||||
+68
-28
@@ -24,8 +24,8 @@ import com.itsaky.androidide.lsp.java.compiler.JavaCompilerService
|
||||
import com.itsaky.androidide.lsp.java.edits.ClassImportEditHandler
|
||||
import com.itsaky.androidide.lsp.java.providers.BaseJavaServiceProvider
|
||||
import com.itsaky.androidide.lsp.java.utils.EditHelper
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.Command
|
||||
import com.itsaky.androidide.lsp.models.CompletionData
|
||||
import com.itsaky.androidide.lsp.models.CompletionItem
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.ENUM_MEMBER
|
||||
@@ -36,8 +36,11 @@ import com.itsaky.androidide.lsp.models.CompletionItemKind.NONE
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.PROPERTY
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.VARIABLE
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult
|
||||
import com.itsaky.androidide.lsp.models.FieldCompletionData
|
||||
import com.itsaky.androidide.lsp.models.ICompletionData
|
||||
import com.itsaky.androidide.lsp.models.InsertTextFormat.SNIPPET
|
||||
import com.itsaky.androidide.lsp.models.MatchLevel
|
||||
import com.itsaky.androidide.lsp.models.MethodCompletionData
|
||||
import com.itsaky.androidide.progress.ProgressManager.Companion.abortIfCancelled
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.sun.source.tree.Tree
|
||||
@@ -80,6 +83,7 @@ abstract class IJavaCompletionProvider(
|
||||
protected lateinit var filePackage: String
|
||||
protected lateinit var fileImports: Set<String>
|
||||
|
||||
@Suppress("Since15")
|
||||
open fun complete(
|
||||
task: CompileTask,
|
||||
path: TreePath,
|
||||
@@ -250,7 +254,7 @@ abstract class IJavaCompletionProvider(
|
||||
item.detail = packageName(className).toString()
|
||||
item.sortText = item.label.toString()
|
||||
item.matchLevel = matchLevel
|
||||
item.data = CompletionData().apply { this.className = className }
|
||||
item.data = ClassCompletionData(className)
|
||||
|
||||
// If file is not provided, we are probably completing an import path
|
||||
item.additionalEditHandler = if (file == null) null else ClassImportEditHandler(imports, file)
|
||||
@@ -312,34 +316,70 @@ abstract class IJavaCompletionProvider(
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun data(task: CompileTask, element: Element, overloads: Int): CompletionData? {
|
||||
protected open fun data(task: CompileTask, element: Element, overloads: Int): ICompletionData? {
|
||||
abortIfCancelled()
|
||||
abortCompletionIfCancelled()
|
||||
val data = CompletionData()
|
||||
when {
|
||||
element is TypeElement -> data.className = element.qualifiedName.toString()
|
||||
element.kind == FIELD -> {
|
||||
val field = element as VariableElement
|
||||
val type = field.enclosingElement as TypeElement
|
||||
data.className = type.qualifiedName.toString()
|
||||
data.memberName = field.simpleName.toString()
|
||||
}
|
||||
element is ExecutableElement -> {
|
||||
val types = task.task.types
|
||||
val type = element.enclosingElement as TypeElement
|
||||
data.className = type.qualifiedName.toString()
|
||||
data.memberName = element.simpleName.toString()
|
||||
data.erasedParameterTypes = Array(element.parameters.size) { "" }
|
||||
for (i in 0 until data.erasedParameterTypes.size) {
|
||||
val p = element.parameters[i].asType()
|
||||
data.erasedParameterTypes[i] = types.erasure(p).toString()
|
||||
}
|
||||
data.plusOverloads = overloads - 1
|
||||
}
|
||||
else -> {
|
||||
return null
|
||||
}
|
||||
return when {
|
||||
element is TypeElement -> getClassCompletionData(element)
|
||||
element.kind == FIELD -> getFieldCompletionData(element)
|
||||
element is ExecutableElement -> getMethodCompletionData(task, element, overloads)
|
||||
else -> return null
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
protected open fun getMethodCompletionData(
|
||||
task: CompileTask,
|
||||
element: ExecutableElement,
|
||||
overloads: Int
|
||||
): MethodCompletionData {
|
||||
val types = task.task.types
|
||||
val type = element.enclosingElement as TypeElement
|
||||
val parameterTypes = Array(element.parameters.size) { "" }
|
||||
val erasedParameterTypes = Array(parameterTypes.size) { "" }
|
||||
val plusOverloads = overloads - 1
|
||||
|
||||
for (i in element.parameters.indices) {
|
||||
val p = element.parameters[i].asType()
|
||||
parameterTypes[i] = p.toString()
|
||||
erasedParameterTypes[i] = types.erasure(p).toString()
|
||||
}
|
||||
|
||||
return MethodCompletionData(
|
||||
element.simpleName.toString(),
|
||||
getClassCompletionData(type),
|
||||
parameterTypes.toList(),
|
||||
erasedParameterTypes.toList(),
|
||||
plusOverloads
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun getFieldCompletionData(element: Element): FieldCompletionData {
|
||||
val field = element as VariableElement
|
||||
val type = field.enclosingElement as TypeElement
|
||||
return FieldCompletionData(field.simpleName.toString(), getClassCompletionData(type))
|
||||
}
|
||||
|
||||
protected open fun getClassCompletionData(element: TypeElement) =
|
||||
ClassCompletionData(
|
||||
element.qualifiedName.toString(),
|
||||
element.enclosingElement.kind != PACKAGE,
|
||||
element.findTopLevelElement().qualifiedName.toString()
|
||||
)
|
||||
|
||||
protected open fun TypeElement.findTopLevelElement(): TypeElement {
|
||||
if (enclosingElement.kind == PACKAGE) {
|
||||
return this
|
||||
}
|
||||
|
||||
var element: TypeElement? = this
|
||||
while (true) {
|
||||
if (element?.enclosingElement?.kind == PACKAGE) {
|
||||
break
|
||||
}
|
||||
|
||||
element = element?.enclosingElement as? TypeElement
|
||||
}
|
||||
|
||||
return element!!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.lsp.models
|
||||
|
||||
/** Contains information about a completion item. */
|
||||
interface ICompletionData
|
||||
|
||||
/**
|
||||
* Information about a class-related completion item.
|
||||
*
|
||||
* @property className The fully qualified name of the class.
|
||||
* @property isNested Whether the given class is a nested class or not.
|
||||
* @property topLevelClass If [isNested] is true, then this must be set to the fully qualified name
|
||||
* @property simpleName The simple name of the class.
|
||||
* @property nameWithoutTopLevel The name of this class without the fully qualified name of its top
|
||||
* level class. For example, the value of this property for class name
|
||||
* `com.my.pck.MyClass.Inner.InnerInner` will be `Inner.InnerInner`
|
||||
*/
|
||||
data class ClassCompletionData
|
||||
@JvmOverloads
|
||||
constructor(val className: String, val isNested: Boolean = false, val topLevelClass: String = "") :
|
||||
ICompletionData {
|
||||
val simpleName: String
|
||||
get() {
|
||||
return className.substringAfterLast(delimiter = '.')
|
||||
}
|
||||
|
||||
val nameWithoutTopLevel: String
|
||||
get() {
|
||||
if (!isNested) {
|
||||
return className
|
||||
}
|
||||
return className.substring(topLevelClass.length + 1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a member of a class.
|
||||
*
|
||||
* @property memberName The simple name of the class member.
|
||||
* @property classInfo Information about the class [memberName] is a member of.
|
||||
*/
|
||||
interface MemberCompletionData : ICompletionData {
|
||||
val memberName: String
|
||||
val classInfo: ClassCompletionData
|
||||
}
|
||||
|
||||
/** Information about a field-related completion item. */
|
||||
data class FieldCompletionData(
|
||||
override val memberName: String,
|
||||
override val classInfo: ClassCompletionData
|
||||
) : MemberCompletionData
|
||||
|
||||
/**
|
||||
* Information about a method-related completion item.
|
||||
*
|
||||
* @property erasedParameterTypes The erased parameter types of the method.
|
||||
* @property plusOverloads The number of existing overloaded versions of this method.
|
||||
*/
|
||||
data class MethodCompletionData(
|
||||
override val memberName: String,
|
||||
override val classInfo: ClassCompletionData,
|
||||
val parameterTypes: List<String>,
|
||||
val erasedParameterTypes: List<String>,
|
||||
val plusOverloads: Int
|
||||
) : MemberCompletionData
|
||||
@@ -79,7 +79,11 @@ open class CompletionResult(items: Collection<CompletionItem>) {
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun mapAndFilter(src: CompletionResult, partial: String, map: Consumer<CompletionItem> = Consumer { }): CompletionResult {
|
||||
fun mapAndFilter(
|
||||
src: CompletionResult,
|
||||
partial: String,
|
||||
map: Consumer<CompletionItem> = Consumer {}
|
||||
): CompletionResult {
|
||||
val newItems = src.items.toMutableList()
|
||||
newItems.forEach(map)
|
||||
newItems.removeIf { !it.label.startsWith(partial) }
|
||||
@@ -120,7 +124,7 @@ open class CompletionItem(
|
||||
var kind: CompletionItemKind,
|
||||
var matchLevel: MatchLevel,
|
||||
var additionalTextEdits: List<TextEdit>?,
|
||||
var data: CompletionData?
|
||||
var data: ICompletionData?
|
||||
) :
|
||||
io.github.rosemoe.sora.lang.completion.CompletionItem(label, detail), Comparable<CompletionItem> {
|
||||
|
||||
@@ -267,54 +271,6 @@ constructor(
|
||||
val snippet: CodeSnippet? = null
|
||||
)
|
||||
|
||||
data class CompletionData(
|
||||
var className: String,
|
||||
var memberName: String,
|
||||
var erasedParameterTypes: Array<String>,
|
||||
var plusOverloads: Int
|
||||
) {
|
||||
|
||||
constructor() : this("", "", arrayOf(), -1)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (javaClass != other?.javaClass) {
|
||||
return false
|
||||
}
|
||||
|
||||
other as CompletionData
|
||||
|
||||
if (className != other.className) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (memberName != other.memberName) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!erasedParameterTypes.contentEquals(other.erasedParameterTypes)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (plusOverloads != other.plusOverloads) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = className.hashCode()
|
||||
result = 31 * result + memberName.hashCode()
|
||||
result = 31 * result + erasedParameterTypes.contentHashCode()
|
||||
result = 31 * result + plusOverloads
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
data class Command(var title: String, var command: String) {
|
||||
companion object {
|
||||
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ import com.android.aaptcompiler.ResourceTable
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.lsp.api.ICompletionProvider
|
||||
import com.itsaky.androidide.lsp.api.describeSnippet
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.Command
|
||||
import com.itsaky.androidide.lsp.models.CompletionData
|
||||
import com.itsaky.androidide.lsp.models.CompletionItem
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.CLASS
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.FIELD
|
||||
@@ -149,7 +149,7 @@ abstract class IXmlCompletionProvider(private val provider: ICompletionProvider)
|
||||
this.editHandler = TagEditHandler()
|
||||
this.matchLevel = matchLevel
|
||||
this.kind = CLASS
|
||||
this.data = CompletionData().apply { className = qualifiedName }
|
||||
this.data = ClassCompletionData(className = qualifiedName)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-6
@@ -28,12 +28,13 @@ 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.CompletionData
|
||||
import com.itsaky.androidide.lsp.models.ClassCompletionData
|
||||
import com.itsaky.androidide.lsp.models.CompletionItem
|
||||
import com.itsaky.androidide.lsp.models.CompletionItemKind.FIELD
|
||||
import com.itsaky.androidide.lsp.models.CompletionParams
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult
|
||||
import com.itsaky.androidide.lsp.models.CompletionResult.Companion.EMPTY
|
||||
import com.itsaky.androidide.lsp.models.FieldCompletionData
|
||||
import com.itsaky.androidide.lsp.models.InsertTextFormat.PLAIN_TEXT
|
||||
import com.itsaky.androidide.lsp.models.MatchLevel.NO_MATCH
|
||||
import com.itsaky.androidide.lsp.xml.providers.completion.AttrValueCompletionProvider
|
||||
@@ -72,7 +73,7 @@ class ManifestAttrValueCompletionProvider(provider: ICompletionProvider) :
|
||||
}
|
||||
return super.doComplete(params, pathData, document, type, prefix)
|
||||
}
|
||||
|
||||
|
||||
override fun resTableForFindAttr(): ResourceTable? {
|
||||
return manifestResourceTable().firstOrNull()
|
||||
}
|
||||
@@ -96,10 +97,10 @@ class ManifestAttrValueCompletionProvider(provider: ICompletionProvider) :
|
||||
// Show API information
|
||||
item.kind = FIELD
|
||||
item.data =
|
||||
CompletionData().apply {
|
||||
this.className = SdkConstants.CLASS_MANIFEST_PERMISSION
|
||||
this.memberName = value.name
|
||||
}
|
||||
FieldCompletionData(
|
||||
memberName = value.name,
|
||||
classInfo = ClassCompletionData(className = SdkConstants.CLASS_MANIFEST_PERMISSION)
|
||||
)
|
||||
result.add(item)
|
||||
}
|
||||
return CompletionResult(result)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user