Unverified Commit 7c0300a3 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter] throw more specific error messages if a lerp'd type does not conform...

[flutter] throw more specific error messages if a lerp'd type does not conform to Tween API (#74684)
parent 4a1445bb
......@@ -256,6 +256,51 @@ class Tween<T extends dynamic> extends Animatable<T> {
T lerp(double t) {
assert(begin != null);
assert(end != null);
assert(() {
// Assertions that attempt to catch common cases of tweening types
// that do not conform to the Tween requirements.
dynamic? result;
try {
result = begin + (end - begin) * t;
result as T;
return true;
} on NoSuchMethodError {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Cannot lerp between "$begin" and "$end".'),
ErrorDescription(
'The type ${begin.runtimeType} might not fully implement `+`, `-`, and/or `*`. '
'See "Types with special considerations" at https://api.flutter.dev/flutter/animation/Tween-class.html '
'for more information.',
),
if (begin is Color || end is Color)
ErrorHint('To lerp colors, consider ColorTween instead.')
else if (begin is Rect || end is Rect)
ErrorHint('To lerp rects, consider RectTween instead.')
else
ErrorHint(
'There may be a dedicated "${begin.runtimeType}Tween" for this type, '
'or you may need to create one.'
),
]);
} on TypeError {
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Cannot lerp between "$begin" and "$end".'),
ErrorDescription(
'The type ${begin.runtimeType} returned a ${result.runtimeType} after '
'multiplication with a double value. '
'See "Types with special considerations" at https://api.flutter.dev/flutter/animation/Tween-class.html '
'for more information.',
),
if (begin is int || end is int)
ErrorHint('To lerp int values, consider IntTween or StepTween instead.')
else
ErrorHint(
'There may be a dedicated "${begin.runtimeType}Tween" for this type, '
'or you may need to create one.'
),
]);
}
}());
return begin + (end - begin) * t as T;
}
......
......@@ -7,7 +7,105 @@ import 'package:flutter/animation.dart';
import 'package:flutter/widgets.dart';
import 'package:vector_math/vector_math_64.dart';
const String kApiDocsLink = 'See "Types with special considerations" at https://api.flutter.dev/flutter/animation/Tween-class.html for more information.';
void main() {
test('throws flutter error when tweening types that do not fully satisfy tween requirements - Object', () {
final Tween<Object> objectTween = Tween<Object>(
begin: Object(),
end: Object(),
);
FlutterError? error;
try {
objectTween.transform(0.1);
} on FlutterError catch (err) {
error = err;
}
if (error == null) {
fail('Expected Tween.transform to throw a FlutterError');
}
expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), <String>[
'Cannot lerp between "Instance of \'Object\'" and "Instance of \'Object\'".',
'The type Object might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
'There may be a dedicated "ObjectTween" for this type, or you may need to create one.'
]);
});
test('throws flutter error when tweening types that do not fully satisfy tween requirements - Color', () {
final Tween<Color> colorTween = Tween<Color>(
begin: const Color(0xFF000000),
end: const Color(0xFFFFFFFF),
);
FlutterError? error;
try {
colorTween.transform(0.1);
} on FlutterError catch (err) {
error = err;
}
if (error == null) {
fail('Expected Tween.transform to throw a FlutterError');
}
expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), <String>[
'Cannot lerp between "Color(0xff000000)" and "Color(0xffffffff)".',
'The type Color might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
'To lerp colors, consider ColorTween instead.',
]);
});
test('throws flutter error when tweening types that do not fully satisfy tween requirements - Rect', () {
final Tween<Rect> rectTween = Tween<Rect>(
begin: const Rect.fromLTWH(0, 0, 10, 10),
end: const Rect.fromLTWH(2, 2, 2, 2)
);
FlutterError? error;
try {
rectTween.transform(0.1);
} on FlutterError catch (err) {
error = err;
}
if (error == null) {
fail('Expected Tween.transform to throw a FlutterError');
}
expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), <String>[
'Cannot lerp between "Rect.fromLTRB(0.0, 0.0, 10.0, 10.0)" and "Rect.fromLTRB(2.0, 2.0, 4.0, 4.0)".',
'The type Rect might not fully implement `+`, `-`, and/or `*`. $kApiDocsLink',
'To lerp rects, consider RectTween instead.',
]);
});
test('throws flutter error when tweening types that do not fully satisfy tween requirements - int', () {
final Tween<int> colorTween = Tween<int>(
begin: 0,
end: 1,
);
FlutterError? error;
try {
colorTween.transform(0.1);
} on FlutterError catch (err) {
error = err;
}
if (error == null) {
fail('Expected Tween.transform to throw a FlutterError');
}
expect(error.diagnostics.map((DiagnosticsNode node) => node.toString()), <String>[
'Cannot lerp between "0" and "1".',
'The type int returned a double after multiplication with a double value. $kApiDocsLink',
'To lerp int values, consider IntTween or StepTween instead.',
]);
});
test('Can chain tweens', () {
final Tween<double> tween = Tween<double>(begin: 0.30, end: 0.50);
expect(tween, hasOneLineDescription);
......
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