Added insertion handlers for XML completion items

This commit is contained in:
Akash Yadav
2022-09-06 12:27:30 +05:30
parent d5e77be04e
commit 64aff3bee0
4 changed files with 67 additions and 38 deletions
@@ -49,20 +49,27 @@ open class DefaultEditHandler : IEditHandler {
ThreadUtils.runOnUiThread { performEditsInternal(item, editor, text, line, column, index) }
return
}
performEditsInternal(item, editor, text, line, column, index)
}
private fun performEditsInternal(item: CompletionItem, editor: CodeEditor, text: Content, line: Int, column: Int, index: Int) {
private fun performEditsInternal(
item: CompletionItem,
editor: CodeEditor,
text: Content,
line: Int,
column: Int,
index: Int
) {
if (item.insertTextFormat == SNIPPET) {
insertSnippet(item, editor, text, line, column, index)
return
}
val start = getIdentifierStart(text.getLine(line), column)
text.delete(line, start, line, column)
editor.commitText(item.insertText)
text.beginBatchEdit()
if (item.additionalEditHandler != null) {
item.additionalEditHandler!!.performEdits(item, editor, text, line, column, index)
@@ -70,11 +77,18 @@ open class DefaultEditHandler : IEditHandler {
RewriteHelper.performEdits(item.additionalTextEdits!!, editor)
}
text.beginBatchEdit()
executeCommand(editor, item.command)
}
protected open fun insertSnippet(item: CompletionItem, editor: CodeEditor, text: Content, line: Int, column: Int, index: Int) {
protected open fun insertSnippet(
item: CompletionItem,
editor: CodeEditor,
text: Content,
line: Int,
column: Int,
index: Int
) {
item.snippetDescription!!
val snippet = CodeSnippetParser.parse(item.insertText)
val prefixLength = item.snippetDescription!!.selectedLength
@@ -86,7 +100,7 @@ open class DefaultEditHandler : IEditHandler {
}
editor.snippetController.startSnippet(actionIndex, snippet, selectedText)
}
protected open fun executeCommand(editor: CodeEditor, command: Command?) {
if (command == null) {
return
@@ -104,7 +118,7 @@ open class DefaultEditHandler : IEditHandler {
protected open fun getIdentifierStart(text: CharSequence, end: Int): Int {
var start = end
while (start > 0) {
if (Character.isJavaIdentifierPart(text[start - 1])) {
if (isPartialPart(text[start - 1])) {
start--
continue
}
@@ -112,4 +126,6 @@ open class DefaultEditHandler : IEditHandler {
}
return start
}
protected open fun isPartialPart(c: Char) = Character.isJavaIdentifierPart(c)
}
@@ -17,6 +17,7 @@
package com.itsaky.androidide.lsp.xml.edits
import com.itsaky.androidide.lsp.edits.DefaultEditHandler
import com.itsaky.androidide.lsp.edits.IEditHandler
import com.itsaky.androidide.lsp.models.CompletionItem
import io.github.rosemoe.sora.text.Content
@@ -28,32 +29,9 @@ import io.github.rosemoe.sora.widget.CodeEditor
*
* @author Akash Yadav
*/
class QualifiedValueEditHandler : IEditHandler {
override fun performEdits(item: CompletionItem, editor: CodeEditor, text: Content, line: Int, column: Int, index: Int) {
val cursor = editor.cursor
val text = editor.text
val line = cursor.leftLine
val column = cursor.leftColumn
val start = getIdentifierStart(text.getLine(line), column)
text.delete(line, start, line, column)
// Do not use CompletionItem.insertText as it is always '.'
editor.commitText(
item.label
)
}
private fun getIdentifierStart(text: CharSequence, end: Int): Int {
var start = end
while (start > 0) {
val c = text[start - 1]
if (Character.isJavaIdentifierPart(c) || c == '.') {
start--
continue
}
break
}
return start
open class QualifiedValueEditHandler : DefaultEditHandler() {
override fun isPartialPart(c: Char): Boolean {
return super.isPartialPart(c) || c == '.' // Tags can contain '.' as well
}
}
@@ -0,0 +1,30 @@
/*
* 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.xml.edits
/**
* Handles insertion of a tag name.
*
* @author Akash Yadav
*/
open class TagEditHandler : QualifiedValueEditHandler() {
override fun isPartialPart(c: Char): Boolean {
return super.isPartialPart(c) || c == '-' // Tags can contain '-' as well
}
}
@@ -33,6 +33,8 @@ import com.itsaky.androidide.lsp.models.CompletionParams
import com.itsaky.androidide.lsp.models.CompletionResult
import com.itsaky.androidide.lsp.models.InsertTextFormat.SNIPPET
import com.itsaky.androidide.lsp.models.MatchLevel
import com.itsaky.androidide.lsp.xml.edits.QualifiedValueEditHandler
import com.itsaky.androidide.lsp.xml.edits.TagEditHandler
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE
import com.itsaky.androidide.lsp.xml.utils.XmlUtils.NodeType.ATTRIBUTE_VALUE
@@ -101,7 +103,7 @@ abstract class IXmlCompletionProvider(private val provider: ICompletionProvider)
this.attrAtCursor =
document.findAttrAt(params.position.requireIndex()) ?: return CompletionResult.EMPTY
}
this.allNamespaces = findAllNamespaces(this.nodeAtCursor)
return doComplete(params, pathData, document, type, prefix)
}
@@ -140,6 +142,7 @@ abstract class IXmlCompletionProvider(private val provider: ICompletionProvider)
this.label = simpleName
this.detail = qualifiedName
this.sortText = label.toString()
this.editHandler = TagEditHandler()
this.matchLevel = matchLevel
this.kind = CLASS
this.data = CompletionData().apply { className = qualifiedName }
@@ -210,6 +213,7 @@ abstract class IXmlCompletionProvider(private val provider: ICompletionProvider)
this.overrideTypeText = type.uppercase()
this.sortText = if (pck == ResourceTableRegistry.PCK_ANDROID) "zzz$text" else text
this.insertText = text
this.editHandler = QualifiedValueEditHandler()
this.matchLevel = matchLevel
}
}
@@ -232,6 +236,7 @@ abstract class IXmlCompletionProvider(private val provider: ICompletionProvider)
this.kind = VALUE
this.sortText = "000$name"
this.insertText = name
this.editHandler = QualifiedValueEditHandler()
this.matchLevel = matchLevel
}
}