diff --git a/annotations/org.ow2.asm_asm-debug-all_4.1/org/objectweb/asm/tree/annotations.xml b/annotations/org.ow2.asm_asm-debug-all_4.1/org/objectweb/asm/tree/annotations.xml
index 924d69cca1f..7866c5dc168 100644
--- a/annotations/org.ow2.asm_asm-debug-all_4.1/org/objectweb/asm/tree/annotations.xml
+++ b/annotations/org.ow2.asm_asm-debug-all_4.1/org/objectweb/asm/tree/annotations.xml
@@ -116,6 +116,9 @@
-
+ -
+
+
-
@@ -125,6 +128,9 @@
+ -
+
+
-
diff --git a/src/org/jetbrains/eval4j/interpreter.kt b/src/org/jetbrains/eval4j/interpreter.kt
index 528606163b5..38734a2e413 100644
--- a/src/org/jetbrains/eval4j/interpreter.kt
+++ b/src/org/jetbrains/eval4j/interpreter.kt
@@ -14,27 +14,6 @@ import org.objectweb.asm.tree.TypeInsnNode
import org.objectweb.asm.tree.JumpInsnNode
import org.objectweb.asm.tree.IincInsnNode
-data class MethodDescription(
- val ownerInternalName: String,
- val name: String,
- val desc: String,
- val isStatic: Boolean
-)
-
-fun MethodDescription(insn: MethodInsnNode): MethodDescription =
- MethodDescription(
- insn.owner,
- insn.name,
- insn.desc,
- insn.getOpcode() == INVOKESTATIC
- )
-
-val MethodDescription.returnType: Type
- get() = Type.getReturnType(desc)
-
-val MethodDescription.parameterTypes: List
- get() = Type.getArgumentTypes(desc).toList()
-
class UnsupportedByteCodeException(message: String) : RuntimeException(message)
trait Eval {
@@ -50,12 +29,12 @@ trait Eval {
fun getArrayElement(array: Value, index: Value): Value
fun setArrayElement(array: Value, index: Value, newValue: Value)
- fun getStaticField(fieldDesc: String): Value
- fun setStaticField(fieldDesc: String, newValue: Value)
+ fun getStaticField(fieldDesc: FieldDescription): Value
+ fun setStaticField(fieldDesc: FieldDescription, newValue: Value)
fun invokeStaticMethod(methodDesc: MethodDescription, arguments: List): Value
- fun getField(instance: Value, fieldDesc: String): Value
- fun setField(instance: Value, fieldDesc: String, newValue: Value)
+ fun getField(instance: Value, fieldDesc: FieldDescription): Value
+ fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value)
fun invokeMethod(instance: Value, methodDesc: MethodDescription, arguments: List, invokespecial: Boolean = false): Value
}
@@ -118,7 +97,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter(
}
}
JSR -> LabelValue((insn as JumpInsnNode).label)
- GETSTATIC -> eval.getStaticField((insn as FieldInsnNode).desc)
+ GETSTATIC -> eval.getStaticField(FieldDescription(insn as FieldInsnNode))
NEW -> eval.newInstance(Type.getType((insn as TypeInsnNode).desc))
else -> throw UnsupportedByteCodeException("$insn")
}
@@ -164,11 +143,11 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter(
LOOKUPSWITCH -> throw UnsupportedByteCodeException("Switch is not supported yet")
PUTSTATIC -> {
- eval.setStaticField((insn as FieldInsnNode).desc, value)
+ eval.setStaticField(FieldDescription(insn as FieldInsnNode), value)
null
}
- GETFIELD -> eval.getField(value, (insn as FieldInsnNode).desc)
+ GETFIELD -> eval.getField(value, FieldDescription(insn as FieldInsnNode))
NEWARRAY -> {
val typeStr = when ((insn as IntInsnNode).operand) {
@@ -313,7 +292,7 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter(
}
PUTFIELD -> {
- eval.setField(value1, (insn as FieldInsnNode).desc, value2)
+ eval.setField(value1, FieldDescription(insn as FieldInsnNode), value2)
null
}
diff --git a/src/org/jetbrains/eval4j/members.kt b/src/org/jetbrains/eval4j/members.kt
new file mode 100644
index 00000000000..4961ca0bee4
--- /dev/null
+++ b/src/org/jetbrains/eval4j/members.kt
@@ -0,0 +1,53 @@
+package org.jetbrains.eval4j
+
+import org.objectweb.asm.tree.MethodInsnNode
+import org.objectweb.asm.Opcodes.*
+import org.objectweb.asm.*
+import org.objectweb.asm.tree.FieldInsnNode
+
+open data class MemberDescription(
+ val ownerInternalName: String,
+ val name: String,
+ val desc: String,
+ val isStatic: Boolean
+)
+
+class MethodDescription(
+ ownerInternalName: String,
+ name: String,
+ desc: String,
+ isStatic: Boolean
+) : MemberDescription(ownerInternalName, name, desc, isStatic)
+
+fun MethodDescription(insn: MethodInsnNode): MethodDescription =
+ MethodDescription(
+ insn.owner,
+ insn.name,
+ insn.desc,
+ insn.getOpcode() == INVOKESTATIC
+ )
+
+val MethodDescription.returnType: Type
+ get() = Type.getReturnType(desc)
+
+val MethodDescription.parameterTypes: List
+ get() = Type.getArgumentTypes(desc).toList()
+
+
+class FieldDescription(
+ ownerInternalName: String,
+ name: String,
+ desc: String,
+ isStatic: Boolean
+) : MemberDescription(ownerInternalName, name, desc, isStatic)
+
+fun FieldDescription(insn: FieldInsnNode): FieldDescription =
+ FieldDescription(
+ insn.owner,
+ insn.name,
+ insn.desc,
+ insn.getOpcode() in setOf(GETSTATIC, PUTSTATIC)
+ )
+
+val FieldDescription.fieldType: Type
+ get() = Type.getType(desc)
diff --git a/test/org/jetbrains/eval4j/test/TestData.java b/test/org/jetbrains/eval4j/test/TestData.java
index ca446e9ace7..55c20d32cc0 100644
--- a/test/org/jetbrains/eval4j/test/TestData.java
+++ b/test/org/jetbrains/eval4j/test/TestData.java
@@ -152,4 +152,8 @@ class TestData {
return String.valueOf("str");
}
+ static Object testGetStaticField() {
+ return String.CASE_INSENSITIVE_ORDER;
+ }
+
}
diff --git a/test/org/jetbrains/eval4j/test/main.kt b/test/org/jetbrains/eval4j/test/main.kt
index 158c3796cd9..5b958d5b225 100644
--- a/test/org/jetbrains/eval4j/test/main.kt
+++ b/test/org/jetbrains/eval4j/test/main.kt
@@ -9,6 +9,8 @@ import org.junit.Assert.*
import junit.framework.TestSuite
import junit.framework.TestCase
import java.lang.reflect.Method
+import java.lang.reflect.Field
+import kotlin.test.assertNotNull
fun suite(): TestSuite {
val suite = TestSuite()
@@ -129,11 +131,18 @@ object REFLECTION_EVAL : Eval {
throw UnsupportedOperationException()
}
- override fun getStaticField(fieldDesc: String): Value {
- throw UnsupportedOperationException()
+ override fun getStaticField(fieldDesc: FieldDescription): Value {
+ assertTrue(fieldDesc.isStatic)
+ val owner = lookup.findClass(fieldDesc.ownerInternalName)
+ assertNotNull("Class not found: ${fieldDesc.ownerInternalName}", owner)
+ val field = owner!!.findField(fieldDesc)
+ assertNotNull("Field not found: $fieldDesc", field)
+ val result = field!!.get(null)
+ return objectToValue(result, fieldDesc.fieldType)
}
- override fun setStaticField(fieldDesc: String, newValue: Value) {
- throw UnsupportedOperationException()
+
+ override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
+ assertTrue(fieldDesc.isStatic)
}
override fun invokeStaticMethod(methodDesc: MethodDescription, arguments: List): Value {
@@ -146,10 +155,10 @@ object REFLECTION_EVAL : Eval {
return objectToValue(result, methodDesc.returnType)
}
- override fun getField(instance: Value, fieldDesc: String): Value {
+ override fun getField(instance: Value, fieldDesc: FieldDescription): Value {
throw UnsupportedOperationException()
}
- override fun setField(instance: Value, fieldDesc: String, newValue: Value) {
+ override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) {
throw UnsupportedOperationException()
}
override fun invokeMethod(instance: Value, methodDesc: MethodDescription, arguments: List, invokespecial: Boolean): Value {
@@ -191,4 +200,27 @@ fun MethodDescription.matches(method: Method): Boolean {
return returnType.matches(method.getReturnType()!!)
}
+[suppress("UNCHECKED_CAST")]
+fun Class.findField(fieldDesc: FieldDescription): Field? {
+ for (declared in getDeclaredFields()) {
+ if (fieldDesc.matches(declared)) return declared
+ }
+
+ val fromSuperClass = (getSuperclass() as Class).findField(fieldDesc)
+ if (fromSuperClass != null) return fromSuperClass
+
+ for (supertype in getInterfaces()) {
+ val fromSuper = (supertype as Class).findField(fieldDesc)
+ if (fromSuper != null) return fromSuper
+ }
+
+ return null
+}
+
+fun FieldDescription.matches(field: Field): Boolean {
+ if (name != field.getName()) return false
+
+ return fieldType.matches(field.getType()!!)
+}
+
fun Type.matches(_class: Class<*>): Boolean = this == Type.getType(_class)
\ No newline at end of file