More information when no containing field found

This commit is contained in:
Andrey Breslav
2014-11-19 14:55:25 +03:00
parent 93a409d459
commit 08ad4bec64
2 changed files with 42 additions and 13 deletions
@@ -39,6 +39,9 @@ import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.jet.lang.psi.debugText.getDebugText
import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionCandidate
import java.lang.reflect.GenericDeclaration
import java.lang.reflect.Method
import java.lang.reflect.Constructor
class LazyOperationsLog(
val stringSanitizer: (String) -> String
@@ -109,7 +112,7 @@ class LazyOperationsLog(
val data = record.data
val sb = StringBuilder()
sb.append(data.field?.getName() ?: "<name not found>")
sb.append(data.field?.getName() ?: "in ${data.lambdaCreatedIn.getDeclarationName()}")
if (!data.arguments.isEmpty()) {
sb.append(data.arguments.map { render(it) }.join(", ", "(", ")"))
@@ -209,4 +212,13 @@ private fun Printer.indent(body: Printer.() -> Unit): Printer {
body()
popIndent()
return this
}
}
private fun GenericDeclaration?.getDeclarationName(): String? {
return when (this) {
is Class<*> -> getName().substringAfterLast(".")
is Method -> getDeclaringClass().getDeclarationName() + "::" + getName() + "()"
is Constructor<*> -> getDeclaringClass().getDeclarationName() + "::" + getName() + "()"
else -> "<no name>"
}
}
@@ -58,12 +58,12 @@ public class LoggingStorageManager(
}
private fun computeCallerData(lambda: Any, wrapper: Any, arguments: List<Any?>, result: Any?): CallData {
val jClass = lambda.javaClass
val lambdaClass = lambda.javaClass
val outerClass: Class<out Any?>? = jClass.getEnclosingClass()
val outerClass: Class<out Any?>? = lambdaClass.getEnclosingClass()
// fields named "this" or "this$0"
val referenceToOuter = jClass.getAllDeclaredFields().firstOrNull {
val referenceToOuter = lambdaClass.getAllDeclaredFields().firstOrNull {
field ->
field.getType() == outerClass && field.getName()!!.contains("this")
}
@@ -71,6 +71,11 @@ public class LoggingStorageManager(
val outerInstance = referenceToOuter?.get(lambda)
fun Class<*>.findFunctionField(): Field? {
return this.getAllDeclaredFields().firstOrNull {
it.getType()?.getName()?.startsWith("kotlin.Function") ?: false
}
}
val containingField = if (outerInstance == null) null
else outerClass?.getAllDeclaredFields()?.firstOrNull {
(field): Boolean ->
@@ -79,10 +84,7 @@ public class LoggingStorageManager(
if (value == null) return@firstOrNull false
val valueClass = value.javaClass
val functionField = valueClass.getAllDeclaredFields().firstOrNull {
it.getType()?.getName()?.startsWith("kotlin.Function") ?: false
}
val functionField = valueClass.findFunctionField()
if (functionField == null) return@firstOrNull false
functionField.setAccessible(true)
@@ -90,11 +92,26 @@ public class LoggingStorageManager(
functionValue == wrapper
}
val enclosingEntity = jClass.getEnclosingConstructor()
?: jClass.getEnclosingMethod()
?: jClass.getEnclosingClass()
if (containingField == null) {
val wrappedLambdaField = lambdaClass.findFunctionField()
if (wrappedLambdaField != null) {
wrappedLambdaField.setAccessible(true)
val wrappedLambda = wrappedLambdaField.get(lambda)
return CallData(outerInstance, null, enclosingEntity(wrappedLambda.javaClass), arguments, result)
}
}
return CallData(outerInstance, containingField, enclosingEntity as GenericDeclaration?, arguments, result)
val enclosingEntity = enclosingEntity(lambdaClass)
return CallData(outerInstance, containingField, enclosingEntity, arguments, result)
}
private fun enclosingEntity(_class: Class<Any>): GenericDeclaration? {
val result = _class.getEnclosingConstructor()
?: _class.getEnclosingMethod()
?: _class.getEnclosingClass()
return result as GenericDeclaration?
}
private fun Class<*>.getAllDeclaredFields(): List<Field> {