mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-11-14 07:42:05 +08:00
fix(lsp/java): impl optimizations in JavaJarModelBuilder
- avoid allocating temporary lists - avoid multiple string operations Apart from this, the commit fixes some compilation errors.
This commit is contained in:
@@ -17,15 +17,18 @@
|
||||
|
||||
package com.itsaky.androidide.utils
|
||||
|
||||
import android.app.Application
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = Application::class)
|
||||
class JdkUtilsTest {
|
||||
|
||||
companion object {
|
||||
@@ -154,7 +157,8 @@ OpenJDK 64-Bit Server VM (build 21.0.1-internal-adhoc.root.src, mixed mode)
|
||||
assertThat(dist).isNotNull()
|
||||
assertThat(dist!!.javaVersion).isEqualTo("17-internal")
|
||||
assertThat(dist.javaHome).isEqualTo(
|
||||
"/data/data/com.itsaky.androidide/files/usr/opt/openjdk-17.0")
|
||||
"/data/data/com.itsaky.androidide/files/usr/opt/openjdk-17.0"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,7 +167,8 @@ OpenJDK 64-Bit Server VM (build 21.0.1-internal-adhoc.root.src, mixed mode)
|
||||
assertThat(dist).isNotNull()
|
||||
assertThat(dist!!.javaVersion).isEqualTo("21.0.1-internal")
|
||||
assertThat(dist.javaHome).isEqualTo(
|
||||
"/data/data/com.itsaky.androidide/files/usr/opt/openjdk-21.0.1")
|
||||
"/data/data/com.itsaky.androidide/files/usr/opt/openjdk-21.0.1"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,19 +17,22 @@
|
||||
|
||||
package com.itsaky.androidide.utils
|
||||
|
||||
import android.app.Application
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = Application::class)
|
||||
class ShiftedArrayTest {
|
||||
|
||||
@Test
|
||||
fun `test positive shift` () {
|
||||
fun `test positive shift`() {
|
||||
val backing = LongArray(10) { it.toLong() }
|
||||
val array = MutableShiftedLongArray(backing)
|
||||
for (s in 0..<array.size) {
|
||||
@@ -45,7 +48,7 @@ class ShiftedArrayTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test negative shift` () {
|
||||
fun `test negative shift`() {
|
||||
val backing = LongArray(10) { it.toLong() }
|
||||
val array = MutableShiftedLongArray(backing)
|
||||
array.shift(-1)
|
||||
@@ -62,7 +65,7 @@ class ShiftedArrayTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test negative shift - 2` () {
|
||||
fun `test negative shift - 2`() {
|
||||
val backing = LongArray(10) { it.toLong() }
|
||||
val array = MutableShiftedLongArray(backing)
|
||||
array.shift(-2)
|
||||
|
||||
+86
-64
@@ -64,9 +64,7 @@ import java.util.zip.ZipFile
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class JavaJarModelBuilder(
|
||||
private val jar: File
|
||||
) {
|
||||
class JavaJarModelBuilder(private val jar: File) {
|
||||
|
||||
// for testing purposes
|
||||
// prefer using consumeTypes(Function)
|
||||
@@ -78,15 +76,15 @@ class JavaJarModelBuilder(
|
||||
|
||||
fun consumeTypes(consumer: (IJavaType<*, *>) -> Unit) {
|
||||
ZipFile(jar).use { jar ->
|
||||
for (entry in jar.entries()) {
|
||||
if (!entry.name.endsWith(".class")) {
|
||||
continue
|
||||
}
|
||||
|
||||
jar.getInputStream(entry).use { inputStream ->
|
||||
jar.entries().asSequence().filter { it.name.endsWith(".class") }.forEach { entry ->
|
||||
jar.getInputStream(entry).buffered().use { inputStream ->
|
||||
val classFile = ClassFile.read(inputStream)!!
|
||||
val type = buildType(classFile)
|
||||
consumer(type)
|
||||
|
||||
// build model only if the class is not an anonymous or local class
|
||||
if (classFile.getAttribute(Attribute.EnclosingMethod) == null) {
|
||||
val type = buildType(classFile)
|
||||
consumer(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,27 +93,69 @@ class JavaJarModelBuilder(
|
||||
private fun buildType(classFile: ClassFile): IJavaType<*, *> {
|
||||
val classInfo = classFile.constant_pool.getClassInfo(classFile.this_class)
|
||||
val fqn = classInfo.baseName
|
||||
val name = simpleName(fqn)
|
||||
val pck = fqn.substring(0, fqn.length - name.length - 1)
|
||||
return buildType(fqn, name, pck, classFile)
|
||||
val (pck, name, isInner) = splitFqn(fqn)
|
||||
return buildType(fqn, pck, name, isInner, classFile)
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the given fully qualified name of a class and return the package name and the simple name
|
||||
* of the class, along with whether the class is an inner class.
|
||||
*/
|
||||
private fun splitFqn(fqn: String): Triple<String, String, Boolean> {
|
||||
val dolIdx = fqn.lastIndexOf('$')
|
||||
|
||||
// start looking for '/' from the index of the last '$'
|
||||
// a '/' will always appear before a '$'
|
||||
val slaIdx = fqn.lastIndexOf('/', startIndex = if (dolIdx == -1) fqn.lastIndex else dolIdx - 1)
|
||||
|
||||
if (slaIdx == -1 && dolIdx != -1) {
|
||||
// fqn == SomeClass$InnerClass (inner class of a class in the root package)
|
||||
// pck is empty, but fqn is not the class's simple name
|
||||
return Triple("", fqn.substring(dolIdx + 1), true)
|
||||
}
|
||||
|
||||
if (slaIdx == -1) {
|
||||
// fqn == SomeClass (class in the root package)
|
||||
// pck is empty and fqn is class's simple name
|
||||
return Triple("", fqn, false)
|
||||
}
|
||||
|
||||
if (dolIdx == -1) {
|
||||
// fqn == com/example/SomeClass
|
||||
return Triple(fqn.substring(0, slaIdx), fqn.substring(slaIdx + 1), false)
|
||||
}
|
||||
|
||||
// fqn == com/example/SomeClass$InnerClass
|
||||
return Triple(fqn.substring(0, slaIdx), fqn.substring(dolIdx + 1), true)
|
||||
}
|
||||
|
||||
private fun buildType(
|
||||
fqn: String, name: String, pck: String, classFile: ClassFile
|
||||
fqn: String,
|
||||
pck: String,
|
||||
name: String,
|
||||
isInner: Boolean,
|
||||
classFile: ClassFile
|
||||
): IJavaType<*, *> {
|
||||
if (classFile.access_flags.`is`(AccessFlags.ACC_ENUM)) {
|
||||
return buildEnum(fqn, name, pck, classFile)
|
||||
}
|
||||
return when {
|
||||
classFile.access_flags.`is`(AccessFlags.ACC_ENUM) -> buildEnum(fqn, name, pck, classFile)
|
||||
classFile.access_flags.`is`(AccessFlags.ACC_ANNOTATION) -> buildAnnotation(
|
||||
fqn,
|
||||
name,
|
||||
pck,
|
||||
classFile
|
||||
)
|
||||
|
||||
if (classFile.access_flags.`is`(AccessFlags.ACC_ANNOTATION)) {
|
||||
return buildAnnotation(fqn, name, pck, classFile)
|
||||
}
|
||||
classFile.access_flags.`is`(AccessFlags.ACC_INTERFACE) -> buildInterface(
|
||||
fqn,
|
||||
name,
|
||||
pck,
|
||||
classFile
|
||||
)
|
||||
|
||||
if (classFile.access_flags.`is`(AccessFlags.ACC_INTERFACE)) {
|
||||
return buildInterface(fqn, name, pck, classFile)
|
||||
else -> buildClass(fqn, name, pck, classFile)
|
||||
}.also {
|
||||
it.isInner = isInner
|
||||
}
|
||||
|
||||
return buildClass(fqn, name, pck, classFile)
|
||||
}
|
||||
|
||||
private fun buildClass(fqn: String, name: String, pck: String, classFile: ClassFile): JavaClass {
|
||||
@@ -182,7 +222,7 @@ class JavaJarModelBuilder(
|
||||
|
||||
private fun IJavaType<*, JavaMethod>.setMethods(classFile: ClassFile) {
|
||||
methods = RealmList<JavaMethod>().apply {
|
||||
addAll(classFile.methods.map { method ->
|
||||
classFile.methods.forEach { method ->
|
||||
val descriptor = classFile.constant_pool.getUTF8Value(method.descriptor.index)
|
||||
val methodName = method.getName(classFile.constant_pool)
|
||||
val methodType = DescriptorUtils.returnType(descriptor)
|
||||
@@ -190,18 +230,19 @@ class JavaJarModelBuilder(
|
||||
addAll(DescriptorUtils.paramTypes(descriptor))
|
||||
}
|
||||
|
||||
JavaMethod.newInstance(methodName, paramTypes, methodType, method.access_flags.flags)
|
||||
})
|
||||
add(JavaMethod.newInstance(methodName, paramTypes, methodType, method.access_flags.flags))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IJavaType<JavaField, *>.setFields(classFile: ClassFile) {
|
||||
fields = RealmList<JavaField>().apply {
|
||||
addAll(classFile.fields.map { field ->
|
||||
classFile.fields.forEach { field ->
|
||||
val descriptor = classFile.constant_pool.getUTF8Value(field.descriptor.index)
|
||||
val fieldName = field.getName(classFile.constant_pool)
|
||||
val fieldType = DescriptorUtils.type(descriptor)
|
||||
JavaField.newField(fieldName, fieldType, field.access_flags.flags).apply {
|
||||
|
||||
add(JavaField.newField(fieldName, fieldType, field.access_flags.flags).apply {
|
||||
field.attributes.get(Attribute.ConstantValue)?.also { constAttr ->
|
||||
val constantValue = constAttr as ConstantValue_attribute
|
||||
val constant = classFile.constant_pool.get(constantValue.constantvalue_index)
|
||||
@@ -214,19 +255,19 @@ class JavaJarModelBuilder(
|
||||
|
||||
this.constantValue = javaConstant
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JavaAnnotation.setAnnotationElements(classFile: ClassFile) {
|
||||
methods = RealmList<AnnotationElement>().apply {
|
||||
addAll(classFile.methods.map { method ->
|
||||
classFile.methods.forEach { method ->
|
||||
val descriptor = classFile.constant_pool.getUTF8Value(method.descriptor.index)
|
||||
val methodName = method.getName(classFile.constant_pool)
|
||||
val methodType = DescriptorUtils.returnType(descriptor)
|
||||
|
||||
this@setAnnotationElements.newAnnotationElement(
|
||||
add(this@setAnnotationElements.newAnnotationElement(
|
||||
methodName, methodType, method.access_flags.flags
|
||||
).apply {
|
||||
val annotationDefault =
|
||||
@@ -236,8 +277,8 @@ class JavaJarModelBuilder(
|
||||
val value = toAnnotationElementValue(defaultValue, classFile)
|
||||
this.defaultValue = value.let(RealmAny::valueOf) ?: RealmAny.nullValue()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,18 +300,8 @@ class JavaJarModelBuilder(
|
||||
JavaType.KIND_LONG,
|
||||
JavaType.KIND_FLOAT,
|
||||
JavaType.KIND_DOUBLE -> PrimitiveAnnotationElementValue.newInstance(
|
||||
kind = when (kind) {
|
||||
JavaType.KIND_BOOLEAN -> IAnnotationElementValue.KIND_BOOLEAN
|
||||
JavaType.KIND_BYTE -> IAnnotationElementValue.KIND_BYTE
|
||||
JavaType.KIND_CHAR -> IAnnotationElementValue.KIND_CHAR
|
||||
JavaType.KIND_SHORT -> IAnnotationElementValue.KIND_SHORT
|
||||
JavaType.KIND_INT -> IAnnotationElementValue.KIND_INT
|
||||
JavaType.KIND_LONG -> IAnnotationElementValue.KIND_LONG
|
||||
JavaType.KIND_FLOAT -> IAnnotationElementValue.KIND_FLOAT
|
||||
JavaType.KIND_DOUBLE -> IAnnotationElementValue.KIND_DOUBLE
|
||||
else -> throw IllegalArgumentException("Unknown value tag: $char")
|
||||
},
|
||||
|
||||
// annotation value kinds are same as JavaType.KIND_*
|
||||
kind = kind,
|
||||
value = toPrimitiveConstant(
|
||||
classFile.constant_pool, kind, char, defaultValue as Primitive_element_value
|
||||
)
|
||||
@@ -300,15 +331,13 @@ class JavaJarModelBuilder(
|
||||
}
|
||||
|
||||
'c' -> {
|
||||
val clazz = defaultValue as Class_element_value
|
||||
|
||||
// even though the name is given as "class_info_index", the constant at that index
|
||||
// is actually a CONSTANT_Utf8_info representing a return type descriptor (JLS $4.3.3)
|
||||
// this has been clearly mentioned in the Java Language Specification
|
||||
ClassAnnotationElementValue.newInstance(
|
||||
DescriptorUtils.type(
|
||||
classFile.constant_pool.getUTF8Value(
|
||||
clazz.class_info_index
|
||||
(defaultValue as Class_element_value).class_info_index
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -332,13 +361,12 @@ class JavaJarModelBuilder(
|
||||
}
|
||||
|
||||
'[' -> {
|
||||
val arr = defaultValue as Array_element_value
|
||||
ArrayAnnotationElementValue.newInstance(values = RealmList<RealmAny>().apply {
|
||||
addAll(arr.values.map { element ->
|
||||
toAnnotationElementValue(element, classFile).let { elementValue ->
|
||||
(defaultValue as Array_element_value).values.forEach { element ->
|
||||
add(toAnnotationElementValue(element, classFile).let { elementValue ->
|
||||
RealmAny.valueOf(elementValue)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -349,7 +377,7 @@ class JavaJarModelBuilder(
|
||||
}
|
||||
|
||||
private fun toPrimitiveConstant(
|
||||
constantPool: ConstantPool, kind: Short, char: Char, prim: Primitive_element_value
|
||||
constantPool: ConstantPool, kind: Int, char: Char, prim: Primitive_element_value
|
||||
): JavaConstant {
|
||||
if (kind == JavaType.KIND_REF && char != 's') {
|
||||
throw IllegalArgumentException("Unknown value tag: $char")
|
||||
@@ -360,7 +388,7 @@ class JavaJarModelBuilder(
|
||||
}
|
||||
|
||||
private fun toJavaConstant(
|
||||
kind: Short, constant: CPInfo, char: Char?
|
||||
kind: Int, constant: CPInfo, char: Char?
|
||||
): JavaConstant {
|
||||
val realmAny = when (kind) {
|
||||
JavaType.KIND_BOOLEAN,
|
||||
@@ -390,10 +418,4 @@ class JavaJarModelBuilder(
|
||||
value = realmAny
|
||||
)
|
||||
}
|
||||
|
||||
private fun simpleName(fqn: String): String {
|
||||
var idx = fqn.lastIndexOf('$')
|
||||
idx = if (idx == -1) fqn.lastIndexOf('/') else idx
|
||||
return fqn.substring(idx + 1)
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@ interface IJavaType<FieldT : IJavaSymbol, MethodT : IJavaSymbol> : IJavaSymbol {
|
||||
var fqn: String?
|
||||
var name: String?
|
||||
var packageName: String?
|
||||
var isInner: Boolean
|
||||
|
||||
/**
|
||||
* The fully qualified name of the superclass of the type.
|
||||
|
||||
+5
@@ -52,6 +52,9 @@ open class JavaAnnotation : IJavaType<JavaField, AnnotationElement> {
|
||||
@RealmField("pck")
|
||||
override var packageName: String? = null
|
||||
|
||||
@RealmField("isInner")
|
||||
override var isInner: Boolean = false
|
||||
|
||||
@RealmField("superClassFqn")
|
||||
override var superClassFqn: String? = null
|
||||
|
||||
@@ -83,6 +86,7 @@ open class JavaAnnotation : IJavaType<JavaField, AnnotationElement> {
|
||||
name: String,
|
||||
packageName: String,
|
||||
accessFlags: Int,
|
||||
isInner: Boolean = false,
|
||||
superInterfacesFqn: RealmList<String>? = null,
|
||||
apiInfo: ApiInfo? = null,
|
||||
fields: RealmList<JavaField>? = null,
|
||||
@@ -92,6 +96,7 @@ open class JavaAnnotation : IJavaType<JavaField, AnnotationElement> {
|
||||
this.fqn = fqn
|
||||
this.name = name
|
||||
this.packageName = packageName
|
||||
this.isInner = isInner
|
||||
this.superClassFqn = superClassFqn
|
||||
this.superInterfacesFqn = superInterfacesFqn
|
||||
this.accessFlags = accessFlags
|
||||
|
||||
@@ -47,6 +47,9 @@ open class JavaClass : IJavaType<JavaField, JavaMethod> {
|
||||
@RealmField("pck")
|
||||
override var packageName: String? = null
|
||||
|
||||
@RealmField("isInner")
|
||||
override var isInner: Boolean = false
|
||||
|
||||
@RealmField("superClassFqn")
|
||||
override var superClassFqn: String? = null
|
||||
|
||||
@@ -75,6 +78,7 @@ open class JavaClass : IJavaType<JavaField, JavaMethod> {
|
||||
name: String,
|
||||
packageName: String,
|
||||
accessFlags: Int,
|
||||
isInner: Boolean = false,
|
||||
superClassFqn: String? = null,
|
||||
superInterfacesFqn: RealmList<String>? = null,
|
||||
apiInfo: ApiInfo? = null,
|
||||
@@ -85,6 +89,7 @@ open class JavaClass : IJavaType<JavaField, JavaMethod> {
|
||||
this.fqn = fqn
|
||||
this.name = name
|
||||
this.packageName = packageName
|
||||
this.isInner = isInner
|
||||
this.superClassFqn = superClassFqn
|
||||
this.superInterfacesFqn = superInterfacesFqn
|
||||
this.accessFlags = accessFlags
|
||||
|
||||
+7
-5
@@ -43,13 +43,15 @@ open class JavaConstant : ISharedJavaIndexable {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
private var kind: Short = JavaType.KIND_UNKNOWN
|
||||
var kind: Int = JavaType.KIND_UNKNOWN
|
||||
private set
|
||||
|
||||
@RealmField("value")
|
||||
private var value: RealmAny? = null
|
||||
var value: RealmAny? = null
|
||||
private set
|
||||
|
||||
companion object {
|
||||
fun newInstance(kind: Short, value: RealmAny): JavaConstant {
|
||||
fun newInstance(kind: Int, value: RealmAny): JavaConstant {
|
||||
return JavaConstant().apply {
|
||||
this.kind = kind
|
||||
this.value = value
|
||||
@@ -58,7 +60,7 @@ open class JavaConstant : ISharedJavaIndexable {
|
||||
}
|
||||
}
|
||||
|
||||
fun update(kind: Short = this.kind, value: RealmAny? = this.value) {
|
||||
fun update(kind: Int = this.kind, value: RealmAny? = this.value) {
|
||||
this.kind = kind
|
||||
this.value = value
|
||||
this.computeId()
|
||||
@@ -113,7 +115,7 @@ open class JavaConstant : ISharedJavaIndexable {
|
||||
return safeCast(JavaType.KIND_CHAR) { asInteger()?.toChar() }
|
||||
}
|
||||
|
||||
private inline fun <R> safeCast(kind: Short, action: RealmAny.() -> R): R? {
|
||||
private inline fun <R> safeCast(kind: Int, action: RealmAny.() -> R): R? {
|
||||
return value?.let {
|
||||
if (this.kind == kind) {
|
||||
try {
|
||||
|
||||
@@ -46,6 +46,9 @@ open class JavaEnum : IJavaType<JavaField, JavaMethod> {
|
||||
@RealmField("pck")
|
||||
override var packageName: String? = null
|
||||
|
||||
@RealmField("isInner")
|
||||
override var isInner: Boolean = false
|
||||
|
||||
@RealmField("superClassFqn")
|
||||
override var superClassFqn: String? = null
|
||||
|
||||
@@ -74,6 +77,7 @@ open class JavaEnum : IJavaType<JavaField, JavaMethod> {
|
||||
name: String,
|
||||
packageName: String,
|
||||
accessFlags: Int,
|
||||
isInner: Boolean = false,
|
||||
superClassFqn: String? = null,
|
||||
superInterfacesFqn: RealmList<String>? = null,
|
||||
apiInfo: ApiInfo? = null,
|
||||
@@ -84,6 +88,7 @@ open class JavaEnum : IJavaType<JavaField, JavaMethod> {
|
||||
this.fqn = fqn
|
||||
this.name = name
|
||||
this.packageName = packageName
|
||||
this.isInner = isInner
|
||||
this.superClassFqn = superClassFqn
|
||||
this.superInterfacesFqn = superInterfacesFqn
|
||||
this.accessFlags = accessFlags
|
||||
|
||||
@@ -47,6 +47,9 @@ open class JavaInterface : IJavaType<JavaField, JavaMethod> {
|
||||
@RealmField("pck")
|
||||
override var packageName: String? = null
|
||||
|
||||
@RealmField("isInner")
|
||||
override var isInner: Boolean = false
|
||||
|
||||
@RealmField("superClassFqn")
|
||||
override var superClassFqn: String? = null
|
||||
|
||||
@@ -75,6 +78,7 @@ open class JavaInterface : IJavaType<JavaField, JavaMethod> {
|
||||
name: String,
|
||||
packageName: String,
|
||||
accessFlags: Int,
|
||||
isInner: Boolean = false,
|
||||
superInterfacesFqn: RealmList<String>? = null,
|
||||
apiInfo: ApiInfo? = null,
|
||||
fields: RealmList<JavaField>? = null,
|
||||
@@ -84,6 +88,7 @@ open class JavaInterface : IJavaType<JavaField, JavaMethod> {
|
||||
this.fqn = fqn
|
||||
this.name = name
|
||||
this.packageName = packageName
|
||||
this.isInner = isInner
|
||||
this.superInterfacesFqn = superInterfacesFqn
|
||||
this.accessFlags = accessFlags
|
||||
this.apiInfo = apiInfo
|
||||
|
||||
@@ -42,7 +42,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable {
|
||||
var name: String? = null
|
||||
|
||||
@RealmField("kind")
|
||||
var kind: Short = KIND_UNKNOWN
|
||||
var kind: Int = KIND_UNKNOWN
|
||||
|
||||
@RealmField("arrayDims")
|
||||
var arrayDims: Int = 0
|
||||
@@ -146,17 +146,25 @@ open class JavaType : ISharedJavaIndexable, ICloneable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KIND_UNKNOWN: Short = -1
|
||||
const val KIND_BOOLEAN: Short = 0
|
||||
const val KIND_BYTE: Short = 1
|
||||
const val KIND_CHAR: Short = 2
|
||||
const val KIND_DOUBLE: Short = 3
|
||||
const val KIND_FLOAT: Short = 4
|
||||
const val KIND_INT: Short = 5
|
||||
const val KIND_LONG: Short = 6
|
||||
const val KIND_SHORT: Short = 7
|
||||
const val KIND_VOID: Short = 8
|
||||
const val KIND_REF: Short = 9
|
||||
const val KIND_UNKNOWN = -1
|
||||
const val KIND_BOOLEAN = 0
|
||||
const val KIND_BYTE = 1
|
||||
const val KIND_CHAR = 2
|
||||
const val KIND_DOUBLE = 3
|
||||
const val KIND_FLOAT = 4
|
||||
const val KIND_INT = 5
|
||||
const val KIND_LONG = 6
|
||||
const val KIND_SHORT = 7
|
||||
const val KIND_VOID = 8
|
||||
const val KIND_REF = 9
|
||||
|
||||
// kind values used in IAnnotationElementValue
|
||||
// defined here for convenience
|
||||
internal const val __KIND_STRING = 10
|
||||
internal const val __KIND_CLASS = 11
|
||||
internal const val __KIND_ENUM = 12
|
||||
internal const val __KIND_ANNOTATION = 13
|
||||
internal const val __KIND_ARRAY = 14
|
||||
|
||||
const val TYPE_BOOLEAN = 'Z'
|
||||
const val TYPE_BYTE = 'B'
|
||||
@@ -219,7 +227,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun typeForKind(kind: Short) = when (kind) {
|
||||
fun typeForKind(kind: Int) = when (kind) {
|
||||
KIND_BOOLEAN -> TYPE_BOOLEAN
|
||||
KIND_BYTE -> TYPE_BYTE
|
||||
KIND_CHAR -> TYPE_CHAR
|
||||
@@ -249,7 +257,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(name: String?, kind: Short, arrayDims: Int = 0): JavaType {
|
||||
fun newInstance(name: String?, kind: Int, arrayDims: Int = 0): JavaType {
|
||||
return JavaType().apply {
|
||||
this.name = name
|
||||
this.kind = kind
|
||||
@@ -259,7 +267,7 @@ open class JavaType : ISharedJavaIndexable, ICloneable {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(name: Char, kind: Short, arrayDims: Int = 0): JavaType {
|
||||
fun newInstance(name: Char, kind: Int, arrayDims: Int = 0): JavaType {
|
||||
return newInstance(name.toString(), kind, arrayDims)
|
||||
}
|
||||
}
|
||||
|
||||
+22
-21
@@ -29,23 +29,24 @@ import io.realm.annotations.RealmField
|
||||
import io.realm.annotations.Required
|
||||
|
||||
sealed interface IAnnotationElementValue : ISharedJavaIndexable {
|
||||
var kind: Byte
|
||||
var kind: Int
|
||||
|
||||
companion object {
|
||||
const val KIND_UNKNOWN: Byte = -1
|
||||
const val KIND_BOOLEAN: Byte = 0
|
||||
const val KIND_BYTE: Byte = 1
|
||||
const val KIND_CHAR: Byte = 2
|
||||
const val KIND_DOUBLE: Byte = 3
|
||||
const val KIND_FLOAT: Byte = 4
|
||||
const val KIND_INT: Byte = 5
|
||||
const val KIND_LONG: Byte = 6
|
||||
const val KIND_SHORT: Byte = 7
|
||||
const val KIND_STRING: Byte = 8
|
||||
const val KIND_CLASS: Byte = 9
|
||||
const val KIND_ENUM: Byte = 10
|
||||
const val KIND_ANNOTATION: Byte = 11
|
||||
const val KIND_ARRAY: Byte = 12
|
||||
const val KIND_UNKNOWN = JavaType.KIND_UNKNOWN
|
||||
const val KIND_BOOLEAN = JavaType.KIND_BOOLEAN
|
||||
const val KIND_BYTE = JavaType.KIND_BYTE
|
||||
const val KIND_CHAR = JavaType.KIND_CHAR
|
||||
const val KIND_DOUBLE = JavaType.KIND_DOUBLE
|
||||
const val KIND_FLOAT = JavaType.KIND_FLOAT
|
||||
const val KIND_INT = JavaType.KIND_INT
|
||||
const val KIND_LONG = JavaType.KIND_LONG
|
||||
const val KIND_SHORT = JavaType.KIND_SHORT
|
||||
|
||||
const val KIND_STRING = JavaType.__KIND_STRING
|
||||
const val KIND_CLASS = JavaType.__KIND_CLASS
|
||||
const val KIND_ENUM = JavaType.__KIND_ENUM
|
||||
const val KIND_ANNOTATION = JavaType.__KIND_ANNOTATION
|
||||
const val KIND_ARRAY = JavaType.__KIND_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ open class PrimitiveAnnotationElementValue : IAnnotationElementValue {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
override var kind: Byte = 0
|
||||
override var kind: Int = 0
|
||||
|
||||
@RealmField("value")
|
||||
var value: JavaConstant? = null
|
||||
@@ -92,7 +93,7 @@ open class PrimitiveAnnotationElementValue : IAnnotationElementValue {
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun newInstance(kind: Byte, value: JavaConstant): PrimitiveAnnotationElementValue {
|
||||
fun newInstance(kind: Int, value: JavaConstant): PrimitiveAnnotationElementValue {
|
||||
return PrimitiveAnnotationElementValue().apply {
|
||||
this.kind = kind
|
||||
this.value = value
|
||||
@@ -111,7 +112,7 @@ open class EnumAnnotationElementValue : IAnnotationElementValue {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
override var kind: Byte = IAnnotationElementValue.KIND_ENUM
|
||||
override var kind: Int = IAnnotationElementValue.KIND_ENUM
|
||||
|
||||
@RealmField("name")
|
||||
var name: String? = null
|
||||
@@ -169,7 +170,7 @@ open class ArrayAnnotationElementValue : IAnnotationElementValue {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
override var kind: Byte = IAnnotationElementValue.KIND_ARRAY
|
||||
override var kind: Int = IAnnotationElementValue.KIND_ARRAY
|
||||
|
||||
@RealmField("numValues")
|
||||
var numValues: Int = 0
|
||||
@@ -230,7 +231,7 @@ open class ClassAnnotationElementValue : IAnnotationElementValue {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
override var kind: Byte = IAnnotationElementValue.KIND_CLASS
|
||||
override var kind: Int = IAnnotationElementValue.KIND_CLASS
|
||||
|
||||
@RealmField("type")
|
||||
var type: JavaType? = null
|
||||
@@ -282,7 +283,7 @@ open class AnnotationAnnotationElementValue : IAnnotationElementValue {
|
||||
override var id: Int? = null
|
||||
|
||||
@RealmField("kind")
|
||||
override var kind: Byte = IAnnotationElementValue.KIND_ANNOTATION
|
||||
override var kind: Int = IAnnotationElementValue.KIND_ANNOTATION
|
||||
|
||||
@RealmField("type")
|
||||
var type: JavaType? = null
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.itsaky.androidide.lsp.testing.LSPTest
|
||||
import com.itsaky.androidide.projects.api.ModuleProject
|
||||
import com.itsaky.androidide.projects.util.findAppModule
|
||||
import com.itsaky.androidide.xml.resources.ResourceTableRegistry
|
||||
import com.itsaky.androidide.xml.versions.ApiVersions
|
||||
import com.itsaky.androidide.xml.widgets.WidgetTable
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
|
||||
@@ -706,7 +706,7 @@ class ResourceEntry(val name : String) {
|
||||
var allowNew: AllowNew? = null
|
||||
var overlayable: OverlayableItem? = null
|
||||
|
||||
internal val values = mutableListOf<ResourceConfigValue>()
|
||||
val values = mutableListOf<ResourceConfigValue>()
|
||||
|
||||
fun findValue(config: ConfigDescription, product: String = ""): ResourceConfigValue? {
|
||||
return values.find { it.config == config && it.product == product }
|
||||
|
||||
Reference in New Issue
Block a user