diff --git a/dev/bots/custom_rules/avoid_future_catcherror.dart b/dev/bots/custom_rules/avoid_future_catcherror.dart index 1ff83be792..ce9d014115 100644 --- a/dev/bots/custom_rules/avoid_future_catcherror.dart +++ b/dev/bots/custom_rules/avoid_future_catcherror.dart @@ -77,13 +77,11 @@ class _Visitor extends RecursiveAstVisitor { @override void visitMethodInvocation(MethodInvocation node) { - if (node.methodName.name != 'onError' && node.methodName.name != 'catchError') { - return; + if (node case MethodInvocation( + methodName: SimpleIdentifier(name: 'onError' || 'catchError'), + realTarget: Expression(staticType: DartType(isDartAsyncFuture: true)), + )) { + _offendingNodes.add(node); } - final DartType? targetType = node.realTarget?.staticType; - if (targetType == null || !targetType.isDartAsyncFuture) { - return; - } - _offendingNodes.add(node); } } diff --git a/dev/bots/test/analyze-gen-defaults/dev/tools/gen_defaults/bin/template.dart b/dev/bots/test/analyze-gen-defaults/dev/tools/gen_defaults/bin/template.dart index 1e611feb98..9478d29088 100644 --- a/dev/bots/test/analyze-gen-defaults/dev/tools/gen_defaults/bin/template.dart +++ b/dev/bots/test/analyze-gen-defaults/dev/tools/gen_defaults/bin/template.dart @@ -169,16 +169,12 @@ abstract class TokenTemplate { } String? _numToString(Object? value, [int? digits]) { - if (value == null) { - return null; - } - if (value is num) { - if (value == double.infinity) { - return 'double.infinity'; - } - return digits == null ? value.toString() : value.toStringAsFixed(digits); - } - return getToken(value as String).toString(); + return switch (value) { + null => null, + double.infinity => 'double.infinity', + num() => digits == null ? value.toString() : value.toStringAsFixed(digits), + _ => getToken(value as String).toString(), + }; } /// Generate an elevation value for the given component token. diff --git a/dev/bots/test/analyze-test-input/root/dev/tools/localization/bin/gen_localizations.dart b/dev/bots/test/analyze-test-input/root/dev/tools/localization/bin/gen_localizations.dart index 8505054ed5..bc0f30f542 100644 --- a/dev/bots/test/analyze-test-input/root/dev/tools/localization/bin/gen_localizations.dart +++ b/dev/bots/test/analyze-test-input/root/dev/tools/localization/bin/gen_localizations.dart @@ -3,13 +3,11 @@ // found in the LICENSE file. void main(List args) { - String type = ''; - if (args[0] == '--material') { - type = 'material'; - } - if (args[0] == '--cupertino') { - type = 'cupertino'; - } + final String type = switch (args.first) { + '--material' => 'material', + '--cupertino' => 'cupertino', + _ => '', + }; print(''' // Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/dev/devicelab/lib/framework/ios.dart b/dev/devicelab/lib/framework/ios.dart index 7fc35606eb..2f61af1299 100644 --- a/dev/devicelab/lib/framework/ios.dart +++ b/dev/devicelab/lib/framework/ios.dart @@ -85,14 +85,10 @@ Future testWithNewIOSSimulator( final String? iosKey = decodeResult.keys .where((String key) => key.contains('iphoneos')) .firstOrNull; - final Object? iosDetails = decodeResult[iosKey]; - String? runtimeBuildForSelectedXcode; - if (iosDetails != null && iosDetails is Map) { - final Object? preferredBuild = iosDetails['preferredBuild']; - if (preferredBuild is String) { - runtimeBuildForSelectedXcode = preferredBuild; - } - } + final String? runtimeBuildForSelectedXcode = switch (decodeResult[iosKey]) { + {'preferredBuild': final String build} => build, + _ => null, + }; String? iOSSimRuntime; diff --git a/dev/devicelab/lib/framework/metrics_center.dart b/dev/devicelab/lib/framework/metrics_center.dart index 1f5adda62a..2cb78ab48b 100644 --- a/dev/devicelab/lib/framework/metrics_center.dart +++ b/dev/devicelab/lib/framework/metrics_center.dart @@ -12,14 +12,12 @@ import 'package:metrics_center/metrics_center.dart'; /// /// It supports both token and credential authentications. Future connectFlutterDestination() async { - const String kTokenPath = 'TOKEN_PATH'; - const String kGcpProject = 'GCP_PROJECT'; final Map env = Platform.environment; final bool isTesting = env['IS_TESTING'] == 'true'; - if (env.containsKey(kTokenPath) && env.containsKey(kGcpProject)) { + if (env case {'TOKEN_PATH': final String path, 'GCP_PROJECT': final String project}) { return FlutterDestination.makeFromAccessToken( - File(env[kTokenPath]!).readAsStringSync(), - env[kGcpProject]!, + File(path).readAsStringSync(), + project, isTesting: isTesting, ); } diff --git a/dev/integration_tests/flutter_gallery/lib/demo/shrine/model/app_state_model.dart b/dev/integration_tests/flutter_gallery/lib/demo/shrine/model/app_state_model.dart index 71ac5d763c..a28668cd09 100644 --- a/dev/integration_tests/flutter_gallery/lib/demo/shrine/model/app_state_model.dart +++ b/dev/integration_tests/flutter_gallery/lib/demo/shrine/model/app_state_model.dart @@ -70,16 +70,12 @@ class AppStateModel extends Model { // Removes an item from the cart. void removeItemFromCart(int productId) { - final int? value = _productsInCart[productId]; - - if (value != null) { - if (_productsInCart[productId] == 1) { + switch (_productsInCart[productId]) { + case 1: _productsInCart.remove(productId); - } else { + case final int value: _productsInCart[productId] = value - 1; - } } - notifyListeners(); } diff --git a/dev/integration_tests/flutter_gallery/test/live_smoketest.dart b/dev/integration_tests/flutter_gallery/test/live_smoketest.dart index cbc7fe9a60..abcbf92156 100644 --- a/dev/integration_tests/flutter_gallery/test/live_smoketest.dart +++ b/dev/integration_tests/flutter_gallery/test/live_smoketest.dart @@ -92,15 +92,10 @@ Future main() async { } final Finder backFinder = find.byElementPredicate( - (Element element) { - final Widget widget = element.widget; - if (widget is Tooltip) { - return widget.message == 'Back'; - } - if (widget is CupertinoNavigationBarBackButton) { - return true; - } - return false; + (Element element) => switch (element.widget) { + Tooltip(message: 'Back') => true, + CupertinoNavigationBarBackButton() => true, + _ => false, }, description: 'Material or Cupertino back button', ); diff --git a/dev/integration_tests/new_gallery/lib/studies/reply/adaptive_nav.dart b/dev/integration_tests/new_gallery/lib/studies/reply/adaptive_nav.dart index 088fb3f37d..d9bcdfb468 100644 --- a/dev/integration_tests/new_gallery/lib/studies/reply/adaptive_nav.dart +++ b/dev/integration_tests/new_gallery/lib/studies/reply/adaptive_nav.dart @@ -574,16 +574,14 @@ class _MobileNavState extends State<_MobileNav> with TickerProviderStateMixin { } bool _handleScrollNotification(ScrollNotification notification) { - if (notification.depth == 0) { - if (notification is UserScrollNotification) { - switch (notification.direction) { - case ScrollDirection.forward: - _bottomAppBarController.forward(); - case ScrollDirection.reverse: - _bottomAppBarController.reverse(); - case ScrollDirection.idle: - break; - } + if (notification case UserScrollNotification(depth: 0)) { + switch (notification.direction) { + case ScrollDirection.forward: + _bottomAppBarController.forward(); + case ScrollDirection.reverse: + _bottomAppBarController.reverse(); + case ScrollDirection.idle: + break; } } return false; diff --git a/dev/manual_tests/lib/focus.dart b/dev/manual_tests/lib/focus.dart index 6680909e45..5c9da3d8d3 100644 --- a/dev/manual_tests/lib/focus.dart +++ b/dev/manual_tests/lib/focus.dart @@ -108,20 +108,15 @@ class _FocusDemoState extends State { return KeyEventResult.handled; } } - if (event.logicalKey == LogicalKeyboardKey.arrowLeft) { - node.focusInDirection(TraversalDirection.left); - return KeyEventResult.handled; - } - if (event.logicalKey == LogicalKeyboardKey.arrowRight) { - node.focusInDirection(TraversalDirection.right); - return KeyEventResult.handled; - } - if (event.logicalKey == LogicalKeyboardKey.arrowUp) { - node.focusInDirection(TraversalDirection.up); - return KeyEventResult.handled; - } - if (event.logicalKey == LogicalKeyboardKey.arrowDown) { - node.focusInDirection(TraversalDirection.down); + final TraversalDirection? direction = switch (event.logicalKey) { + LogicalKeyboardKey.arrowLeft => TraversalDirection.left, + LogicalKeyboardKey.arrowRight => TraversalDirection.right, + LogicalKeyboardKey.arrowUp => TraversalDirection.up, + LogicalKeyboardKey.arrowDown => TraversalDirection.down, + _ => null, + }; + if (direction != null) { + node.focusInDirection(direction); return KeyEventResult.handled; } } diff --git a/dev/snippets/bin/snippets.dart b/dev/snippets/bin/snippets.dart index eb73a4b8ff..2d1042d07e 100644 --- a/dev/snippets/bin/snippets.dart +++ b/dev/snippets/bin/snippets.dart @@ -57,13 +57,12 @@ String getChannelName({ Platform platform = const LocalPlatform(), ProcessManager processManager = const LocalProcessManager(), }) { - final String? envReleaseChannel = platform.environment['LUCI_BRANCH']?.trim(); - if (['master', 'stable', 'main'].contains(envReleaseChannel)) { + switch (platform.environment['LUCI_BRANCH']?.trim()) { // Backward compatibility: Still support running on "master", but pretend it is "main". - if (envReleaseChannel == 'master') { + case 'master' || 'main': return 'main'; - } - return envReleaseChannel!; + case 'stable': + return 'stable'; } final RegExp gitBranchRegexp = RegExp(r'^## (?.*)'); diff --git a/examples/api/lib/widgets/focus_traversal/focus_traversal_group.0.dart b/examples/api/lib/widgets/focus_traversal/focus_traversal_group.0.dart index eaaccadef1..7b492e67da 100644 --- a/examples/api/lib/widgets/focus_traversal/focus_traversal_group.0.dart +++ b/examples/api/lib/widgets/focus_traversal/focus_traversal_group.0.dart @@ -71,12 +71,10 @@ class _OrderedButtonState extends State> { @override Widget build(BuildContext context) { - FocusOrder order; - if (widget.order is num) { - order = NumericFocusOrder((widget.order as num).toDouble()); - } else { - order = LexicalFocusOrder(widget.order.toString()); - } + final FocusOrder order = switch (widget.order) { + final num number => NumericFocusOrder(number.toDouble()), + final Object? object => LexicalFocusOrder(object.toString()), + }; return FocusTraversalOrder( order: order, diff --git a/packages/flutter/lib/src/foundation/assertions.dart b/packages/flutter/lib/src/foundation/assertions.dart index aa433f13bb..081766441a 100644 --- a/packages/flutter/lib/src/foundation/assertions.dart +++ b/packages/flutter/lib/src/foundation/assertions.dart @@ -676,16 +676,12 @@ class FlutterErrorDetails with Diagnosticable { if (exception is num) { properties.add(ErrorDescription('The number $exception was $verb.')); } else { - final DiagnosticsNode errorName; - if (exception is AssertionError) { - errorName = ErrorDescription('assertion'); - } else if (exception is String) { - errorName = ErrorDescription('message'); - } else if (exception is Error || exception is Exception) { - errorName = ErrorDescription('${exception.runtimeType}'); - } else { - errorName = ErrorDescription('${exception.runtimeType} object'); - } + final DiagnosticsNode errorName = ErrorDescription(switch (exception) { + AssertionError() => 'assertion', + String() => 'message', + Error() || Exception() => '${exception.runtimeType}', + _ => '${exception.runtimeType} object', + }); properties.add(ErrorDescription('The following $errorName was $verb:')); if (diagnosticable != null) { diagnosticable.debugFillProperties(properties); diff --git a/packages/flutter/lib/src/foundation/synchronous_future.dart b/packages/flutter/lib/src/foundation/synchronous_future.dart index 2b08456c69..6ac4d08a76 100644 --- a/packages/flutter/lib/src/foundation/synchronous_future.dart +++ b/packages/flutter/lib/src/foundation/synchronous_future.dart @@ -40,11 +40,10 @@ class SynchronousFuture implements Future { @override Future then(FutureOr Function(T value) onValue, { Function? onError }) { - final FutureOr result = onValue(_value); - if (result is Future) { - return result; - } - return SynchronousFuture(result); + return switch (onValue(_value)) { + final Future result => result, + final R result => SynchronousFuture(result), + }; } @override diff --git a/packages/flutter/lib/src/material/dropdown.dart b/packages/flutter/lib/src/material/dropdown.dart index ed1d15ee2c..0cbbf6bec8 100644 --- a/packages/flutter/lib/src/material/dropdown.dart +++ b/packages/flutter/lib/src/material/dropdown.dart @@ -1700,7 +1700,6 @@ class DropdownButtonFormField extends FormField { ? effectiveHint != null : effectiveHint != null || effectiveDisabledHint != null; final bool isEmpty = !showSelectedItem && !isHintOrDisabledHintAvailable; - final bool hasError = effectiveDecoration.errorText != null; // An unfocusable Focus widget so that this widget can detect if its // descendants have focus or not. @@ -1709,31 +1708,17 @@ class DropdownButtonFormField extends FormField { skipTraversal: true, child: Builder(builder: (BuildContext context) { final bool isFocused = Focus.of(context).hasFocus; - InputBorder? resolveInputBorder() { - if (hasError) { - if (isFocused) { - return effectiveDecoration.focusedErrorBorder; - } - return effectiveDecoration.errorBorder; - } - if (isFocused) { - return effectiveDecoration.focusedBorder; - } - if (effectiveDecoration.enabled) { - return effectiveDecoration.enabledBorder; - } - return effectiveDecoration.border; - } - BorderRadius? effectiveBorderRadius() { - final InputBorder? inputBorder = resolveInputBorder(); - if (inputBorder is OutlineInputBorder) { - return inputBorder.borderRadius; - } - if (inputBorder is UnderlineInputBorder) { - return inputBorder.borderRadius; - } - return null; - } + late final InputBorder? resolvedBorder = switch (( + enabled: effectiveDecoration.enabled, + focused: isFocused, + error: effectiveDecoration.errorText != null, + )) { + (enabled: _, focused: true, error: true) => effectiveDecoration.focusedErrorBorder, + (enabled: _, focused: _, error: true) => effectiveDecoration.errorBorder, + (enabled: _, focused: true, error: _) => effectiveDecoration.focusedBorder, + (enabled: true, focused: _, error: _) => effectiveDecoration.enabledBorder, + (enabled: false, focused: _, error: _) => effectiveDecoration.border, + }; return DropdownButtonHideUnderline( child: DropdownButton._formField( @@ -1760,7 +1745,11 @@ class DropdownButtonFormField extends FormField { menuMaxHeight: menuMaxHeight, enableFeedback: enableFeedback, alignment: alignment, - borderRadius: borderRadius ?? effectiveBorderRadius(), + borderRadius: borderRadius ?? switch (resolvedBorder) { + final OutlineInputBorder border => border.borderRadius, + final UnderlineInputBorder border => border.borderRadius, + _ => null, + }, // Clear the decoration hintText because DropdownButton has its own hint logic. inputDecoration: effectiveDecoration.copyWith( errorText: field.errorText, diff --git a/packages/flutter/lib/src/material/input_decorator.dart b/packages/flutter/lib/src/material/input_decorator.dart index 4a45868703..08c13d661e 100644 --- a/packages/flutter/lib/src/material/input_decorator.dart +++ b/packages/flutter/lib/src/material/input_decorator.dart @@ -931,16 +931,10 @@ class _RenderDecoration extends RenderBox with SlottedContainerRenderObjectMixin required ChildLayouter layoutChild, required _ChildBaselineGetter getBaseline, }) { - final RenderBox? counter = this.counter; - Size counterSize; - final double counterAscent; - if (counter != null) { - counterSize = layoutChild(counter, constraints); - counterAscent = getBaseline(counter, constraints); - } else { - counterSize = Size.zero; - counterAscent = 0.0; - } + final (Size counterSize, double counterAscent) = switch (counter) { + final RenderBox box => (layoutChild(box, constraints), getBaseline(box, constraints)), + null => (Size.zero, 0.0), + }; final BoxConstraints helperErrorConstraints = constraints.deflate(EdgeInsets.only(left: counterSize.width)); final double helperErrorHeight = layoutChild(helperError, helperErrorConstraints).height; diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 45de852821..34969c9b2b 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -1700,22 +1700,17 @@ class _TabBarState extends State { } final List wrappedTabs = List.generate(widget.tabs.length, (int index) { - const double verticalAdjustment = (_kTextAndIconTabHeight - _kTabHeight)/2.0; - EdgeInsetsGeometry? adjustedPadding; + EdgeInsetsGeometry padding = widget.labelPadding ?? tabBarTheme.labelPadding ?? kTabLabelPadding; + const double verticalAdjustment = (_kTextAndIconTabHeight - _kTabHeight) / 2.0; - if (widget.tabs[index] is PreferredSizeWidget) { - final PreferredSizeWidget tab = widget.tabs[index] as PreferredSizeWidget; - if (widget.tabHasTextAndIcon && tab.preferredSize.height == _kTabHeight) { - if (widget.labelPadding != null || tabBarTheme.labelPadding != null) { - adjustedPadding = (widget.labelPadding ?? tabBarTheme.labelPadding!).add(const EdgeInsets.symmetric(vertical: verticalAdjustment)); - } - else { - adjustedPadding = const EdgeInsets.symmetric(vertical: verticalAdjustment, horizontal: 16.0); - } - } + final Widget tab = widget.tabs[index]; + if ( + tab is PreferredSizeWidget && tab.preferredSize.height == _kTabHeight + && widget.tabHasTextAndIcon + ) { + padding = padding.add(const EdgeInsets.symmetric(vertical: verticalAdjustment)); } - - _labelPaddings[index] = adjustedPadding ?? widget.labelPadding ?? tabBarTheme.labelPadding ?? kTabLabelPadding; + _labelPaddings[index] = padding; return Center( heightFactor: 1.0, diff --git a/packages/flutter/lib/src/painting/alignment.dart b/packages/flutter/lib/src/painting/alignment.dart index 81825536a5..76f0cc62e8 100644 --- a/packages/flutter/lib/src/painting/alignment.dart +++ b/packages/flutter/lib/src/painting/alignment.dart @@ -355,35 +355,18 @@ class Alignment extends AlignmentGeometry { Alignment resolve(TextDirection? direction) => this; static String _stringify(double x, double y) { - if (x == -1.0 && y == -1.0) { - return 'Alignment.topLeft'; - } - if (x == 0.0 && y == -1.0) { - return 'Alignment.topCenter'; - } - if (x == 1.0 && y == -1.0) { - return 'Alignment.topRight'; - } - if (x == -1.0 && y == 0.0) { - return 'Alignment.centerLeft'; - } - if (x == 0.0 && y == 0.0) { - return 'Alignment.center'; - } - if (x == 1.0 && y == 0.0) { - return 'Alignment.centerRight'; - } - if (x == -1.0 && y == 1.0) { - return 'Alignment.bottomLeft'; - } - if (x == 0.0 && y == 1.0) { - return 'Alignment.bottomCenter'; - } - if (x == 1.0 && y == 1.0) { - return 'Alignment.bottomRight'; - } - return 'Alignment(${x.toStringAsFixed(1)}, ' - '${y.toStringAsFixed(1)})'; + return switch ((x, y)) { + (-1.0, -1.0) => 'Alignment.topLeft', + ( 0.0, -1.0) => 'Alignment.topCenter', + ( 1.0, -1.0) => 'Alignment.topRight', + (-1.0, 0.0) => 'Alignment.centerLeft', + ( 0.0, 0.0) => 'Alignment.center', + ( 1.0, 0.0) => 'Alignment.centerRight', + (-1.0, 1.0) => 'Alignment.bottomLeft', + ( 0.0, 1.0) => 'Alignment.bottomCenter', + ( 1.0, 1.0) => 'Alignment.bottomRight', + _ => 'Alignment(${x.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})', + }; } @override @@ -550,35 +533,18 @@ class AlignmentDirectional extends AlignmentGeometry { } static String _stringify(double start, double y) { - if (start == -1.0 && y == -1.0) { - return 'AlignmentDirectional.topStart'; - } - if (start == 0.0 && y == -1.0) { - return 'AlignmentDirectional.topCenter'; - } - if (start == 1.0 && y == -1.0) { - return 'AlignmentDirectional.topEnd'; - } - if (start == -1.0 && y == 0.0) { - return 'AlignmentDirectional.centerStart'; - } - if (start == 0.0 && y == 0.0) { - return 'AlignmentDirectional.center'; - } - if (start == 1.0 && y == 0.0) { - return 'AlignmentDirectional.centerEnd'; - } - if (start == -1.0 && y == 1.0) { - return 'AlignmentDirectional.bottomStart'; - } - if (start == 0.0 && y == 1.0) { - return 'AlignmentDirectional.bottomCenter'; - } - if (start == 1.0 && y == 1.0) { - return 'AlignmentDirectional.bottomEnd'; - } - return 'AlignmentDirectional(${start.toStringAsFixed(1)}, ' - '${y.toStringAsFixed(1)})'; + return switch ((start, y)) { + (-1.0, -1.0) => 'AlignmentDirectional.topStart', + ( 0.0, -1.0) => 'AlignmentDirectional.topCenter', + ( 1.0, -1.0) => 'AlignmentDirectional.topEnd', + (-1.0, 0.0) => 'AlignmentDirectional.centerStart', + ( 0.0, 0.0) => 'AlignmentDirectional.center', + ( 1.0, 0.0) => 'AlignmentDirectional.centerEnd', + (-1.0, 1.0) => 'AlignmentDirectional.bottomStart', + ( 0.0, 1.0) => 'AlignmentDirectional.bottomCenter', + ( 1.0, 1.0) => 'AlignmentDirectional.bottomEnd', + _ => 'AlignmentDirectional(${start.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})', + }; } @override diff --git a/packages/flutter/lib/src/painting/box_decoration.dart b/packages/flutter/lib/src/painting/box_decoration.dart index f643acf40f..493ff0f892 100644 --- a/packages/flutter/lib/src/painting/box_decoration.dart +++ b/packages/flutter/lib/src/painting/box_decoration.dart @@ -248,26 +248,18 @@ class BoxDecoration extends Decoration { bool get isComplex => boxShadow != null; @override - BoxDecoration? lerpFrom(Decoration? a, double t) { - if (a == null) { - return scale(t); - } - if (a is BoxDecoration) { - return BoxDecoration.lerp(a, this, t); - } - return super.lerpFrom(a, t) as BoxDecoration?; - } + BoxDecoration? lerpFrom(Decoration? a, double t) => switch (a) { + null => scale(t), + BoxDecoration() => BoxDecoration.lerp(a, this, t), + _ => super.lerpFrom(a, t) as BoxDecoration? + }; @override - BoxDecoration? lerpTo(Decoration? b, double t) { - if (b == null) { - return scale(1.0 - t); - } - if (b is BoxDecoration) { - return BoxDecoration.lerp(this, b, t); - } - return super.lerpTo(b, t) as BoxDecoration?; - } + BoxDecoration? lerpTo(Decoration? b, double t) => switch (b) { + null => scale(1.0 - t), + BoxDecoration() => BoxDecoration.lerp(this, b, t), + _ => super.lerpTo(b, t) as BoxDecoration? + }; /// Linearly interpolate between two box decorations. /// diff --git a/packages/flutter/lib/src/painting/matrix_utils.dart b/packages/flutter/lib/src/painting/matrix_utils.dart index 738e780982..697fe82799 100644 --- a/packages/flutter/lib/src/painting/matrix_utils.dart +++ b/packages/flutter/lib/src/painting/matrix_utils.dart @@ -17,23 +17,15 @@ abstract final class MatrixUtils { /// /// Otherwise, returns null. static Offset? getAsTranslation(Matrix4 transform) { - final Float64List values = transform.storage; - // Values are stored in column-major order. - if (values[0] == 1.0 && // col 1 - values[1] == 0.0 && - values[2] == 0.0 && - values[3] == 0.0 && - values[4] == 0.0 && // col 2 - values[5] == 1.0 && - values[6] == 0.0 && - values[7] == 0.0 && - values[8] == 0.0 && // col 3 - values[9] == 0.0 && - values[10] == 1.0 && - values[11] == 0.0 && - values[14] == 0.0 && // bottom of col 4 (values 12 and 13 are the x and y offsets) - values[15] == 1.0) { - return Offset(values[12], values[13]); + // Values are stored in column-major order, so the appearance + // of dx is transposed from the top-right to the bottom-left. + if (transform.storage case [ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + final double dx, final double dy, 0.0, 1.0, + ]) { + return Offset(dx, dy); } return null; } @@ -43,24 +35,15 @@ abstract final class MatrixUtils { /// /// Otherwise, returns null. static double? getAsScale(Matrix4 transform) { - final Float64List values = transform.storage; - // Values are stored in column-major order. - if (values[1] == 0.0 && // col 1 (value 0 is the scale) - values[2] == 0.0 && - values[3] == 0.0 && - values[4] == 0.0 && // col 2 (value 5 is the scale) - values[6] == 0.0 && - values[7] == 0.0 && - values[8] == 0.0 && // col 3 - values[9] == 0.0 && - values[10] == 1.0 && - values[11] == 0.0 && - values[12] == 0.0 && // col 4 - values[13] == 0.0 && - values[14] == 0.0 && - values[15] == 1.0 && - values[0] == values[5]) { // uniform scale - return values[0]; + // Values are stored in column-major order + // (but this symmetric matrix is unaffected). + if (transform.storage case [ + final double diagonal1, 0.0, 0.0, 0.0, + 0.0, final double diagonal2, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + ] when diagonal1 == diagonal2) { + return diagonal1; } return null; } diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 4d10ffd278..8061bc3835 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -1456,10 +1456,10 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, ..textDirection = initialDirection ..attributedLabel = AttributedString(info.semanticsLabel ?? info.text, attributes: info.stringAttributes); switch (info.recognizer) { - case TapGestureRecognizer(onTap: final VoidCallback? onTap): - case DoubleTapGestureRecognizer(onDoubleTap: final VoidCallback? onTap): - if (onTap != null) { - configuration.onTap = onTap; + case TapGestureRecognizer(onTap: final VoidCallback? handler): + case DoubleTapGestureRecognizer(onDoubleTap: final VoidCallback? handler): + if (handler != null) { + configuration.onTap = handler; configuration.isLink = true; } case LongPressGestureRecognizer(onLongPress: final GestureLongPressCallback? onLongPress): diff --git a/packages/flutter/lib/src/rendering/mouse_tracker.dart b/packages/flutter/lib/src/rendering/mouse_tracker.dart index a68a0f0e9a..3d6afabdb6 100644 --- a/packages/flutter/lib/src/rendering/mouse_tracker.dart +++ b/packages/flutter/lib/src/rendering/mouse_tracker.dart @@ -309,13 +309,10 @@ class MouseTracker extends ChangeNotifier { if (event is PointerSignalEvent) { return; } - final HitTestResult result; - if (event is PointerRemovedEvent) { - result = HitTestResult(); - } else { - final int viewId = event.viewId; - result = hitTestResult ?? _hitTestInView(event.position, viewId); - } + final HitTestResult result = switch (event) { + PointerRemovedEvent() => HitTestResult(), + _ => hitTestResult ?? _hitTestInView(event.position, event.viewId), + }; final int device = event.device; final _MouseState? existingState = _mouseStates[device]; if (!_shouldMarkStateDirty(existingState, event)) { diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index 41df07cb57..afe956d96d 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -1227,10 +1227,10 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin onPointerDown?.call(event), + PointerMoveEvent() => onPointerMove?.call(event), + PointerUpEvent() => onPointerUp?.call(event), + PointerHoverEvent() => onPointerHover?.call(event), + PointerCancelEvent() => onPointerCancel?.call(event), + PointerPanZoomStartEvent() => onPointerPanZoomStart?.call(event), + PointerPanZoomUpdateEvent() => onPointerPanZoomUpdate?.call(event), + PointerPanZoomEndEvent() => onPointerPanZoomEnd?.call(event), + PointerSignalEvent() => onPointerSignal?.call(event), + _ => null, + }; } @override diff --git a/packages/flutter/lib/src/services/message_codecs.dart b/packages/flutter/lib/src/services/message_codecs.dart index d16bb0906e..97f5dc1afe 100644 --- a/packages/flutter/lib/src/services/message_codecs.dart +++ b/packages/flutter/lib/src/services/message_codecs.dart @@ -147,10 +147,8 @@ class JSONMethodCodec implements MethodCodec { if (decoded is! Map) { throw FormatException('Expected method call Map, got $decoded'); } - final Object? method = decoded['method']; - final Object? arguments = decoded['args']; - if (method is String) { - return MethodCall(method, arguments); + if (decoded case {'method': final String method}) { + return MethodCall(method, decoded['args']); } throw FormatException('Invalid method call: $decoded'); } diff --git a/packages/flutter/lib/src/services/platform_views.dart b/packages/flutter/lib/src/services/platform_views.dart index 2cefb2f50c..addeef1a5b 100644 --- a/packages/flutter/lib/src/services/platform_views.dart +++ b/packages/flutter/lib/src/services/platform_views.dart @@ -624,20 +624,16 @@ class _AndroidMotionEventConverter { return null; } - final int action; - if (event is PointerDownEvent) { - action = numPointers == 1 - ? AndroidViewController.kActionDown - : AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerDown); - } else if (event is PointerUpEvent) { - action = numPointers == 1 - ? AndroidViewController.kActionUp - : AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerUp); - } else if (event is PointerMoveEvent) { - action = AndroidViewController.kActionMove; - } else if (event is PointerCancelEvent) { - action = AndroidViewController.kActionCancel; - } else { + final int? action = switch (event) { + PointerDownEvent() when numPointers == 1 => AndroidViewController.kActionDown, + PointerUpEvent() when numPointers == 1 => AndroidViewController.kActionUp, + PointerDownEvent() => AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerDown), + PointerUpEvent() => AndroidViewController.pointerAction(pointerIdx, AndroidViewController.kActionPointerUp), + PointerMoveEvent() => AndroidViewController.kActionMove, + PointerCancelEvent() => AndroidViewController.kActionCancel, + _ => null, + }; + if (action == null) { return null; } diff --git a/packages/flutter/lib/src/widgets/actions.dart b/packages/flutter/lib/src/widgets/actions.dart index 998ffebf81..dfdb409448 100644 --- a/packages/flutter/lib/src/widgets/actions.dart +++ b/packages/flutter/lib/src/widgets/actions.dart @@ -246,13 +246,10 @@ abstract class Action with Diagnosticable { /// [ContextAction] instead of [Action]. bool isEnabled(T intent) => isActionEnabled; - bool _isEnabled(T intent, BuildContext? context) { - final Action self = this; - if (self is ContextAction) { - return self.isEnabled(intent, context); - } - return self.isEnabled(intent); - } + bool _isEnabled(T intent, BuildContext? context) => switch (this) { + final ContextAction action => action.isEnabled(intent, context), + _ => isEnabled(intent), + }; /// Whether this [Action] is inherently enabled. /// @@ -338,13 +335,10 @@ abstract class Action with Diagnosticable { @protected Object? invoke(T intent); - Object? _invoke(T intent, BuildContext? context) { - final Action self = this; - if (self is ContextAction) { - return self.invoke(intent, context); - } - return self.invoke(intent); - } + Object? _invoke(T intent, BuildContext? context) => switch (this) { + final ContextAction action => action.invoke(intent, context), + _ => invoke(intent), + }; /// Register a callback to listen for changes to the state of this action. /// diff --git a/packages/flutter/lib/src/widgets/focus_scope.dart b/packages/flutter/lib/src/widgets/focus_scope.dart index 25fb1fc9ec..d0ee7d558a 100644 --- a/packages/flutter/lib/src/widgets/focus_scope.dart +++ b/packages/flutter/lib/src/widgets/focus_scope.dart @@ -444,20 +444,15 @@ class Focus extends StatefulWidget { /// * [of], which is similar to this function, but will throw an exception if /// it doesn't find a [Focus] node, instead of returning null. static FocusNode? maybeOf(BuildContext context, { bool scopeOk = false, bool createDependency = true }) { - final _FocusInheritedScope? scope; - if (createDependency) { - scope = context.dependOnInheritedWidgetOfExactType<_FocusInheritedScope>(); - } else { - scope = context.getInheritedWidgetOfExactType<_FocusInheritedScope>(); - } - final FocusNode? node = scope?.notifier; - if (node == null) { - return null; - } - if (!scopeOk && node is FocusScopeNode) { - return null; - } - return node; + final _FocusInheritedScope? scope = createDependency + ? context.dependOnInheritedWidgetOfExactType<_FocusInheritedScope>() + : context.getInheritedWidgetOfExactType<_FocusInheritedScope>(); + + return switch (scope?.notifier) { + null => null, + FocusScopeNode() when !scopeOk => null, + final FocusNode node => node, + }; } /// Returns true if the nearest enclosing [Focus] widget's node is focused. diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 15394fd373..a1553a2ba1 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -187,17 +187,10 @@ abstract class GlobalKey> extends Key { /// The current state is null if (1) there is no widget in the tree that /// matches this global key, (2) that widget is not a [StatefulWidget], or the /// associated [State] object is not a subtype of `T`. - T? get currentState { - final Element? element = _currentElement; - if (element is StatefulElement) { - final StatefulElement statefulElement = element; - final State state = statefulElement.state; - if (state is T) { - return state; - } - } - return null; - } + T? get currentState => switch (_currentElement) { + StatefulElement(:final T state) => state, + _ => null, + }; } /// A global key with a debugging label. diff --git a/packages/flutter/lib/src/widgets/inherited_theme.dart b/packages/flutter/lib/src/widgets/inherited_theme.dart index f95efeafde..56500b1335 100644 --- a/packages/flutter/lib/src/widgets/inherited_theme.dart +++ b/packages/flutter/lib/src/widgets/inherited_theme.dart @@ -110,8 +110,7 @@ abstract class InheritedTheme extends InheritedWidget { }()); return false; } - if (ancestor is InheritedElement && ancestor.widget is InheritedTheme) { - final InheritedTheme theme = ancestor.widget as InheritedTheme; + if (ancestor case InheritedElement(widget: final InheritedTheme theme)) { final Type themeType = theme.runtimeType; // Only remember the first theme of any type. This assumes // that inherited themes completely shadow ancestors of the diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index cdbe527242..0bfcaf7709 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -2808,17 +2808,15 @@ class Navigator extends StatefulWidget { BuildContext context, { bool rootNavigator = false, }) { - // Handles the case where the input context is a navigator element. NavigatorState? navigator; - if (context is StatefulElement && context.state is NavigatorState) { - navigator = context.state as NavigatorState; - } - if (rootNavigator) { - navigator = context.findRootAncestorStateOfType() ?? navigator; - } else { - navigator = navigator ?? context.findAncestorStateOfType(); + if (context case StatefulElement(:final NavigatorState state)) { + navigator = state; } + navigator = rootNavigator + ? context.findRootAncestorStateOfType() ?? navigator + : navigator ?? context.findAncestorStateOfType(); + assert(() { if (navigator == null) { throw FlutterError( @@ -2858,17 +2856,14 @@ class Navigator extends StatefulWidget { BuildContext context, { bool rootNavigator = false, }) { - // Handles the case where the input context is a navigator element. NavigatorState? navigator; - if (context is StatefulElement && context.state is NavigatorState) { - navigator = context.state as NavigatorState; + if (context case StatefulElement(:final NavigatorState state)) { + navigator = state; } - if (rootNavigator) { - navigator = context.findRootAncestorStateOfType() ?? navigator; - } else { - navigator = navigator ?? context.findAncestorStateOfType(); - } - return navigator; + + return rootNavigator + ? context.findRootAncestorStateOfType() ?? navigator + : navigator ?? context.findAncestorStateOfType(); } /// Turn a route name into a set of [Route] objects. diff --git a/packages/flutter/lib/src/widgets/platform_menu_bar.dart b/packages/flutter/lib/src/widgets/platform_menu_bar.dart index 4f74381647..f2056102e9 100644 --- a/packages/flutter/lib/src/widgets/platform_menu_bar.dart +++ b/packages/flutter/lib/src/widgets/platform_menu_bar.dart @@ -606,7 +606,7 @@ class PlatformMenu extends PlatformMenuItem with DiagnosticableTreeMixin { previousItem = item; return false; }); - if (result.isNotEmpty && result.last[_kIsDividerKey] == true) { + if (result.lastOrNull case {_kIsDividerKey: true}) { result.removeLast(); } return { diff --git a/packages/flutter/test/services/message_codecs_testing.dart b/packages/flutter/test/services/message_codecs_testing.dart index 50bc8fa248..693d1e85f9 100644 --- a/packages/flutter/test/services/message_codecs_testing.dart +++ b/packages/flutter/test/services/message_codecs_testing.dart @@ -49,25 +49,20 @@ bool deepEquals(dynamic valueA, dynamic valueB) { bool deepEqualsTypedData(TypedData valueA, TypedData valueB) { if (valueA is ByteData) { - return valueB is ByteData - && deepEqualsList(valueA.buffer.asUint8List(), valueB.buffer.asUint8List()); + return valueB is ByteData && deepEqualsList( + valueA.buffer.asUint8List(), + valueB.buffer.asUint8List(), + ); } - if (valueA is Uint8List) { - return valueB is Uint8List && deepEqualsList(valueA, valueB); - } - if (valueA is Int32List) { - return valueB is Int32List && deepEqualsList(valueA, valueB); - } - if (valueA is Int64List) { - return valueB is Int64List && deepEqualsList(valueA, valueB); - } - if (valueA is Float32List) { - return valueB is Float32List && deepEqualsList(valueA, valueB); - } - if (valueA is Float64List) { - return valueB is Float64List && deepEqualsList(valueA, valueB); - } - throw 'Unexpected typed data: $valueA'; + + return switch (valueA) { + Uint8List() => valueB is Uint8List && deepEqualsList(valueA, valueB), + Int32List() => valueB is Int32List && deepEqualsList(valueA, valueB), + Int64List() => valueB is Int64List && deepEqualsList(valueA, valueB), + Float32List() => valueB is Float32List && deepEqualsList(valueA, valueB), + Float64List() => valueB is Float64List && deepEqualsList(valueA, valueB), + _ => throw 'Unexpected typed data: $valueA', + }; } bool deepEqualsList(List valueA, List valueB) { diff --git a/packages/flutter/test/widgets/widget_inspector_test.dart b/packages/flutter/test/widgets/widget_inspector_test.dart index 59c95fbf7f..e7c673158c 100644 --- a/packages/flutter/test/widgets/widget_inspector_test.dart +++ b/packages/flutter/test/widgets/widget_inspector_test.dart @@ -5258,33 +5258,23 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService { ), ), ); - final Finder columnWidgetFinder = find.byType(Column); - expect(columnWidgetFinder, findsOneWidget); - final Element columnWidgetElement = columnWidgetFinder - .evaluate() - .first; - final DiagnosticsNode node = columnWidgetElement.toDiagnosticsNode(); - final InspectorSerializationDelegate delegate = - InspectorSerializationDelegate( - service: service, - includeProperties: true, - addAdditionalPropertiesCallback: - (DiagnosticsNode node, InspectorSerializationDelegate delegate) { - final Map additionalJson = {}; - final Object? value = node.value; - if (value is Element) { - final RenderObject? renderObject = value.renderObject; - if (renderObject != null) { - additionalJson['renderObject'] = - renderObject.toDiagnosticsNode().toJsonMap( - delegate.copyWith(subtreeDepth: 0), - ); - } - } - additionalJson['callbackExecuted'] = true; - return additionalJson; - }, - ); + + final Finder columnFinder = find.byType(Column); + expect(columnFinder, findsOneWidget); + + final DiagnosticsNode node = columnFinder.evaluate().first.toDiagnosticsNode(); + final InspectorSerializationDelegate delegate = InspectorSerializationDelegate( + service: service, + includeProperties: true, + addAdditionalPropertiesCallback: + (DiagnosticsNode node, InspectorSerializationDelegate delegate) => { + if (node.value case Element(:final RenderObject renderObject)) + 'renderObject': renderObject.toDiagnosticsNode().toJsonMap( + delegate.copyWith(subtreeDepth: 0), + ), + 'callbackExecuted': true, + }, + ); final Map json = node.toJsonMap(delegate); expect(json['callbackExecuted'], true); expect(json.containsKey('renderObject'), true); diff --git a/packages/flutter_driver/lib/src/common/handler_factory.dart b/packages/flutter_driver/lib/src/common/handler_factory.dart index 0446b3c6d8..68101ff1f3 100644 --- a/packages/flutter_driver/lib/src/common/handler_factory.dart +++ b/packages/flutter_driver/lib/src/common/handler_factory.dart @@ -94,15 +94,10 @@ mixin CreateFinderFactory { } Finder _createPageBackFinder() { - return find.byElementPredicate((Element element) { - final Widget widget = element.widget; - if (widget is Tooltip) { - return widget.message == 'Back'; - } - if (widget is CupertinoNavigationBarBackButton) { - return true; - } - return false; + return find.byElementPredicate((Element element) => switch (element.widget) { + Tooltip(message: 'Back') => true, + CupertinoNavigationBarBackButton() => true, + _ => false, }, description: 'Material or Cupertino back button'); } diff --git a/packages/flutter_driver/lib/src/driver/frame_request_pending_latency_summarizer.dart b/packages/flutter_driver/lib/src/driver/frame_request_pending_latency_summarizer.dart index 96a334d565..dec36b168a 100644 --- a/packages/flutter_driver/lib/src/driver/frame_request_pending_latency_summarizer.dart +++ b/packages/flutter_driver/lib/src/driver/frame_request_pending_latency_summarizer.dart @@ -45,18 +45,16 @@ class FrameRequestPendingLatencySummarizer { List _computeFrameRequestPendingLatencies() { final List result = []; final Map starts = {}; - for (int i = 0; i < frameRequestPendingEvents.length; i++) { - final TimelineEvent event = frameRequestPendingEvents[i]; - if (event.phase == 'b') { - final String? id = event.json['id'] as String?; - if (id != null) { + for (final TimelineEvent event in frameRequestPendingEvents) { + switch (event) { + case TimelineEvent(phase: 'b', json: {'id': final String id}): starts[id] = event.timestampMicros!; - } - } else if (event.phase == 'e') { - final int? start = starts[event.json['id']]; - if (start != null) { - result.add((event.timestampMicros! - start).toDouble()); - } + + case TimelineEvent(phase: 'e', json: {'id': final String id}): + final int? start = starts[id]; + if (start != null) { + result.add((event.timestampMicros! - start).toDouble()); + } } } return result; diff --git a/packages/flutter_goldens/lib/flutter_goldens.dart b/packages/flutter_goldens/lib/flutter_goldens.dart index 3c32f83139..7ed06ed306 100644 --- a/packages/flutter_goldens/lib/flutter_goldens.dart +++ b/packages/flutter_goldens/lib/flutter_goldens.dart @@ -210,27 +210,15 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator { required FileSystem fs, }) { final Directory flutterRoot = fs.directory(platform.environment[_kFlutterRootKey]); - Directory comparisonRoot; + final Directory comparisonRoot = switch (suffix) { + null => flutterRoot.childDirectory(fs.path.join('bin', 'cache', 'pkg', 'skia_goldens')), + _ => fs.systemTempDirectory.createTempSync(suffix), + }; - if (suffix != null) { - comparisonRoot = fs.systemTempDirectory.createTempSync(suffix); - } else { - comparisonRoot = flutterRoot.childDirectory( - fs.path.join( - 'bin', - 'cache', - 'pkg', - 'skia_goldens', - ) - ); - } - - final Directory testDirectory = fs.directory(defaultComparator.basedir); - final String testDirectoryRelativePath = fs.path.relative( - testDirectory.path, - from: flutterRoot.path, + final String testPath = fs.directory(defaultComparator.basedir).path; + return comparisonRoot.childDirectory( + fs.path.relative(testPath, from: flutterRoot.path), ); - return comparisonRoot.childDirectory(testDirectoryRelativePath); } /// Returns the golden [File] identified by the given [Uri]. diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index d763c15329..fc8d7a6af4 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -849,20 +849,15 @@ abstract class TestWidgetsFlutterBinding extends BindingBase } Future _handleAnnouncementMessage(Object? mockMessage) async { - final Map message = mockMessage! as Map; - if (message['type'] == 'announce') { - final Map data = - message['data']! as Map; - final String dataMessage = data['message'].toString(); - final TextDirection textDirection = - TextDirection.values[data['textDirection']! as int]; - final int assertivenessLevel = (data['assertiveness'] as int?) ?? 0; - final Assertiveness assertiveness = - Assertiveness.values[assertivenessLevel]; - final CapturedAccessibilityAnnouncement announcement = - CapturedAccessibilityAnnouncement._( - dataMessage, textDirection, assertiveness); - _announcements.add(announcement); + if (mockMessage! case { + 'type': 'announce', + 'data': final Map data as Map, + }) { + _announcements.add(CapturedAccessibilityAnnouncement._( + data['message'].toString(), + TextDirection.values[data['textDirection']! as int], + Assertiveness.values[(data['assertiveness'] ?? 0) as int], + )); } } diff --git a/packages/flutter_tools/lib/src/build_system/targets/assets.dart b/packages/flutter_tools/lib/src/build_system/targets/assets.dart index 9a4496a451..ce10d1222d 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/assets.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/assets.dart @@ -302,14 +302,14 @@ DevFSContent? processSkSLBundle(String? bundlePath, { throw Exception('SkSL bundle was invalid'); } - final String? parsedPlatform = bundle['platform'] as String?; - TargetPlatform? bundleTargetPlatform; - if (parsedPlatform != null) { - bundleTargetPlatform = getTargetPlatformForName(parsedPlatform); - } - if (bundleTargetPlatform == null || bundleTargetPlatform != targetPlatform) { + final TargetPlatform? bundlePlatform = switch (bundle['platform'] as String?) { + final String platform => getTargetPlatformForName(platform), + null => null, + }; + + if (bundlePlatform != targetPlatform) { logger.printError( - 'The SkSL bundle was created for $bundleTargetPlatform, but the current ' + 'The SkSL bundle was created for $bundlePlatform, but the current ' 'platform is $targetPlatform. This may lead to less efficient shader ' 'caching.' ); diff --git a/packages/flutter_tools/lib/src/daemon.dart b/packages/flutter_tools/lib/src/daemon.dart index c53913af15..0415405502 100644 --- a/packages/flutter_tools/lib/src/daemon.dart +++ b/packages/flutter_tools/lib/src/daemon.dart @@ -349,10 +349,8 @@ class DaemonConnection { } else { _incomingCommands.add(message); } - } else if (data['event'] != null) { - // This is an event - _logger.printTrace('<- Event received: ${data['event']}'); - final Object? eventName = data['event']; + } else if (data case {'event': final Object eventName}) { + _logger.printTrace('<- Event received: $eventName'); if (eventName is String) { _events.add(DaemonEventData( eventName, diff --git a/packages/flutter_tools/lib/src/dart_pub_json_formatter.dart b/packages/flutter_tools/lib/src/dart_pub_json_formatter.dart index 156df4804d..07c6d5e62a 100644 --- a/packages/flutter_tools/lib/src/dart_pub_json_formatter.dart +++ b/packages/flutter_tools/lib/src/dart_pub_json_formatter.dart @@ -16,31 +16,23 @@ class DartDependencyPackage { }); factory DartDependencyPackage.fromHashMap(dynamic packageInfo) { - String name = ''; - String version = ''; - String source = ''; - List dependencies = []; - - if (packageInfo is LinkedHashMap) { - final LinkedHashMap info = packageInfo as LinkedHashMap; - if (info.containsKey('name')) { - name = info['name'] as String; - } - if (info.containsKey('version')) { - version = info['version'] as String; - } - if (info.containsKey('source')) { - source = info['source'] as String; - } - if (info.containsKey('dependencies')) { - dependencies = info['dependencies'] as List; - } + if (packageInfo is! LinkedHashMap) { + return DartDependencyPackage( + name: '', + version: '', + source: '', + dependencies: [], + ); } + return DartDependencyPackage( - name: name, - version: version, - source: source, - dependencies: dependencies.map((dynamic e) => e.toString()).toList(), + name: packageInfo['name'] as String? ?? '', + version: packageInfo['version'] as String? ?? '', + source: packageInfo['source'] as String? ?? '', + dependencies: switch (packageInfo['dependencies'] as List?) { + final List list => list.map((Object? e) => '$e').toList(), + null => [], + }, ); } diff --git a/packages/flutter_tools/lib/src/flutter_manifest.dart b/packages/flutter_tools/lib/src/flutter_manifest.dart index b59b3216ac..537714826f 100644 --- a/packages/flutter_tools/lib/src/flutter_manifest.dart +++ b/packages/flutter_tools/lib/src/flutter_manifest.dart @@ -166,11 +166,10 @@ class FlutterManifest { /// - assets/foo_license.txt /// ``` List get additionalLicenses { - final Object? licenses = _flutterDescriptor['licenses']; - if (licenses is YamlList) { - return licenses.map((Object? element) => element.toString()).toList(); - } - return []; + return [ + if (_flutterDescriptor case {'licenses': final YamlList list}) + for (final Object? item in list) '$item', + ]; } /// True if this manifest declares a Flutter module project. @@ -197,27 +196,19 @@ class FlutterManifest { /// such declaration. String? get androidPackage { if (isModule) { - final Object? module = _flutterDescriptor['module']; - if (module is YamlMap) { - return module['androidPackage'] as String?; + if (_flutterDescriptor case {'module': final YamlMap map}) { + return map['androidPackage'] as String?; } } - final Map? platforms = supportedPlatforms; - if (platforms == null) { + + late final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?; + + return switch (supportedPlatforms) { + {'android': final YamlMap map} => map['package'] as String?, // Pre-multi-platform plugin format - if (isPlugin) { - final YamlMap? plugin = _flutterDescriptor['plugin'] as YamlMap?; - return plugin?['androidPackage'] as String?; - } - return null; - } - if (platforms.containsKey('android')) { - final Object? android = platforms['android']; - if (android is YamlMap) { - return android['package'] as String?; - } - } - return null; + null when isPlugin => plugin?['androidPackage'] as String?, + _ => null, + }; } /// Returns the deferred components configuration if declared. Returns @@ -253,9 +244,8 @@ class FlutterManifest { /// module descriptor. Returns null if there is no such declaration. String? get iosBundleIdentifier { if (isModule) { - final Object? module = _flutterDescriptor['module']; - if (module is YamlMap) { - return module['iosBundleIdentifier'] as String?; + if (_flutterDescriptor case {'module': final YamlMap map}) { + return map['iosBundleIdentifier'] as String?; } } return null; diff --git a/packages/flutter_tools/lib/src/ios/core_devices.dart b/packages/flutter_tools/lib/src/ios/core_devices.dart index adc6eddfe6..e7eff51e28 100644 --- a/packages/flutter_tools/lib/src/ios/core_devices.dart +++ b/packages/flutter_tools/lib/src/ios/core_devices.dart @@ -396,15 +396,14 @@ class IOSCoreDevice { required Logger logger, }) { final List<_IOSCoreDeviceCapability> capabilitiesList = <_IOSCoreDeviceCapability>[ - if (data['capabilities'] case final List capabilitiesData) + if (data case {'capabilities': final List capabilitiesData}) for (final Object? capabilityData in capabilitiesData) if (capabilityData != null && capabilityData is Map) _IOSCoreDeviceCapability.fromBetaJson(capabilityData), ]; _IOSCoreDeviceConnectionProperties? connectionProperties; - if (data['connectionProperties'] is Map) { - final Map connectionPropertiesData = data['connectionProperties']! as Map; + if (data case {'connectionProperties': final Map connectionPropertiesData}) { connectionProperties = _IOSCoreDeviceConnectionProperties.fromBetaJson( connectionPropertiesData, logger: logger, @@ -412,14 +411,12 @@ class IOSCoreDevice { } IOSCoreDeviceProperties? deviceProperties; - if (data['deviceProperties'] is Map) { - final Map devicePropertiesData = data['deviceProperties']! as Map; + if (data case {'deviceProperties': final Map devicePropertiesData}) { deviceProperties = IOSCoreDeviceProperties.fromBetaJson(devicePropertiesData); } _IOSCoreDeviceHardwareProperties? hardwareProperties; - if (data['hardwareProperties'] is Map) { - final Map hardwarePropertiesData = data['hardwareProperties']! as Map; + if (data case {'hardwareProperties': final Map hardwarePropertiesData}) { hardwareProperties = _IOSCoreDeviceHardwareProperties.fromBetaJson( hardwarePropertiesData, logger: logger, @@ -535,8 +532,7 @@ class _IOSCoreDeviceConnectionProperties { required Logger logger, }) { List? localHostnames; - if (data['localHostnames'] is List) { - final List values = data['localHostnames']! as List; + if (data case {'localHostnames': final List values}) { try { localHostnames = List.from(values); } on TypeError { @@ -545,8 +541,7 @@ class _IOSCoreDeviceConnectionProperties { } List? potentialHostnames; - if (data['potentialHostnames'] is List) { - final List values = data['potentialHostnames']! as List; + if (data case {'potentialHostnames': final List values}) { try { potentialHostnames = List.from(values); } on TypeError { @@ -700,12 +695,12 @@ class _IOSCoreDeviceHardwareProperties { required Logger logger, }) { _IOSCoreDeviceCPUType? cpuType; - if (data['cpuType'] case final Map betaJson) { + if (data case {'cpuType': final Map betaJson}) { cpuType = _IOSCoreDeviceCPUType.fromBetaJson(betaJson); } List<_IOSCoreDeviceCPUType>? supportedCPUTypes; - if (data['supportedCPUTypes'] case final List values) { + if (data case {'supportedCPUTypes': final List values}) { supportedCPUTypes = <_IOSCoreDeviceCPUType>[ for (final Object? cpuTypeData in values) if (cpuTypeData is Map) @@ -714,8 +709,7 @@ class _IOSCoreDeviceHardwareProperties { } List? supportedDeviceFamilies; - if (data['supportedDeviceFamilies'] is List) { - final List values = data['supportedDeviceFamilies']! as List; + if (data case {'supportedDeviceFamilies': final List values}) { try { supportedDeviceFamilies = List.from(values); } on TypeError { diff --git a/packages/flutter_tools/lib/src/ios/xcode_debug.dart b/packages/flutter_tools/lib/src/ios/xcode_debug.dart index ac86858693..ce0eda1485 100644 --- a/packages/flutter_tools/lib/src/ios/xcode_debug.dart +++ b/packages/flutter_tools/lib/src/ios/xcode_debug.dart @@ -468,10 +468,8 @@ class XcodeAutomationScriptResponse { factory XcodeAutomationScriptResponse.fromJson(Map data) { XcodeAutomationScriptDebugResult? debugResult; - if (data['debugResult'] != null && data['debugResult'] is Map) { - debugResult = XcodeAutomationScriptDebugResult.fromJson( - data['debugResult']! as Map, - ); + if (data case {'debugResult': final Map resultData}) { + debugResult = XcodeAutomationScriptDebugResult.fromJson(resultData); } return XcodeAutomationScriptResponse._( status: data['status'] is bool? ? data['status'] as bool? : null, diff --git a/packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart b/packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart index 58169d592b..e3e74239a1 100644 --- a/packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart +++ b/packages/flutter_tools/lib/src/migrations/swift_package_manager_integration_migration.dart @@ -862,33 +862,26 @@ class ParsedProjectInfo { final List parsedSwiftPackageProductDependencies = []; final List parsedLocalSwiftPackageProductDependencies = []; - if (data['objects'] is Map) { - final Map values = - data['objects']! as Map; + if (data case {'objects': final Map values}) { for (final String key in values.keys) { - if (values[key] is Map) { - final Map details = - values[key]! as Map; - if (details['isa'] is String) { - final String objectType = details['isa']! as String; - if (objectType == 'PBXBuildFile') { + if (values[key] case final Map details) { + switch (details['isa']) { + case 'PBXBuildFile': buildFiles.add(key); - } else if (objectType == 'PBXFileReference') { + case 'PBXFileReference': references.add(key); - } else if (objectType == 'PBXGroup') { + case 'PBXGroup': groups.add(ParsedProjectGroup.fromJson(key, details)); - } else if (objectType == 'PBXFrameworksBuildPhase') { - buildPhases.add( - ParsedProjectFrameworksBuildPhase.fromJson(key, details)); - } else if (objectType == 'PBXNativeTarget') { + case 'PBXFrameworksBuildPhase': + buildPhases.add(ParsedProjectFrameworksBuildPhase.fromJson(key, details)); + case 'PBXNativeTarget': native.add(ParsedNativeTarget.fromJson(key, details)); - } else if (objectType == 'PBXProject') { + case 'PBXProject': project.add(ParsedProject.fromJson(key, details)); - } else if (objectType == 'XCSwiftPackageProductDependency') { + case 'XCSwiftPackageProductDependency': parsedSwiftPackageProductDependencies.add(key); - } else if (objectType == 'XCLocalSwiftPackageReference') { + case 'XCLocalSwiftPackageReference': parsedLocalSwiftPackageProductDependencies.add(key); - } } } } @@ -935,27 +928,16 @@ class ParsedProjectInfo { /// Representation of data parsed from PBXGroup section in Xcode project's project.pbxproj. class ParsedProjectGroup { - ParsedProjectGroup._(this.identifier, this.children, this.name); - - factory ParsedProjectGroup.fromJson(String key, Map data) { - String? name; - if (data['name'] is String) { - name = data['name']! as String; - } else if (data['path'] is String) { - name = data['path']! as String; - } - - final List parsedChildren = []; - if (data['children'] is List) { - for (final Object? item in data['children']! as List) { - if (item is String) { - parsedChildren.add(item); - } - } - return ParsedProjectGroup._(key, parsedChildren, name); - } - return ParsedProjectGroup._(key, null, name); - } + ParsedProjectGroup.fromJson(this.identifier, Map data) + : children = switch (data['children']) { + final List children => children.whereType().toList(), + _ => null, + }, + name = switch (data) { + {'name': final String name} => name, + {'path': final String path} => path, + _ => null, + }; final String identifier; final List? children; @@ -965,21 +947,13 @@ class ParsedProjectGroup { /// Representation of data parsed from PBXFrameworksBuildPhase section in Xcode /// project's project.pbxproj. class ParsedProjectFrameworksBuildPhase { - ParsedProjectFrameworksBuildPhase._(this.identifier, this.files); - - factory ParsedProjectFrameworksBuildPhase.fromJson( - String key, Map data) { - final List parsedFiles = []; - if (data['files'] is List) { - for (final Object? item in data['files']! as List) { - if (item is String) { - parsedFiles.add(item); - } - } - return ParsedProjectFrameworksBuildPhase._(key, parsedFiles); - } - return ParsedProjectFrameworksBuildPhase._(key, null); - } + ParsedProjectFrameworksBuildPhase.fromJson( + this.identifier, + Map data, + ) : files = switch (data['files']) { + final List files => files.whereType().toList(), + _ => null, + }; final String identifier; final List? files; @@ -988,31 +962,15 @@ class ParsedProjectFrameworksBuildPhase { /// Representation of data parsed from PBXNativeTarget section in Xcode project's /// project.pbxproj. class ParsedNativeTarget { - ParsedNativeTarget._( - this.data, - this.identifier, - this.name, - this.packageProductDependencies, - ); - - factory ParsedNativeTarget.fromJson(String key, Map data) { - String? name; - if (data['name'] is String) { - name = data['name']! as String; - } - - final List parsedChildren = []; - if (data['packageProductDependencies'] is List) { - for (final Object? item - in data['packageProductDependencies']! as List) { - if (item is String) { - parsedChildren.add(item); - } - } - return ParsedNativeTarget._(data, key, name, parsedChildren); - } - return ParsedNativeTarget._(data, key, name, null); - } + ParsedNativeTarget.fromJson(this.identifier, this.data) + : name = switch (data) { + {'name': final String name} => name, + _ => null, + }, + packageProductDependencies = switch (data['packageProductDependencies']) { + final List dependencies => dependencies.whereType().toList(), + _ => null, + }; final Map data; final String identifier; @@ -1023,24 +981,11 @@ class ParsedNativeTarget { /// Representation of data parsed from PBXProject section in Xcode project's /// project.pbxproj. class ParsedProject { - ParsedProject._( - this.data, - this.identifier, - this.packageReferences, - ); - - factory ParsedProject.fromJson(String key, Map data) { - final List parsedChildren = []; - if (data['packageReferences'] is List) { - for (final Object? item in data['packageReferences']! as List) { - if (item is String) { - parsedChildren.add(item); - } - } - return ParsedProject._(data, key, parsedChildren); - } - return ParsedProject._(data, key, null); - } + ParsedProject.fromJson(this.identifier, this.data) + : packageReferences = switch (data['packageReferences']) { + final List references => references.whereType().toList(), + _ => null, + }; final Map data; final String identifier; diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart index db3cf0eee1..98ae0bcdf8 100644 --- a/packages/flutter_tools/lib/src/vmservice.dart +++ b/packages/flutter_tools/lib/src/vmservice.dart @@ -851,8 +851,8 @@ class FlutterVmService { ? {'value': platform} : {}, ); - if (result != null && result['value'] is String) { - return result['value']! as String; + if (result case {'value': final String value}) { + return value; } return 'unknown'; } diff --git a/packages/flutter_tools/test/integration.shard/test_driver.dart b/packages/flutter_tools/test/integration.shard/test_driver.dart index b493c14756..017a4f99c3 100644 --- a/packages/flutter_tools/test/integration.shard/test_driver.dart +++ b/packages/flutter_tools/test/integration.shard/test_driver.dart @@ -423,14 +423,11 @@ abstract class FlutterTestDriver { final StringBuffer error = StringBuffer(); error.write('Received app.stop event while waiting for $interestingOccurrence\n\n$_errorBuffer'); final Object? jsonParams = json['params']; - if (jsonParams is Map) { - if (jsonParams['error'] != null) { - error.write('${jsonParams['error']}\n\n'); - } - final Object? trace = jsonParams['trace']; - if (trace != null) { - error.write('$trace\n\n'); - } + if (jsonParams case {'error': final Object errorObject}) { + error.write('$errorObject\n\n'); + } + if (jsonParams case {'trace': final Object trace}) { + error.write('$trace\n\n'); } response.completeError(Exception(error.toString())); }