Commit cb9152ca authored by Ian Hickson's avatar Ian Hickson

Merge pull request #1637 from Hixie/asserts

Improve exceptions and asserts for rendering lib.
parents 79828ef2 1a0484cc
...@@ -79,16 +79,16 @@ abstract class RenderSector extends RenderObject { ...@@ -79,16 +79,16 @@ abstract class RenderSector extends RenderObject {
} }
SectorConstraints get constraints => super.constraints; SectorConstraints get constraints => super.constraints;
bool debugDoesMeetConstraints() { void debugAssertDoesMeetConstraints() {
assert(constraints != null); assert(constraints != null);
assert(deltaRadius != null); assert(deltaRadius != null);
assert(deltaRadius < double.INFINITY); assert(deltaRadius < double.INFINITY);
assert(deltaTheta != null); assert(deltaTheta != null);
assert(deltaTheta < double.INFINITY); assert(deltaTheta < double.INFINITY);
return constraints.minDeltaRadius <= deltaRadius && assert(constraints.minDeltaRadius <= deltaRadius);
deltaRadius <= math.max(constraints.minDeltaRadius, constraints.maxDeltaRadius) && assert(deltaRadius <= math.max(constraints.minDeltaRadius, constraints.maxDeltaRadius));
constraints.minDeltaTheta <= deltaTheta && assert(constraints.minDeltaTheta <= deltaTheta);
deltaTheta <= math.max(constraints.minDeltaTheta, constraints.maxDeltaTheta); assert(deltaTheta <= math.max(constraints.minDeltaTheta, constraints.maxDeltaTheta));
} }
void performResize() { void performResize() {
// default behaviour for subclasses that have sizedByParent = true // default behaviour for subclasses that have sizedByParent = true
......
...@@ -350,8 +350,9 @@ class RenderBlockViewport extends RenderBlockBase { ...@@ -350,8 +350,9 @@ class RenderBlockViewport extends RenderBlockBase {
double result; double result;
if (intrinsicCallback == null) { if (intrinsicCallback == null) {
assert(() { assert(() {
'RenderBlockViewport does not support returning intrinsic dimensions if the relevant callbacks have not been specified.'; if (!RenderObject.debugCheckingIntrinsics)
return RenderObject.debugInDebugDoesMeetConstraints; throw new UnsupportedError('$runtimeType does not support returning intrinsic dimensions if the relevant callbacks have not been specified.');
return true;
}); });
return constrainer(0.0); return constrainer(0.0);
} }
......
...@@ -98,7 +98,7 @@ class BoxConstraints extends Constraints { ...@@ -98,7 +98,7 @@ class BoxConstraints extends Constraints {
/// Returns new box constraints that are smaller by the given edge dimensions. /// Returns new box constraints that are smaller by the given edge dimensions.
BoxConstraints deflate(EdgeDims edges) { BoxConstraints deflate(EdgeDims edges) {
assert(edges != null); assert(edges != null);
assert(isNormalized); assert(debugAssertIsNormalized);
double horizontal = edges.left + edges.right; double horizontal = edges.left + edges.right;
double vertical = edges.top + edges.bottom; double vertical = edges.top + edges.bottom;
double deflatedMinWidth = math.max(0.0, minWidth - horizontal); double deflatedMinWidth = math.max(0.0, minWidth - horizontal);
...@@ -113,7 +113,7 @@ class BoxConstraints extends Constraints { ...@@ -113,7 +113,7 @@ class BoxConstraints extends Constraints {
/// Returns new box constraints that remove the minimum width and height requirements. /// Returns new box constraints that remove the minimum width and height requirements.
BoxConstraints loosen() { BoxConstraints loosen() {
assert(isNormalized); assert(debugAssertIsNormalized);
return new BoxConstraints( return new BoxConstraints(
minWidth: 0.0, minWidth: 0.0,
maxWidth: maxWidth, maxWidth: maxWidth,
...@@ -154,14 +154,14 @@ class BoxConstraints extends Constraints { ...@@ -154,14 +154,14 @@ class BoxConstraints extends Constraints {
/// Returns the width that both satisfies the constraints and is as close as /// Returns the width that both satisfies the constraints and is as close as
/// possible to the given width. /// possible to the given width.
double constrainWidth([double width = double.INFINITY]) { double constrainWidth([double width = double.INFINITY]) {
assert(isNormalized); assert(debugAssertIsNormalized);
return width.clamp(minWidth, maxWidth); return width.clamp(minWidth, maxWidth);
} }
/// Returns the height that both satisfies the constraints and is as close as /// Returns the height that both satisfies the constraints and is as close as
/// possible to the given height. /// possible to the given height.
double constrainHeight([double height = double.INFINITY]) { double constrainHeight([double height = double.INFINITY]) {
assert(isNormalized); assert(debugAssertIsNormalized);
return height.clamp(minHeight, maxHeight); return height.clamp(minHeight, maxHeight);
} }
...@@ -192,9 +192,15 @@ class BoxConstraints extends Constraints { ...@@ -192,9 +192,15 @@ class BoxConstraints extends Constraints {
/// Whether there is exactly one size that satifies the constraints. /// Whether there is exactly one size that satifies the constraints.
bool get isTight => hasTightWidth && hasTightHeight; bool get isTight => hasTightWidth && hasTightHeight;
/// Whether there is an upper bound on the maximum width.
bool get hasBoundedWidth => maxWidth < double.INFINITY;
/// Whether there is an upper bound on the maximum height.
bool get hasBoundedHeight => maxHeight < double.INFINITY;
/// Whether the given size satisfies the constraints. /// Whether the given size satisfies the constraints.
bool isSatisfiedBy(Size size) { bool isSatisfiedBy(Size size) {
assert(isNormalized); assert(debugAssertIsNormalized);
return (minWidth <= size.width) && (size.width <= maxWidth) && return (minWidth <= size.width) && (size.width <= maxWidth) &&
(minHeight <= size.height) && (size.height <= maxHeight); (minHeight <= size.height) && (size.height <= maxHeight);
} }
...@@ -245,8 +251,8 @@ class BoxConstraints extends Constraints { ...@@ -245,8 +251,8 @@ class BoxConstraints extends Constraints {
return b * t; return b * t;
if (b == null) if (b == null)
return a * (1.0 - t); return a * (1.0 - t);
assert(a.isNormalized); assert(a.debugAssertIsNormalized);
assert(b.isNormalized); assert(b.debugAssertIsNormalized);
return new BoxConstraints( return new BoxConstraints(
minWidth: ui.lerpDouble(a.minWidth, b.minWidth, t), minWidth: ui.lerpDouble(a.minWidth, b.minWidth, t),
maxWidth: ui.lerpDouble(a.maxWidth, b.maxWidth, t), maxWidth: ui.lerpDouble(a.maxWidth, b.maxWidth, t),
...@@ -255,8 +261,34 @@ class BoxConstraints extends Constraints { ...@@ -255,8 +261,34 @@ class BoxConstraints extends Constraints {
); );
} }
/// Returns whether the object's constraints are normalized.
/// Constraints are normalised if the minimums are less than or
/// equal to the corresponding maximums.
///
/// For example, a BoxConstraints object with a minWidth of 100.0
/// and a maxWidth of 90.0 is not normalized.
///
/// Most of the APIs on BoxConstraints expect the constraints to be
/// normalized and have undefined behavior when they are not. In
/// checked mode, many of these APIs will assert if the constraints
/// are not normalized.
bool get isNormalized => minWidth <= maxWidth && minHeight <= maxHeight; bool get isNormalized => minWidth <= maxWidth && minHeight <= maxHeight;
/// Same as [isNormalized] but, in checked mode, throws an exception
/// if isNormalized is false.
bool get debugAssertIsNormalized {
assert(() {
if (maxWidth < minWidth && maxHeight < minHeight)
throw new RenderingError('BoxConstraints has both width and height constraints non-normalized.\n$this');
if (maxWidth < minWidth)
throw new RenderingError('BoxConstraints has non-normalized width constraints.\n$this');
if (maxHeight < minHeight)
throw new RenderingError('BoxConstraints has non-normalized height constraints.\n$this');
return isNormalized;
});
return isNormalized;
}
BoxConstraints normalize() { BoxConstraints normalize() {
return new BoxConstraints( return new BoxConstraints(
minWidth: minWidth, minWidth: minWidth,
...@@ -267,13 +299,13 @@ class BoxConstraints extends Constraints { ...@@ -267,13 +299,13 @@ class BoxConstraints extends Constraints {
} }
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
assert(isNormalized); assert(debugAssertIsNormalized);
if (identical(this, other)) if (identical(this, other))
return true; return true;
if (other is! BoxConstraints) if (other is! BoxConstraints)
return false; return false;
final BoxConstraints typedOther = other; final BoxConstraints typedOther = other;
assert(typedOther.isNormalized); assert(typedOther.debugAssertIsNormalized);
return minWidth == typedOther.minWidth && return minWidth == typedOther.minWidth &&
maxWidth == typedOther.maxWidth && maxWidth == typedOther.maxWidth &&
minHeight == typedOther.minHeight && minHeight == typedOther.minHeight &&
...@@ -281,7 +313,7 @@ class BoxConstraints extends Constraints { ...@@ -281,7 +313,7 @@ class BoxConstraints extends Constraints {
} }
int get hashCode { int get hashCode {
assert(isNormalized); assert(debugAssertIsNormalized);
return hashValues(minWidth, maxWidth, minHeight, maxHeight); return hashValues(minWidth, maxWidth, minHeight, maxHeight);
} }
...@@ -362,7 +394,7 @@ abstract class RenderBox extends RenderObject { ...@@ -362,7 +394,7 @@ abstract class RenderBox extends RenderObject {
/// ///
/// Override in subclasses that implement [performLayout]. /// Override in subclasses that implement [performLayout].
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.isNormalized); assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(0.0); return constraints.constrainWidth(0.0);
} }
...@@ -371,7 +403,7 @@ abstract class RenderBox extends RenderObject { ...@@ -371,7 +403,7 @@ abstract class RenderBox extends RenderObject {
/// ///
/// Override in subclasses that implement [performLayout]. /// Override in subclasses that implement [performLayout].
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.isNormalized); assert(constraints.debugAssertIsNormalized);
return constraints.constrainWidth(0.0); return constraints.constrainWidth(0.0);
} }
...@@ -380,7 +412,7 @@ abstract class RenderBox extends RenderObject { ...@@ -380,7 +412,7 @@ abstract class RenderBox extends RenderObject {
/// ///
/// Override in subclasses that implement [performLayout]. /// Override in subclasses that implement [performLayout].
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.isNormalized); assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(0.0); return constraints.constrainHeight(0.0);
} }
...@@ -393,7 +425,7 @@ abstract class RenderBox extends RenderObject { ...@@ -393,7 +425,7 @@ abstract class RenderBox extends RenderObject {
/// ///
/// Override in subclasses that implement [performLayout]. /// Override in subclasses that implement [performLayout].
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.isNormalized); assert(constraints.debugAssertIsNormalized);
return constraints.constrainHeight(0.0); return constraints.constrainHeight(0.0);
} }
...@@ -447,7 +479,7 @@ abstract class RenderBox extends RenderObject { ...@@ -447,7 +479,7 @@ abstract class RenderBox extends RenderObject {
_size = new _DebugSize(_size, this, debugCanParentUseSize); _size = new _DebugSize(_size, this, debugCanParentUseSize);
return true; return true;
}); });
assert(debugDoesMeetConstraints()); assert(() { debugAssertDoesMeetConstraints(); return true; });
} }
Rect get semanticBounds => Point.origin & size; Rect get semanticBounds => Point.origin & size;
...@@ -532,32 +564,91 @@ abstract class RenderBox extends RenderObject { ...@@ -532,32 +564,91 @@ abstract class RenderBox extends RenderObject {
/// The box constraints most recently received from the parent. /// The box constraints most recently received from the parent.
BoxConstraints get constraints => super.constraints; BoxConstraints get constraints => super.constraints;
bool debugDoesMeetConstraints() { void debugAssertDoesMeetConstraints() {
assert(!RenderObject.debugInDebugDoesMeetConstraints);
RenderObject.debugInDebugDoesMeetConstraints = true;
assert(constraints != null); assert(constraints != null);
// verify that the size is not infinite
assert(_size != null); assert(_size != null);
assert(() { // verify that the size is not infinite
'See https://flutter.io/layout/#unbounded-constraints'; if (_size.isInfinite) {
return !_size.isInfinite; StringBuffer information = new StringBuffer();
}); if (!constraints.hasBoundedWidth) {
RenderBox node = this;
while (!node.constraints.hasBoundedWidth && node.parent is RenderBox)
node = node.parent;
information.writeln('The nearest ancestor providing an unbounded width constraint is:');
information.writeln(' $node');
List<String> settings = <String>[];
node.debugDescribeSettings(settings);
for (String line in settings)
information.writeln(' $line');
}
if (!constraints.hasBoundedHeight) {
RenderBox node = this;
while (!node.constraints.hasBoundedHeight && node.parent is RenderBox)
node = node.parent;
information.writeln('The nearest ancestor providing an unbounded height constraint is:');
information.writeln(' $node');
List<String> settings = <String>[];
node.debugDescribeSettings(settings);
for (String line in settings)
information.writeln(' $line');
}
throw new RenderingError(
'$runtimeType object was given an infinite size during layout.\n'
'This probably means that it is a render object that tries to be\n'
'as big as possible, but it was put inside another render object\n'
'that allows its children to pick their own size.\n'
'$information'
'See https://flutter.io/layout/ for more information.'
);
}
// verify that the size is within the constraints // verify that the size is within the constraints
bool result = constraints.isSatisfiedBy(_size); if (!constraints.isSatisfiedBy(_size)) {
if (!result) throw new RenderingError(
debugPrint("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size"); '$runtimeType does not meet its constraints.\n'
'Constraints: $constraints\n'
'Size: $_size\n'
'If you are not writing your own RenderBox subclass, then this is not\n'
'your fault. Contact support: https://github.com/flutter/flutter/issues/new'
);
}
// verify that the intrinsics are also within the constraints // verify that the intrinsics are also within the constraints
assert(!RenderObject.debugCheckingIntrinsics);
RenderObject.debugCheckingIntrinsics = true;
double intrinsic; double intrinsic;
StringBuffer failures = new StringBuffer();
int failureCount = 0;
intrinsic = getMinIntrinsicWidth(constraints); intrinsic = getMinIntrinsicWidth(constraints);
assert(intrinsic == constraints.constrainWidth(intrinsic)); if (intrinsic != constraints.constrainWidth(intrinsic)) {
failures.writeln(' * getMinIntrinsicWidth() -- returned: w=$intrinsic');
failureCount += 1;
}
intrinsic = getMaxIntrinsicWidth(constraints); intrinsic = getMaxIntrinsicWidth(constraints);
assert(intrinsic == constraints.constrainWidth(intrinsic)); if (intrinsic != constraints.constrainWidth(intrinsic)) {
failures.writeln(' * getMaxIntrinsicWidth() -- returned: w=$intrinsic');
failureCount += 1;
}
intrinsic = getMinIntrinsicHeight(constraints); intrinsic = getMinIntrinsicHeight(constraints);
assert(intrinsic == constraints.constrainHeight(intrinsic)); if (intrinsic != constraints.constrainHeight(intrinsic)) {
failures.writeln(' * getMinIntrinsicHeight() -- returned: h=$intrinsic');
failureCount += 1;
}
intrinsic = getMaxIntrinsicHeight(constraints); intrinsic = getMaxIntrinsicHeight(constraints);
assert(intrinsic == constraints.constrainHeight(intrinsic)); if (intrinsic != constraints.constrainHeight(intrinsic)) {
RenderObject.debugInDebugDoesMeetConstraints = false; failures.writeln(' * getMaxIntrinsicHeight() -- returned: h=$intrinsic');
return result; failureCount += 1;
}
RenderObject.debugCheckingIntrinsics = false;
if (failures.isNotEmpty) {
assert(failureCount > 0);
throw new RenderingError(
'The intrinsic dimension methods of the $runtimeType class returned values that violate the given constraints.\n'
'The constraints were: $constraints\n'
'The following method${failureCount > 1 ? "s" : ""} returned values outside of those constraints:\n'
'$failures'
'If you are not writing your own RenderBox subclass, then this is not\n'
'your fault. Contact support: https://github.com/flutter/flutter/issues/new'
);
}
} }
void markNeedsLayout() { void markNeedsLayout() {
......
...@@ -724,52 +724,45 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -724,52 +724,45 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
void visitChildren(RenderObjectVisitor visitor) { } void visitChildren(RenderObjectVisitor visitor) { }
dynamic debugOwner; dynamic debugOwner;
static int _debugPrintedExceptionCount = 0;
void _debugReportException(String method, dynamic exception, StackTrace stack) { void _debugReportException(String method, dynamic exception, StackTrace stack) {
try { try {
if (debugRenderingExceptionHandler != null) { if (debugRenderingExceptionHandler != null) {
debugRenderingExceptionHandler(this, method, exception, stack); debugRenderingExceptionHandler(this, method, exception, stack);
} else { } else {
debugPrint('-- EXCEPTION CAUGHT BY RENDERING LIBRARY -------------------------------'); _debugPrintedExceptionCount += 1;
debugPrint('The following exception was raised during $method():'); if (_debugPrintedExceptionCount == 1) {
debugPrint('$exception'); debugPrint('-- EXCEPTION CAUGHT BY RENDERING LIBRARY -------------------------------');
debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}'); debugPrint('The following exception was raised during $method():');
if (debugOwner != null) debugPrint('$exception');
debugPrint('This RenderObject had the following owner:\n$debugOwner'); debugPrint('The following RenderObject was being processed when the exception was fired:\n${this}');
int depth = 0; if (debugOwner != null)
List<String> descendants = <String>[]; debugPrint('This RenderObject had the following owner:\n$debugOwner');
const int maxDepth = 5; int depth = 0;
void visitor(RenderObject child) { List<String> descendants = <String>[];
descendants.add('${" " * depth}$child'); const int maxDepth = 5;
depth += 1; void visitor(RenderObject child) {
if (depth < maxDepth) descendants.add('${" " * depth}$child');
child.visitChildren(visitor); depth += 1;
depth -= 1; if (depth < maxDepth)
} child.visitChildren(visitor);
visitChildren(visitor); depth -= 1;
if (descendants.length > 1) { }
debugPrint('This RenderObject had the following descendants (showing up to depth $maxDepth):'); visitChildren(visitor);
} else if (descendants.length == 1) { if (descendants.length > 1) {
debugPrint('This RenderObject had the following child:'); debugPrint('This RenderObject had the following descendants (showing up to depth $maxDepth):');
} else if (descendants.length == 1) {
debugPrint('This RenderObject had the following child:');
} else {
debugPrint('This RenderObject has no descendants.');
}
descendants.forEach(debugPrint);
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
} else { } else {
debugPrint('This RenderObject has no descendants.'); debugPrint('Another exception was raised: ${exception.toString().split("\n")[0]}');
} }
descendants.forEach(debugPrint);
assert(() {
if (debugInDebugDoesMeetConstraints) {
debugPrint('This exception was thrown while debugDoesMeetConstraints() was running.');
debugPrint('debugDoesMeetConstraints() verifies that some invariants are not being');
debugPrint('violated. For example, it verifies that RenderBox objects are sized in');
debugPrint('a manner consistent with the constraints provided, and, in addition, that');
debugPrint('the getMinIntrinsicWidth(), getMaxIntrinsicWidth(), etc, functions all');
debugPrint('return consistent values within the same constraints.');
debugPrint('If you are not writing your own RenderObject subclass, then this is not');
debugPrint('your fault. Contact support: https://github.com/flutter/flutter/issues/new');
}
return true;
});
debugPrint('Stack trace:');
debugPrint('$stack');
debugPrint('------------------------------------------------------------------------');
} }
} catch (exception) { } catch (exception) {
debugPrint('(exception during exception handler: $exception)'); debugPrint('(exception during exception handler: $exception)');
...@@ -809,15 +802,23 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -809,15 +802,23 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
Constraints _constraints; Constraints _constraints;
/// The layout constraints most recently supplied by the parent. /// The layout constraints most recently supplied by the parent.
Constraints get constraints => _constraints; Constraints get constraints => _constraints;
/// Override this function in a subclass to verify that your state matches the constraints object. /// Verify that the object's constraints are being met. Override
bool debugDoesMeetConstraints(); /// this function in a subclass to verify that your state matches
/// When true, debugDoesMeetConstraints() is currently executing. /// the constraints object. This function is only called in checked
/// /// mode. If the constraints are not met, it should assert or throw
/// This should be set by implementations of debugDoesMeetConstraints() so that /// an exception.
/// tests can selectively ignore custom layout callbacks. It should not be set void debugAssertDoesMeetConstraints();
/// outside of debugDoesMeetConstraints() implementations and should not be used
/// for purposes other than tests. /// When true, debugAssertDoesMeetConstraints() is currently
static bool debugInDebugDoesMeetConstraints = false; /// executing asserts for verifying the consistent behaviour of
/// intrinsic dimensions methods.
///
/// This should only be set by debugAssertDoesMeetConstraints()
/// implementations. It is used by tests to selectively ignore
/// custom layout callbacks. It should not be set outside of
/// debugAssertDoesMeetConstraints(), and should not be checked in
/// release mode (where it will always be false).
static bool debugCheckingIntrinsics = false;
bool debugAncestorsAlreadyMarkedNeedsLayout() { bool debugAncestorsAlreadyMarkedNeedsLayout() {
if (_relayoutSubtreeRoot == null) if (_relayoutSubtreeRoot == null)
return true; // we haven't yet done layout even once, so there's nothing for us to do return true; // we haven't yet done layout even once, so there's nothing for us to do
...@@ -1022,7 +1023,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1022,7 +1023,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
assert(() { _debugDoingThisResize = true; return true; }); assert(() { _debugDoingThisResize = true; return true; });
try { try {
performResize(); performResize();
assert(debugDoesMeetConstraints()); assert(() { debugAssertDoesMeetConstraints(); return true; });
} catch (e, stack) { } catch (e, stack) {
_debugReportException('performResize', e, stack); _debugReportException('performResize', e, stack);
} }
...@@ -1038,7 +1039,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1038,7 +1039,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
try { try {
performLayout(); performLayout();
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
assert(debugDoesMeetConstraints()); assert(() { debugAssertDoesMeetConstraints(); return true; });
} catch (e, stack) { } catch (e, stack) {
_debugReportException('performLayout', e, stack); _debugReportException('performLayout', e, stack);
} }
...@@ -2023,3 +2024,10 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent ...@@ -2023,3 +2024,10 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
return result; return result;
} }
} }
/// Error thrown when the rendering library encounters a contract violation.
class RenderingError extends AssertionError {
RenderingError(this.message);
final String message;
String toString() => message;
}
...@@ -78,7 +78,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> ...@@ -78,7 +78,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
// We never call layout() on this class, so this should never get // We never call layout() on this class, so this should never get
// checked. (This class is laid out using scheduleInitialLayout().) // checked. (This class is laid out using scheduleInitialLayout().)
bool debugDoesMeetConstraints() { assert(false); return false; } void debugAssertDoesMeetConstraints() { assert(false); }
void performResize() { void performResize() {
assert(false); assert(false);
......
...@@ -155,10 +155,14 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> { ...@@ -155,10 +155,14 @@ class _MixedViewportElement extends RenderObjectElement<MixedViewport> {
double _noIntrinsicExtent(BoxConstraints constraints) { double _noIntrinsicExtent(BoxConstraints constraints) {
assert(() { assert(() {
'MixedViewport does not support returning intrinsic dimensions. ' + if (!RenderObject.debugCheckingIntrinsics) {
'Calculating the intrinsic dimensions would require walking the entire child list, ' + throw new UnsupportedError(
'which defeats the entire point of having a lazily-built list of children.'; 'MixedViewport does not support returning intrinsic dimensions.\n'
return RenderObject.debugInDebugDoesMeetConstraints; 'Calculating the intrinsic dimensions would require walking the entire child list,\n'
'which defeats the entire point of having a lazily-built list of children.'
);
}
return true;
}); });
return null; return null;
} }
......
...@@ -442,13 +442,14 @@ class ScrollableViewportState extends ScrollableState<ScrollableViewport> { ...@@ -442,13 +442,14 @@ class ScrollableViewportState extends ScrollableState<ScrollableViewport> {
class Block extends StatelessComponent { class Block extends StatelessComponent {
Block({ Block({
Key key, Key key,
this.children, this.children: const <Widget>[],
this.padding, this.padding,
this.initialScrollOffset, this.initialScrollOffset,
this.scrollDirection: Axis.vertical, this.scrollDirection: Axis.vertical,
this.onScroll, this.onScroll,
this.scrollableKey this.scrollableKey
}) : super(key: key) { }) : super(key: key) {
assert(children != null);
assert(!children.any((Widget child) => child == null)); assert(!children.any((Widget child) => child == null));
} }
......
...@@ -11,7 +11,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate { ...@@ -11,7 +11,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
BoxConstraints getSizeConstraints; BoxConstraints getSizeConstraints;
Size getSize(BoxConstraints constraints) { Size getSize(BoxConstraints constraints) {
if (!RenderObject.debugInDebugDoesMeetConstraints) if (!RenderObject.debugCheckingIntrinsics)
getSizeConstraints = constraints; getSizeConstraints = constraints;
return new Size(200.0, 300.0); return new Size(200.0, 300.0);
} }
...@@ -23,7 +23,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate { ...@@ -23,7 +23,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
bool performLayoutIsChild; bool performLayoutIsChild;
void performLayout(Size size, BoxConstraints constraints) { void performLayout(Size size, BoxConstraints constraints) {
assert(!RenderObject.debugInDebugDoesMeetConstraints); assert(!RenderObject.debugCheckingIntrinsics);
expect(() { expect(() {
performLayoutSize = size; performLayoutSize = size;
performLayoutConstraints = constraints; performLayoutConstraints = constraints;
...@@ -36,7 +36,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate { ...@@ -36,7 +36,7 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
bool shouldRelayoutCalled = false; bool shouldRelayoutCalled = false;
bool shouldRelayoutValue = false; bool shouldRelayoutValue = false;
bool shouldRelayout(_) { bool shouldRelayout(_) {
assert(!RenderObject.debugInDebugDoesMeetConstraints); assert(!RenderObject.debugCheckingIntrinsics);
shouldRelayoutCalled = true; shouldRelayoutCalled = true;
return shouldRelayoutValue; return shouldRelayoutValue;
} }
......
...@@ -14,13 +14,13 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate { ...@@ -14,13 +14,13 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate {
Size childSizeFromGetPositionForChild; Size childSizeFromGetPositionForChild;
Size getSize(BoxConstraints constraints) { Size getSize(BoxConstraints constraints) {
if (!RenderObject.debugInDebugDoesMeetConstraints) if (!RenderObject.debugCheckingIntrinsics)
constraintsFromGetSize = constraints; constraintsFromGetSize = constraints;
return new Size(200.0, 300.0); return new Size(200.0, 300.0);
} }
BoxConstraints getConstraintsForChild(BoxConstraints constraints) { BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
assert(!RenderObject.debugInDebugDoesMeetConstraints); assert(!RenderObject.debugCheckingIntrinsics);
constraintsFromGetConstraintsForChild = constraints; constraintsFromGetConstraintsForChild = constraints;
return new BoxConstraints( return new BoxConstraints(
minWidth: 100.0, minWidth: 100.0,
...@@ -31,7 +31,7 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate { ...@@ -31,7 +31,7 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate {
} }
Offset getPositionForChild(Size size, Size childSize) { Offset getPositionForChild(Size size, Size childSize) {
assert(!RenderObject.debugInDebugDoesMeetConstraints); assert(!RenderObject.debugCheckingIntrinsics);
sizeFromGetPositionForChild = size; sizeFromGetPositionForChild = size;
childSizeFromGetPositionForChild = childSize; childSizeFromGetPositionForChild = childSize;
return Offset.zero; return Offset.zero;
...@@ -40,7 +40,7 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate { ...@@ -40,7 +40,7 @@ class TestOneChildLayoutDelegate extends OneChildLayoutDelegate {
bool shouldRelayoutCalled = false; bool shouldRelayoutCalled = false;
bool shouldRelayoutValue = false; bool shouldRelayoutValue = false;
bool shouldRelayout(_) { bool shouldRelayout(_) {
assert(!RenderObject.debugInDebugDoesMeetConstraints); assert(!RenderObject.debugCheckingIntrinsics);
shouldRelayoutCalled = true; shouldRelayoutCalled = true;
return shouldRelayoutValue; return shouldRelayoutValue;
} }
......
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