From b83187d8f304c3a760a9b9e1bbfbb6bf0a0e5a62 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 4 Dec 2015 12:19:44 -0800 Subject: [PATCH] MultiChildLayoutDelegate should assert that all children have had layoutChild called exactly once Fixes #692 Fixes #690 --- .../lib/src/rendering/custom_layout.dart | 25 +++++++++++++++++++ packages/flutter/lib/src/widgets/basic.dart | 4 ++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/custom_layout.dart b/packages/flutter/lib/src/rendering/custom_layout.dart index 0d3ade003a8..ab300bf3948 100644 --- a/packages/flutter/lib/src/rendering/custom_layout.dart +++ b/packages/flutter/lib/src/rendering/custom_layout.dart @@ -11,6 +11,7 @@ class MultiChildLayoutParentData extends ContainerBoxParentDataMixin abstract class MultiChildLayoutDelegate { Map _idToChild; + Set _debugChildrenNeedingLayout; /// Returns the size of this object given the incomming constraints. /// The size cannot reflect the instrinsic sizes of the children. @@ -26,6 +27,10 @@ abstract class MultiChildLayoutDelegate { Size layoutChild(Object childId, BoxConstraints constraints) { final RenderBox child = _idToChild[childId]; assert(child != null); + assert(() { + 'A MultiChildLayoutDelegate cannot layout the same child more than once.'; + return _debugChildrenNeedingLayout.remove(child); + }); child.layout(constraints, parentUsesSize: true); return child.size; } @@ -40,6 +45,14 @@ abstract class MultiChildLayoutDelegate { void _callPerformLayout(Size size, BoxConstraints constraints, RenderBox firstChild) { final Map previousIdToChild = _idToChild; + + Set debugPreviousChildrenNeedingLayout; + assert(() { + debugPreviousChildrenNeedingLayout = _debugChildrenNeedingLayout; + _debugChildrenNeedingLayout = new Set(); + return true; + }); + try { _idToChild = new Map(); RenderBox child = firstChild; @@ -47,11 +60,23 @@ abstract class MultiChildLayoutDelegate { final MultiChildLayoutParentData childParentData = child.parentData; assert(childParentData.id != null); _idToChild[childParentData.id] = child; + assert(() { + _debugChildrenNeedingLayout.add(child); + return true; + }); child = childParentData.nextSibling; } performLayout(size, constraints); + assert(() { + 'A MultiChildLayoutDelegate needs to call layoutChild on every child.'; + return _debugChildrenNeedingLayout.isEmpty; + }); } finally { _idToChild = previousIdToChild; + assert(() { + _debugChildrenNeedingLayout = debugPreviousChildrenNeedingLayout; + return true; + }); } } diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 954f69488ee..ee46a0e60ff 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -305,7 +305,9 @@ class LayoutId extends ParentDataWidget { Key key, Widget child, this.id - }) : super(key: key, child: child); + }) : super(key: key, child: child) { + assert(child != null); + } final Object id;