in packages/devtools_app/assets/scripts/inspector_polyfill_script.dart [102:361]
String addServiceExtensions() {
// INSPECTOR_POLYFILL_SCRIPT_START
T toEnumEntry<T>(List<T> enumEntries, String name) {
for (T entry in enumEntries) {
if (entry.toString() == name) {
return entry;
}
}
throw 'Enum value $name not found';
}
/// This is identical to Flutter's getRootWidgetSummaryTree service extension,
/// but with the added properties.
Future<Map<String, dynamic>> getRootWidgetSummaryTreeWithPreviews(
Map<String, String> parameters) {
final instance = WidgetInspectorService.instance;
final groupName = parameters['groupName'];
final result = instance._nodeToJson(
WidgetsBinding.instance?.renderViewElement?.toDiagnosticsNode(),
InspectorSerializationDelegate(
groupName: groupName,
subtreeDepth: 1000000,
summaryTree: true,
service: instance,
addAdditionalPropertiesCallback: (DiagnosticsNode node, delegate) {
final additionalJson = <String, Object>{};
final value = node.value;
if (value is Element) {
final renderObject = value.renderObject;
if (renderObject is RenderParagraph) {
additionalJson['textPreview'] = renderObject.text.toPlainText();
}
}
return additionalJson;
},
),
);
return Future.value(<String, dynamic>{
'result': result,
});
}
Future<Map<String, dynamic>> getLayoutExplorerNode(
Map<String, String> parameters) {
final id = parameters['id'];
final subtreeDepth = int.parse(parameters['subtreeDepth'] as String);
final groupName = parameters['groupName'];
var result = <String, dynamic>{};
final instance = WidgetInspectorService.instance;
final root = instance.toObject(id);
if (root == null) {
return Future.value(<String, dynamic>{
'result': result,
});
}
result = instance._nodeToJson(
root as DiagnosticsNode,
InspectorSerializationDelegate(
groupName: groupName,
summaryTree: true,
subtreeDepth: subtreeDepth,
service: instance,
addAdditionalPropertiesCallback: (node, delegate) {
final Map<String, Object> additionalJson = <String, Object>{};
final value = node.value;
if (value is Element) {
final renderObject = value.renderObject;
if (renderObject != null) {
additionalJson['renderObject'] =
renderObject.toDiagnosticsNode().toJsonMap(
delegate.copyWith(
subtreeDepth: 0,
includeProperties: true,
),
) as Object;
final renderParent = renderObject.parent;
if (renderParent is RenderObject && subtreeDepth > 0) {
final parentCreator = renderParent.debugCreator;
if (parentCreator is DebugCreator) {
additionalJson['parentRenderElement'] =
parentCreator.element.toDiagnosticsNode().toJsonMap(
delegate.copyWith(
subtreeDepth: 0,
includeProperties: true,
),
) as Object;
// TODO(jacobr): also describe the path back up the tree to
// the RenderParentElement from the current element. It
// could be a surprising distance up the tree if a lot of
// elements don't have their own RenderObjects.
}
}
try {
if (!renderObject.debugNeedsLayout) {
final constraints = renderObject.constraints;
final constraintsProperty = <String, Object>{
'type': constraints.runtimeType.toString(),
'description': constraints.toString(),
};
if (constraints is BoxConstraints) {
constraintsProperty.addAll(<String, Object>{
'minWidth': constraints.minWidth.toString(),
'minHeight': constraints.minHeight.toString(),
'maxWidth': constraints.maxWidth.toString(),
'maxHeight': constraints.maxHeight.toString(),
});
}
additionalJson['constraints'] = constraintsProperty;
}
} catch (e) {
// Constraints are sometimes unavailable even though
// debugNeedsLayout is false.
}
try {
if (renderObject is RenderBox) {
additionalJson['isBox'] = true;
additionalJson['size'] = <String, Object>{
'width': renderObject.size.width.toString(),
'height': renderObject.size.height.toString(),
};
final parentData = renderObject.parentData;
if (parentData is FlexParentData) {
additionalJson['flexFactor'] = parentData.flex as int;
additionalJson['flexFit'] =
describeEnum(parentData.fit ?? FlexFit.tight);
} else if (parentData is BoxParentData) {
final offset = parentData.offset;
additionalJson['parentData'] = {
'offsetX': offset.dx.toString(),
'offsetY': offset.dy.toString(),
};
}
} else if (renderObject is RenderView) {
additionalJson['size'] = <String, Object>{
'width': renderObject.size.width.toString(),
'height': renderObject.size.height.toString(),
};
}
} catch (e) {
// Not laid out yet.
}
}
}
return additionalJson;
}),
) as Map<String, dynamic>;
return Future.value(<String, dynamic>{
'result': result,
});
}
Future<Map<String, dynamic>> setFlexFit(Map<String, String> parameters) {
final String id = parameters['id'] as String;
final parameter = parameters['flexFit'] as String;
final FlexFit flexFit = toEnumEntry<FlexFit>(FlexFit.values, parameter);
final dynamic object = WidgetInspectorService.instance.toObject(id);
bool succeed = false;
if (object != null) {
final render = object.renderObject;
final parentData = render.parentData;
if (parentData is FlexParentData) {
parentData.fit = flexFit;
render.markNeedsLayout();
succeed = true;
}
}
return Future.value(<String, Object>{
'result': succeed,
});
}
Future<Map<String, dynamic>> setFlexFactor(Map<String, String> parameters) {
final String id = parameters['id'] as String;
final String flexFactor = parameters['flexFactor'] as String;
final factor = flexFactor == 'null' ? null : int.parse(flexFactor);
final dynamic object = WidgetInspectorService.instance.toObject(id);
bool succeed = false;
if (object != null) {
final render = object.renderObject;
final parentData = render.parentData;
if (parentData is FlexParentData) {
parentData.flex = factor;
render.markNeedsLayout();
succeed = true;
}
}
return Future.value({'result': succeed});
}
Future<Map<String, dynamic>> setFlexProperties(
Map<String, String> parameters) {
final String id = parameters['id'] as String;
final MainAxisAlignment mainAxisAlignment = toEnumEntry<MainAxisAlignment>(
MainAxisAlignment.values,
parameters['mainAxisAlignment'] as String,
);
final CrossAxisAlignment crossAxisAlignment =
toEnumEntry<CrossAxisAlignment>(
CrossAxisAlignment.values,
parameters['crossAxisAlignment'] as String,
);
final dynamic object = WidgetInspectorService.instance.toObject(id);
bool succeed = false;
if (object != null) {
final render = object.renderObject;
if (render is RenderFlex) {
render.mainAxisAlignment = mainAxisAlignment;
render.crossAxisAlignment = crossAxisAlignment;
render.markNeedsLayout();
render.markNeedsPaint();
succeed = true;
}
}
return Future.value(<String, Object>{'result': succeed});
}
Future<Map<String, dynamic>> getPubRootDirectories(
Map<String, String> parameters,
) {
return Future.value(<String, Object>{
'result': WidgetInspectorService.instance._pubRootDirectories ?? [],
});
}
final failures = <String, String>{};
void registerHelper(String name, ServiceExtensionCallback callback) {
try {
WidgetInspectorService.instance.registerServiceExtension(
name: name,
callback: callback,
);
} catch (e) {
// It is not a fatal error if some of the extensions fail to register
// as could be the case if some are already defined directly within
// package:flutter for the version of package:flutter being used.
failures[name] = e.toString();
}
}
registerHelper('getLayoutExplorerNode', getLayoutExplorerNode);
registerHelper('setFlexFit', setFlexFit);
registerHelper('setFlexFactor', setFlexFactor);
registerHelper('setFlexProperties', setFlexProperties);
registerHelper('getPubRootDirectories', getPubRootDirectories);
registerHelper(
'getRootWidgetSummaryTreeWithPreviews',
getRootWidgetSummaryTreeWithPreviews,
);
return WidgetInspectorService.instance._safeJsonEncode(failures);
// INSPECTOR_POLYFILL_SCRIPT_END
}