feat: add LSP support in TreeSitterLanguage

This commit is contained in:
Akash Yadav
2022-12-24 20:21:52 +05:30
parent 55a090dd6d
commit 7facb96a43
9 changed files with 84 additions and 27 deletions
@@ -31,6 +31,7 @@ import com.itsaky.androidide.R.string
import com.itsaky.androidide.actions.ActionData
import com.itsaky.androidide.actions.ActionItem.Location.EDITOR_TOOLBAR
import com.itsaky.androidide.actions.ActionsRegistry.Companion.getInstance
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
import com.itsaky.androidide.editor.ui.IDEEditor
import com.itsaky.androidide.interfaces.IEditorHandler
import com.itsaky.androidide.models.OpenedFile
@@ -38,6 +39,7 @@ import com.itsaky.androidide.models.OpenedFilesCache
import com.itsaky.androidide.models.Range
import com.itsaky.androidide.models.SaveResult
import com.itsaky.androidide.projects.ProjectManager.generateSources
import com.itsaky.androidide.tasks.executeAsync
import com.itsaky.androidide.ui.editor.CodeEditorView
import com.itsaky.androidide.utils.DialogUtils.newYesNoDialog
import com.itsaky.androidide.utils.IntentUtils.openImage
@@ -150,6 +152,8 @@ open class EditorHandlerActivity : ProjectHandlerActivity(), IEditorHandler {
}
}
viewModel.openedFilesCache = null
executeAsync { IDEColorSchemeProvider.init() }
} catch (err: Throwable) {
log.error("Failed to reopen recently opened files", err)
}
@@ -22,10 +22,12 @@ import android.net.Uri
import com.blankj.utilcode.util.ThrowableUtils
import com.itsaky.androidide.BuildConfig
import com.itsaky.androidide.activities.CrashHandlerActivity
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
import com.itsaky.androidide.events.AppEventsIndex
import com.itsaky.androidide.events.LspApiEventsIndex
import com.itsaky.androidide.events.LspJavaEventsIndex
import com.itsaky.androidide.events.ProjectsApiEventsIndex
import com.itsaky.androidide.tasks.executeAsync
import com.itsaky.androidide.utils.ILogger
import com.itsaky.toaster.Toaster.Type.ERROR
import com.itsaky.toaster.toast
@@ -211,12 +211,11 @@ public class CodeEditorView extends LinearLayout {
String ext = FileUtils.getFileExtension(file);
switch (ext) {
case "java":
binding.editor.setColorScheme(IDEColorSchemeProvider.INSTANCE.getScheme());
return new TreeSitterLanguage(
getLanguageSpec(
getContext(), ext, TSLanguageJava.newInstance(), newLocalCaptureSpec(ext)),
ext);
// return new JavaLanguage();
IDEColorSchemeProvider.INSTANCE.readScheme(binding.editor::setColorScheme);
final var tsLangJava = TSLanguageJava.newInstance();
final var localsSpec = newLocalCaptureSpec(ext);
final var languageSpec = getLanguageSpec(getContext(), ext, tsLangJava, localsSpec);
return new TreeSitterLanguage(new JavaLanguage(), languageSpec, ext);
case "xml":
return new XMLLanguage();
case "gradle":
@@ -44,14 +44,11 @@ public class JavaLanguage extends IDELanguage {
private static final ILogger LOG = ILogger.newInstance("JavaLanguage");
private final NewlineHandler[] newlineHandlers;
private final CommonSymbolPairs symbolPairs = new JavaSymbolPairs();
private JavaAnalyzer analyzer;
private CommonCompletionProvider completer;
public JavaLanguage() {
final var server = getLanguageServer();
this.analyzer = new JavaAnalyzer();
this.completer = new CommonCompletionProvider(server);
this.newlineHandlers = new NewlineHandler[1];
this.newlineHandlers[0] = new BraceHandler(this::getIndentAdvance, this::useTab);
@@ -121,7 +118,6 @@ public class JavaLanguage extends IDELanguage {
@Override
public void destroy() {
analyzer = null;
completer = null;
}
public static class JavaSymbolPairs extends CommonSymbolPairs {
@@ -17,11 +17,17 @@
package com.itsaky.androidide.editor.language.treesitter
import android.os.Bundle
import com.itsaky.androidide.editor.language.IDELanguage
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
import com.itsaky.androidide.preferences.internal.useSoftTab
import com.itsaky.androidide.utils.ILogger
import io.github.rosemoe.sora.editor.ts.TsLanguage
import io.github.rosemoe.sora.editor.ts.TsLanguageSpec
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
import io.github.rosemoe.sora.lang.format.Formatter
import io.github.rosemoe.sora.lang.smartEnter.NewlineHandler
import io.github.rosemoe.sora.text.CharPosition
import io.github.rosemoe.sora.text.ContentReference
import io.github.rosemoe.sora.widget.SymbolPairMatch
/**
* Tree Sitter language implementation.
@@ -29,6 +35,7 @@ import io.github.rosemoe.sora.editor.ts.TsLanguageSpec
* @author Akash Yadav
*/
class TreeSitterLanguage(
private val lang: IDELanguage,
languageSpec: TsLanguageSpec,
type: String,
) :
@@ -36,17 +43,45 @@ class TreeSitterLanguage(
languageSpec = languageSpec,
tab = false,
themeDescription = {
val scheme = IDEColorSchemeProvider.scheme
val lang =
checkNotNull(scheme.languages[type]) { "No color scheme found for file type '$type'" }
val log = ILogger.newInstance("TreeSitterThemeBuilder")
lang.styles.forEach {
log.debug("${it.value.makeStyle()} applyTo ${it.key}")
it.value.makeStyle() applyTo it.key }
IDEColorSchemeProvider.readScheme { scheme ->
val langScheme =
checkNotNull(scheme.languages[type]) { "No color scheme found for file type '$type'" }
langScheme.styles.forEach { it.value.makeStyle() applyTo it.key }
}
}
) {
override fun getInterruptionLevel(): Int {
return lang.interruptionLevel
}
override fun requireAutoComplete(
content: ContentReference,
position: CharPosition,
publisher: CompletionPublisher,
extraArguments: Bundle
) {
lang.requireAutoComplete(content, position, publisher, extraArguments)
}
override fun useTab(): Boolean {
return !useSoftTab
return lang.useTab()
}
override fun getFormatter(): Formatter {
return lang.formatter
}
override fun getSymbolPairs(): SymbolPairMatch {
return lang.symbolPairs
}
override fun getNewlineHandlers(): Array<NewlineHandler> {
return lang.newlineHandlers ?: emptyArray()
}
override fun destroy() {
super.destroy()
lang.destroy()
}
}
@@ -47,14 +47,12 @@ class IDEColorScheme : EditorColorScheme() {
this.colorIds[++colorId] = color
return colorId
}
@Suppress("UNNECESSARY_SAFE_CALL")
override fun getColor(type: Int): Int {
// getColor is called in superclass constructor
// in this case, the below properties will be null
val result = this.editorScheme?.get(type) ?: this.colorIds?.get(type) ?: super.getColor(type)
println("getColor($type) = $result")
return result
return editorScheme?.get(type) ?: colorIds?.get(type) ?: super.getColor(type)
}
}
@@ -115,7 +113,6 @@ data class StyleDef(
private val log = ILogger.newInstance("StyleDef")
fun makeStyle() : Long {
val style = TextStyle.makeStyle(this.fg, this.bg, this.bold, this.italic, this.strikeThrough, !this.completion)
log.debug("fg: ${TextStyle.getForegroundColorId(style)}")
return style
}
}
@@ -18,15 +18,39 @@
package com.itsaky.androidide.editor.schemes
import com.itsaky.androidide.editor.schemes.internal.parser.SchemeParser
import com.itsaky.androidide.tasks.executeAsyncProvideError
import com.itsaky.androidide.utils.Environment
import com.itsaky.androidide.utils.ILogger
import java.io.File
import java.util.function.Consumer
/** @author Akash Yadav */
object IDEColorSchemeProvider {
private val log = ILogger.newInstance("IDEColorSchemeProvider")
val scheme: IDEColorScheme by lazy {
val baseSchemePath = "editor/schemes/default"
SchemeParser { File(Environment.ANDROIDIDE_UI, "$baseSchemePath/$it") }
.parse(File(Environment.ANDROIDIDE_UI, "$baseSchemePath/default.json"))
}
@JvmStatic
fun init() {
scheme
}
fun readScheme(schemeConsumer: Consumer<IDEColorScheme>) {
readScheme(schemeConsumer::accept)
}
fun readScheme(consume: (IDEColorScheme) -> Unit) {
executeAsyncProvideError({ this.scheme }) { scheme, error ->
if (scheme == null || error != null) {
log.error("Failed to read color scheme", error)
return@executeAsyncProvideError
}
consume(scheme)
}
}
}
@@ -30,7 +30,7 @@ object LocalCaptureSpecProvider {
val scheme = IDEColorSchemeProvider.scheme
val lang = scheme.languages[type] ?: return LocalsCaptureSpec.DEFAULT
return object : LocalsCaptureSpec() {
override fun isDefinitionCapture(captureName: String): Boolean {
return lang.isLocalDef(captureName)
}
Binary file not shown.