Commit 42eafce0 authored by Adam Barth's avatar Adam Barth

Merge pull request #740 from abarth/custom_layout_assert

MultiChildLayoutDelegate should assert that all children have had layoutChild called exactly once
parents 8b3df848 b83187d8
...@@ -11,6 +11,7 @@ class MultiChildLayoutParentData extends ContainerBoxParentDataMixin<RenderBox> ...@@ -11,6 +11,7 @@ class MultiChildLayoutParentData extends ContainerBoxParentDataMixin<RenderBox>
abstract class MultiChildLayoutDelegate { abstract class MultiChildLayoutDelegate {
Map<Object, RenderBox> _idToChild; Map<Object, RenderBox> _idToChild;
Set<RenderBox> _debugChildrenNeedingLayout;
/// Returns the size of this object given the incomming constraints. /// Returns the size of this object given the incomming constraints.
/// The size cannot reflect the instrinsic sizes of the children. /// The size cannot reflect the instrinsic sizes of the children.
...@@ -26,6 +27,10 @@ abstract class MultiChildLayoutDelegate { ...@@ -26,6 +27,10 @@ abstract class MultiChildLayoutDelegate {
Size layoutChild(Object childId, BoxConstraints constraints) { Size layoutChild(Object childId, BoxConstraints constraints) {
final RenderBox child = _idToChild[childId]; final RenderBox child = _idToChild[childId];
assert(child != null); assert(child != null);
assert(() {
'A MultiChildLayoutDelegate cannot layout the same child more than once.';
return _debugChildrenNeedingLayout.remove(child);
});
child.layout(constraints, parentUsesSize: true); child.layout(constraints, parentUsesSize: true);
return child.size; return child.size;
} }
...@@ -40,6 +45,14 @@ abstract class MultiChildLayoutDelegate { ...@@ -40,6 +45,14 @@ abstract class MultiChildLayoutDelegate {
void _callPerformLayout(Size size, BoxConstraints constraints, RenderBox firstChild) { void _callPerformLayout(Size size, BoxConstraints constraints, RenderBox firstChild) {
final Map<Object, RenderBox> previousIdToChild = _idToChild; final Map<Object, RenderBox> previousIdToChild = _idToChild;
Set<RenderBox> debugPreviousChildrenNeedingLayout;
assert(() {
debugPreviousChildrenNeedingLayout = _debugChildrenNeedingLayout;
_debugChildrenNeedingLayout = new Set<RenderBox>();
return true;
});
try { try {
_idToChild = new Map<Object, RenderBox>(); _idToChild = new Map<Object, RenderBox>();
RenderBox child = firstChild; RenderBox child = firstChild;
...@@ -47,11 +60,23 @@ abstract class MultiChildLayoutDelegate { ...@@ -47,11 +60,23 @@ abstract class MultiChildLayoutDelegate {
final MultiChildLayoutParentData childParentData = child.parentData; final MultiChildLayoutParentData childParentData = child.parentData;
assert(childParentData.id != null); assert(childParentData.id != null);
_idToChild[childParentData.id] = child; _idToChild[childParentData.id] = child;
assert(() {
_debugChildrenNeedingLayout.add(child);
return true;
});
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
performLayout(size, constraints); performLayout(size, constraints);
assert(() {
'A MultiChildLayoutDelegate needs to call layoutChild on every child.';
return _debugChildrenNeedingLayout.isEmpty;
});
} finally { } finally {
_idToChild = previousIdToChild; _idToChild = previousIdToChild;
assert(() {
_debugChildrenNeedingLayout = debugPreviousChildrenNeedingLayout;
return true;
});
} }
} }
......
...@@ -305,7 +305,9 @@ class LayoutId extends ParentDataWidget { ...@@ -305,7 +305,9 @@ class LayoutId extends ParentDataWidget {
Key key, Key key,
Widget child, Widget child,
this.id this.id
}) : super(key: key, child: child); }) : super(key: key, child: child) {
assert(child != null);
}
final Object id; final Object id;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment