Add message when traversal has error
Summary: By sending a message to the desktop we can report to log view and inform the user what happened Reviewed By: lblasa Differential Revision: D50369853 fbshipit-source-id: b4852d736232477261bfdf6f94c9395ce29cceaf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
da903b8bc5
commit
ee7f12ef85
@@ -13,10 +13,12 @@ import com.facebook.flipper.plugins.uidebugger.common.BitmapPool
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
|
||||
import com.facebook.flipper.plugins.uidebugger.model.FrameworkEvent
|
||||
import com.facebook.flipper.plugins.uidebugger.model.FrameworkEventMetadata
|
||||
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
|
||||
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
||||
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverManager
|
||||
import com.facebook.flipper.plugins.uidebugger.scheduler.SharedThrottle
|
||||
import com.facebook.flipper.plugins.uidebugger.traversal.PartialLayoutTraversal
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
interface ConnectionListener {
|
||||
fun onConnect()
|
||||
@@ -34,8 +36,7 @@ class UIDContext(
|
||||
private val pendingFrameworkEvents: MutableList<FrameworkEvent>
|
||||
) {
|
||||
|
||||
val layoutTraversal: PartialLayoutTraversal =
|
||||
PartialLayoutTraversal(descriptorRegister, observerFactory)
|
||||
val layoutTraversal: PartialLayoutTraversal = PartialLayoutTraversal(this)
|
||||
|
||||
val treeObserverManager = TreeObserverManager(this)
|
||||
val sharedThrottle: SharedThrottle = SharedThrottle()
|
||||
@@ -45,6 +46,11 @@ class UIDContext(
|
||||
synchronized(pendingFrameworkEvents) { pendingFrameworkEvents.add(frameworkEvent) }
|
||||
}
|
||||
|
||||
fun onError(traversalError: TraversalError) {
|
||||
connectionRef.connection?.send(
|
||||
TraversalError.name, Json.encodeToString(TraversalError.serializer(), traversalError))
|
||||
}
|
||||
|
||||
fun extractPendingFrameworkEvents(): List<FrameworkEvent> {
|
||||
synchronized(pendingFrameworkEvents) {
|
||||
val copy = pendingFrameworkEvents.toList()
|
||||
|
||||
@@ -10,21 +10,21 @@ package com.facebook.flipper.plugins.uidebugger.model
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class InitEvent(val rootId: Id, val frameworkEventMetadata: List<FrameworkEventMetadata>) {
|
||||
class InitEvent(val rootId: Id, val frameworkEventMetadata: List<FrameworkEventMetadata>) {
|
||||
companion object {
|
||||
const val name = "init"
|
||||
}
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class MetadataUpdateEvent(val attributeMetadata: Map<MetadataId, Metadata> = emptyMap()) {
|
||||
class MetadataUpdateEvent(val attributeMetadata: Map<MetadataId, Metadata> = emptyMap()) {
|
||||
companion object {
|
||||
const val name = "metadataUpdate"
|
||||
}
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class FrameScanEvent(
|
||||
class FrameScanEvent(
|
||||
val frameTime: Long,
|
||||
val nodes: List<Node>,
|
||||
val snapshot: Snapshot?,
|
||||
@@ -35,11 +35,23 @@ data class FrameScanEvent(
|
||||
}
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable data class Snapshot(val nodeId: Id, val data: String)
|
||||
@kotlinx.serialization.Serializable
|
||||
class TraversalError(
|
||||
val nodeName: String,
|
||||
val errorType: String,
|
||||
val errorMessage: String,
|
||||
val stack: String
|
||||
) {
|
||||
companion object {
|
||||
const val name = "traversalError"
|
||||
}
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable class Snapshot(val nodeId: Id, val data: String)
|
||||
|
||||
/** Separate optional performance statistics event */
|
||||
@kotlinx.serialization.Serializable
|
||||
data class PerfStatsEvent(
|
||||
class PerfStatsEvent(
|
||||
val txId: Long,
|
||||
val observerType: String,
|
||||
val nodesCount: Int,
|
||||
|
||||
@@ -10,13 +10,13 @@ package com.facebook.flipper.plugins.uidebugger.model
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class FrameworkEventMetadata(
|
||||
class FrameworkEventMetadata(
|
||||
val type: String,
|
||||
val documentation: String,
|
||||
)
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class FrameworkEvent(
|
||||
class FrameworkEvent(
|
||||
val treeId: Id,
|
||||
val nodeId: Id,
|
||||
val type: String,
|
||||
|
||||
@@ -17,7 +17,7 @@ typealias MetadataId = Int
|
||||
* identity, attributes, layout, documentation, or a custom type.
|
||||
*/
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Metadata(
|
||||
class Metadata(
|
||||
val id: MetadataId,
|
||||
val type: String,
|
||||
val namespace: String,
|
||||
|
||||
@@ -22,7 +22,7 @@ data class Bounds(val x: Int, val y: Int, val width: Int, val height: Int) {
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int) {
|
||||
class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int) {
|
||||
companion object {
|
||||
fun fromRect(rect: Rect): SpaceBox {
|
||||
return SpaceBox(rect.top, rect.right, rect.bottom, rect.left)
|
||||
@@ -31,7 +31,7 @@ data class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
|
||||
class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
|
||||
companion object {
|
||||
fun fromColor(color: Int): Color {
|
||||
val alpha: Int = (color shr 24) and 0xFF / 255
|
||||
@@ -48,20 +48,20 @@ data class Color(val r: Int, val g: Int, val b: Int, val a: Int) {
|
||||
}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Coordinate(
|
||||
class Coordinate(
|
||||
@Serializable(with = NumberSerializer::class) val x: Number,
|
||||
@Serializable(with = NumberSerializer::class) val y: Number
|
||||
) {}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Coordinate3D(
|
||||
class Coordinate3D(
|
||||
@Serializable(with = NumberSerializer::class) val x: Number,
|
||||
@Serializable(with = NumberSerializer::class) val y: Number,
|
||||
@Serializable(with = NumberSerializer::class) val z: Number
|
||||
) {}
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Size(
|
||||
class Size(
|
||||
@Serializable(with = NumberSerializer::class) val width: Number,
|
||||
@Serializable(with = NumberSerializer::class) val height: Number
|
||||
) {}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.facebook.flipper.plugins.uidebugger.model.MetadataUpdateEvent
|
||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
||||
import com.facebook.flipper.plugins.uidebugger.model.Snapshot
|
||||
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
|
||||
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@@ -107,7 +108,19 @@ class TreeObserverManager(val context: UIDContext) {
|
||||
|
||||
val workerThreadStartTimestamp = System.currentTimeMillis()
|
||||
|
||||
val nodes = batchedUpdate.updates.flatMap { it.deferredNodes.map { it.value() } }
|
||||
val nodes =
|
||||
try {
|
||||
batchedUpdate.updates.flatMap { it.deferredNodes.map { it.value() } }
|
||||
} catch (exception: Exception) {
|
||||
context.onError(
|
||||
TraversalError(
|
||||
"DeferredProcessing",
|
||||
exception.javaClass.simpleName,
|
||||
exception.message ?: "",
|
||||
exception.stackTraceToString()))
|
||||
return
|
||||
}
|
||||
|
||||
val frameworkEvents = context.extractPendingFrameworkEvents()
|
||||
val snapshotUpdate = batchedUpdate.updates.find { it.snapshot != null }
|
||||
val deferredComputationEndTimestamp = System.currentTimeMillis()
|
||||
|
||||
@@ -9,11 +9,11 @@ package com.facebook.flipper.plugins.uidebugger.traversal
|
||||
|
||||
import android.util.Log
|
||||
import com.facebook.flipper.plugins.uidebugger.LogTag
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
|
||||
import com.facebook.flipper.plugins.uidebugger.core.UIDContext
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
|
||||
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
||||
import com.facebook.flipper.plugins.uidebugger.model.TraversalError
|
||||
import com.facebook.flipper.plugins.uidebugger.util.Immediate
|
||||
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||
|
||||
@@ -24,12 +24,11 @@ import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||
* - The second item are any observable roots discovered.
|
||||
*/
|
||||
class PartialLayoutTraversal(
|
||||
private val descriptorRegister: DescriptorRegister,
|
||||
private val treeObserverFactory: TreeObserverFactory,
|
||||
private val context: UIDContext,
|
||||
) {
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
||||
private fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
||||
|
||||
fun traverse(root: Any, parentId: Id?): Pair<List<MaybeDeferred<Node>>, List<Pair<Any, Id?>>> {
|
||||
|
||||
@@ -47,12 +46,13 @@ class PartialLayoutTraversal(
|
||||
|
||||
try {
|
||||
// If we encounter a node that has it own observer, don't traverse
|
||||
if (node != root && treeObserverFactory.hasObserverFor(node)) {
|
||||
if (node != root && context.observerFactory.hasObserverFor(node)) {
|
||||
observableRoots.add((node to parentId))
|
||||
continue
|
||||
}
|
||||
|
||||
val descriptor = descriptorRegister.descriptorForClassUnsafe(node::class.java).asAny()
|
||||
val descriptor =
|
||||
context.descriptorRegister.descriptorForClassUnsafe(node::class.java).asAny()
|
||||
|
||||
val curId = descriptor.getId(node)
|
||||
if (shallow.contains(node)) {
|
||||
@@ -82,13 +82,13 @@ class PartialLayoutTraversal(
|
||||
var activeChildId: Id? = null
|
||||
if (activeChild != null) {
|
||||
val activeChildDescriptor =
|
||||
descriptorRegister.descriptorForClassUnsafe(activeChild.javaClass)
|
||||
context.descriptorRegister.descriptorForClassUnsafe(activeChild.javaClass)
|
||||
activeChildId = activeChildDescriptor.getId(activeChild)
|
||||
}
|
||||
|
||||
val childrenIds = mutableListOf<Id>()
|
||||
children.forEach { child ->
|
||||
val childDescriptor = descriptorRegister.descriptorForClassUnsafe(child.javaClass)
|
||||
val childDescriptor = context.descriptorRegister.descriptorForClassUnsafe(child.javaClass)
|
||||
childrenIds.add(childDescriptor.getId(child))
|
||||
stack.add(Pair(child, curId))
|
||||
// If there is an active child then don't traverse it
|
||||
@@ -117,6 +117,12 @@ class PartialLayoutTraversal(
|
||||
})
|
||||
} catch (exception: Exception) {
|
||||
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
|
||||
context.onError(
|
||||
TraversalError(
|
||||
node.javaClass.simpleName,
|
||||
exception.javaClass.simpleName,
|
||||
exception.message ?: "",
|
||||
exception.stackTraceToString()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user