Unverified Commit d127f2c9 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Fix nullability for some routing related stuff (#67675)

parent 4042eb97
......@@ -2225,7 +2225,7 @@ class FollowerLayer extends ContainerLayer {
Matrix4? _invertedTransform;
bool _inverseDirty = true;
Offset? _transformOffset<S extends Object>(Offset localPosition) {
Offset? _transformOffset(Offset localPosition) {
if (_inverseDirty) {
_invertedTransform = Matrix4.tryInvert(getLastTransform()!);
_inverseDirty = false;
......@@ -2245,7 +2245,7 @@ class FollowerLayer extends ContainerLayer {
}
return false;
}
final Offset? transformedOffset = _transformOffset<S>(localPosition);
final Offset? transformedOffset = _transformOffset(localPosition);
if (transformedOffset == null) {
return false;
}
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'dart:ui';
......@@ -737,7 +736,7 @@ class RawKeyboard {
}
@immutable
class _ModifierSidePair extends Object {
class _ModifierSidePair {
const _ModifierSidePair(this.modifier, this.side);
final ModifierKey modifier;
......
......@@ -131,7 +131,6 @@ class Draggable<T extends Object> extends StatefulWidget {
assert(maxSimultaneousDrags == null || maxSimultaneousDrags >= 0),
super(key: key);
/// The data that will be dropped by this draggable.
final T? data;
......
......@@ -881,7 +881,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
/// The given [BuildContext] will be rebuilt if the state of the route changes
/// while it is visible (specifically, if [isCurrent] or [canPop] change value).
@optionalTypeArgs
static ModalRoute<T>? of<T extends Object>(BuildContext context) {
static ModalRoute<T>? of<T extends Object?>(BuildContext context) {
final _ModalScopeStatus? widget = context.dependOnInheritedWidgetOfExactType<_ModalScopeStatus>();
return widget?.route as ModalRoute<T>?;
}
......@@ -1818,7 +1818,7 @@ class _DialogRoute<T> extends PopupRoute<T> {
///
/// * [showDialog], which displays a Material-style dialog.
/// * [showCupertinoDialog], which displays an iOS-style dialog.
Future<T> showGeneralDialog<T extends Object>({
Future<T> showGeneralDialog<T extends Object?>({
required BuildContext context,
required RoutePageBuilder pageBuilder,
bool barrierDismissible = false,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:collection';
import 'package:flutter/foundation.dart';
......@@ -19,7 +17,7 @@ final List<String> results = <String>[];
Set<TestRoute> routes = HashSet<TestRoute>();
class TestRoute extends Route<String> with LocalHistoryRoute<String> {
class TestRoute extends Route<String?> with LocalHistoryRoute<String?> {
TestRoute(this.name);
final String name;
......@@ -57,7 +55,7 @@ class TestRoute extends Route<String> with LocalHistoryRoute<String> {
}
@override
void didReplace(Route<dynamic> oldRoute) {
void didReplace(Route<dynamic>? oldRoute) {
expect(oldRoute, isA<TestRoute>());
final TestRoute castRoute = oldRoute as TestRoute;
log('didReplace ${castRoute.name}');
......@@ -65,11 +63,11 @@ class TestRoute extends Route<String> with LocalHistoryRoute<String> {
}
@override
bool didPop(String result) {
bool didPop(String? result) {
log('didPop $result');
bool returnValue;
if (returnValue = super.didPop(result))
navigator.finalizeRoute(this);
navigator!.finalizeRoute(this);
return returnValue;
}
......@@ -82,9 +80,9 @@ class TestRoute extends Route<String> with LocalHistoryRoute<String> {
}
@override
void didChangeNext(Route<dynamic> nextRoute) {
void didChangeNext(Route<dynamic>? nextRoute) {
expect(nextRoute, anyOf(isNull, isA<TestRoute>()));
final TestRoute castRoute = nextRoute as TestRoute;
final TestRoute? castRoute = nextRoute as TestRoute?;
log('didChangeNext ${castRoute?.name}');
super.didChangeNext(castRoute);
}
......@@ -148,7 +146,7 @@ void main() {
),
),
);
final NavigatorState host = navigatorKey.currentState;
final NavigatorState host = navigatorKey.currentState!;
await runNavigatorTest(
tester,
host,
......@@ -159,7 +157,7 @@ void main() {
'initial: didChangeNext null',
],
);
TestRoute second;
late TestRoute second;
await runNavigatorTest(
tester,
host,
......@@ -231,7 +229,7 @@ void main() {
),
),
);
final NavigatorState host = navigatorKey.currentState;
final NavigatorState host = navigatorKey.currentState!;
await runNavigatorTest(
tester,
host,
......@@ -242,7 +240,7 @@ void main() {
'first: didChangeNext null',
],
);
TestRoute second;
late TestRoute second;
await runNavigatorTest(
tester,
host,
......@@ -294,7 +292,7 @@ void main() {
'second: didChangeNext three',
],
);
TestRoute four;
late TestRoute four;
await runNavigatorTest(
tester,
host,
......@@ -342,7 +340,7 @@ void main() {
),
),
);
final NavigatorState host = navigatorKey.currentState;
final NavigatorState host = navigatorKey.currentState!;
await runNavigatorTest(
tester,
host,
......@@ -364,7 +362,7 @@ void main() {
'A: didChangeNext B',
],
);
TestRoute routeC;
late TestRoute routeC;
await runNavigatorTest(
tester,
host,
......@@ -377,7 +375,7 @@ void main() {
],
);
expect(routeC.isActive, isTrue);
TestRoute routeB;
late TestRoute routeB;
await runNavigatorTest(
tester,
host,
......@@ -424,7 +422,7 @@ void main() {
),
),
);
final NavigatorState host = navigatorKey.currentState;
final NavigatorState host = navigatorKey.currentState!;
await runNavigatorTest(
tester,
host,
......@@ -552,7 +550,7 @@ void main() {
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
PageRouteBuilder<void>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> input, Animation<double> out) {
......@@ -601,7 +599,7 @@ void main() {
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
PageRouteBuilder<void>(
settings: settings,
pageBuilder: (BuildContext context, Animation<double> input, Animation<double> out) {
......@@ -656,9 +654,9 @@ void main() {
);
// Push page one, its secondary animation is kAlwaysDismissedAnimation.
ProxyAnimation secondaryAnimationProxyPageOne;
ProxyAnimation animationPageOne;
navigator.currentState.push(
late ProxyAnimation secondaryAnimationProxyPageOne;
late ProxyAnimation animationPageOne;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
......@@ -675,9 +673,9 @@ void main() {
// Push page two, the secondary animation of page one is the primary
// animation of page two.
ProxyAnimation secondaryAnimationProxyPageTwo;
ProxyAnimation animationPageTwo;
navigator.currentState.push(
late ProxyAnimation secondaryAnimationProxyPageTwo;
late ProxyAnimation animationPageTwo;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageTwo = secondaryAnimation as ProxyAnimation;
......@@ -695,7 +693,7 @@ void main() {
// Pop page two, the secondary animation of page one becomes
// kAlwaysDismissedAnimation.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(secondaryAnimationPageOne.parent, animationPageTwo.parent);
......@@ -714,9 +712,9 @@ void main() {
);
// Push page one, its secondary animation is kAlwaysDismissedAnimation.
ProxyAnimation secondaryAnimationProxyPageOne;
ProxyAnimation animationPageOne;
navigator.currentState.push(
late ProxyAnimation secondaryAnimationProxyPageOne;
late ProxyAnimation animationPageOne;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
......@@ -733,10 +731,10 @@ void main() {
// Push page two, the secondary animation of page one is the primary
// animation of page two.
ProxyAnimation secondaryAnimationProxyPageTwo;
ProxyAnimation animationPageTwo;
late ProxyAnimation secondaryAnimationProxyPageTwo;
late ProxyAnimation animationPageTwo;
Route<void> secondRoute;
navigator.currentState.push(
navigator.currentState!.push(
secondRoute = PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageTwo = secondaryAnimation as ProxyAnimation;
......@@ -754,7 +752,7 @@ void main() {
// Remove the second route, the secondary animation of page one is
// kAlwaysDismissedAnimation again.
navigator.currentState.removeRoute(secondRoute);
navigator.currentState!.removeRoute(secondRoute);
await tester.pump();
expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
});
......@@ -769,9 +767,9 @@ void main() {
);
// Push page one, its secondary animation is kAlwaysDismissedAnimation.
ProxyAnimation secondaryAnimationProxyPageOne;
ProxyAnimation animationPageOne;
navigator.currentState.push(
late ProxyAnimation secondaryAnimationProxyPageOne;
late ProxyAnimation animationPageOne;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
......@@ -788,8 +786,8 @@ void main() {
// Push page two, the secondary animation of page one is the primary
// animation of page two.
ProxyAnimation animationPageTwo;
navigator.currentState.push(
late ProxyAnimation animationPageTwo;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
animationPageTwo = animation as ProxyAnimation;
......@@ -803,8 +801,8 @@ void main() {
// Replace with a different route while push is ongoing to trigger
// TrainHopping.
ProxyAnimation animationPageThree;
navigator.currentState.pushReplacement(
late ProxyAnimation animationPageThree;
navigator.currentState!.pushReplacement(
TestPageRouteBuilder(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
animationPageThree = animation as ProxyAnimation;
......@@ -825,7 +823,7 @@ void main() {
expect(secondaryAnimationPageOne.parent, animationPageThree.parent);
// Pop page three.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
await tester.pumpAndSettle();
expect(secondaryAnimationPageOne.parent, kAlwaysDismissedAnimation);
......@@ -841,9 +839,9 @@ void main() {
);
// Push page one, its secondary animation is kAlwaysDismissedAnimation.
ProxyAnimation secondaryAnimationProxyPageOne;
ProxyAnimation animationPageOne;
navigator.currentState.push(
late ProxyAnimation secondaryAnimationProxyPageOne;
late ProxyAnimation animationPageOne;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
secondaryAnimationProxyPageOne = secondaryAnimation as ProxyAnimation;
......@@ -860,8 +858,8 @@ void main() {
// Push page two, the secondary animation of page one is the primary
// animation of page two.
ProxyAnimation animationPageTwo;
navigator.currentState.push(
late ProxyAnimation animationPageTwo;
navigator.currentState!.push(
PageRouteBuilder<void>(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
animationPageTwo = animation as ProxyAnimation;
......@@ -875,7 +873,7 @@ void main() {
// Replace with a different route while push is ongoing to trigger
// TrainHopping.
navigator.currentState.pushReplacement(
navigator.currentState!.pushReplacement(
TestPageRouteBuilder(
pageBuilder: (_, Animation<double> animation, Animation<double> secondaryAnimation) {
return const Text('Page Three');
......@@ -889,7 +887,7 @@ void main() {
expect(trainHopper.currentTrain, animationPageTwo.parent);
// Pop page three while replacement push is ongoing.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
expect(secondaryAnimationPageOne.parent, isA<TrainHoppingAnimation>());
final TrainHoppingAnimation trainHopper2 = secondaryAnimationPageOne.parent as TrainHoppingAnimation;
......@@ -902,8 +900,8 @@ void main() {
testWidgets('secondary animation is triggered when pop initial route', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
Animation<double> secondaryAnimationOfRouteOne;
Animation<double> primaryAnimationOfRouteTwo;
late Animation<double> secondaryAnimationOfRouteOne;
late Animation<double> primaryAnimationOfRouteTwo;
await tester.pumpWidget(
MaterialApp(
navigatorKey: navigator,
......@@ -927,7 +925,7 @@ void main() {
expect(secondaryAnimationOfRouteOne.value, 1.0);
expect(secondaryAnimationOfRouteOne.value, primaryAnimationOfRouteTwo.value);
// Pops the top most route and verifies two routes are still chained.
navigator.currentState.pop();
navigator.currentState!.pop();
await tester.pump();
await tester.pump(const Duration(milliseconds: 30));
expect(secondaryAnimationOfRouteOne.value, 0.9);
......@@ -1127,7 +1125,7 @@ void main() {
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext innerContext) {
return Container(
......@@ -1177,7 +1175,7 @@ void main() {
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
ModifiedReverseTransitionDurationRoute<void>(
builder: (BuildContext innerContext) {
return Container(
......@@ -1236,7 +1234,7 @@ void main() {
builder: (BuildContext context) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
ModifiedReverseTransitionDurationRoute<void>(
builder: (BuildContext innerContext) {
return Container(
......@@ -1298,7 +1296,7 @@ void main() {
child: ElevatedButton(
child: const Text('X'),
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
_TestDialogRouteWithCustomBarrierCurve<void>(
child: const Text('Hello World'),
)
......@@ -1360,7 +1358,7 @@ void main() {
child: ElevatedButton(
child: const Text('X'),
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
_TestDialogRouteWithCustomBarrierCurve<void>(
child: const Text('Hello World'),
barrierCurve: Curves.linear,
......@@ -1425,7 +1423,7 @@ void main() {
child: ElevatedButton(
child: const Text('X'),
onPressed: () {
Navigator.of(context).push<void>(
Navigator.of(context)!.push<void>(
_TestDialogRouteWithCustomBarrierCurve<void>(
child: const Text('Hello World'),
barrierLabel: 'test label',
......@@ -1499,7 +1497,7 @@ void main() {
expect(focusNodeOnPageOne.hasFocus, isTrue);
// Pushes one page.
navigatorKey.currentState.push<void>(
navigatorKey.currentState!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('dummy2'),
)
......@@ -1513,7 +1511,7 @@ void main() {
expect(focusNodeOnPageTwo.hasFocus, isTrue);
// Pushes another page.
navigatorKey.currentState.push<void>(
navigatorKey.currentState!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('dummy3'),
)
......@@ -1527,7 +1525,7 @@ void main() {
expect(focusNodeOnPageThree.hasFocus, isTrue);
// Pops two pages simultaneously.
navigatorKey.currentState.popUntil((Route<void> route) => route.isFirst);
navigatorKey.currentState!.popUntil((Route<void> route) => route.isFirst);
await tester.pumpAndSettle();
// It should refocus page one after pops.
expect(focusNodeOnPageOne.hasFocus, isTrue);
......@@ -1545,7 +1543,7 @@ void main() {
expect(focusNodeOnPageOne.hasFocus, isTrue);
// Pushes one page.
navigatorKey.currentState.push<void>(
navigatorKey.currentState!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Material(child: TextField()),
)
......@@ -1565,7 +1563,7 @@ void main() {
expect(focusNodeOnPageTwo.hasPrimaryFocus, isFalse);
// Pushes another page.
navigatorKey.currentState.push<void>(
navigatorKey.currentState!.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('dummy3'),
)
......@@ -1579,7 +1577,7 @@ void main() {
expect(focusNodeOnPageThree.hasFocus, isTrue);
// Pops two pages simultaneously.
navigatorKey.currentState.popUntil((Route<void> route) => route.isFirst);
navigatorKey.currentState!.popUntil((Route<void> route) => route.isFirst);
await tester.pumpAndSettle();
// It should refocus page one after pops.
expect(focusNodeOnPageOne.hasFocus, isTrue);
......@@ -1629,6 +1627,28 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('dialog1'), findsNothing);
});
testWidgets('ModalRoute.of works for void routes', (WidgetTester tester) async {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
navigatorKey: navigatorKey,
home: const Text('home'),
));
expect(find.text('page2'), findsNothing);
navigatorKey.currentState!.push<void>(MaterialPageRoute<void>(
builder: (BuildContext context) {
return const Text('page2');
}
));
await tester.pumpAndSettle();
expect(find.text('page2'), findsOneWidget);
final ModalRoute<void>? parentRoute = ModalRoute.of<void>(tester.element(find.text('page2')));
expect(parentRoute, isNotNull);
expect(parentRoute, isA<MaterialPageRoute<void>>());
});
}
double _getOpacity(GlobalKey key, WidgetTester tester) {
......@@ -1644,9 +1664,9 @@ double _getOpacity(GlobalKey key, WidgetTester tester) {
class ModifiedReverseTransitionDurationRoute<T> extends MaterialPageRoute<T> {
ModifiedReverseTransitionDurationRoute({
@required WidgetBuilder builder,
RouteSettings settings,
this.reverseTransitionDuration,
required WidgetBuilder builder,
RouteSettings? settings,
required this.reverseTransitionDuration,
bool fullscreenDialog = false,
}) : super(
builder: builder,
......@@ -1690,7 +1710,7 @@ class MockRouteAware extends Fake implements RouteAware {
}
class TestPageRouteBuilder extends PageRouteBuilder<void> {
TestPageRouteBuilder({RoutePageBuilder pageBuilder}) : super(pageBuilder: pageBuilder);
TestPageRouteBuilder({required RoutePageBuilder pageBuilder}) : super(pageBuilder: pageBuilder);
@override
Animation<double> createAnimation() {
......@@ -1703,7 +1723,7 @@ class DialogObserver extends NavigatorObserver {
int dialogCount = 0;
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
if (route.toString().contains('_DialogRoute')) {
dialogRoutes.add(route as ModalRoute<dynamic>);
dialogCount++;
......@@ -1712,7 +1732,7 @@ class DialogObserver extends NavigatorObserver {
}
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
if (route.toString().contains('_DialogRoute')) {
dialogRoutes.removeLast();
dialogCount--;
......@@ -1723,9 +1743,9 @@ class DialogObserver extends NavigatorObserver {
class _TestDialogRouteWithCustomBarrierCurve<T> extends PopupRoute<T> {
_TestDialogRouteWithCustomBarrierCurve({
@required Widget child,
required Widget child,
this.barrierLabel,
Curve barrierCurve,
Curve? barrierCurve,
}) : _barrierCurve = barrierCurve,
_child = child;
......@@ -1735,7 +1755,7 @@ class _TestDialogRouteWithCustomBarrierCurve<T> extends PopupRoute<T> {
bool get barrierDismissible => true;
@override
final String barrierLabel;
final String? barrierLabel;
@override
Color get barrierColor => Colors.black; // easier value to test against
......@@ -1745,9 +1765,9 @@ class _TestDialogRouteWithCustomBarrierCurve<T> extends PopupRoute<T> {
if (_barrierCurve == null) {
return super.barrierCurve;
}
return _barrierCurve;
return _barrierCurve!;
}
final Curve _barrierCurve;
final Curve? _barrierCurve;
@override
Duration get transitionDuration => const Duration(milliseconds: 100); // easier value to test against
......@@ -1768,10 +1788,10 @@ class WidgetWithLocalHistory extends StatefulWidget {
}
class WidgetWithLocalHistoryState extends State<WidgetWithLocalHistory> {
LocalHistoryEntry _localHistory;
late LocalHistoryEntry _localHistory;
void addLocalHistory() {
final ModalRoute<dynamic> route = ModalRoute.of(context);
final ModalRoute<dynamic> route = ModalRoute.of(context)!;
_localHistory = LocalHistoryEntry();
route.addLocalHistoryEntry(_localHistory);
}
......@@ -1792,9 +1812,9 @@ class TransitionDetector extends DefaultTransitionDelegate<void> {
bool hasTransition = false;
@override
Iterable<RouteTransitionRecord> resolve({
List<RouteTransitionRecord> newPageRouteHistory,
Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes
required List<RouteTransitionRecord> newPageRouteHistory,
required Map<RouteTransitionRecord?, RouteTransitionRecord> locationToExitingPageRoute,
required Map<RouteTransitionRecord?, List<RouteTransitionRecord>> pageRouteToPagelessRoutes
}) {
hasTransition = true;
return super.resolve(
......@@ -1806,13 +1826,13 @@ class TransitionDetector extends DefaultTransitionDelegate<void> {
}
Widget buildNavigator({
List<Page<dynamic>> pages,
PopPageCallback onPopPage,
GlobalKey<NavigatorState> key,
TransitionDelegate<dynamic> transitionDelegate
required List<Page<dynamic>> pages,
required PopPageCallback onPopPage,
GlobalKey<NavigatorState>? key,
TransitionDelegate<dynamic>? transitionDelegate
}) {
return MediaQuery(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window),
data: MediaQueryData.fromWindow(WidgetsBinding.instance!.window),
child: Localizations(
locale: const Locale('en', 'US'),
delegates: const <LocalizationsDelegate<dynamic>>[
......
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