88/// @docImport 'package:flutter/widgets.dart';
99library ;
1010
11+ import 'dart:collection' ;
1112import 'dart:math' as math;
1213import 'dart:ui' show clampDouble;
1314
@@ -1421,6 +1422,17 @@ class TextTreeRenderer {
14211422 }
14221423}
14231424
1425+ /// The JSON representation of a [DiagnosticsNode] .
1426+ typedef _JsonDiagnosticsNode = Map <String , Object ?>;
1427+
1428+ /// Stack containing [DiagnosticNode] s to convert to JSON and the callback to
1429+ /// call with the JSON.
1430+ ///
1431+ /// Using a stack is required to process the widget tree iteratively instead of
1432+ /// recursively.
1433+ typedef _NodesToJsonifyStack
1434+ = ListQueue <(DiagnosticsNode , void Function (_JsonDiagnosticsNode ))>;
1435+
14241436/// Defines diagnostics data for a [value] .
14251437///
14261438/// For debug and profile modes, [DiagnosticsNode] provides a high quality
@@ -1605,29 +1617,12 @@ abstract class DiagnosticsNode {
16051617 /// by this method and interactive tree views in the Flutter IntelliJ
16061618 /// plugin.
16071619 @mustCallSuper
1608- Map <String , Object ?> toJsonMap (
1609- DiagnosticsSerializationDelegate delegate, {
1610- bool fullDetails = true ,
1611- }) {
1620+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
16121621 Map <String , Object ?> result = < String , Object ? > {};
16131622 assert (() {
16141623 final bool hasChildren = getChildren ().isNotEmpty;
1615- final Map < String , Object ?> essentialDetails = < String , Object ? > {
1624+ result = < String , Object ? > {
16161625 'description' : toDescription (),
1617- 'shouldIndent' : style != DiagnosticsTreeStyle .flat &&
1618- style != DiagnosticsTreeStyle .error,
1619- ...delegate.additionalNodeProperties (this , fullDetails: fullDetails),
1620- if (delegate.subtreeDepth > 0 )
1621- 'children' : toJsonList (
1622- delegate.filterChildren (getChildren (), this ),
1623- this ,
1624- delegate,
1625- fullDetails: fullDetails,
1626- ),
1627- };
1628-
1629- result = ! fullDetails ? essentialDetails : < String , Object ? > {
1630- ...essentialDetails,
16311626 'type' : runtimeType.toString (),
16321627 if (name != null )
16331628 'name' : name,
@@ -1651,19 +1646,54 @@ abstract class DiagnosticsNode {
16511646 'allowWrap' : allowWrap,
16521647 if (allowNameWrap)
16531648 'allowNameWrap' : allowNameWrap,
1649+ ...delegate.additionalNodeProperties (this ),
16541650 if (delegate.includeProperties)
16551651 'properties' : toJsonList (
16561652 delegate.filterProperties (getProperties (), this ),
16571653 this ,
16581654 delegate,
1659- fullDetails: fullDetails,
1655+ ),
1656+ if (delegate.subtreeDepth > 0 )
1657+ 'children' : toJsonList (
1658+ delegate.filterChildren (getChildren (), this ),
1659+ this ,
1660+ delegate,
16601661 ),
16611662 };
16621663 return true ;
16631664 }());
16641665 return result;
16651666 }
16661667
1668+ /// Iteratively serialize the node to a JSON map according to the
1669+ /// configuration provided in the [DiagnosticsSerializationDelegate] .
1670+ ///
1671+ /// This is only used when [WidgetInspectorServiceExtensions.getRootWidgetTree]
1672+ /// is called with fullDetails=false. To get the full widget details, including
1673+ /// any details provided by subclasses, [toJsonMap] should be used instead.
1674+ ///
1675+ /// See https://github.com/flutter/devtools/issues/8553 for details about this
1676+ /// iterative approach.
1677+ Map <String , Object ?> toJsonMapIterative (
1678+ DiagnosticsSerializationDelegate delegate,
1679+ ) {
1680+ final _NodesToJsonifyStack childrenToJsonify =
1681+ ListQueue <(DiagnosticsNode , void Function (_JsonDiagnosticsNode ))>();
1682+ _JsonDiagnosticsNode result = < String , Object ? > {};
1683+ assert (() {
1684+ result = _toJson (
1685+ delegate,
1686+ childrenToJsonify: childrenToJsonify,
1687+ );
1688+ _jsonifyNextNodesInStack (
1689+ childrenToJsonify,
1690+ delegate: delegate,
1691+ );
1692+ return true ;
1693+ }());
1694+ return result;
1695+ }
1696+
16671697 /// Serializes a [List] of [DiagnosticsNode] s to a JSON list according to
16681698 /// the configuration provided by the [DiagnosticsSerializationDelegate] .
16691699 ///
@@ -1672,9 +1702,8 @@ abstract class DiagnosticsNode {
16721702 static List <Map <String , Object ?>> toJsonList (
16731703 List <DiagnosticsNode >? nodes,
16741704 DiagnosticsNode ? parent,
1675- DiagnosticsSerializationDelegate delegate, {
1676- bool fullDetails = true ,
1677- }) {
1705+ DiagnosticsSerializationDelegate delegate,
1706+ ) {
16781707 bool truncated = false ;
16791708 if (nodes == null ) {
16801709 return const < Map <String , Object ?>> [];
@@ -1685,11 +1714,9 @@ abstract class DiagnosticsNode {
16851714 nodes.add (DiagnosticsNode .message ('...' ));
16861715 truncated = true ;
16871716 }
1688- final List <Map <String , Object ?>> json = nodes.map <Map <String , Object ?>>((DiagnosticsNode node) {
1689- return node.toJsonMap (
1690- delegate.delegateForNode (node),
1691- fullDetails: fullDetails,
1692- );
1717+ final List <_JsonDiagnosticsNode > json =
1718+ nodes.map <_JsonDiagnosticsNode >((DiagnosticsNode node) {
1719+ return node.toJsonMap (delegate.delegateForNode (node));
16931720 }).toList ();
16941721 if (truncated) {
16951722 json.last['truncated' ] = true ;
@@ -1803,6 +1830,73 @@ abstract class DiagnosticsNode {
18031830 }());
18041831 return result;
18051832 }
1833+
1834+ void _jsonifyNextNodesInStack (
1835+ _NodesToJsonifyStack toJsonify, {
1836+ required DiagnosticsSerializationDelegate delegate,
1837+ }) {
1838+ while (toJsonify.isNotEmpty) {
1839+ final (
1840+ DiagnosticsNode nextNode,
1841+ void Function (_JsonDiagnosticsNode ) callback
1842+ ) = toJsonify.removeFirst ();
1843+ final _JsonDiagnosticsNode nodeAsJson = nextNode._toJson (
1844+ delegate,
1845+ childrenToJsonify: toJsonify,
1846+ );
1847+ callback (nodeAsJson);
1848+ }
1849+ }
1850+
1851+ Map <String , Object ?> _toJson (
1852+ DiagnosticsSerializationDelegate delegate, {
1853+ required _NodesToJsonifyStack childrenToJsonify,
1854+ }) {
1855+ final List <_JsonDiagnosticsNode > childrenJsonList =
1856+ < _JsonDiagnosticsNode > [];
1857+ final bool includeChildren =
1858+ getChildren ().isNotEmpty && delegate.subtreeDepth > 0 ;
1859+
1860+ // Collect the children nodes to convert to JSON later.
1861+ bool truncated = false ;
1862+ if (includeChildren) {
1863+ List <DiagnosticsNode > childrenNodes =
1864+ delegate.filterChildren (getChildren (), this );
1865+ final int originalNodeCount = childrenNodes.length;
1866+ childrenNodes = delegate.truncateNodesList (childrenNodes, this );
1867+ if (childrenNodes.length != originalNodeCount) {
1868+ childrenNodes.add (DiagnosticsNode .message ('...' ));
1869+ truncated = true ;
1870+ }
1871+ for (final DiagnosticsNode child in childrenNodes) {
1872+ childrenToJsonify.add ((
1873+ child,
1874+ (_JsonDiagnosticsNode jsonChild) {
1875+ childrenJsonList.add (jsonChild);
1876+ }
1877+ ));
1878+ }
1879+ }
1880+
1881+ final String description = toDescription ();
1882+ final String widgetRuntimeType =
1883+ description == '[root]' ? 'RootWidget' : description.split ('-' ).first;
1884+ final bool shouldIndent = style != DiagnosticsTreeStyle .flat &&
1885+ style != DiagnosticsTreeStyle .error;
1886+
1887+ return < String , Object ? > {
1888+ 'description' : description,
1889+ 'shouldIndent' : shouldIndent,
1890+ // TODO(elliette): This can be removed to reduce the JSON response even
1891+ // further once DevTools computes the widget runtime type from the
1892+ // description instead, see:
1893+ // https://github.com/flutter/devtools/issues/8556
1894+ 'widgetRuntimeType' : widgetRuntimeType,
1895+ 'truncated' : truncated,
1896+ ...delegate.additionalNodeProperties (this , fullDetails: false ),
1897+ if (includeChildren) 'children' : childrenJsonList,
1898+ };
1899+ }
18061900}
18071901
18081902/// Debugging message displayed like a property.
@@ -1872,17 +1966,8 @@ class StringProperty extends DiagnosticsProperty<String> {
18721966 final bool quoted;
18731967
18741968 @override
1875- Map <String , Object ?> toJsonMap (
1876- DiagnosticsSerializationDelegate delegate, {
1877- bool fullDetails = true ,
1878- }) {
1879- final Map <String , Object ?> json = super .toJsonMap (
1880- delegate,
1881- fullDetails: fullDetails,
1882- );
1883- if (! fullDetails) {
1884- return json;
1885- }
1969+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
1970+ final Map <String , Object ?> json = super .toJsonMap (delegate);
18861971 json['quoted' ] = quoted;
18871972 return json;
18881973 }
@@ -1937,18 +2022,8 @@ abstract class _NumProperty<T extends num> extends DiagnosticsProperty<T> {
19372022 }) : super .lazy ();
19382023
19392024 @override
1940- Map <String , Object ?> toJsonMap (
1941- DiagnosticsSerializationDelegate delegate, {
1942- bool fullDetails = true ,
1943- }) {
1944- final Map <String , Object ?> json = super .toJsonMap (
1945- delegate,
1946- fullDetails: fullDetails,
1947- );
1948- if (! fullDetails) {
1949- return json;
1950- }
1951-
2025+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
2026+ final Map <String , Object ?> json = super .toJsonMap (delegate);
19522027 if (unit != null ) {
19532028 json['unit' ] = unit;
19542029 }
@@ -2131,17 +2206,8 @@ class FlagProperty extends DiagnosticsProperty<bool> {
21312206 );
21322207
21332208 @override
2134- Map <String , Object ?> toJsonMap (
2135- DiagnosticsSerializationDelegate delegate, {
2136- bool fullDetails = true ,
2137- }) {
2138- final Map <String , Object ?> json = super .toJsonMap (
2139- delegate,
2140- fullDetails: fullDetails,
2141- );
2142- if (! fullDetails) {
2143- return json;
2144- }
2209+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
2210+ final Map <String , Object ?> json = super .toJsonMap (delegate);
21452211 if (ifTrue != null ) {
21462212 json['ifTrue' ] = ifTrue;
21472213 }
@@ -2262,17 +2328,8 @@ class IterableProperty<T> extends DiagnosticsProperty<Iterable<T>> {
22622328 }
22632329
22642330 @override
2265- Map <String , Object ?> toJsonMap (
2266- DiagnosticsSerializationDelegate delegate, {
2267- bool fullDetails = true ,
2268- }) {
2269- final Map <String , Object ?> json = super .toJsonMap (
2270- delegate,
2271- fullDetails: fullDetails,
2272- );
2273- if (! fullDetails) {
2274- return json;
2275- }
2331+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
2332+ final Map <String , Object ?> json = super .toJsonMap (delegate);
22762333 if (value != null ) {
22772334 json['values' ] = value! .map <String >((T value) => value.toString ()).toList ();
22782335 }
@@ -2409,17 +2466,8 @@ class ObjectFlagProperty<T> extends DiagnosticsProperty<T> {
24092466 }
24102467
24112468 @override
2412- Map <String , Object ?> toJsonMap (
2413- DiagnosticsSerializationDelegate delegate, {
2414- bool fullDetails = true ,
2415- }) {
2416- final Map <String , Object ?> json = super .toJsonMap (
2417- delegate,
2418- fullDetails: fullDetails,
2419- );
2420- if (! fullDetails) {
2421- return json;
2422- }
2469+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
2470+ final Map <String , Object ?> json = super .toJsonMap (delegate);
24232471 if (ifPresent != null ) {
24242472 json['ifPresent' ] = ifPresent;
24252473 }
@@ -2496,17 +2544,8 @@ class FlagsSummary<T> extends DiagnosticsProperty<Map<String, T?>> {
24962544 }
24972545
24982546 @override
2499- Map <String , Object ?> toJsonMap (
2500- DiagnosticsSerializationDelegate delegate, {
2501- bool fullDetails = true ,
2502- }) {
2503- final Map <String , Object ?> json = super .toJsonMap (
2504- delegate,
2505- fullDetails: fullDetails,
2506- );
2507- if (! fullDetails) {
2508- return json;
2509- }
2547+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
2548+ final Map <String , Object ?> json = super .toJsonMap (delegate);
25102549 if (value.isNotEmpty) {
25112550 json['values' ] = _formattedValues ().toList ();
25122551 }
@@ -2625,10 +2664,7 @@ class DiagnosticsProperty<T> extends DiagnosticsNode {
26252664 final bool allowNameWrap;
26262665
26272666 @override
2628- Map <String , Object ?> toJsonMap (
2629- DiagnosticsSerializationDelegate delegate, {
2630- bool fullDetails = true ,
2631- }) {
2667+ Map <String , Object ?> toJsonMap (DiagnosticsSerializationDelegate delegate) {
26322668 final T ? v = value;
26332669 List <Map <String , Object ?>>? properties;
26342670 if (delegate.expandPropertyValues && delegate.includeProperties && v is Diagnosticable && getProperties ().isEmpty) {
@@ -2638,16 +2674,9 @@ class DiagnosticsProperty<T> extends DiagnosticsNode {
26382674 delegate.filterProperties (v.toDiagnosticsNode ().getProperties (), this ),
26392675 this ,
26402676 delegate,
2641- fullDetails: fullDetails,
26422677 );
26432678 }
2644- final Map <String , Object ?> json = super .toJsonMap (
2645- delegate,
2646- fullDetails: fullDetails,
2647- );
2648- if (! fullDetails) {
2649- return json;
2650- }
2679+ final Map <String , Object ?> json = super .toJsonMap (delegate);
26512680 if (properties != null ) {
26522681 json['properties' ] = properties;
26532682 }
0 commit comments