Add support for tagged messages on the Layout Inspector
Summary:
Related diff [CK]: D23243009
This diff adds support for a protocol for layout messages where the type is recursively encoded as:
```
{
kind: "type",
data: ???
}
```
The meat of the diff is on FlipperEditor.java, SetDataOperations.java and InspectorFlipperPlugin.java. The others are there just for a change on an interface.
We check if the message adheres to the new encoding, otherwise we fall back to the old behavior. If it's the new encoding, the message is traversed recursively flattening the types to EditorValue using the type hints provided.
Reviewed By: muraziz
Differential Revision: D23243009
fbshipit-source-id: 0f313455885930f3beaaadb66f3bf394f109ea23
This commit is contained in:
committed by
Facebook GitHub Bot
parent
19b5b65081
commit
ff3584e2e0
@@ -22,6 +22,7 @@ import com.facebook.flipper.plugins.inspector.HighlightedOverlay;
|
||||
import com.facebook.flipper.plugins.inspector.InspectorValue;
|
||||
import com.facebook.flipper.plugins.inspector.Named;
|
||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.flipper.plugins.inspector.SetDataOperations;
|
||||
import com.facebook.flipper.plugins.inspector.Touch;
|
||||
import com.facebook.flipper.plugins.inspector.descriptors.ObjectDescriptor;
|
||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.ContextDescriptorUtils;
|
||||
@@ -48,51 +49,61 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
|
||||
private Map<String, List<Pair<String[], FlipperDynamic>>> mOverrides = new HashMap<>();
|
||||
private Map<
|
||||
String, List<Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>>>>
|
||||
mOverrides = new HashMap<>();
|
||||
private DebugComponent.Overrider mOverrider =
|
||||
new DebugComponent.Overrider() {
|
||||
@Override
|
||||
public void applyComponentOverrides(String key, Component component) {
|
||||
final List<Pair<String[], FlipperDynamic>> overrides = mOverrides.get(key);
|
||||
final List<Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>>>
|
||||
overrides = mOverrides.get(key);
|
||||
if (overrides == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Pair<String[], FlipperDynamic> override : overrides) {
|
||||
for (Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>> override :
|
||||
overrides) {
|
||||
if (override.first[0].equals("Props")) {
|
||||
applyReflectiveOverride(component, override.first, override.second);
|
||||
applyReflectiveOverride(
|
||||
component, override.first, override.second.first, override.second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyStateOverrides(String key, StateContainer stateContainer) {
|
||||
final List<Pair<String[], FlipperDynamic>> overrides = mOverrides.get(key);
|
||||
final List<Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>>>
|
||||
overrides = mOverrides.get(key);
|
||||
if (overrides == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Pair<String[], FlipperDynamic> override : overrides) {
|
||||
for (Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>> override :
|
||||
overrides) {
|
||||
if (override.first[0].equals("State")) {
|
||||
applyReflectiveOverride(stateContainer, override.first, override.second);
|
||||
applyReflectiveOverride(
|
||||
stateContainer, override.first, override.second.first, override.second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyLayoutOverrides(String key, DebugLayoutNode node) {
|
||||
final List<Pair<String[], FlipperDynamic>> overrides = mOverrides.get(key);
|
||||
final List<Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>>>
|
||||
overrides = mOverrides.get(key);
|
||||
if (overrides == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Pair<String[], FlipperDynamic> override : overrides) {
|
||||
for (Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>> override :
|
||||
overrides) {
|
||||
if (override.first[0].equals("Layout")) {
|
||||
try {
|
||||
applyLayoutOverride(
|
||||
node,
|
||||
Arrays.copyOfRange(override.first, 1, override.first.length),
|
||||
override.second);
|
||||
override.second.second);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
@@ -327,13 +338,18 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(DebugComponent node, String[] path, FlipperDynamic value) {
|
||||
List<Pair<String[], FlipperDynamic>> overrides = mOverrides.get(node.getGlobalKey());
|
||||
public void setValue(
|
||||
DebugComponent node,
|
||||
String[] path,
|
||||
@Nullable SetDataOperations.FlipperValueHint kind,
|
||||
FlipperDynamic value) {
|
||||
List<Pair<String[], Pair<SetDataOperations.FlipperValueHint, FlipperDynamic>>> overrides =
|
||||
mOverrides.get(node.getGlobalKey());
|
||||
if (overrides == null) {
|
||||
overrides = new ArrayList<>();
|
||||
mOverrides.put(node.getGlobalKey(), overrides);
|
||||
}
|
||||
overrides.add(new Pair<>(path, value));
|
||||
overrides.add(new Pair<>(path, new Pair<>(kind, value)));
|
||||
|
||||
node.setOverrider(mOverrider);
|
||||
node.rerender();
|
||||
@@ -554,11 +570,13 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
|
||||
// The path follows the pattern (Props|State)/field/(field|index)*
|
||||
private static void applyReflectiveOverride(
|
||||
Object o, final String[] path, final FlipperDynamic dynamic) {
|
||||
Object o,
|
||||
final String[] path,
|
||||
@Nullable SetDataOperations.FlipperValueHint hint,
|
||||
final FlipperDynamic dynamic) {
|
||||
try {
|
||||
final Field field = o.getClass().getDeclaredField(path[1]);
|
||||
FlipperEditor.updateComponent(path, field, o, dynamic);
|
||||
|
||||
FlipperEditor.updateComponent(path, field, o, hint, dynamic);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.inspector.HighlightedOverlay;
|
||||
import com.facebook.flipper.plugins.inspector.Named;
|
||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.flipper.plugins.inspector.SetDataOperations;
|
||||
import com.facebook.flipper.plugins.inspector.Touch;
|
||||
import com.facebook.litho.sections.Section;
|
||||
import com.facebook.litho.sections.debug.DebugSection;
|
||||
@@ -96,7 +97,12 @@ public class DebugSectionDescriptor extends NodeDescriptor<DebugSection> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(DebugSection node, String[] path, FlipperDynamic value) throws Exception {
|
||||
public void setValue(
|
||||
DebugSection node,
|
||||
String[] path,
|
||||
@Nullable SetDataOperations.FlipperValueHint kind,
|
||||
FlipperDynamic value)
|
||||
throws Exception {
|
||||
// TODO T39526148
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
|
||||
package com.facebook.flipper.plugins.litho;
|
||||
|
||||
import androidx.core.util.Pair;
|
||||
import com.facebook.flipper.core.FlipperArray;
|
||||
import com.facebook.flipper.core.FlipperDynamic;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.core.FlipperValue;
|
||||
import com.facebook.flipper.plugins.inspector.InspectorValue;
|
||||
import com.facebook.flipper.plugins.inspector.SetDataOperations;
|
||||
import com.facebook.litho.editor.EditorRegistry;
|
||||
import com.facebook.litho.editor.model.EditorArray;
|
||||
import com.facebook.litho.editor.model.EditorBool;
|
||||
@@ -20,7 +22,10 @@ import com.facebook.litho.editor.model.EditorShape;
|
||||
import com.facebook.litho.editor.model.EditorString;
|
||||
import com.facebook.litho.editor.model.EditorValue;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -53,7 +58,36 @@ public class FlipperEditor {
|
||||
* chain into the object. Fields retain their name, positions in an array use their index.
|
||||
*/
|
||||
public static @Nullable Boolean updateComponent(
|
||||
String[] path, Field field, Object o, FlipperDynamic dynamic) {
|
||||
String[] path,
|
||||
Field field,
|
||||
Object o,
|
||||
final @Nullable SetDataOperations.FlipperValueHint hint,
|
||||
FlipperDynamic dynamic) {
|
||||
EditorValue edit = parseEditorValue(hint, dynamic);
|
||||
for (int i = path.length - 1; i > 0; i--) {
|
||||
HashMap<String, EditorValue> content = new HashMap<>();
|
||||
content.put(path[i], edit);
|
||||
edit = EditorValue.shape(content);
|
||||
}
|
||||
return EditorRegistry.write(field.getType(), field, o, edit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout Plugin supports a protocol that tags the type of all messages. This enables support for
|
||||
* heterogeneous Maps and Arrays.
|
||||
*
|
||||
* @param hint type hint for the FlipperDynamic parameter
|
||||
* @param dynamic The value produced by the Flipper user
|
||||
* @return an EditorValue extracted from dynamic
|
||||
*/
|
||||
private static EditorValue parseEditorValue(
|
||||
@Nullable SetDataOperations.FlipperValueHint hint, FlipperDynamic dynamic) {
|
||||
// TODO(festevezga) - Remove educated guess when the Layout Plugin is updated to produce tagged
|
||||
// messages
|
||||
return hint == null ? guessEditorValue(dynamic) : extractEditorValue(hint, dynamic);
|
||||
}
|
||||
|
||||
private static EditorValue guessEditorValue(FlipperDynamic dynamic) {
|
||||
Object raw = dynamic.raw();
|
||||
EditorValue edit;
|
||||
if (raw instanceof String) {
|
||||
@@ -65,12 +99,59 @@ public class FlipperEditor {
|
||||
} else {
|
||||
edit = EditorValue.string(raw.toString());
|
||||
}
|
||||
for (int i = path.length - 1; i > 0; i--) {
|
||||
HashMap<String, EditorValue> content = new HashMap<>();
|
||||
content.put(path[i], edit);
|
||||
edit = EditorValue.shape(content);
|
||||
return edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method flattens the Layout Editor messages using the type hints, recursively.
|
||||
*
|
||||
* @param hint type hint for the FlipperDynamic parameter
|
||||
* @param dynamic The value produced by the Flipper user
|
||||
* @return an EditorValue extracted from dynamic
|
||||
*/
|
||||
private static EditorValue extractEditorValue(
|
||||
SetDataOperations.FlipperValueHint hint, FlipperDynamic dynamic) {
|
||||
switch (hint) {
|
||||
case STRING:
|
||||
return EditorValue.string(dynamic.asString());
|
||||
case NUMBER:
|
||||
return EditorValue.number(dynamic.asDouble());
|
||||
case OBJECT:
|
||||
return EditorValue.shape(parseObject(dynamic.asObject()));
|
||||
case ARRAY:
|
||||
return EditorValue.array(parseArray(dynamic.asArray()));
|
||||
case NULL:
|
||||
// TODO(festevezga) - add support for null
|
||||
return EditorValue.string("null");
|
||||
default:
|
||||
// Java switch isn't exhaustive before Java 13
|
||||
return EditorValue.string("If you see this, report an error to the Flipper repository");
|
||||
}
|
||||
return EditorRegistry.write(field.getType(), field, o, edit);
|
||||
}
|
||||
|
||||
private static Map<String, EditorValue> parseObject(FlipperObject flipperObject) {
|
||||
final Iterator<String> keys = flipperObject.keys();
|
||||
final Map<String, EditorValue> values = new HashMap<>();
|
||||
while (keys.hasNext()) {
|
||||
final String field = keys.next();
|
||||
final FlipperObject object = flipperObject.getObject(field);
|
||||
final Pair<SetDataOperations.FlipperValueHint, FlipperDynamic> value =
|
||||
SetDataOperations.parseLayoutEditorMessage(object);
|
||||
values.put(field, parseEditorValue(value.first, value.second));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private static List<EditorValue> parseArray(FlipperArray flipperArray) {
|
||||
ArrayList<EditorValue> values = new ArrayList<>();
|
||||
for (int i = 0; i < flipperArray.length(); i++) {
|
||||
final FlipperObject object = flipperArray.getObject(i);
|
||||
final Pair<SetDataOperations.FlipperValueHint, FlipperDynamic> value =
|
||||
SetDataOperations.parseLayoutEditorMessage(object);
|
||||
values.add(parseEditorValue(value.first, value.second));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/** Converts into one of FlipperValue, FlipperObject, or FlipperArray */
|
||||
|
||||
@@ -13,11 +13,13 @@ import com.facebook.flipper.core.FlipperDynamic;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.inspector.Named;
|
||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.flipper.plugins.inspector.SetDataOperations;
|
||||
import com.facebook.flipper.plugins.inspector.Touch;
|
||||
import com.facebook.litho.sections.debug.DebugSection;
|
||||
import com.facebook.litho.widget.LithoRecylerView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class LithoRecyclerViewDescriptor extends NodeDescriptor<LithoRecylerView> {
|
||||
|
||||
@@ -105,10 +107,14 @@ public class LithoRecyclerViewDescriptor extends NodeDescriptor<LithoRecylerView
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(LithoRecylerView node, String[] path, FlipperDynamic value)
|
||||
public void setValue(
|
||||
LithoRecylerView node,
|
||||
String[] path,
|
||||
@Nullable SetDataOperations.FlipperValueHint kind,
|
||||
FlipperDynamic value)
|
||||
throws Exception {
|
||||
final NodeDescriptor descriptor = descriptorForClass(ViewGroup.class);
|
||||
descriptor.setValue(node, path, value);
|
||||
descriptor.setValue(node, path, kind, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.facebook.flipper.core.FlipperDynamic;
|
||||
import com.facebook.flipper.core.FlipperObject;
|
||||
import com.facebook.flipper.plugins.inspector.Named;
|
||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.flipper.plugins.inspector.SetDataOperations;
|
||||
import com.facebook.flipper.plugins.inspector.Touch;
|
||||
import com.facebook.litho.DebugComponent;
|
||||
import com.facebook.litho.LithoView;
|
||||
@@ -108,9 +109,14 @@ public class LithoViewDescriptor extends NodeDescriptor<LithoView> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(LithoView node, String[] path, FlipperDynamic value) throws Exception {
|
||||
public void setValue(
|
||||
LithoView node,
|
||||
String[] path,
|
||||
@Nullable SetDataOperations.FlipperValueHint kind,
|
||||
FlipperDynamic value)
|
||||
throws Exception {
|
||||
final NodeDescriptor descriptor = descriptorForClass(ViewGroup.class);
|
||||
descriptor.setValue(node, path, value);
|
||||
descriptor.setValue(node, path, kind, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user