mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
fix(editor): various improvements related to tree sitter code analysis
- Integrate the 'language-treesitter' module from sora-editor into the IDE itself for better control and customization of the tree sitter analysis. - Invalidate line span generator when tree is edited - This is required because TSTree instances are not thread-safe and the spans generator tries to query the tree after it is edited. This results in SEGV_MAPERR errors in native code because the TSNodes are invalidatd after TSTree.edit() calls and the cursor tries to query those invalidated nodes. - Recycle and reuse TS* instances - When analyzing the source code using Tree Sitter, a huge number of objects are created and deleted. This results in an increased of times the garbage collector is invoked.
This commit is contained in:
@@ -25,6 +25,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.androidide.ts)
|
||||
api(projects.lsp.api)
|
||||
api(projects.lsp.models)
|
||||
|
||||
|
||||
@@ -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 java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
internal class DefaultSynchronized(
|
||||
// disabled by default
|
||||
private val isEnabled: Boolean = false
|
||||
) : TSSynchronized {
|
||||
|
||||
private val lock = ReentrantLock()
|
||||
|
||||
override fun lock(timeout: Long, unit: TimeUnit): Boolean {
|
||||
return if (isEnabled) {
|
||||
require(timeout > 0) { "Timeout must be greater than 0" }
|
||||
lock.tryLock() || lock.tryLock(timeout, unit)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun unlock() {
|
||||
if (isEnabled) {
|
||||
lock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> withLock(timeout: Long, unit: TimeUnit, action: () -> T): T {
|
||||
if (!isEnabled) {
|
||||
return action()
|
||||
}
|
||||
|
||||
check(lock(timeout, unit)) { "Failed to acquire lock" }
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Synchronization for tree sitter objects.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
interface TSSynchronized {
|
||||
|
||||
/**
|
||||
* Acquires the lock. Throws an [IllegalStateException] if the lock can not be acquired within
|
||||
* the given [timeout].
|
||||
*
|
||||
* @param timeout The timeout duration.
|
||||
* @param unit The time unit for the timeout duration.
|
||||
* @return Whether the lock was held or not.
|
||||
*/
|
||||
fun lock(timeout: Long = 3, unit: TimeUnit = TimeUnit.SECONDS): Boolean
|
||||
|
||||
/**
|
||||
* Releases the lock.
|
||||
*/
|
||||
fun unlock()
|
||||
|
||||
/**
|
||||
* Execute the given [action] with the lock. The lock will be held before executing the action
|
||||
* and finally released. Throws an [IllegalStateException] if the lock can not be acquired within
|
||||
* * the given [timeout].
|
||||
*
|
||||
* @param timeout The timeout duration.
|
||||
* @param unit The time unit for the timeout duration.
|
||||
* @param action The action to perform.
|
||||
*/
|
||||
fun <T : Any?> withLock(timeout: Long = 3, unit: TimeUnit = TimeUnit.SECONDS, action: () -> T): T
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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(), TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
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() {
|
||||
withLock {
|
||||
this.startByte = 0
|
||||
this.oldEndByte = 0
|
||||
this.newEndByte = 0
|
||||
this.startPoint = null
|
||||
this.oldEndPoint = null
|
||||
this.newEndPoint = null
|
||||
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
}
|
||||
+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.treesitter.TSLanguage
|
||||
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(),
|
||||
TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterLookaheadIterator {
|
||||
return obtainFromPool<TreeSitterLookaheadIterator>().apply {
|
||||
nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun next(): Boolean {
|
||||
return withLock {
|
||||
super.next()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCurrentSymbol(): Short {
|
||||
return withLock {
|
||||
super.getCurrentSymbol()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCurrentSymbolName(): String {
|
||||
return withLock {
|
||||
super.getCurrentSymbolName()
|
||||
}
|
||||
}
|
||||
|
||||
override fun resetState(stateId: Short): Boolean {
|
||||
return withLock {
|
||||
super.resetState(stateId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset(language: TSLanguage?, stateId: Short): Boolean {
|
||||
return withLock {
|
||||
super.reset(language, stateId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLanguage(): TSLanguage {
|
||||
return withLock {
|
||||
super.getLanguage()
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
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,226 @@
|
||||
/*
|
||||
* 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.TSPoint
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursor
|
||||
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(), TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
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 getTree(): TSTree {
|
||||
return withLock { super.getTree() }
|
||||
}
|
||||
|
||||
override fun getChild(index: Int): TSNode {
|
||||
return withLock { super.getChild(index) }
|
||||
}
|
||||
|
||||
override fun getNamedChild(index: Int): TSNode {
|
||||
return withLock { super.getNamedChild(index) }
|
||||
}
|
||||
|
||||
override fun getChildByFieldName(fieldName: String?): TSNode {
|
||||
return withLock { super.getChildByFieldName(fieldName) }
|
||||
}
|
||||
|
||||
override fun walk(): TSTreeCursor {
|
||||
return withLock { super.walk() }
|
||||
}
|
||||
|
||||
override fun findNodeWithType(type: String?, namedOnly: Boolean): TSNode {
|
||||
return withLock { super.findNodeWithType(type, namedOnly) }
|
||||
}
|
||||
|
||||
override fun findChildrenWithType(type: String?, reverseSearch: Boolean,
|
||||
namedOnly: Boolean): MutableList<TSNode> {
|
||||
return withLock { super.findChildrenWithType(type, reverseSearch, namedOnly) }
|
||||
}
|
||||
|
||||
override fun findChildrenWithTypeReverse(type: String?, namedOnly: Boolean): MutableList<TSNode> {
|
||||
return withLock { super.findChildrenWithTypeReverse(type, namedOnly) }
|
||||
}
|
||||
|
||||
override fun getParent(): TSNode {
|
||||
return withLock { super.getParent() }
|
||||
}
|
||||
|
||||
override fun getFieldNameForChild(p0: Int): String {
|
||||
return withLock { super.getFieldNameForChild(p0) }
|
||||
}
|
||||
|
||||
override fun getChildByFieldId(p0: Int): TSNode {
|
||||
return withLock { super.getChildByFieldId(p0) }
|
||||
}
|
||||
|
||||
override fun getNextSibling(): TSNode {
|
||||
return withLock { super.getNextSibling() }
|
||||
}
|
||||
|
||||
override fun getPreviousSibling(): TSNode {
|
||||
return withLock { super.getPreviousSibling() }
|
||||
}
|
||||
|
||||
override fun getNextNamedSibling(): TSNode {
|
||||
return withLock { super.getNextNamedSibling() }
|
||||
}
|
||||
|
||||
override fun getPreviousNamedSibling(): TSNode {
|
||||
return withLock { super.getPreviousNamedSibling() }
|
||||
}
|
||||
|
||||
override fun getFirstChildForByte(p0: Int): TSNode {
|
||||
return withLock { super.getFirstChildForByte(p0) }
|
||||
}
|
||||
|
||||
override fun getFirstNamedChildForByte(p0: Int): TSNode {
|
||||
return withLock { super.getFirstNamedChildForByte(p0) }
|
||||
}
|
||||
|
||||
override fun getDescendantForByteRange(p0: Int, p1: Int): TSNode {
|
||||
return withLock { super.getDescendantForByteRange(p0, p1) }
|
||||
}
|
||||
|
||||
override fun getDescendantForPointRange(p0: TSPoint?, p1: TSPoint?): TSNode {
|
||||
return withLock { super.getDescendantForPointRange(p0, p1) }
|
||||
}
|
||||
|
||||
override fun getNamedDescendantForByteRange(p0: Int, p1: Int): TSNode {
|
||||
return withLock { super.getNamedDescendantForByteRange(p0, p1) }
|
||||
}
|
||||
|
||||
override fun getNamedDescendantForPointRange(p0: TSPoint?, p1: TSPoint?): TSNode? {
|
||||
return withLock { super.getNamedDescendantForPointRange(p0, p1) }
|
||||
}
|
||||
|
||||
override fun isEqualTo(p0: TSNode?): Boolean {
|
||||
return withLock { super.isEqualTo(p0) }
|
||||
}
|
||||
|
||||
override fun getChildCount(): Int {
|
||||
return withLock { super.getChildCount() }
|
||||
}
|
||||
|
||||
override fun getNamedChildCount(): Int {
|
||||
return withLock { super.getNamedChildCount() }
|
||||
}
|
||||
|
||||
override fun getNodeString(): String {
|
||||
return withLock { super.getNodeString() }
|
||||
}
|
||||
|
||||
override fun getStartByte(): Int {
|
||||
return withLock { super.getStartByte() }
|
||||
}
|
||||
|
||||
override fun getEndByte(): Int {
|
||||
return withLock { super.getEndByte() }
|
||||
}
|
||||
|
||||
override fun getStartPoint(): TSPoint {
|
||||
return withLock { super.getStartPoint() }
|
||||
}
|
||||
|
||||
override fun getEndPoint(): TSPoint {
|
||||
return withLock { super.getEndPoint() }
|
||||
}
|
||||
|
||||
override fun getType(): String {
|
||||
return withLock { super.getType() }
|
||||
}
|
||||
|
||||
override fun getSymbol(): Int {
|
||||
return withLock { super.getSymbol() }
|
||||
}
|
||||
|
||||
override fun isNull(): Boolean {
|
||||
return withLock { super.isNull() }
|
||||
}
|
||||
|
||||
override fun isNamed(): Boolean {
|
||||
return withLock { super.isNamed() }
|
||||
}
|
||||
|
||||
override fun isExtra(): Boolean {
|
||||
return withLock { super.isExtra() }
|
||||
}
|
||||
|
||||
override fun isMissing(): Boolean {
|
||||
return withLock { super.isMissing() }
|
||||
}
|
||||
|
||||
override fun hasChanges(): Boolean {
|
||||
return withLock { super.hasChanges() }
|
||||
}
|
||||
|
||||
override fun hasErrors(): Boolean {
|
||||
return withLock { super.hasErrors() }
|
||||
}
|
||||
|
||||
override fun isError(): Boolean {
|
||||
return withLock { super.isError() }
|
||||
}
|
||||
|
||||
override fun getParseState(): Short {
|
||||
return withLock { super.getParseState() }
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
withLock {
|
||||
this.context0 = 0
|
||||
this.context1 = 0
|
||||
this.context2 = 0
|
||||
this.context3 = 0
|
||||
this.id = 0
|
||||
this.tree = 0
|
||||
this.mTree = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.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)
|
||||
}
|
||||
}
|
||||
+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,87 @@
|
||||
/*
|
||||
* 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.treesitter.TSParser
|
||||
import com.itsaky.androidide.treesitter.TSRange
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import com.itsaky.androidide.treesitter.string.UTF16String
|
||||
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(),
|
||||
TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(
|
||||
pointer: Long
|
||||
): TreeSitterParser {
|
||||
return obtainFromPool<TreeSitterParser>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLanguage(language: TSLanguage?) {
|
||||
withLock { super.setLanguage(language) }
|
||||
}
|
||||
|
||||
override fun parseString(oldTree: TSTree?, source: UTF16String?): TSTree {
|
||||
return withLock { super.parseString(oldTree, source) }
|
||||
}
|
||||
|
||||
override fun setTimeout(microseconds: Long) {
|
||||
withLock { super.setTimeout(microseconds) }
|
||||
}
|
||||
|
||||
override fun getTimeout(): Long {
|
||||
return withLock { super.getTimeout() }
|
||||
}
|
||||
|
||||
override fun setIncludedRanges(ranges: Array<out TSRange>?): Boolean {
|
||||
return withLock { super.setIncludedRanges(ranges) }
|
||||
}
|
||||
|
||||
override fun getIncludedRanges(): Array<TSRange> {
|
||||
return withLock { super.getIncludedRanges() }
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
withLock { super.reset() }
|
||||
}
|
||||
|
||||
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,106 @@
|
||||
/*
|
||||
* 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.TSQuantifier
|
||||
import com.itsaky.androidide.treesitter.TSQuery
|
||||
import com.itsaky.androidide.treesitter.TSQueryPredicateStep
|
||||
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(),
|
||||
TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterQuery {
|
||||
return obtainFromPool<TreeSitterQuery>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCaptureCount(): Int {
|
||||
return withLock { super.getCaptureCount() }
|
||||
}
|
||||
|
||||
override fun getPatternCount(): Int {
|
||||
return withLock { super.getPatternCount() }
|
||||
}
|
||||
|
||||
override fun getStringCount(): Int {
|
||||
return withLock { super.getStringCount() }
|
||||
}
|
||||
|
||||
override fun getCaptureNames(): Array<String> {
|
||||
return withLock { super.getCaptureNames() }
|
||||
}
|
||||
|
||||
override fun getStartByteForPattern(pattern: Int): Int {
|
||||
return withLock { super.getStartByteForPattern(pattern) }
|
||||
}
|
||||
|
||||
override fun getPredicatesForPattern(pattern: Int): Array<TSQueryPredicateStep> {
|
||||
return withLock { super.getPredicatesForPattern(pattern) }
|
||||
}
|
||||
|
||||
override fun isPatternRooted(pattern: Int): Boolean {
|
||||
return withLock { super.isPatternRooted(pattern) }
|
||||
}
|
||||
|
||||
override fun isPatternNonLocal(pattern: Int): Boolean {
|
||||
return withLock { super.isPatternNonLocal(pattern) }
|
||||
}
|
||||
|
||||
override fun isPatternGuaranteedAtStep(offset: Int): Boolean {
|
||||
return withLock { super.isPatternGuaranteedAtStep(offset) }
|
||||
}
|
||||
|
||||
override fun getCaptureNameForId(id: Int): String {
|
||||
return withLock { super.getCaptureNameForId(id) }
|
||||
}
|
||||
|
||||
override fun getStringValueForId(id: Int): String {
|
||||
return withLock { super.getStringValueForId(id) }
|
||||
}
|
||||
|
||||
override fun getCaptureQuantifierForId(pattern: Int, capture: Int): TSQuantifier {
|
||||
return withLock { super.getCaptureQuantifierForId(pattern, capture) }
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
super.close()
|
||||
recycle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.nativeObject = 0
|
||||
this.captureNames = null
|
||||
this.errorOffset = 0
|
||||
this.errorType = 0
|
||||
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.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?)?.recycle()
|
||||
this.index = 0
|
||||
this.node = null
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.TSPoint
|
||||
import com.itsaky.androidide.treesitter.TSQuery
|
||||
import com.itsaky.androidide.treesitter.TSQueryCursor
|
||||
import com.itsaky.androidide.treesitter.TSQueryMatch
|
||||
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(),
|
||||
TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterQueryCursor {
|
||||
return obtainFromPool<TreeSitterQueryCursor>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun exec(query: TSQuery?, node: TSNode?) {
|
||||
withLock { super.exec(query, node) }
|
||||
}
|
||||
|
||||
override fun didExceedMatchLimit(): Boolean {
|
||||
return withLock { super.didExceedMatchLimit() }
|
||||
}
|
||||
|
||||
override fun getMatchLimit(): Int {
|
||||
return withLock { super.getMatchLimit() }
|
||||
}
|
||||
|
||||
override fun setMatchLimit(newLimit: Int) {
|
||||
withLock { super.setMatchLimit(newLimit) }
|
||||
}
|
||||
|
||||
override fun setByteRange(start: Int, end: Int) {
|
||||
withLock { super.setByteRange(start, end) }
|
||||
}
|
||||
|
||||
override fun setPointRange(start: TSPoint?, end: TSPoint?) {
|
||||
withLock { super.setPointRange(start, end) }
|
||||
}
|
||||
|
||||
override fun nextMatch(): TSQueryMatch? {
|
||||
return withLock { super.nextMatch() }
|
||||
}
|
||||
|
||||
override fun removeMatch(id: Int) {
|
||||
withLock { super.removeMatch(id) }
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
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),
|
||||
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,94 @@
|
||||
/*
|
||||
* 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.TSNode
|
||||
import com.itsaky.androidide.treesitter.TSRange
|
||||
import com.itsaky.androidide.treesitter.TSTree
|
||||
import com.itsaky.androidide.utils.DefaultRecyclable
|
||||
import com.itsaky.androidide.utils.RecyclableObjectPool
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class TreeSitterTree @JvmOverloads internal constructor(
|
||||
pointer: Long = 0,
|
||||
private val synchronized: DefaultSynchronized = DefaultSynchronized()
|
||||
) : TSTree(pointer), RecyclableObjectPool.Recyclable by DefaultRecyclable(),
|
||||
TSSynchronized by synchronized {
|
||||
|
||||
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 getRootNode(): TSNode {
|
||||
return withLock { super.getRootNode() }
|
||||
}
|
||||
|
||||
override fun getChangedRanges(oldTree: TSTree?): Array<TSRange> {
|
||||
return withLock { super.getChangedRanges(oldTree) }
|
||||
}
|
||||
|
||||
override fun copy(): TSTree {
|
||||
return withLock { super.copy() }
|
||||
}
|
||||
|
||||
override fun edit(edit: TSInputEdit?) {
|
||||
withLock { super.edit(edit) }
|
||||
}
|
||||
|
||||
override fun getLanguage(): TSLanguage {
|
||||
return withLock { super.getLanguage() }
|
||||
}
|
||||
|
||||
override fun <T> withLock(timeout: Long, unit: TimeUnit, action: () -> T): T {
|
||||
// check(ownerThread != null && Thread.currentThread() == ownerThread) {
|
||||
// "TSTree instances are not thread-safe. Copy the tree if you need to use it on multiple threads." +
|
||||
// "currentThread=${Thread.currentThread()} initialThread=$ownerThread"
|
||||
// }
|
||||
|
||||
return synchronized.withLock(timeout, unit, action)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
super.close()
|
||||
this.nativeObject = 0
|
||||
recycle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
this.ownerThread = null
|
||||
if (!canAccess()) {
|
||||
returnToPool()
|
||||
}
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.TSPoint
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursor
|
||||
import com.itsaky.androidide.treesitter.TSTreeCursorNode
|
||||
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(),
|
||||
TSSynchronized by DefaultSynchronized() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun obtain(pointer: Long): TreeSitterTreeCursor {
|
||||
return obtainFromPool<TreeSitterTreeCursor>().apply {
|
||||
this.nativeObject = pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCurrentNode(): TSNode {
|
||||
return withLock { super.getCurrentNode() }
|
||||
}
|
||||
|
||||
override fun getCurrentFieldName(): String {
|
||||
return withLock { super.getCurrentFieldName() }
|
||||
}
|
||||
|
||||
override fun getCurrentFieldId(): Short {
|
||||
return withLock { super.getCurrentFieldId() }
|
||||
}
|
||||
|
||||
override fun getCurrentTreeCursorNode(): TSTreeCursorNode {
|
||||
return withLock { super.getCurrentTreeCursorNode() }
|
||||
}
|
||||
|
||||
override fun gotoFirstChild(): Boolean {
|
||||
return withLock { super.gotoFirstChild() }
|
||||
}
|
||||
|
||||
override fun gotoFirstChildForByte(byteIndex: Int): Long {
|
||||
return withLock { super.gotoFirstChildForByte(byteIndex) }
|
||||
}
|
||||
|
||||
override fun gotoFirstChildForPoint(point: TSPoint?): Boolean {
|
||||
return withLock { super.gotoFirstChildForPoint(point) }
|
||||
}
|
||||
|
||||
override fun gotoLastChild(): Boolean {
|
||||
return withLock { super.gotoLastChild() }
|
||||
}
|
||||
|
||||
override fun gotoNextSibling(): Boolean {
|
||||
return withLock { super.gotoNextSibling() }
|
||||
}
|
||||
|
||||
override fun gotoPreviousSibling(): Boolean {
|
||||
return withLock { super.gotoPreviousSibling() }
|
||||
}
|
||||
|
||||
override fun gotoParent(): Boolean {
|
||||
return withLock { super.gotoParent() }
|
||||
}
|
||||
|
||||
override fun gotoDescendant(descendantIndex: Int) {
|
||||
withLock { super.gotoDescendant(descendantIndex) }
|
||||
}
|
||||
|
||||
override fun getCurrentDescendantIndex(): Int {
|
||||
return withLock { super.getCurrentDescendantIndex() }
|
||||
}
|
||||
|
||||
override fun getDepth(): Int {
|
||||
return withLock { super.getDepth() }
|
||||
}
|
||||
|
||||
override fun reset(node: TSNode?) {
|
||||
withLock { super.reset(node) }
|
||||
}
|
||||
|
||||
override fun resetTo(another: TSTreeCursor?) {
|
||||
withLock { super.resetTo(another) }
|
||||
}
|
||||
|
||||
override fun copy(): TSTreeCursor {
|
||||
return withLock { super.copy() }
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
withLock {
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user