idea: cleanup code
This commit is contained in:
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.eval4j
|
||||
@@ -182,7 +171,11 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
|
||||
when {
|
||||
value == NULL_VALUE -> NULL_VALUE
|
||||
eval.isInstanceOf(value, targetType) -> ObjectValue(value.obj(), targetType)
|
||||
else -> throwInterpretingException(ClassCastException("${value.asmType.className} cannot be cast to ${targetType.className}"))
|
||||
else -> throwInterpretingException(
|
||||
ClassCastException(
|
||||
"${value.asmType.className} cannot be cast to ${targetType.className}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.eval4j.jdi
|
||||
@@ -444,10 +433,13 @@ open class JDIEval(
|
||||
listOf(instance, mirrorOfArgs(args))
|
||||
)
|
||||
|
||||
if (methodDesc.returnType.sort != Type.OBJECT && methodDesc.returnType.sort != Type.ARRAY && methodDesc.returnType.sort != Type.VOID) {
|
||||
return unboxType(invocationResult, methodDesc.returnType)
|
||||
}
|
||||
return invocationResult
|
||||
return if (methodDesc.returnType.sort != Type.OBJECT &&
|
||||
methodDesc.returnType.sort != Type.ARRAY &&
|
||||
methodDesc.returnType.sort != Type.VOID
|
||||
)
|
||||
unboxType(invocationResult, methodDesc.returnType)
|
||||
else
|
||||
invocationResult
|
||||
}
|
||||
|
||||
private fun mirrorOfArgs(args: List<jdi_Value?>): Value {
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.eval4j.jdi.test
|
||||
@@ -57,8 +46,8 @@ fun suite(): TestSuite {
|
||||
req.enable()
|
||||
|
||||
val latch = CountDownLatch(1)
|
||||
var classLoader : ClassLoaderReference? = null
|
||||
var thread : ThreadReference? = null
|
||||
var classLoader: ClassLoaderReference? = null
|
||||
var thread: ThreadReference? = null
|
||||
|
||||
Thread {
|
||||
val eventQueue = vm.eventQueue()
|
||||
@@ -89,7 +78,8 @@ fun suite(): TestSuite {
|
||||
|
||||
break@mainLoop
|
||||
}
|
||||
else -> {}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,8 +91,7 @@ fun suite(): TestSuite {
|
||||
|
||||
var remainingTests = AtomicInteger(0)
|
||||
|
||||
val suite = buildTestSuite {
|
||||
methodNode, ownerClass, expected ->
|
||||
val suite = buildTestSuite { methodNode, ownerClass, expected ->
|
||||
remainingTests.incrementAndGet()
|
||||
object : TestCase(getTestName(methodNode.name)) {
|
||||
|
||||
@@ -112,47 +101,45 @@ fun suite(): TestSuite {
|
||||
val args = if ((methodNode.access and Opcodes.ACC_STATIC) == 0) {
|
||||
// Instance method
|
||||
val newInstance = eval.newInstance(Type.getType(ownerClass))
|
||||
val thisValue = eval.invokeMethod(newInstance, MethodDescription(ownerClass.name, "<init>", "()V", false), listOf(), true)
|
||||
val thisValue =
|
||||
eval.invokeMethod(newInstance, MethodDescription(ownerClass.name, "<init>", "()V", false), listOf(), true)
|
||||
listOf(thisValue)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
listOf()
|
||||
}
|
||||
|
||||
val value = interpreterLoop(
|
||||
methodNode,
|
||||
makeInitialFrame(methodNode, args),
|
||||
eval
|
||||
methodNode,
|
||||
makeInitialFrame(methodNode, args),
|
||||
eval
|
||||
)
|
||||
|
||||
fun ObjectReference?.callToString(): String? {
|
||||
if (this == null) return "null"
|
||||
return (eval.invokeMethod(
|
||||
this.asValue(),
|
||||
MethodDescription(
|
||||
"java/lang/Object",
|
||||
"toString",
|
||||
"()Ljava/lang/String;",
|
||||
false
|
||||
),
|
||||
listOf()).jdiObj as StringReference).value()
|
||||
this.asValue(),
|
||||
MethodDescription(
|
||||
"java/lang/Object",
|
||||
"toString",
|
||||
"()Ljava/lang/String;",
|
||||
false
|
||||
),
|
||||
listOf()
|
||||
).jdiObj as StringReference).value()
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
if (expected is ValueReturned && value is ValueReturned && value.result is ObjectValue) {
|
||||
assertEquals(expected.result.obj().toString(), value.result.jdiObj.callToString())
|
||||
}
|
||||
else if (expected is ExceptionThrown && value is ExceptionThrown) {
|
||||
} else if (expected is ExceptionThrown && value is ExceptionThrown) {
|
||||
val valueObj = value.exception.obj()
|
||||
val actual = if (valueObj is ObjectReference) valueObj.callToString() else valueObj.toString()
|
||||
assertEquals(expected.exception.obj().toString(), actual)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
assertEquals(expected, value)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
if (remainingTests.decrementAndGet() == 0) vm.resume()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.eval4j.test
|
||||
@@ -28,45 +17,42 @@ import org.junit.Assert.assertTrue
|
||||
import java.lang.reflect.*
|
||||
import java.lang.reflect.Array as JArray
|
||||
|
||||
fun suite(): TestSuite = buildTestSuite {
|
||||
methodNode, ownerClass, expected ->
|
||||
fun suite(): TestSuite = buildTestSuite { methodNode, ownerClass, expected ->
|
||||
object : TestCase(getTestName(methodNode.name)) {
|
||||
|
||||
override fun runTest() {
|
||||
if (!isIgnored(methodNode)) {
|
||||
val value = interpreterLoop(
|
||||
methodNode,
|
||||
initFrame(
|
||||
ownerClass.getInternalName(),
|
||||
methodNode
|
||||
),
|
||||
REFLECTION_EVAL
|
||||
)
|
||||
|
||||
if (expected is ExceptionThrown && value is ExceptionThrown) {
|
||||
assertEquals(expected.exception.toString(), value.exception.toString())
|
||||
}
|
||||
else {
|
||||
assertEquals(expected.toString(), value.toString())
|
||||
}
|
||||
override fun runTest() {
|
||||
if (!isIgnored(methodNode)) {
|
||||
val value = interpreterLoop(
|
||||
methodNode,
|
||||
initFrame(
|
||||
ownerClass.getInternalName(),
|
||||
methodNode
|
||||
),
|
||||
REFLECTION_EVAL
|
||||
)
|
||||
|
||||
if (expected is ExceptionThrown && value is ExceptionThrown) {
|
||||
assertEquals(expected.exception.toString(), value.exception.toString())
|
||||
} else {
|
||||
assertEquals(expected.toString(), value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun isIgnored(methodNode: MethodNode): Boolean {
|
||||
return methodNode.visibleAnnotations?.any {
|
||||
val annotationDesc = it.desc
|
||||
annotationDesc != null &&
|
||||
Type.getType(annotationDesc) == Type.getType(IgnoreInReflectionTests::class.java)
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
private fun isIgnored(methodNode: MethodNode): Boolean {
|
||||
return methodNode.visibleAnnotations?.any {
|
||||
val annotationDesc = it.desc
|
||||
annotationDesc != null && Type.getType(annotationDesc) == Type.getType(IgnoreInReflectionTests::class.java)
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Class<*>.getInternalName(): String = Type.getType(this).internalName
|
||||
|
||||
fun initFrame(
|
||||
owner: String,
|
||||
m: MethodNode
|
||||
owner: String,
|
||||
m: MethodNode
|
||||
): Frame<Value> {
|
||||
val current = Frame<Value>(m.maxLocals, m.maxStack)
|
||||
current.setReturn(makeNotInitializedValue(Type.getReturnType(m.desc)))
|
||||
@@ -80,7 +66,7 @@ fun initFrame(
|
||||
}
|
||||
|
||||
val args = Type.getArgumentTypes(m.desc)
|
||||
for (i in 0..args.size - 1) {
|
||||
for (i in args.indices) {
|
||||
current.setLocal(local++, makeNotInitializedValue(args[i]))
|
||||
if (args[i].size == 2) {
|
||||
current.setLocal(local++, NOT_A_VALUE)
|
||||
@@ -198,12 +184,10 @@ object REFLECTION_EVAL : Eval {
|
||||
try {
|
||||
try {
|
||||
return f()
|
||||
} catch (ite: InvocationTargetException) {
|
||||
throw ite.cause ?: ite
|
||||
}
|
||||
catch (ite: InvocationTargetException) {
|
||||
throw ite.cause ?: ite
|
||||
}
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
throw ThrownFromEvaluatedCodeException(ObjectValue(e, Type.getType(e::class.java)))
|
||||
}
|
||||
}
|
||||
@@ -211,14 +195,14 @@ object REFLECTION_EVAL : Eval {
|
||||
override fun getStaticField(fieldDesc: FieldDescription): Value {
|
||||
val field = findStaticField(fieldDesc)
|
||||
|
||||
val result = mayThrow {field.get(null)}
|
||||
val result = mayThrow { field.get(null) }
|
||||
return objectToValue(result, fieldDesc.fieldType)
|
||||
}
|
||||
|
||||
override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
|
||||
val field = findStaticField(fieldDesc)
|
||||
val obj = newValue.obj(fieldDesc.fieldType)
|
||||
mayThrow {field.set(null, obj)}
|
||||
mayThrow { field.set(null, obj) }
|
||||
}
|
||||
|
||||
fun findStaticField(fieldDesc: FieldDescription): Field {
|
||||
@@ -234,7 +218,7 @@ object REFLECTION_EVAL : Eval {
|
||||
val method = findClass(methodDesc).findMethod(methodDesc)
|
||||
assertNotNull("Method not found: $methodDesc", method)
|
||||
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
|
||||
val result = mayThrow {method!!.invoke(null, *args)}
|
||||
val result = mayThrow { method!!.invoke(null, *args) }
|
||||
return objectToValue(result, methodDesc.returnType)
|
||||
}
|
||||
|
||||
@@ -250,7 +234,7 @@ object REFLECTION_EVAL : Eval {
|
||||
val obj = instance.obj().checkNull()
|
||||
val field = findInstanceField(obj, fieldDesc)
|
||||
|
||||
return objectToValue(mayThrow {field.get(obj)}, fieldDesc.fieldType)
|
||||
return objectToValue(mayThrow { field.get(obj) }, fieldDesc.fieldType)
|
||||
}
|
||||
|
||||
override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) {
|
||||
@@ -258,7 +242,7 @@ object REFLECTION_EVAL : Eval {
|
||||
val field = findInstanceField(obj, fieldDesc)
|
||||
|
||||
val newObj = newValue.obj(fieldDesc.fieldType)
|
||||
mayThrow {field.set(obj, newObj)}
|
||||
mayThrow { field.set(obj, newObj) }
|
||||
}
|
||||
|
||||
fun findInstanceField(obj: Any, fieldDesc: FieldDescription): Field {
|
||||
@@ -277,11 +261,10 @@ object REFLECTION_EVAL : Eval {
|
||||
val ctor = _class.findConstructor(methodDesc)
|
||||
assertNotNull("Constructor not found: $methodDesc", ctor)
|
||||
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
|
||||
val result = mayThrow {ctor!!.newInstance(*args)}
|
||||
val result = mayThrow { ctor!!.newInstance(*args) }
|
||||
instance.value = result
|
||||
return objectToValue(result, instance.asmType)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// TODO
|
||||
throw UnsupportedOperationException("invokespecial is not suported in reflection eval")
|
||||
}
|
||||
@@ -290,7 +273,7 @@ object REFLECTION_EVAL : Eval {
|
||||
val method = obj::class.java.findMethod(methodDesc)
|
||||
assertNotNull("Method not found: $methodDesc", method)
|
||||
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
|
||||
val result = mayThrow {method!!.invoke(obj, *args)}
|
||||
val result = mayThrow { method!!.invoke(obj, *args) }
|
||||
return objectToValue(result, methodDesc.returnType)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.eval4j.test
|
||||
@@ -29,23 +18,26 @@ import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.lang.reflect.Modifier
|
||||
import java.lang.reflect.Array as JArray
|
||||
|
||||
fun buildTestSuite(
|
||||
create: (MethodNode, Class<*>, InterpreterResult?) -> TestCase
|
||||
create: (MethodNode, Class<*>, InterpreterResult?) -> TestCase
|
||||
): TestSuite {
|
||||
val suite = TestSuite()
|
||||
|
||||
val ownerClass = TestData::class.java
|
||||
ownerClass.classLoader!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!.use { inputStream ->
|
||||
ClassReader(inputStream).accept(object : ClassVisitor(API_VERSION) {
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
return object : MethodNode(API_VERSION, access, name, desc, signature, exceptions) {
|
||||
override fun visitEnd() {
|
||||
val testCase = buildTestCase(ownerClass, this, create)
|
||||
if (testCase != null) {
|
||||
suite.addTest(testCase)
|
||||
}
|
||||
override fun visitMethod(
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?
|
||||
): MethodVisitor? = object : MethodNode(API_VERSION, access, name, desc, signature, exceptions) {
|
||||
override fun visitEnd() {
|
||||
val testCase = buildTestCase(ownerClass, this, create)
|
||||
if (testCase != null) {
|
||||
suite.addTest(testCase)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,32 +47,33 @@ fun buildTestSuite(
|
||||
return suite
|
||||
}
|
||||
|
||||
private fun buildTestCase(ownerClass: Class<TestData>,
|
||||
methodNode: MethodNode,
|
||||
create: (MethodNode, Class<out Any?>, InterpreterResult?) -> TestCase): TestCase? {
|
||||
private fun buildTestCase(
|
||||
ownerClass: Class<TestData>,
|
||||
methodNode: MethodNode,
|
||||
create: (MethodNode, Class<out Any?>, InterpreterResult?) -> TestCase
|
||||
): TestCase? {
|
||||
var expected: InterpreterResult? = null
|
||||
for (method in ownerClass.declaredMethods) {
|
||||
if (method.name == methodNode.name) {
|
||||
val isStatic = (method.modifiers and Modifier.STATIC) != 0
|
||||
if (method.parameterTypes!!.size > 0) {
|
||||
if (method.parameterTypes!!.isNotEmpty()) {
|
||||
println("Skipping method with parameters: $method")
|
||||
}
|
||||
else if (!isStatic && !method.name!!.startsWith("test")) {
|
||||
} else if (!isStatic && !method.name!!.startsWith("test")) {
|
||||
println("Skipping instance method (should be started with 'test') : $method")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
method.isAccessible = true
|
||||
try {
|
||||
val result = method.invoke(if (isStatic) null else ownerClass.newInstance())
|
||||
val returnType = Type.getType(method.returnType!!)
|
||||
expected = ValueReturned(objectToValue(result, returnType))
|
||||
}
|
||||
catch (e: UnsupportedOperationException) {
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
println("Skipping $method: $e")
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
} catch (e: Throwable) {
|
||||
val cause = e.cause ?: e
|
||||
expected = ExceptionThrown(objectToValue(cause, Type.getType(cause::class.java)) as ObjectValue, ExceptionThrown.ExceptionKind.FROM_EVALUATOR)
|
||||
expected = ExceptionThrown(
|
||||
objectToValue(cause, Type.getType(cause::class.java)) as ObjectValue,
|
||||
ExceptionThrown.ExceptionKind.FROM_EVALUATOR
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user