mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
build: reorganize and reconfigure modules to resolve dependency resolution errors
Gradle, for some reason, does not the path of modules to identify them uniquely. Instead, the 'build id' is used to do so, which consists of the maven group and artifact ID. So, even if two modules are located in separate directories, but have the name group and artifact ID, including both of them in other modules may result in dependency resolution errors.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
import com.itsaky.androidide.build.config.BuildConfig
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("kotlin-android")
|
||||
}
|
||||
|
||||
groupConfig {
|
||||
groupIdSuffix.set("core")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "${BuildConfig.packageName}.editor.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.androidide.ts)
|
||||
|
||||
api(projects.core.lspApi)
|
||||
api(projects.core.lspModels)
|
||||
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.logging.logger)
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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.editor.api;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.itsaky.androidide.models.Position;
|
||||
import com.itsaky.androidide.models.Range;
|
||||
|
||||
import io.github.rosemoe.sora.text.CharPosition;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Interface for other modules to access the editor.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public interface IEditor {
|
||||
|
||||
String KEY_FILE = "ide.editor.file";
|
||||
|
||||
/**
|
||||
* Get the file that this editor is currently editing.
|
||||
*
|
||||
* @return The file instance.
|
||||
*/
|
||||
@Nullable
|
||||
File getFile();
|
||||
|
||||
/**
|
||||
* Whether the content of this editor differs from the content of the file on disk.
|
||||
*
|
||||
* @return <code>true</code> if the content has been modified, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isModified();
|
||||
|
||||
/**
|
||||
* Set the selection of this editor to the given position.
|
||||
*
|
||||
* @param position The position to select.
|
||||
*/
|
||||
void setSelection(@NonNull Position position);
|
||||
|
||||
/**
|
||||
* Set selection to the given range.
|
||||
*
|
||||
* @param range The range to select.
|
||||
*/
|
||||
default void setSelection(@NonNull Range range) {
|
||||
setSelection(range.getStart(), range.getEnd());
|
||||
}
|
||||
|
||||
void setSelection(@NonNull Position start, @NonNull Position end);
|
||||
|
||||
/**
|
||||
* Set selection around the given position.
|
||||
* @param position The position to set selection around.
|
||||
*/
|
||||
default void setSelectionAround(CharPosition position) {
|
||||
setSelectionAround(position.getLine(), position.getColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selection around the given position.
|
||||
* @param position The position to set selection around.
|
||||
*/
|
||||
default void setSelectionAround(Position position) {
|
||||
setSelectionAround(position.getLine(), position.getColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set selection around the given position.
|
||||
* @param line The line index.
|
||||
* @param column The column index.
|
||||
*/
|
||||
void setSelectionAround(int line, int column);
|
||||
|
||||
/**
|
||||
* Get the cursor's selection range in the form of {@link Range}.
|
||||
*
|
||||
* @return The {@link Range} of the cursor.
|
||||
*/
|
||||
Range getCursorLSPRange();
|
||||
|
||||
/**
|
||||
* Get the cursor's position in the form of {@link Position}.
|
||||
*
|
||||
* @return The {@link Position} of the cursor.
|
||||
*/
|
||||
Position getCursorLSPPosition();
|
||||
|
||||
/**
|
||||
* Validates the range if it is invalid and returns a valid range.
|
||||
*
|
||||
* @param range Th range to validate.
|
||||
* @return A new, validated range.
|
||||
*/
|
||||
void validateRange(@NonNull Range range);
|
||||
|
||||
/**
|
||||
* Checks if the given range is valid for this editor's text.
|
||||
*
|
||||
* @param range The range to check.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
default boolean isValidRange(Range range) {
|
||||
return isValidRange(range, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given range is valid for this editor's text.
|
||||
*
|
||||
* @param range The range to check.
|
||||
* @param allowColumnEqual Whether to allow <code>column</code> to be equal to column count of *
|
||||
* <code>line</code>.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isValidRange(Range range, boolean allowColumnEqual);
|
||||
|
||||
/**
|
||||
* Checks if the given position is valid for this editor's text.
|
||||
*
|
||||
* @param position The position to check.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
default boolean isValidPosition(Position position) {
|
||||
return isValidPosition(position, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given position is valid for this editor's text.
|
||||
*
|
||||
* @param position The position to check.
|
||||
* @param allowColumnEqual Whether to allow <code>column</code> to be equal to column count of *
|
||||
* <code>line</code>.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isValidPosition(Position position, boolean allowColumnEqual);
|
||||
|
||||
/**
|
||||
* Checks if the given line is valid for this editor's text.
|
||||
*
|
||||
* @param line The line to check.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isValidLine(int line);
|
||||
|
||||
/**
|
||||
* Checks if the given column is valid for this editor's text.
|
||||
*
|
||||
* @param line The line of the column to check.
|
||||
* @param column The column to check.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
* @see #isValidColumn(int, int, boolean)
|
||||
*/
|
||||
default boolean isValidColumn(int line, int column) {
|
||||
return isValidColumn(line, column, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given column is valid for this editor's text.
|
||||
*
|
||||
* @param line The line of the column to check.
|
||||
* @param column The column to check.
|
||||
* @param allowColumnEqual Whether to allow <code>column</code> to be equal to column count of
|
||||
* <code>line</code>.
|
||||
* @return <code>true</code> if valid, <code>false</code> otherwise.
|
||||
*/
|
||||
boolean isValidColumn(int line, int column, boolean allowColumnEqual);
|
||||
|
||||
/**
|
||||
* Append the given text at the end of the editor's content.
|
||||
*
|
||||
* @param text The text to append.
|
||||
* @return The line at which the text was appended.
|
||||
*/
|
||||
int append(CharSequence text);
|
||||
|
||||
/**
|
||||
* Replaces the editor's existing content with the given content.
|
||||
*
|
||||
* @param newContent The new content to set to the editor.
|
||||
*/
|
||||
void replaceContent(CharSequence newContent);
|
||||
|
||||
/** Set the selection of the editor's cursor to the last line of the it's content. */
|
||||
void goToEnd();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.editor.api
|
||||
|
||||
import com.itsaky.androidide.lsp.api.ILanguageClient
|
||||
import com.itsaky.androidide.lsp.api.ILanguageServer
|
||||
import com.itsaky.androidide.lsp.models.Command
|
||||
import com.itsaky.androidide.lsp.models.SignatureHelp
|
||||
|
||||
/**
|
||||
* LSP functions for the editor.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
interface ILspEditor {
|
||||
/**
|
||||
* Set the language server that this editor will connect with. If the language client is not set,
|
||||
* it'll be set to [ILanguageClient] from the language server.
|
||||
*
|
||||
* @param server The server to set. Provide `null` to disable all the language server features.
|
||||
*/
|
||||
fun setLanguageServer(server: ILanguageServer?)
|
||||
|
||||
/**
|
||||
* Set the language client to this editor.
|
||||
*
|
||||
* @param client The client to set.
|
||||
*/
|
||||
fun setLanguageClient(client: ILanguageClient?)
|
||||
|
||||
/**
|
||||
* Execute the given LSP command in the editor.
|
||||
*
|
||||
* @param command The command to execute.
|
||||
*/
|
||||
fun executeCommand(command: Command?)
|
||||
|
||||
/**
|
||||
* If any language server is set, requests signature help at the cursor's position. On a valid
|
||||
* response, shows the signature help in a popup window.
|
||||
*/
|
||||
fun signatureHelp()
|
||||
|
||||
/**
|
||||
* Shows the given signature help in the editor.
|
||||
*
|
||||
* @param help The signature help data to show.
|
||||
*/
|
||||
fun showSignatureHelp(help: SignatureHelp?)
|
||||
|
||||
/**
|
||||
* If any language server is set, asks the language server to find the definition of token at the
|
||||
* cursor position.
|
||||
*
|
||||
* If the server returns a valid response, and the file specified in the response is same the file
|
||||
* in this editor, the range specified in the response will be selected.
|
||||
*/
|
||||
fun findDefinition()
|
||||
|
||||
/**
|
||||
* If any language server instance is set, finds the references to of the token at the current
|
||||
* cursor position.
|
||||
*
|
||||
* If the server returns a valid response, that response is forwarded to the [ ].
|
||||
*/
|
||||
fun findReferences()
|
||||
|
||||
/**
|
||||
* Requests the language server to provided a semantically larger selection than the current
|
||||
* selection. If a valid response is received, that range will be selected.
|
||||
*/
|
||||
fun expandSelection()
|
||||
|
||||
/** Ensures that all the windows are dismissed. */
|
||||
fun ensureWindowsDismissed()
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSInputEdit
|
||||
import com.itsaky.androidide.treesitter.TSPoint
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
class TreeSitterInputEdit @JvmOverloads internal constructor(
|
||||
startByte: Int = 0,
|
||||
oldEndByte: Int = 0,
|
||||
newEndByte: Int = 0,
|
||||
startPoint: TSPoint? = null,
|
||||
oldEndPoint: TSPoint? = null,
|
||||
newEndPoint: TSPoint? = null
|
||||
) : TSInputEdit(startByte, oldEndByte, newEndByte, startPoint, oldEndPoint, newEndPoint),
|
||||
RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Obtain an instance of [TreeSitterInputEdit].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun obtain(startByte: Int,
|
||||
oldEndByte: Int,
|
||||
newEndByte: Int,
|
||||
startPoint: TSPoint,
|
||||
oldEndPoint: TSPoint,
|
||||
newEndPoint: TSPoint): TreeSitterInputEdit {
|
||||
|
||||
return obtainFromPool<TreeSitterInputEdit>().apply {
|
||||
this.startByte = startByte
|
||||
this.oldEndByte = oldEndByte
|
||||
this.newEndByte = newEndByte
|
||||
this.startPoint = startPoint
|
||||
this.oldEndPoint = oldEndPoint
|
||||
this.newEndPoint = newEndPoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.startByte = 0
|
||||
this.oldEndByte = 0
|
||||
this.newEndByte = 0
|
||||
this.startPoint = null
|
||||
this.oldEndPoint = null
|
||||
this.newEndPoint = null
|
||||
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSLookaheadIterator
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterLookaheadIterator @JvmOverloads internal constructor(pointer: Long = 0) :
|
||||
TSLookaheadIterator(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterLookaheadIterator {
|
||||
return obtainFromPool<TreeSitterLookaheadIterator>().apply {
|
||||
nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
this.langName = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSLanguage
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterNativeLanguage @JvmOverloads internal constructor(
|
||||
name: String? = null,
|
||||
pointers: LongArray? = longArrayOf(0, 0)
|
||||
) : TSLanguage(name, pointers), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(name: String?, pointers: LongArray?): TreeSitterNativeLanguage {
|
||||
return obtainFromPool<TreeSitterNativeLanguage>().apply {
|
||||
this.name = name
|
||||
this.nativeObject = pointers?.get(0) ?: 0
|
||||
this.libHandle = pointers?.get(1) ?: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
this.name = null
|
||||
this.libHandle = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSNode
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterNode @JvmOverloads internal constructor(
|
||||
context0: Int = 0,
|
||||
context1: Int = 0,
|
||||
context2: Int = 0,
|
||||
context3: Int = 0,
|
||||
id: Long = 0,
|
||||
tree: Long = 0
|
||||
) : TSNode(context0, context1, context2, context3, id, tree),
|
||||
RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(
|
||||
context0: Int, context1: Int, context2: Int, context3: Int, id: Long, tree: Long
|
||||
): TreeSitterNode {
|
||||
return obtainFromPool<TreeSitterNode>().apply {
|
||||
this.context0 = context0
|
||||
this.context1 = context1
|
||||
this.context2 = context2
|
||||
this.context3 = context3
|
||||
this.id = id
|
||||
this.tree = tree
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.context0 = 0
|
||||
this.context1 = 0
|
||||
this.context2 = 0
|
||||
this.context3 = 0
|
||||
this.id = 0
|
||||
this.tree = 0
|
||||
this.mTree = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSInputEdit
|
||||
import com.itsaky.androidide.treesitter.TSLanguage
|
||||
import com.itsaky.androidide.treesitter.TSLookaheadIterator
|
||||
import com.itsaky.androidide.treesitter.TSNode
|
||||
import com.itsaky.androidide.treesitter.TSParser
|
||||
import com.itsaky.androidide.treesitter.TSPoint
|
||||
import com.itsaky.androidide.treesitter.TSQuery
|
||||
import com.itsaky.androidide.treesitter.TSQueryCapture
|
||||
import com.itsaky.androidide.treesitter.TSQueryCursor
|
||||
import com.itsaky.androidide.treesitter.TSQueryMatch
|
||||
import com.itsaky.androidide.treesitter.TSQueryPredicateStep
|
||||
import com.itsaky.androidide.treesitter.TSRange
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursor
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursorNode
|
||||
import com.itsaky.androidide.treesitter.string.SynchronizedUTF16String
|
||||
import com.itsaky.androidide.treesitter.string.UTF16String
|
||||
import com.itsaky.androidide.treesitter.util.TSObjectFactory
|
||||
|
||||
/**
|
||||
* [TSObjectFactory] implementation for AndroidIDE.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterObjectFactory : TSObjectFactory {
|
||||
|
||||
override fun createInputEdit(startByte: Int, oldEndByte: Int, newEndByte: Int,
|
||||
startPoint: TSPoint, oldEndPoint: TSPoint, newEndPoint: TSPoint): TSInputEdit {
|
||||
return TreeSitterInputEdit.obtain(
|
||||
startByte,
|
||||
oldEndByte,
|
||||
newEndByte,
|
||||
startPoint,
|
||||
oldEndPoint,
|
||||
newEndPoint
|
||||
)
|
||||
}
|
||||
|
||||
override fun createParser(parserPointer: Long): TSParser {
|
||||
return TreeSitterParser.obtain(parserPointer)
|
||||
}
|
||||
|
||||
override fun createQuery(queryPointer: Long): TSQuery {
|
||||
return TreeSitterQuery.obtain(queryPointer)
|
||||
}
|
||||
|
||||
override fun createQueryCursor(pointer: Long): TSQueryCursor {
|
||||
return TreeSitterQueryCursor.obtain(pointer)
|
||||
}
|
||||
|
||||
override fun createPoint(row: Int, column: Int): TSPoint {
|
||||
return TreeSitterPoint.obtain(row, column)
|
||||
}
|
||||
|
||||
override fun createRange(startByte: Int, endByte: Int, startPoint: TSPoint,
|
||||
endPoint: TSPoint?): TSRange {
|
||||
return TreeSitterRange.obtain(startByte, endByte, startPoint, endPoint)
|
||||
}
|
||||
|
||||
override fun createRangeArr(size: Int): Array<TSRange?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
|
||||
override fun createTree(pointer: Long): TSTree {
|
||||
return TreeSitterTree.obtain(pointer)
|
||||
}
|
||||
|
||||
override fun createTreeCursor(pointer: Long): TSTreeCursor {
|
||||
return TreeSitterTreeCursor.obtain(pointer)
|
||||
}
|
||||
|
||||
override fun createNode(context0: Int, context1: Int, context2: Int, context3: Int, id: Long,
|
||||
treePointer: Long): TSNode {
|
||||
return TreeSitterNode.obtain(context0, context1, context2, context3, id, treePointer)
|
||||
}
|
||||
|
||||
override fun createQueryCapture(node: TSNode?, index: Int): TSQueryCapture {
|
||||
return TreeSitterQueryCapture.obtain(node, index)
|
||||
}
|
||||
|
||||
override fun createQueryMatch(id: Int, patternIndex: Int,
|
||||
captures: Array<TSQueryCapture?>?): TSQueryMatch {
|
||||
return TreeSitterQueryMatch.obtain(id, patternIndex, captures)
|
||||
}
|
||||
|
||||
override fun createQueryPredicateStep(type: Int, valueId: Int): TSQueryPredicateStep {
|
||||
return TreeSitterQueryPredicateStep.obtain(type, valueId)
|
||||
}
|
||||
|
||||
override fun createQueryPredicateStepArr(size: Int): Array<TSQueryPredicateStep?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
|
||||
override fun createTreeCursorNode(
|
||||
type: String?,
|
||||
name: String?,
|
||||
startByte: Int,
|
||||
endByte: Int
|
||||
): TSTreeCursorNode {
|
||||
return TreeSitterTreeCursorNode.obtain(type, name, startByte, endByte)
|
||||
}
|
||||
|
||||
override fun createLookaheadIterator(pointer: Long): TSLookaheadIterator {
|
||||
return TreeSitterLookaheadIterator.obtain(pointer)
|
||||
}
|
||||
|
||||
override fun createLanguage(name: String?, pointers: LongArray?): TSLanguage {
|
||||
return TreeSitterNativeLanguage.obtain(name, pointers)
|
||||
}
|
||||
|
||||
override fun createString(pointer: Long, isSynchronized: Boolean): UTF16String {
|
||||
return if (isSynchronized) SynchronizedUTF16String(pointer) else UTF16String(pointer)
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool.Companion.CAPACITY_DEFAULT
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool.Companion.CAPACITY_MINI
|
||||
import com.itsaky.androidide.utils.newRecyclableObjectPool
|
||||
import com.itsaky.androidide.utils.uncheckedCast
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Provides instances of [RecyclableObjectPool] for tree sitter objects.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
internal object TreeSitterObjectPoolProvider {
|
||||
|
||||
private val caches = ConcurrentHashMap<Class<out RecyclableObjectPool.Recyclable>, RecyclableObjectPool<*>>()
|
||||
|
||||
init {
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterInputEdit)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterLookaheadIterator)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterNativeLanguage)
|
||||
putPool(capacity = 1_00_000, fillFirst = 1000, factory = ::TreeSitterNode)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterParser)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterPoint)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterQuery)
|
||||
putPool(capacity = 1_00_000, fillFirst = 1000, factory = ::TreeSitterQueryCapture)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterQueryCursor)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterQueryMatch)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterQueryPredicateStep)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterRange)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterTree)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterTreeCursor)
|
||||
putPool(capacity = CAPACITY_MINI, factory = ::TreeSitterTreeCursorNode)
|
||||
}
|
||||
|
||||
fun logMetrics() {
|
||||
caches.forEach { (_, pool) ->
|
||||
pool.logMetrics()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : RecyclableObjectPool.Recyclable> getPool(): RecyclableObjectPool<T>? {
|
||||
return getPool(T::class.java)
|
||||
}
|
||||
|
||||
inline fun <reified T : RecyclableObjectPool.Recyclable> requirePool(): RecyclableObjectPool<T> {
|
||||
return requireNotNull(getPool())
|
||||
}
|
||||
|
||||
fun <T : RecyclableObjectPool.Recyclable> getPool(klass: Class<T>): RecyclableObjectPool<T>? {
|
||||
return caches[klass]?.let { uncheckedCast(it) }
|
||||
}
|
||||
|
||||
fun <T : RecyclableObjectPool.Recyclable> requirePool(klass: Class<T>): RecyclableObjectPool<T> {
|
||||
return requireNotNull(getPool(klass))
|
||||
}
|
||||
|
||||
private inline fun <reified T : RecyclableObjectPool.Recyclable> putPool(
|
||||
capacity: Int = CAPACITY_DEFAULT,
|
||||
fillFirst: Int = 0,
|
||||
factory: RecyclableObjectPool.Factory<T>
|
||||
) {
|
||||
if (caches[T::class.java] != null) {
|
||||
throw IllegalArgumentException("Attempt to replace object pool for ${T::class.java}")
|
||||
}
|
||||
|
||||
// disable metrics logging for tree sitter objects
|
||||
// this is required because the log views also use tree sitter to highlight the lines
|
||||
// if we enable metrics, it would result in an infite loop and 'analyze and log' in some cases
|
||||
caches[T::class.java] = newRecyclableObjectPool(capacity, fillFirst, false, factory)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSParser
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterParser @JvmOverloads internal constructor(
|
||||
pointer: Long = 0
|
||||
) : TSParser(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(
|
||||
pointer: Long
|
||||
): TreeSitterParser {
|
||||
return obtainFromPool<TreeSitterParser>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSPoint
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterPoint @JvmOverloads internal constructor(
|
||||
row: Int = 0,
|
||||
column: Int = 0
|
||||
) : TSPoint(row, column), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(row: Int, column: Int): TreeSitterPoint {
|
||||
return obtainFromPool<TreeSitterPoint>().apply {
|
||||
this.row = row
|
||||
this.column = column
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.row = 0
|
||||
this.column = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSQuery
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterQuery @JvmOverloads internal constructor(
|
||||
pointer: Long = 0
|
||||
) : TSQuery(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterQuery {
|
||||
return obtainFromPool<TreeSitterQuery>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
this.captureNames = null
|
||||
this.errorOffset = 0
|
||||
this.errorType = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSNode
|
||||
import com.itsaky.androidide.treesitter.TSQueryCapture
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterQueryCapture @JvmOverloads internal constructor(
|
||||
node: TSNode? = null,
|
||||
index: Int = 0
|
||||
) : TSQueryCapture(node, index), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(node: TSNode?, index: Int): TreeSitterQueryCapture {
|
||||
return obtainFromPool<TreeSitterQueryCapture>().apply {
|
||||
this.node = node
|
||||
this.index = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
(this.node as? TreeSitterNode?)?.apply {
|
||||
if (!isRecycled) {
|
||||
recycle()
|
||||
}
|
||||
}
|
||||
this.index = 0
|
||||
this.node = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSQueryCursor
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterQueryCursor(
|
||||
pointer: Long = 0
|
||||
) : TSQueryCursor(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterQueryCursor {
|
||||
return obtainFromPool<TreeSitterQueryCursor>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSQueryCapture
|
||||
import com.itsaky.androidide.treesitter.TSQueryMatch
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterQueryMatch @JvmOverloads internal constructor(
|
||||
id: Int = 0,
|
||||
patternIndex: Int = 0,
|
||||
captures: Array<out TSQueryCapture?>? = null
|
||||
) : TSQueryMatch(id, patternIndex, captures, null),
|
||||
RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(id: Int, patternIndex: Int,
|
||||
captures: Array<out TSQueryCapture?>?): TreeSitterQueryMatch {
|
||||
return obtainFromPool<TreeSitterQueryMatch>().apply {
|
||||
this.id = id
|
||||
this.patternIndex = patternIndex
|
||||
this.captures = captures
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.id = 0
|
||||
this.patternIndex = 0
|
||||
this.captures = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSQueryPredicateStep
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterQueryPredicateStep @JvmOverloads internal constructor(
|
||||
type: Int = 0,
|
||||
valueId: Int = 0
|
||||
) : TSQueryPredicateStep(type, valueId), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(type: Int, valueId: Int): TreeSitterQueryPredicateStep {
|
||||
return obtainFromPool<TreeSitterQueryPredicateStep>().apply {
|
||||
this.type = type
|
||||
this.valueId = valueId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.type = 0
|
||||
this.valueId = 0
|
||||
this.cachedType = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSPoint
|
||||
import com.itsaky.androidide.treesitter.TSRange
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterRange @JvmOverloads internal constructor(
|
||||
startByte: Int = 0,
|
||||
endByte: Int = 0,
|
||||
startPoint: TSPoint? = null,
|
||||
endPoint: TSPoint? = null
|
||||
) : TSRange(startByte, endByte, startPoint, endPoint),
|
||||
RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(startByte: Int, endByte: Int, startPoint: TSPoint?,
|
||||
endPoint: TSPoint?): TreeSitterRange {
|
||||
return obtainFromPool<TreeSitterRange>().apply {
|
||||
this.startByte = startByte
|
||||
this.endByte = endByte
|
||||
this.startPoint = startPoint
|
||||
this.endPoint = endPoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
(this.startPoint as? TreeSitterPoint?)?.recycle()
|
||||
(this.endPoint as? TreeSitterPoint?)?.recycle()
|
||||
|
||||
this.startByte = 0
|
||||
this.endByte = 0
|
||||
this.startPoint = null
|
||||
this.endPoint = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterTree @JvmOverloads internal constructor(
|
||||
pointer: Long = 0
|
||||
) : TSTree(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
private var ownerThread: Thread? = null
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterTree {
|
||||
return obtainFromPool<TreeSitterTree>().apply {
|
||||
this.nativeObject = pointer
|
||||
this.ownerThread = Thread.currentThread()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
this.nativeObject = 0
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.ownerThread = null
|
||||
if (!canAccess()) {
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursor
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterTreeCursor @JvmOverloads internal constructor(
|
||||
pointer: Long = 0
|
||||
) : TSTreeCursor(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterTreeCursor {
|
||||
return obtainFromPool<TreeSitterTreeCursor>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
this.context0 = 0
|
||||
this.context1 = 0
|
||||
this.id = 0
|
||||
this.tree = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursorNode
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterTreeCursorNode @JvmOverloads internal constructor(
|
||||
type: String? = null,
|
||||
name: String? = null,
|
||||
startByte: Int = 0,
|
||||
endByte: Int = 0
|
||||
) : TSTreeCursorNode(type, name, startByte, endByte),
|
||||
RecyclableObjectPool.Recyclable by DefaultRecyclable() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(type: String?, name: String?, startByte: Int,
|
||||
endByte: Int): TreeSitterTreeCursorNode {
|
||||
return obtainFromPool<TreeSitterTreeCursorNode>().apply {
|
||||
this.type = type
|
||||
this.name = name
|
||||
this.startByte = startByte
|
||||
this.endByte = endByte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.type = null
|
||||
this.name = null
|
||||
this.startByte = 0
|
||||
this.endByte = 0
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
|
||||
/**
|
||||
* Returns this [RecyclableObjectPool.Recyclable] object to the pool from the [TreeSitterObjectPoolProvider].
|
||||
*
|
||||
* @see TreeSitterObjectPoolProvider.requirePool
|
||||
*/
|
||||
internal inline fun <reified T : RecyclableObjectPool.Recyclable> T.returnToPool() {
|
||||
TreeSitterObjectPoolProvider.requirePool<T>().recycle(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of [T] from the [RecyclableObjectPool] using [TreeSitterObjectPoolProvider].
|
||||
*
|
||||
* @see TreeSitterObjectPoolProvider.requirePool
|
||||
*/
|
||||
internal inline fun <reified T : RecyclableObjectPool.Recyclable> obtainFromPool(): T {
|
||||
return TreeSitterObjectPoolProvider.requirePool<T>().obtain()
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.treesitter.api
|
||||
|
||||
import com.itsaky.androidide.treesitter.TSNode
|
||||
import com.itsaky.androidide.treesitter.TSQuery
|
||||
import com.itsaky.androidide.treesitter.TSQueryCursor
|
||||
import com.itsaky.androidide.treesitter.TSQueryMatch
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
@PublishedApi
|
||||
internal val log = LoggerFactory.getLogger("TsUtilsKt")
|
||||
|
||||
/**
|
||||
* Safely create a query cursor and execute the given [TSQuery]. The given [action] will be called for
|
||||
* every [TSQueryMatch]. If the tree, cursor, tree or the tree's node is closed or edited while the cursor is
|
||||
* querying the node, the [onClosedOrEdited] will be called.
|
||||
*
|
||||
* This method does not close the [TSQueryCursor] instance.
|
||||
*/
|
||||
inline fun <ResultT> TSQueryCursor.safeExecQueryCursor(
|
||||
query: TSQuery,
|
||||
tree: TSTree?,
|
||||
recycleNodeAfterUse: Boolean = true,
|
||||
crossinline matchCondition: (TSQueryMatch?) -> Boolean = { true },
|
||||
crossinline whileTrue: (TSQueryMatch?) -> Boolean = { true },
|
||||
crossinline onClosedOrEdited: () -> Unit = {},
|
||||
debugName: String = "",
|
||||
debugLogging: Boolean = false,
|
||||
crossinline action: (TSQueryMatch) -> ResultT
|
||||
): ResultT? {
|
||||
|
||||
if (tree == null || !tree.canAccess()) {
|
||||
if (debugLogging) {
|
||||
log.debug("$debugName: Cannot execute query, tree is null or not accessible", "tree=$tree",
|
||||
"tree.canAccess=${tree?.canAccess()}")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val rootNode = tree.rootNode
|
||||
if (!rootNode.canAccess() || rootNode.hasChanges()) {
|
||||
if (debugLogging) {
|
||||
log.debug(
|
||||
"$debugName, Cannot execute query, tree's root node is not accessible or has been edited",
|
||||
"rootNode=$rootNode", "rootNode.canAccess=${rootNode.canAccess()}",
|
||||
"rootNode.hasChanges=${rootNode.canAccess() && rootNode.hasChanges()}")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
return safeExecQueryCursor(
|
||||
query = query,
|
||||
node = rootNode,
|
||||
recycleNodeAfterUse = recycleNodeAfterUse,
|
||||
matchCondition = {
|
||||
val result = tree.canAccess() && matchCondition(it)
|
||||
if (!result && debugLogging) {
|
||||
log.debug("$debugName: tree.canAccess=${tree.canAccess()}")
|
||||
}
|
||||
result
|
||||
},
|
||||
whileTrue = whileTrue,
|
||||
onClosedOrEdited = onClosedOrEdited,
|
||||
debugName = debugName,
|
||||
debugLogging = debugLogging,
|
||||
action = action
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely create a query cursor and execute the given [TSQuery]. The given [action] will be called for
|
||||
* every [TSQueryMatch]. If the tree, cursor or the node is closed or edited while the cursor is
|
||||
* querying the node, the [onClosedOrEdited] will be called.
|
||||
*
|
||||
* This method does not close the [TSQueryCursor] instance.
|
||||
*/
|
||||
inline fun <ResultT> TSQueryCursor.safeExecQueryCursor(
|
||||
query: TSQuery,
|
||||
node: TSNode,
|
||||
recycleNodeAfterUse: Boolean = true,
|
||||
crossinline matchCondition: (TSQueryMatch?) -> Boolean = { true },
|
||||
crossinline whileTrue: (TSQueryMatch?) -> Boolean = { true },
|
||||
crossinline onClosedOrEdited: () -> Unit = {},
|
||||
debugName: String = "",
|
||||
debugLogging: Boolean = false,
|
||||
crossinline action: (TSQueryMatch) -> ResultT
|
||||
): ResultT? {
|
||||
|
||||
return doSafeExecQueryCursor(
|
||||
query = query,
|
||||
node = node,
|
||||
recycleNodeAfterUse = recycleNodeAfterUse,
|
||||
matchCondition = { match ->
|
||||
match != null && canAccess() && node.canAccess() && !node.hasChanges() && matchCondition(
|
||||
match)
|
||||
},
|
||||
whileTrue = whileTrue,
|
||||
onClosedOrEdited = onClosedOrEdited,
|
||||
debugName = debugName,
|
||||
debugLogging = debugLogging,
|
||||
action = action)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal inline fun <ResultT> TSQueryCursor.doSafeExecQueryCursor(
|
||||
query: TSQuery,
|
||||
node: TSNode,
|
||||
recycleNodeAfterUse: Boolean = true,
|
||||
crossinline matchCondition: (TSQueryMatch?) -> Boolean,
|
||||
crossinline whileTrue: (TSQueryMatch?) -> Boolean,
|
||||
crossinline onClosedOrEdited: () -> Unit,
|
||||
debugName: String = "",
|
||||
debugLogging: Boolean = false,
|
||||
crossinline action: (TSQueryMatch) -> ResultT
|
||||
): ResultT? {
|
||||
|
||||
if (!query.canAccess()) {
|
||||
if (debugLogging) {
|
||||
log.debug("$debugName: Cannot execute query, query is not accessible")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (!node.canAccess() || node.hasChanges()) {
|
||||
if (debugLogging) {
|
||||
log.debug("$debugName: Cannot execute query, node is not accessible or has been edited",
|
||||
"node.canAccess=${node.canAccess()}",
|
||||
"node.hasChanges=${node.canAccess() && node.hasChanges()}")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
exec(query, node)
|
||||
var match = nextMatch()
|
||||
while (matchCondition(match) && whileTrue(match)) {
|
||||
|
||||
val result = action(match)
|
||||
|
||||
if (!matchCondition(match)) {
|
||||
if (debugLogging) {
|
||||
log.debug(
|
||||
"$debugName: Cannot proceed with query operation.",
|
||||
"cursor.canAccess=${canAccess()}",
|
||||
"query.canAccess=${query.canAccess()}",
|
||||
"node.canAccess=${node.canAccess()}",
|
||||
"node.hasChanges=${node.canAccess() && node.hasErrors()}"
|
||||
)
|
||||
}
|
||||
onClosedOrEdited()
|
||||
break
|
||||
}
|
||||
|
||||
(match as? TreeSitterQueryMatch?)?.recycle()
|
||||
|
||||
// if the action does not produce any output and simply returns Unit (void)
|
||||
// then ignore the result and continue with the capture
|
||||
if (result != Unit && result != null) {
|
||||
return result
|
||||
}
|
||||
|
||||
match = nextMatch()
|
||||
}
|
||||
|
||||
if (recycleNodeAfterUse && node is TreeSitterNode && !node.isRecycled) {
|
||||
node.recycle()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -7,6 +7,10 @@ plugins {
|
||||
id("com.google.devtools.ksp") version libs.versions.ksp
|
||||
}
|
||||
|
||||
groupConfig {
|
||||
groupIdSuffix.set("core")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "${BuildConfig.packageName}.editor"
|
||||
}
|
||||
@@ -18,8 +22,8 @@ kapt {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
ksp(projects.annotationProcessorsKsp)
|
||||
kapt(projects.annotationProcessors)
|
||||
ksp(projects.annotation.processorsKsp)
|
||||
kapt(projects.annotation.processors)
|
||||
|
||||
api(libs.androidide.ts)
|
||||
api(libs.androidide.ts.java)
|
||||
@@ -30,8 +34,8 @@ dependencies {
|
||||
api(libs.androidx.collection)
|
||||
api(libs.common.editor)
|
||||
|
||||
api(projects.editorApi)
|
||||
api(projects.editorTreesitter)
|
||||
api(projects.editor.api)
|
||||
api(projects.editor.treesitter)
|
||||
|
||||
implementation(libs.androidx.annotation)
|
||||
implementation(libs.androidx.appcompat)
|
||||
@@ -42,20 +46,19 @@ dependencies {
|
||||
implementation(libs.common.utilcode)
|
||||
|
||||
implementation(libs.google.material)
|
||||
|
||||
implementation(projects.actions)
|
||||
implementation(projects.annotations)
|
||||
implementation(projects.common)
|
||||
implementation(projects.eventbusAndroid)
|
||||
implementation(projects.eventbusEvents)
|
||||
implementation(projects.lexers)
|
||||
implementation(projects.shared)
|
||||
implementation(projects.resources)
|
||||
|
||||
implementation(projects.lsp.api)
|
||||
implementation(projects.lsp.java)
|
||||
implementation(projects.lsp.xml)
|
||||
|
||||
|
||||
implementation(projects.annotation.annotations)
|
||||
implementation(projects.core.actions)
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.core.lspApi)
|
||||
implementation(projects.core.resources)
|
||||
implementation(projects.editor.lexers)
|
||||
implementation(projects.event.eventbusAndroid)
|
||||
implementation(projects.event.eventbusEvents)
|
||||
implementation(projects.java.lsp)
|
||||
implementation(projects.utilities.shared)
|
||||
implementation(projects.xml.lsp)
|
||||
|
||||
testImplementation(libs.tests.junit)
|
||||
testImplementation(libs.tests.google.truth)
|
||||
testImplementation(libs.tests.robolectric)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user