fix(lsp/java): invalid indentation in snippets

This commit is contained in:
Akash Yadav
2023-03-31 18:22:57 +05:30
parent 80f74d0d27
commit fd4ce13724
2 changed files with 35 additions and 15 deletions
@@ -46,7 +46,6 @@ import com.itsaky.androidide.lsp.models.MethodCompletionData
import com.itsaky.androidide.preferences.utils.indentationString
import com.itsaky.androidide.progress.ProgressManager.Companion.abortIfCancelled
import com.itsaky.androidide.utils.ILogger
import java.nio.file.Path
import jdkx.lang.model.element.Element
import jdkx.lang.model.element.ElementKind.ANNOTATION_TYPE
import jdkx.lang.model.element.ElementKind.CLASS
@@ -70,6 +69,7 @@ import jdkx.lang.model.element.TypeElement
import jdkx.lang.model.element.VariableElement
import openjdk.source.tree.Tree
import openjdk.source.util.TreePath
import java.nio.file.Path
/**
* Completion provider for Java source code.
@@ -293,20 +293,26 @@ abstract class IJavaCompletionProvider(
}
}
protected open fun snippetItem(snippet: JavaSnippet, matchLevel: MatchLevel, partial: String, indent: Int) : CompletionItem {
protected open fun snippetItem(
snippet: JavaSnippet,
matchLevel: MatchLevel,
partial: String,
indent: Int
): CompletionItem {
return JavaCompletionItem().apply {
this.label = snippet.prefix
this.detail = snippet.description
this.completionKind = CompletionItemKind.SNIPPET
this.matchLevel = matchLevel
this.ideSortText = "00000${snippet.prefix}"
this.snippetDescription = describeSnippet(snippet.prefix)
this.snippetDescription = describeSnippet(partial)
val indentation = indentationString(indent)
this.insertTextFormat = SNIPPET
this.insertText = snippet.content.joinToString(separator = "\n") {
indentation + it.replace("\t", indentationString)
}
this.insertText =
snippet.content.joinToString(separator = "\n").also {
it.replace("\t", indentationString).replace("\n", "\n${indentation}")
}
}
}
@@ -23,11 +23,11 @@ import com.itsaky.androidide.lsp.java.compiler.JavaCompilerService
import com.itsaky.androidide.lsp.java.providers.snippet.JavaSnippet
import com.itsaky.androidide.lsp.java.providers.snippet.JavaSnippetRepository
import com.itsaky.androidide.lsp.java.providers.snippet.JavaSnippetScope
import com.itsaky.androidide.lsp.java.utils.EditHelper
import com.itsaky.androidide.lsp.models.CompletionItem
import com.itsaky.androidide.lsp.models.CompletionResult
import com.itsaky.androidide.lsp.models.MatchLevel
import com.itsaky.androidide.preferences.internal.tabSize
import io.github.rosemoe.sora.text.TextUtils
import java.nio.file.Path
import openjdk.source.tree.ClassTree
import openjdk.source.tree.CompilationUnitTree
@@ -53,14 +53,28 @@ class SnippetCompletionProvider(
endsWithParen: Boolean
): CompletionResult {
val scope = findSnippetScope(path) ?: return CompletionResult.EMPTY
val indent = spacesBeforeCursor(task.root().sourceFile.getCharContent(true))
return when (scope.leaf) {
is CompilationUnitTree -> completeTopLevelSnippets(task, path, partial)
is ClassTree -> completeMemberSnippets(task, path, partial)
is MethodTree -> completeLocalSnippets(task, path, partial)
is MethodTree -> completeLocalSnippets(task, path, partial, indent)
else -> CompletionResult.EMPTY
}
}
private fun spacesBeforeCursor(charContent: CharSequence?): Int {
charContent ?: return 0
var start = cursor.toInt()
while (start >= 0) {
val c = charContent[start]
if (c == '\n' || !c.isWhitespace()) {
break
}
--start
}
return TextUtils.countLeadingSpaceCount(charContent.substring(start, cursor.toInt()), tabSize)
}
private fun completeTopLevelSnippets(
task: CompileTask,
path: TreePath,
@@ -80,7 +94,8 @@ class SnippetCompletionProvider(
private fun completeLocalSnippets(
task: CompileTask,
path: TreePath,
partial: String
partial: String,
indent: Int
): CompletionResult {
val items = mutableListOf<CompletionItem>()
val snippets =
@@ -89,7 +104,6 @@ class SnippetCompletionProvider(
JavaSnippetRepository.snippets[JavaSnippetScope.GLOBAL]?.let { addAll(it) }
}
val indent = EditHelper.indent(task.task, task.root(), path.leaf) - tabSize
for (snippet in snippets) {
val matchLevel = matchLevel(snippet.prefix, partial)
if (matchLevel == MatchLevel.NO_MATCH) {
@@ -103,12 +117,12 @@ class SnippetCompletionProvider(
}
private fun findSnippetScope(path: TreePath?): TreePath? {
var treePath = path
while (treePath != null) {
if (treePath.leaf.let { it is CompilationUnitTree || it is ClassTree || it is MethodTree }) {
return treePath
var scope = path
while (scope != null) {
if (scope.leaf.let { it is CompilationUnitTree || it is ClassTree || it is MethodTree }) {
return scope
}
treePath = treePath.parentPath
scope = scope.parentPath
}
return null
}