Skip to content

Commit e5e5f61

Browse files
authored
Improve error messages from slivers. (flutter#9971)
Also, fix some logic in SliverPadding.
1 parent 6ab2958 commit e5e5f61

File tree

4 files changed

+69
-49
lines changed

4 files changed

+69
-49
lines changed

packages/flutter/lib/src/rendering/box.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ class BoxConstraints extends Constraints {
384384
@override
385385
bool debugAssertIsValid({
386386
bool isAppliedConstraint: false,
387-
InformationCollector informationCollector
387+
InformationCollector informationCollector,
388388
}) {
389389
assert(() {
390390
void throwError(String message) {

packages/flutter/lib/src/rendering/sliver.dart

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -397,21 +397,31 @@ class SliverConstraints extends Constraints {
397397
@override
398398
bool debugAssertIsValid({
399399
bool isAppliedConstraint: false,
400-
InformationCollector informationCollector
400+
InformationCollector informationCollector,
401401
}) {
402-
// TODO(ianh): make these show pretty errors
403-
assert(axis != null);
404-
assert(growthDirection != null);
405-
assert(scrollOffset != null);
406-
assert(overlap != null);
407-
assert(remainingPaintExtent != null);
408-
assert(crossAxisExtent != null);
409-
assert(viewportMainAxisExtent != null);
410-
assert(scrollOffset >= 0.0);
411-
assert(crossAxisExtent >= 0.0);
412-
assert(viewportMainAxisExtent >= 0.0);
413-
assert(remainingPaintExtent >= 0.0);
414-
assert(isNormalized); // should be redundant with earlier checks
402+
assert(() {
403+
void verify(bool check, String message) {
404+
if (check)
405+
return;
406+
final StringBuffer information = new StringBuffer();
407+
if (informationCollector != null)
408+
informationCollector(information);
409+
throw new FlutterError('$runtimeType is not valid: $message\n${information}The offending constraints were:\n $this');
410+
}
411+
verify(axis != null, 'The "axis" is null.');
412+
verify(growthDirection != null, 'The "growthDirection" is null.');
413+
verify(scrollOffset != null, 'The "scrollOffset" is null.');
414+
verify(overlap != null, 'The "overlap" is null.');
415+
verify(remainingPaintExtent != null, 'The "remainingPaintExtent" is null.');
416+
verify(crossAxisExtent != null, 'The "crossAxisExtent" is null.');
417+
verify(viewportMainAxisExtent != null, 'The "viewportMainAxisExtent" is null.');
418+
verify(scrollOffset >= 0.0, 'The "scrollOffset" is negative.');
419+
verify(crossAxisExtent >= 0.0, 'The "crossAxisExtent" is negative.');
420+
verify(viewportMainAxisExtent >= 0.0, 'The "viewportMainAxisExtent" is negative.');
421+
verify(remainingPaintExtent >= 0.0, 'The "remainingPaintExtent" is negative.');
422+
verify(isNormalized, 'The constraints are not normalized.'); // should be redundant with earlier checks
423+
return true;
424+
});
415425
return true;
416426
}
417427

@@ -566,39 +576,46 @@ class SliverGeometry {
566576
/// Asserts that this geometry is internally consistent.
567577
///
568578
/// Does nothing if asserts are disabled. Always returns true.
569-
bool get debugAssertIsValid {
570-
assert(scrollExtent != null);
571-
assert(scrollExtent >= 0.0);
572-
assert(paintExtent != null);
573-
assert(paintExtent >= 0.0);
574-
assert(paintOrigin != null);
575-
assert(layoutExtent != null);
576-
assert(layoutExtent >= 0.0);
579+
bool debugAssertIsValid({
580+
InformationCollector informationCollector,
581+
}) {
577582
assert(() {
583+
void verify(bool check, String message) {
584+
if (check)
585+
return;
586+
final StringBuffer information = new StringBuffer();
587+
if (informationCollector != null)
588+
informationCollector(information);
589+
throw new FlutterError('$runtimeType is not valid: $message\n$information');
590+
}
591+
verify(scrollExtent != null, 'The "scrollExtent" is null.');
592+
verify(scrollExtent >= 0.0, 'The "scrollExtent" is negative.');
593+
verify(paintExtent != null, 'The "paintExtent" is null.');
594+
verify(paintExtent >= 0.0, 'The "paintExtent" is negative.');
595+
verify(paintOrigin != null, 'The "paintOrigin" is null.');
596+
verify(layoutExtent != null, 'The "layoutExtent" is null.');
597+
verify(layoutExtent >= 0.0, 'The "layoutExtent" is negative.');
578598
if (layoutExtent > paintExtent) {
579-
throw new FlutterError(
580-
'SliverGeometry has a layoutExtent that exceeds its paintExtent.\n' +
581-
_debugCompareFloats('paintExtent', paintExtent, 'layoutExtent', layoutExtent)
599+
verify(false,
600+
'The "layoutExtent" exceeds the "paintExtent".\n' +
601+
_debugCompareFloats('paintExtent', paintExtent, 'layoutExtent', layoutExtent),
582602
);
583603
}
584-
return true;
585-
});
586-
assert(maxPaintExtent != null);
587-
assert(() {
604+
verify(maxPaintExtent != null, 'The "maxPaintExtent" is null.');
588605
if (maxPaintExtent < paintExtent) {
589-
throw new FlutterError(
590-
'SliverGeometry has a maxPaintExtent that is less than its paintExtent.\n' +
606+
verify(false,
607+
'The "maxPaintExtent" is less than the "paintExtent".\n' +
591608
_debugCompareFloats('maxPaintExtent', maxPaintExtent, 'paintExtent', paintExtent) +
592609
'By definition, a sliver can\'t paint more than the maximum that it can paint!'
593610
);
594611
}
612+
verify(hitTestExtent != null, 'The "hitTestExtent" is null.');
613+
verify(hitTestExtent >= 0.0, 'The "hitTestExtent" is negative.');
614+
verify(visible != null, 'The "visible" property is null.');
615+
verify(hasVisualOverflow != null, 'The "hasVisualOverflow" is null.');
616+
verify(scrollOffsetCorrection != null, 'The "scrollOffsetCorrection" is null.');
595617
return true;
596618
});
597-
assert(hitTestExtent != null);
598-
assert(hitTestExtent >= 0.0);
599-
assert(visible != null);
600-
assert(hasVisualOverflow != null);
601-
assert(scrollOffsetCorrection != null);
602619
return true;
603620
}
604621

@@ -837,7 +854,12 @@ abstract class RenderSliver extends RenderObject {
837854

838855
@override
839856
void debugAssertDoesMeetConstraints() {
840-
assert(geometry.debugAssertIsValid);
857+
assert(geometry.debugAssertIsValid(
858+
informationCollector: (StringBuffer information) {
859+
information.writeln('The RenderSliver that returned the offending geometry was:');
860+
information.writeln(' ${toStringShallow('\n ')}');
861+
},
862+
));
841863
assert(() {
842864
if (geometry.paintExtent > constraints.remainingPaintExtent) {
843865
throw new FlutterError(

packages/flutter/lib/src/rendering/sliver_padding.dart

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,16 +162,14 @@ class RenderSliverPadding extends RenderSliver with RenderObjectWithChildMixin<R
162162
to: mainAxisPadding + childLayoutGeometry.scrollExtent,
163163
);
164164
final double mainAxisPaddingPaintExtent = beforePaddingPaintExtent + afterPaddingPaintExtent;
165+
final double paintExtent = math.min(
166+
beforePaddingPaintExtent + math.max(childLayoutGeometry.paintExtent, childLayoutGeometry.layoutExtent + afterPaddingPaintExtent),
167+
constraints.remainingPaintExtent,
168+
);
165169
geometry = new SliverGeometry(
166170
scrollExtent: mainAxisPadding + childLayoutGeometry.scrollExtent,
167-
paintExtent: math.min(
168-
beforePaddingPaintExtent + math.max(childLayoutGeometry.paintExtent, childLayoutGeometry.layoutExtent + afterPaddingPaintExtent),
169-
constraints.remainingPaintExtent,
170-
),
171-
layoutExtent: math.min(
172-
mainAxisPaddingPaintExtent + childLayoutGeometry.layoutExtent,
173-
constraints.remainingPaintExtent,
174-
),
171+
paintExtent: paintExtent,
172+
layoutExtent: math.min(mainAxisPaddingPaintExtent + childLayoutGeometry.layoutExtent, paintExtent),
175173
maxPaintExtent: mainAxisPadding + childLayoutGeometry.maxPaintExtent,
176174
hitTestExtent: math.max(
177175
mainAxisPaddingPaintExtent + childLayoutGeometry.paintExtent,

packages/flutter/test/rendering/slivers_helpers_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ void main() {
6969
});
7070

7171
test('SliverGeometry', () {
72-
expect(const SliverGeometry().debugAssertIsValid, isTrue);
72+
expect(const SliverGeometry().debugAssertIsValid(), isTrue);
7373
expect(() {
74-
const SliverGeometry(layoutExtent: 10.0, paintExtent: 9.0).debugAssertIsValid;
74+
const SliverGeometry(layoutExtent: 10.0, paintExtent: 9.0).debugAssertIsValid();
7575
}, throwsFlutterError);
7676
expect(() {
77-
const SliverGeometry(paintExtent: 9.0, maxPaintExtent: 8.0).debugAssertIsValid;
77+
const SliverGeometry(paintExtent: 9.0, maxPaintExtent: 8.0).debugAssertIsValid();
7878
}, throwsFlutterError);
7979
});
8080
}

0 commit comments

Comments
 (0)