switch statement cleanup (#148382)

This PR is step 12 in the journey to solve issue #136139 and make the
entire Flutter repo more readable.

Most of it involves implementing switch expressions, and there's also a
few other random things that I wanted to clean up a bit.
This commit is contained in:
Nate 2024-05-16 18:16:06 -06:00 committed by GitHub
parent c4ad1dc1e9
commit fa9992eff6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 301 additions and 529 deletions

View File

@ -1187,10 +1187,8 @@ Future<void> _runInteractive({
case 'q':
checker.cleanupTempDirectory();
exit(0);
case 'r':
if (!busy) {
rerun();
}
case 'r' when !busy:
rerun();
}
});
Watcher(file.absolute.path).events.listen((_) => rerun());

View File

@ -385,23 +385,12 @@ class StartContext extends Context {
/// Determine this release's version number from the [lastVersion] and the [incrementLetter].
Version calculateNextVersion(Version lastVersion, ReleaseType releaseType) {
late final Version nextVersion;
switch (releaseType) {
case ReleaseType.STABLE_INITIAL:
nextVersion = Version(
x: lastVersion.x,
y: lastVersion.y,
z: 0,
type: VersionType.stable,
);
case ReleaseType.STABLE_HOTFIX:
nextVersion = Version.increment(lastVersion, 'z');
case ReleaseType.BETA_INITIAL:
nextVersion = Version.fromCandidateBranch(candidateBranch);
case ReleaseType.BETA_HOTFIX:
nextVersion = Version.increment(lastVersion, 'n');
}
return nextVersion;
return switch (releaseType) {
ReleaseType.STABLE_INITIAL => Version(x: lastVersion.x, y: lastVersion.y, z: 0, type: VersionType.stable),
ReleaseType.STABLE_HOTFIX => Version.increment(lastVersion, 'z'),
ReleaseType.BETA_INITIAL => Version.fromCandidateBranch(candidateBranch),
ReleaseType.BETA_HOTFIX || _ => Version.increment(lastVersion, 'n'),
};
}
/// Ensures the branch point [candidateBranch] and `master` has a version tag.

View File

@ -115,15 +115,11 @@ class ABTest {
if (value == null) {
value = ''.padRight(len);
} else {
switch (aligns[column]) {
case FieldJustification.LEFT:
value = value.padRight(len);
case FieldJustification.RIGHT:
value = value.padLeft(len);
case FieldJustification.CENTER:
value = value.padLeft((len + value.length) ~/2);
value = value.padRight(len);
}
value = switch (aligns[column]) {
FieldJustification.LEFT => value.padRight(len),
FieldJustification.RIGHT => value.padLeft(len),
FieldJustification.CENTER => value.padLeft((len + value.length) ~/ 2).padRight(len),
};
}
if (column > 0) {
value = value.padLeft(len+1);

View File

@ -252,14 +252,11 @@ class AndroidDeviceDiscovery implements DeviceDiscovery {
}
Future<bool> _matchesCPURequirement(AndroidDevice device) async {
switch (cpu) {
case null:
return true;
case AndroidCPU.arm64:
return device.isArm64();
case AndroidCPU.arm:
return device.isArm();
}
return switch (cpu) {
null => Future<bool>.value(true),
AndroidCPU.arm64 => device.isArm64(),
AndroidCPU.arm => device.isArm(),
};
}
/// Picks a random Android device out of connected devices and sets it as

View File

@ -37,19 +37,12 @@ class TestStepResult {
});
factory TestStepResult.fromSnapshot(AsyncSnapshot<TestStepResult> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return const TestStepResult('Not started', nothing, TestStatus.ok);
case ConnectionState.waiting:
return const TestStepResult('Executing', nothing, TestStatus.pending);
case ConnectionState.done:
if (snapshot.hasData) {
return snapshot.data!;
}
return snapshot.error! as TestStepResult;
case ConnectionState.active:
throw 'Unsupported state ${snapshot.connectionState}';
}
return switch (snapshot.connectionState) {
ConnectionState.none => const TestStepResult('Not started', nothing, TestStatus.ok),
ConnectionState.waiting => const TestStepResult('Executing', nothing, TestStatus.pending),
ConnectionState.done => snapshot.data ?? snapshot.error! as TestStepResult,
ConnectionState.active => throw 'Unsupported state: ConnectionState.active',
};
}
final String name;

View File

@ -204,18 +204,12 @@ class _ListDemoState extends State<ListDemo> {
@override
Widget build(BuildContext context) {
final String layoutText = _dense != null ? ' \u2013 Dense' : '';
String? itemTypeText;
switch (_itemType) {
case _MaterialListType.oneLine:
case _MaterialListType.oneLineWithAvatar:
itemTypeText = 'Single-line';
case _MaterialListType.twoLine:
itemTypeText = 'Two-line';
case _MaterialListType.threeLine:
itemTypeText = 'Three-line';
case null:
break;
}
final String? itemTypeText = switch (_itemType) {
_MaterialListType.oneLine || _MaterialListType.oneLineWithAvatar => 'Single-line',
_MaterialListType.twoLine => 'Two-line',
_MaterialListType.threeLine => 'Three-line',
null => null,
};
Iterable<Widget> listTiles = items.map<Widget>((String item) => buildListTile(context, item));
if (_showDividers != null) {

View File

@ -80,29 +80,12 @@ class _CustomRangeThumbShape extends RangeSliderThumbShape {
);
final double size = _thumbSize * sizeTween.evaluate(enableAnimation);
late Path thumbPath;
switch (textDirection) {
case TextDirection.rtl:
switch (thumb) {
case Thumb.start:
thumbPath = _rightTriangle(size, center);
case Thumb.end:
thumbPath = _leftTriangle(size, center);
case null:
break;
}
case TextDirection.ltr:
switch (thumb) {
case Thumb.start:
thumbPath = _leftTriangle(size, center);
case Thumb.end:
thumbPath = _rightTriangle(size, center);
case null:
break;
}
case null:
break;
}
final Path thumbPath = switch ((textDirection!, thumb!)) {
(TextDirection.rtl, Thumb.start) => _rightTriangle(size, center),
(TextDirection.rtl, Thumb.end) => _leftTriangle(size, center),
(TextDirection.ltr, Thumb.start) => _leftTriangle(size, center),
(TextDirection.ltr, Thumb.end) => _rightTriangle(size, center),
};
canvas.drawPath(thumbPath, Paint()..color = colorTween.evaluate(enableAnimation)!);
}
}

View File

@ -50,15 +50,11 @@ enum GalleryDemoCategory {
}
String? displayTitle(GalleryLocalizations localizations) {
switch (this) {
case GalleryDemoCategory.other:
return localizations.homeCategoryReference;
case GalleryDemoCategory.material:
case GalleryDemoCategory.cupertino:
return toString();
case GalleryDemoCategory.study:
}
return null;
return switch (this) {
study => null,
material || cupertino => toString(),
other => localizations.homeCategoryReference,
};
}
}

View File

@ -96,22 +96,15 @@ class GalleryOptions {
/// In other words, if the theme is dark, returns light; if the theme is
/// light, returns dark.
SystemUiOverlayStyle resolvedSystemUiOverlayStyle() {
Brightness brightness;
switch (themeMode) {
case ThemeMode.light:
brightness = Brightness.light;
case ThemeMode.dark:
brightness = Brightness.dark;
case ThemeMode.system:
brightness =
WidgetsBinding.instance.platformDispatcher.platformBrightness;
}
final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark;
return overlayStyle;
final Brightness brightness = switch (themeMode) {
ThemeMode.light => Brightness.light,
ThemeMode.dark => Brightness.dark,
ThemeMode.system => WidgetsBinding.instance.platformDispatcher.platformBrightness,
};
return switch (brightness) {
Brightness.light => SystemUiOverlayStyle.dark,
Brightness.dark => SystemUiOverlayStyle.light,
};
}
GalleryOptions copyWith({

View File

@ -105,18 +105,13 @@ class _CupertinoAlertDemoState extends State<CupertinoAlertDemo>
String _title(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (widget.type) {
case AlertDemoType.alert:
return localizations.demoCupertinoAlertTitle;
case AlertDemoType.alertTitle:
return localizations.demoCupertinoAlertWithTitleTitle;
case AlertDemoType.alertButtons:
return localizations.demoCupertinoAlertButtonsTitle;
case AlertDemoType.alertButtonsOnly:
return localizations.demoCupertinoAlertButtonsOnlyTitle;
case AlertDemoType.actionSheet:
return localizations.demoCupertinoActionSheetTitle;
}
return switch (widget.type) {
AlertDemoType.alert => localizations.demoCupertinoAlertTitle,
AlertDemoType.alertTitle => localizations.demoCupertinoAlertWithTitleTitle,
AlertDemoType.alertButtons => localizations.demoCupertinoAlertButtonsTitle,
AlertDemoType.alertButtonsOnly => localizations.demoCupertinoAlertButtonsOnlyTitle,
AlertDemoType.actionSheet => localizations.demoCupertinoActionSheetTitle,
};
}
static Route<String> _alertDemoDialog(

View File

@ -17,21 +17,17 @@ class BottomSheetDemo extends StatelessWidget {
String _title(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (type) {
case BottomSheetDemoType.persistent:
return localizations.demoBottomSheetPersistentTitle;
case BottomSheetDemoType.modal:
return localizations.demoBottomSheetModalTitle;
}
return switch (type) {
BottomSheetDemoType.persistent => localizations.demoBottomSheetPersistentTitle,
BottomSheetDemoType.modal => localizations.demoBottomSheetModalTitle,
};
}
Widget _bottomSheetDemo(BuildContext context) {
switch (type) {
case BottomSheetDemoType.persistent:
return _PersistentBottomSheetDemo();
case BottomSheetDemoType.modal:
return _ModalBottomSheetDemo();
}
return switch (type) {
BottomSheetDemoType.persistent => _PersistentBottomSheetDemo(),
BottomSheetDemoType.modal => _ModalBottomSheetDemo(),
};
}
@override

View File

@ -13,18 +13,13 @@ class ButtonDemo extends StatelessWidget {
String _title(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (type) {
case ButtonDemoType.text:
return localizations.demoTextButtonTitle;
case ButtonDemoType.elevated:
return localizations.demoElevatedButtonTitle;
case ButtonDemoType.outlined:
return localizations.demoOutlinedButtonTitle;
case ButtonDemoType.toggle:
return localizations.demoToggleButtonTitle;
case ButtonDemoType.floating:
return localizations.demoFloatingButtonTitle;
}
return switch (type) {
ButtonDemoType.text => localizations.demoTextButtonTitle,
ButtonDemoType.elevated => localizations.demoElevatedButtonTitle,
ButtonDemoType.outlined => localizations.demoOutlinedButtonTitle,
ButtonDemoType.toggle => localizations.demoToggleButtonTitle,
ButtonDemoType.floating => localizations.demoFloatingButtonTitle,
};
}
@override

View File

@ -16,16 +16,12 @@ class ChipDemo extends StatelessWidget {
String _title(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (type) {
case ChipDemoType.action:
return localizations.demoActionChipTitle;
case ChipDemoType.choice:
return localizations.demoChoiceChipTitle;
case ChipDemoType.filter:
return localizations.demoFilterChipTitle;
case ChipDemoType.input:
return localizations.demoInputChipTitle;
}
return switch (type) {
ChipDemoType.action => localizations.demoActionChipTitle,
ChipDemoType.choice => localizations.demoChoiceChipTitle,
ChipDemoType.filter => localizations.demoFilterChipTitle,
ChipDemoType.input => localizations.demoInputChipTitle,
};
}
@override

View File

@ -81,16 +81,12 @@ class _DialogDemoState extends State<DialogDemo> with RestorationMixin {
String _title(BuildContext context) {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (widget.type) {
case DialogDemoType.alert:
return localizations.demoAlertDialogTitle;
case DialogDemoType.alertTitle:
return localizations.demoAlertTitleDialogTitle;
case DialogDemoType.simple:
return localizations.demoSimpleDialogTitle;
case DialogDemoType.fullscreen:
return localizations.demoFullscreenDialogTitle;
}
return switch (widget.type) {
DialogDemoType.alert => localizations.demoAlertDialogTitle,
DialogDemoType.alertTitle => localizations.demoAlertTitleDialogTitle,
DialogDemoType.simple => localizations.demoSimpleDialogTitle,
DialogDemoType.fullscreen => localizations.demoFullscreenDialogTitle,
};
}
static Route<String> _alertDialogDemoRoute(

View File

@ -164,14 +164,11 @@ class _PickerDemoState extends State<PickerDemo> with RestorationMixin {
String get _title {
final GalleryLocalizations localizations = GalleryLocalizations.of(context)!;
switch (widget.type) {
case PickerDemoType.date:
return localizations.demoDatePickerTitle;
case PickerDemoType.time:
return localizations.demoTimePickerTitle;
case PickerDemoType.range:
return localizations.demoDateRangePickerTitle;
}
return switch (widget.type) {
PickerDemoType.date => localizations.demoDatePickerTitle,
PickerDemoType.time => localizations.demoTimePickerTitle,
PickerDemoType.range => localizations.demoDateRangePickerTitle,
};
}
String get _labelText {

View File

@ -13,14 +13,10 @@ class TabsDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
Widget tabs;
switch (type) {
case TabsDemoType.scrollable:
tabs = _TabsScrollableDemo();
case TabsDemoType.nonScrollable:
tabs = _TabsNonScrollableDemo();
}
return tabs;
return switch (type) {
TabsDemoType.scrollable => _TabsScrollableDemo(),
TabsDemoType.nonScrollable => _TabsNonScrollableDemo(),
};
}
}

View File

@ -433,16 +433,11 @@ class _GalleryDemoPageState extends State<GalleryDemoPage>
page = AnimatedBuilder(
animation: _codeBackgroundColorController,
builder: (BuildContext context, Widget? child) {
Brightness themeBrightness;
switch (GalleryOptions.of(context).themeMode) {
case ThemeMode.system:
themeBrightness = MediaQuery.of(context).platformBrightness;
case ThemeMode.light:
themeBrightness = Brightness.light;
case ThemeMode.dark:
themeBrightness = Brightness.dark;
}
final Brightness themeBrightness = switch (GalleryOptions.of(context).themeMode) {
ThemeMode.system => MediaQuery.of(context).platformBrightness,
ThemeMode.light => Brightness.light,
ThemeMode.dark => Brightness.dark,
};
Widget contents = Container(
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),

View File

@ -89,17 +89,13 @@ class _ReplyAppState extends State<ReplyApp> with RestorationMixin {
supportedLocales: GalleryLocalizations.supportedLocales,
locale: GalleryOptions.of(context).locale,
initialRoute: ReplyApp.homeRoute,
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case ReplyApp.homeRoute:
return MaterialPageRoute<void>(
builder: (BuildContext context) => const AdaptiveNav(),
settings: settings,
);
case ReplyApp.composeRoute:
return ReplyApp.createComposeRoute(settings);
}
return null;
onGenerateRoute: (RouteSettings settings) => switch (settings.name) {
ReplyApp.homeRoute => MaterialPageRoute<void>(
builder: (BuildContext context) => const AdaptiveNav(),
settings: settings,
),
ReplyApp.composeRoute => ReplyApp.createComposeRoute(settings),
_ => null,
},
),
);

View File

@ -34,40 +34,15 @@ class MailboxBody extends StatelessWidget {
final String destinationString = destination
.toString()
.substring(destination.toString().indexOf('.') + 1);
late List<Email> emails;
switch (destination) {
case MailboxPageType.inbox:
{
emails = model.inboxEmails;
break;
}
case MailboxPageType.sent:
{
emails = model.outboxEmails;
break;
}
case MailboxPageType.starred:
{
emails = model.starredEmails;
break;
}
case MailboxPageType.trash:
{
emails = model.trashEmails;
break;
}
case MailboxPageType.spam:
{
emails = model.spamEmails;
break;
}
case MailboxPageType.drafts:
{
emails = model.draftEmails;
break;
}
}
final List<Email> emails = switch (destination) {
MailboxPageType.inbox => model.inboxEmails,
MailboxPageType.sent => model.outboxEmails,
MailboxPageType.starred => model.starredEmails,
MailboxPageType.trash => model.trashEmails,
MailboxPageType.spam => model.spamEmails,
MailboxPageType.drafts => model.draftEmails,
};
return SafeArea(
bottom: false,

View File

@ -16,21 +16,12 @@ class TestStepResult {
const TestStepResult(this.name, this.description, this.status);
factory TestStepResult.fromSnapshot(AsyncSnapshot<TestStepResult> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return const TestStepResult('Not started', nothing, TestStatus.ok);
case ConnectionState.waiting:
return const TestStepResult('Executing', nothing, TestStatus.pending);
case ConnectionState.done:
if (snapshot.hasData) {
return snapshot.data!;
} else {
final Object? result = snapshot.error;
return result! as TestStepResult;
}
case ConnectionState.active:
throw 'Unsupported state ${snapshot.connectionState}';
}
return switch (snapshot.connectionState) {
ConnectionState.none => const TestStepResult('Not started', nothing, TestStatus.ok),
ConnectionState.waiting => const TestStepResult('Executing', nothing, TestStatus.pending),
ConnectionState.done => snapshot.data ?? snapshot.error! as TestStepResult,
ConnectionState.active => throw 'Unsupported state: ConnectionState.active',
};
}
final String name;

View File

@ -325,26 +325,18 @@ enum SourceElementType {
unknownType,
}
/// Converts the enun type [SourceElementType] to a human readable string.
/// Converts the enum type [SourceElementType] to a human readable string.
String sourceElementTypeAsString(SourceElementType type) {
switch (type) {
case SourceElementType.classType:
return 'class';
case SourceElementType.fieldType:
return 'field';
case SourceElementType.methodType:
return 'method';
case SourceElementType.constructorType:
return 'constructor';
case SourceElementType.typedefType:
return 'typedef';
case SourceElementType.topLevelVariableType:
return 'variable';
case SourceElementType.functionType:
return 'function';
case SourceElementType.unknownType:
return 'unknown';
}
return switch (type) {
SourceElementType.classType => 'class',
SourceElementType.fieldType => 'field',
SourceElementType.methodType => 'method',
SourceElementType.constructorType => 'constructor',
SourceElementType.typedefType => 'typedef',
SourceElementType.topLevelVariableType => 'variable',
SourceElementType.functionType => 'function',
SourceElementType.unknownType => 'unknown',
};
}
/// A class that represents a Dart element in a source file.

View File

@ -62,29 +62,12 @@ class LocaleInfo implements Comparable<LocaleInfo> {
/// across various countries. For example, we know Taiwan uses traditional (Hant)
/// script, so it is safe to apply (Hant) to Taiwanese languages.
if (deriveScriptCode && scriptCode == null) {
switch (languageCode) {
case 'zh': {
if (countryCode == null) {
scriptCode = 'Hans';
}
switch (countryCode) {
case 'CN':
case 'SG':
scriptCode = 'Hans';
case 'TW':
case 'HK':
case 'MO':
scriptCode = 'Hant';
}
break;
}
case 'sr': {
if (countryCode == null) {
scriptCode = 'Cyrl';
}
break;
}
}
scriptCode = switch ((languageCode, countryCode)) {
('zh', 'CN' || 'SG' || null) => 'Hans',
('zh', 'TW' || 'HK' || 'MO') => 'Hant',
('sr', null) => 'Cyrl',
_ => null,
};
// Increment length if we were able to assume a scriptCode.
if (scriptCode != null) {
length += 1;

View File

@ -155,13 +155,12 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
/// See [TextSelectionControls.getHandleAnchor].
@override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
final Size handleSize;
final Size handleSize = getHandleSize(textLineHeight);
switch (type) {
// The circle is at the top for the left handle, and the anchor point is
// all the way at the bottom of the line.
case TextSelectionHandleType.left:
handleSize = getHandleSize(textLineHeight);
return Offset(
handleSize.width / 2,
handleSize.height,
@ -169,14 +168,12 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
// The right handle is vertically flipped, and the anchor point is near
// the top of the circle to give slight overlap.
case TextSelectionHandleType.right:
handleSize = getHandleSize(textLineHeight);
return Offset(
handleSize.width / 2,
handleSize.height - 2 * _kSelectionHandleRadius + _kSelectionHandleOverlap,
);
// A collapsed handle anchors itself so that it's centered.
case TextSelectionHandleType.collapsed:
handleSize = getHandleSize(textLineHeight);
return Offset(
handleSize.width / 2,
textLineHeight + (handleSize.height - textLineHeight) / 2,

View File

@ -174,10 +174,7 @@ class _CupertinoTextSelectionToolbarButtonState extends State<CupertinoTextSelec
: CupertinoColors.inactiveGray,
),
);
if (widget.buttonItem == null) {
return textWidget;
}
switch (widget.buttonItem!.type) {
switch (widget.buttonItem?.type) {
case ContextMenuButtonType.cut:
case ContextMenuButtonType.copy:
case ContextMenuButtonType.paste:
@ -187,6 +184,7 @@ class _CupertinoTextSelectionToolbarButtonState extends State<CupertinoTextSelec
case ContextMenuButtonType.searchWeb:
case ContextMenuButtonType.share:
case ContextMenuButtonType.custom:
case null:
return textWidget;
case ContextMenuButtonType.liveTextInput:
return SizedBox(

View File

@ -903,9 +903,7 @@ class _DestinationLayoutAnimationBuilder extends StatelessWidget {
animation: info.selectedAnimation,
curve: Curves.easeInOutCubicEmphasized,
reverseCurve: Curves.easeInOutCubicEmphasized.flipped,
builder: (BuildContext context, Animation<double> curvedAnimation) {
return builder(context, curvedAnimation);
},
builder: builder,
);
}
}

View File

@ -370,14 +370,11 @@ class Draggable<T extends Object> extends StatefulWidget {
/// recognizing a drag.
@protected
MultiDragGestureRecognizer createRecognizer(GestureMultiDragStartCallback onStart) {
switch (affinity) {
case Axis.horizontal:
return HorizontalMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter)..onStart = onStart;
case Axis.vertical:
return VerticalMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter)..onStart = onStart;
case null:
return ImmediateMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter)..onStart = onStart;
}
return switch (affinity) {
Axis.horizontal => HorizontalMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter),
Axis.vertical => VerticalMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter),
null => ImmediateMultiDragGestureRecognizer(allowedButtonsFilter: allowedButtonsFilter),
}..onStart = onStart;
}
@override

View File

@ -675,12 +675,10 @@ class BouncingScrollPhysics extends ScrollPhysics {
/// as more of the area past the edge is dragged in (represented by an increasing
/// `overscrollFraction` which starts at 0 when there is no overscroll).
double frictionFactor(double overscrollFraction) {
switch (decelerationRate) {
case ScrollDecelerationRate.fast:
return 0.26 * math.pow(1 - overscrollFraction, 2);
case ScrollDecelerationRate.normal:
return 0.52 * math.pow(1 - overscrollFraction, 2);
}
return math.pow(1 - overscrollFraction, 2) * switch (decelerationRate) {
ScrollDecelerationRate.fast => 0.26,
ScrollDecelerationRate.normal => 0.52,
};
}
@override

View File

@ -1724,16 +1724,14 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
// Determines the scroll direction.
final AxisDirection scrollDirection;
switch (position.axisDirection) {
case AxisDirection.up:
case AxisDirection.down:
switch (axisDirectionToAxis(position.axisDirection)) {
case Axis.vertical:
if (details.localPosition.dy > scrollbarPainter._thumbOffset) {
scrollDirection = AxisDirection.down;
} else {
scrollDirection = AxisDirection.up;
}
case AxisDirection.left:
case AxisDirection.right:
case Axis.horizontal:
if (details.localPosition.dx > scrollbarPainter._thumbOffset) {
scrollDirection = AxisDirection.right;
} else {

View File

@ -22,18 +22,17 @@ import 'wait.dart';
mixin DeserializeFinderFactory {
/// Deserializes the finder from JSON generated by [SerializableFinder.serialize].
SerializableFinder deserializeFinder(Map<String, String> json) {
final String? finderType = json['finderType'];
switch (finderType) {
case 'ByType': return ByType.deserialize(json);
case 'ByValueKey': return ByValueKey.deserialize(json);
case 'ByTooltipMessage': return ByTooltipMessage.deserialize(json);
case 'BySemanticsLabel': return BySemanticsLabel.deserialize(json);
case 'ByText': return ByText.deserialize(json);
case 'PageBack': return const PageBack();
case 'Descendant': return Descendant.deserialize(json, this);
case 'Ancestor': return Ancestor.deserialize(json, this);
}
throw DriverError('Unsupported search specification type $finderType');
return switch (json['finderType']) {
'ByType' => ByType.deserialize(json),
'ByValueKey' => ByValueKey.deserialize(json),
'ByTooltipMessage' => ByTooltipMessage.deserialize(json),
'BySemanticsLabel' => BySemanticsLabel.deserialize(json),
'ByText' => ByText.deserialize(json),
'PageBack' => const PageBack(),
'Descendant' => Descendant.deserialize(json, this),
'Ancestor' => Ancestor.deserialize(json, this),
_ => throw DriverError('Unsupported search specification type ${json['finderType']}'),
};
}
}
@ -41,33 +40,31 @@ mixin DeserializeFinderFactory {
mixin DeserializeCommandFactory {
/// Deserializes the finder from JSON generated by [Command.serialize] or [CommandWithTarget.serialize].
Command deserializeCommand(Map<String, String> params, DeserializeFinderFactory finderFactory) {
final String? kind = params['command'];
switch (kind) {
case 'get_health': return GetHealth.deserialize(params);
case 'get_layer_tree': return GetLayerTree.deserialize(params);
case 'get_render_tree': return GetRenderTree.deserialize(params);
case 'enter_text': return EnterText.deserialize(params);
case 'send_text_input_action': return SendTextInputAction.deserialize(params);
case 'get_text': return GetText.deserialize(params, finderFactory);
case 'request_data': return RequestData.deserialize(params);
case 'scroll': return Scroll.deserialize(params, finderFactory);
case 'scrollIntoView': return ScrollIntoView.deserialize(params, finderFactory);
case 'set_frame_sync': return SetFrameSync.deserialize(params);
case 'set_semantics': return SetSemantics.deserialize(params);
case 'set_text_entry_emulation': return SetTextEntryEmulation.deserialize(params);
case 'tap': return Tap.deserialize(params, finderFactory);
case 'waitFor': return WaitFor.deserialize(params, finderFactory);
case 'waitForAbsent': return WaitForAbsent.deserialize(params, finderFactory);
case 'waitForTappable': return WaitForTappable.deserialize(params, finderFactory);
case 'waitForCondition': return WaitForCondition.deserialize(params);
case 'waitUntilNoTransientCallbacks': return WaitForCondition.deserialize(params);
case 'waitUntilNoPendingFrame': return WaitForCondition.deserialize(params);
case 'waitUntilFirstFrameRasterized': return WaitForCondition.deserialize(params);
case 'get_semantics_id': return GetSemanticsId.deserialize(params, finderFactory);
case 'get_offset': return GetOffset.deserialize(params, finderFactory);
case 'get_diagnostics_tree': return GetDiagnosticsTree.deserialize(params, finderFactory);
}
throw DriverError('Unsupported command kind $kind');
return switch (params['command']) {
'get_health' => GetHealth.deserialize(params),
'get_layer_tree' => GetLayerTree.deserialize(params),
'get_render_tree' => GetRenderTree.deserialize(params),
'enter_text' => EnterText.deserialize(params),
'send_text_input_action' => SendTextInputAction.deserialize(params),
'get_text' => GetText.deserialize(params, finderFactory),
'request_data' => RequestData.deserialize(params),
'scroll' => Scroll.deserialize(params, finderFactory),
'scrollIntoView' => ScrollIntoView.deserialize(params, finderFactory),
'set_frame_sync' => SetFrameSync.deserialize(params),
'set_semantics' => SetSemantics.deserialize(params),
'set_text_entry_emulation' => SetTextEntryEmulation.deserialize(params),
'tap' => Tap.deserialize(params, finderFactory),
'waitFor' => WaitFor.deserialize(params, finderFactory),
'waitForAbsent' => WaitForAbsent.deserialize(params, finderFactory),
'waitForTappable' => WaitForTappable.deserialize(params, finderFactory),
'waitForCondition' => WaitForCondition.deserialize(params),
'waitUntilNoTransientCallbacks' => WaitForCondition.deserialize(params),
'waitUntilNoPendingFrame' => WaitForCondition.deserialize(params),
'waitUntilFirstFrameRasterized' => WaitForCondition.deserialize(params),
'get_semantics_id' => GetSemanticsId.deserialize(params, finderFactory),
'get_offset' => GetOffset.deserialize(params, finderFactory),
'get_diagnostics_tree' => GetDiagnosticsTree.deserialize(params, finderFactory),
final String? kind => throw DriverError('Unsupported command kind $kind'),
};
}
}

View File

@ -231,15 +231,11 @@ class ByValueKey extends SerializableFinder {
/// Deserializes the finder from JSON generated by [serialize].
static ByValueKey deserialize(Map<String, String> json) {
final String keyValueString = json['keyValueString']!;
final String keyValueType = json['keyValueType']!;
switch (keyValueType) {
case 'int':
return ByValueKey(int.parse(keyValueString));
case 'String':
return ByValueKey(keyValueString);
default:
throw _createInvalidKeyValueTypeError(keyValueType);
}
return switch (json['keyValueType']!) {
'int' => ByValueKey(int.parse(keyValueString)),
'String' => ByValueKey(keyValueString),
final String keyValueType => throw _createInvalidKeyValueTypeError(keyValueType),
};
}
}

View File

@ -33,27 +33,17 @@ import 'wait.dart';
mixin CreateFinderFactory {
/// Creates the flutter widget finder from [SerializableFinder].
Finder createFinder(SerializableFinder finder) {
final String finderType = finder.finderType;
switch (finderType) {
case 'ByText':
return _createByTextFinder(finder as ByText);
case 'ByTooltipMessage':
return _createByTooltipMessageFinder(finder as ByTooltipMessage);
case 'BySemanticsLabel':
return _createBySemanticsLabelFinder(finder as BySemanticsLabel);
case 'ByValueKey':
return _createByValueKeyFinder(finder as ByValueKey);
case 'ByType':
return _createByTypeFinder(finder as ByType);
case 'PageBack':
return _createPageBackFinder();
case 'Ancestor':
return _createAncestorFinder(finder as Ancestor);
case 'Descendant':
return _createDescendantFinder(finder as Descendant);
default:
throw DriverError('Unsupported search specification type $finderType');
}
return switch (finder.finderType) {
'ByText' => _createByTextFinder(finder as ByText),
'ByTooltipMessage' => _createByTooltipMessageFinder(finder as ByTooltipMessage),
'BySemanticsLabel' => _createBySemanticsLabelFinder(finder as BySemanticsLabel),
'ByValueKey' => _createByValueKeyFinder(finder as ByValueKey),
'ByType' => _createByTypeFinder(finder as ByType),
'PageBack' => _createPageBackFinder(),
'Ancestor' => _createAncestorFinder(finder as Ancestor),
'Descendant' => _createDescendantFinder(finder as Descendant),
final String type => throw DriverError('Unsupported search specification type $type'),
};
}
Finder _createByTextFinder(ByText arguments) {
@ -87,14 +77,11 @@ mixin CreateFinderFactory {
}
Finder _createByValueKeyFinder(ByValueKey arguments) {
switch (arguments.keyValueType) {
case 'int':
return find.byKey(ValueKey<int>(arguments.keyValue as int));
case 'String':
return find.byKey(ValueKey<String>(arguments.keyValue as String));
default:
throw UnimplementedError('Unsupported ByValueKey type: ${arguments.keyValueType}');
}
return switch (arguments.keyValueType) {
'int' => find.byKey(ValueKey<int>(arguments.keyValue as int)),
'String' => find.byKey(ValueKey<String>(arguments.keyValue as String)),
_ => throw UnimplementedError('Unsupported ByValueKey type: ${arguments.keyValueType}'),
};
}
Finder _createByTypeFinder(ByType arguments) {
@ -155,33 +142,33 @@ mixin CommandHandlerFactory {
/// Deserializes the finder from JSON generated by [Command.serialize] or [CommandWithTarget.serialize].
Future<Result> handleCommand(Command command, WidgetController prober, CreateFinderFactory finderFactory) {
switch (command.kind) {
case 'get_health': return _getHealth(command);
case 'get_layer_tree': return _getLayerTree(command);
case 'get_render_tree': return _getRenderTree(command);
case 'enter_text': return _enterText(command);
case 'send_text_input_action': return _sendTextInputAction(command);
case 'get_text': return _getText(command, finderFactory);
case 'request_data': return _requestData(command);
case 'scroll': return _scroll(command, prober, finderFactory);
case 'scrollIntoView': return _scrollIntoView(command, finderFactory);
case 'set_frame_sync': return _setFrameSync(command);
case 'set_semantics': return _setSemantics(command);
case 'set_text_entry_emulation': return _setTextEntryEmulation(command);
case 'tap': return _tap(command, prober, finderFactory);
case 'waitFor': return _waitFor(command, finderFactory);
case 'waitForAbsent': return _waitForAbsent(command, finderFactory);
case 'waitForTappable': return _waitForTappable(command, finderFactory);
case 'waitForCondition': return _waitForCondition(command);
case 'waitUntilNoTransientCallbacks': return _waitUntilNoTransientCallbacks(command);
case 'waitUntilNoPendingFrame': return _waitUntilNoPendingFrame(command);
case 'waitUntilFirstFrameRasterized': return _waitUntilFirstFrameRasterized(command);
case 'get_semantics_id': return _getSemanticsId(command, finderFactory);
case 'get_offset': return _getOffset(command, finderFactory);
case 'get_diagnostics_tree': return _getDiagnosticsTree(command, finderFactory);
}
return switch (command.kind) {
'get_health' => _getHealth(command),
'get_layer_tree' => _getLayerTree(command),
'get_render_tree' => _getRenderTree(command),
'enter_text' => _enterText(command),
'send_text_input_action' => _sendTextInputAction(command),
'get_text' => _getText(command, finderFactory),
'request_data' => _requestData(command),
'scroll' => _scroll(command, prober, finderFactory),
'scrollIntoView' => _scrollIntoView(command, finderFactory),
'set_frame_sync' => _setFrameSync(command),
'set_semantics' => _setSemantics(command),
'set_text_entry_emulation' => _setTextEntryEmulation(command),
'tap' => _tap(command, prober, finderFactory),
'waitFor' => _waitFor(command, finderFactory),
'waitForAbsent' => _waitForAbsent(command, finderFactory),
'waitForTappable' => _waitForTappable(command, finderFactory),
'waitForCondition' => _waitForCondition(command),
'waitUntilNoTransientCallbacks' => _waitUntilNoTransientCallbacks(command),
'waitUntilNoPendingFrame' => _waitUntilNoPendingFrame(command),
'waitUntilFirstFrameRasterized' => _waitUntilFirstFrameRasterized(command),
'get_semantics_id' => _getSemanticsId(command, finderFactory),
'get_offset' => _getOffset(command, finderFactory),
'get_diagnostics_tree' => _getDiagnosticsTree(command, finderFactory),
final String kind => throw DriverError('Unsupported command kind $kind'),
};
throw DriverError('Unsupported command kind ${command.kind}');
}
Future<Health> _getHealth(Command command) async => const Health(HealthStatus.ok);
@ -342,19 +329,13 @@ mixin CommandHandlerFactory {
final Finder finder = await waitForElement(finderFactory.createFinder(getOffsetCommand.finder));
final Element element = finder.evaluate().single;
final RenderBox box = (element.renderObject as RenderBox?)!;
Offset localPoint;
switch (getOffsetCommand.offsetType) {
case OffsetType.topLeft:
localPoint = Offset.zero;
case OffsetType.topRight:
localPoint = box.size.topRight(Offset.zero);
case OffsetType.bottomLeft:
localPoint = box.size.bottomLeft(Offset.zero);
case OffsetType.bottomRight:
localPoint = box.size.bottomRight(Offset.zero);
case OffsetType.center:
localPoint = box.size.center(Offset.zero);
}
final Offset localPoint = switch (getOffsetCommand.offsetType) {
OffsetType.topLeft => Offset.zero,
OffsetType.topRight => box.size.topRight(Offset.zero),
OffsetType.bottomLeft => box.size.bottomLeft(Offset.zero),
OffsetType.bottomRight => box.size.bottomRight(Offset.zero),
OffsetType.center => box.size.center(Offset.zero),
};
final Offset globalPoint = box.localToGlobal(localPoint);
return GetOffsetResult(dx: globalPoint.dx, dy: globalPoint.dy);
}
@ -363,13 +344,10 @@ mixin CommandHandlerFactory {
final GetDiagnosticsTree diagnosticsCommand = command as GetDiagnosticsTree;
final Finder finder = await waitForElement(finderFactory.createFinder(diagnosticsCommand.finder));
final Element element = finder.evaluate().single;
DiagnosticsNode diagnosticsNode;
switch (diagnosticsCommand.diagnosticsType) {
case DiagnosticsType.renderObject:
diagnosticsNode = element.renderObject!.toDiagnosticsNode();
case DiagnosticsType.widget:
diagnosticsNode = element.toDiagnosticsNode();
}
final DiagnosticsNode diagnosticsNode = switch (diagnosticsCommand.diagnosticsType) {
DiagnosticsType.renderObject => element.renderObject!.toDiagnosticsNode(),
DiagnosticsType.widget => element.toDiagnosticsNode(),
};
return DiagnosticsTreeResult(diagnosticsNode.toJsonMap(DiagnosticsSerializationDelegate(
subtreeDepth: diagnosticsCommand.subtreeDepth,
includeProperties: diagnosticsCommand.includeProperties,

View File

@ -195,19 +195,14 @@ class CombinedCondition extends SerializableWaitCondition {
/// Parses a [SerializableWaitCondition] or its subclass from the given [json] map.
SerializableWaitCondition _deserialize(Map<String, String> json) {
final String conditionName = json['conditionName']!;
switch (conditionName) {
case 'NoTransientCallbacksCondition':
return NoTransientCallbacks.deserialize(json);
case 'NoPendingFrameCondition':
return NoPendingFrame.deserialize(json);
case 'FirstFrameRasterizedCondition':
return FirstFrameRasterized.deserialize(json);
case 'NoPendingPlatformMessagesCondition':
return NoPendingPlatformMessages.deserialize(json);
case 'CombinedCondition':
return CombinedCondition.deserialize(json);
}
throw SerializationException(
'Unsupported wait condition $conditionName in the JSON string $json');
return switch (json['conditionName']!) {
'NoTransientCallbacksCondition' => NoTransientCallbacks.deserialize(json),
'NoPendingFrameCondition' => NoPendingFrame.deserialize(json),
'FirstFrameRasterizedCondition' => FirstFrameRasterized.deserialize(json),
'NoPendingPlatformMessagesCondition' => NoPendingPlatformMessages.deserialize(json),
'CombinedCondition' => CombinedCondition.deserialize(json),
final String condition => throw SerializationException(
'Unsupported wait condition $condition in the JSON string $json',
),
};
}

View File

@ -121,16 +121,12 @@ class ProfilingSummarizer {
}
static ProfileType _getProfileType(String? eventName) {
switch (eventName) {
case _kCpuProfile:
return ProfileType.CPU;
case _kGpuProfile:
return ProfileType.GPU;
case _kMemoryProfile:
return ProfileType.Memory;
default:
throw Exception('Invalid profiling event: $eventName.');
}
return switch (eventName) {
_kCpuProfile => ProfileType.CPU,
_kGpuProfile => ProfileType.GPU,
_kMemoryProfile => ProfileType.Memory,
_ => throw Exception('Invalid profiling event: $eventName.'),
};
}
double _getProfileValue(ProfileType profileType, TimelineEvent e) {

View File

@ -601,19 +601,17 @@ const Duration _kPauseBetweenIsolateRefresh = Duration(milliseconds: 100);
// See `timeline_streams` in
// https://github.com/dart-lang/sdk/blob/main/runtime/vm/timeline.cc
List<String> _timelineStreamsToString(List<TimelineStream> streams) {
return streams.map<String>((TimelineStream stream) {
switch (stream) {
case TimelineStream.all: return 'all';
case TimelineStream.api: return 'API';
case TimelineStream.compiler: return 'Compiler';
case TimelineStream.compilerVerbose: return 'CompilerVerbose';
case TimelineStream.dart: return 'Dart';
case TimelineStream.debugger: return 'Debugger';
case TimelineStream.embedder: return 'Embedder';
case TimelineStream.gc: return 'GC';
case TimelineStream.isolate: return 'Isolate';
case TimelineStream.vm: return 'VM';
}
return streams.map<String>((TimelineStream stream) => switch (stream) {
TimelineStream.all => 'all',
TimelineStream.api => 'API',
TimelineStream.dart => 'Dart',
TimelineStream.debugger => 'Debugger',
TimelineStream.embedder => 'Embedder',
TimelineStream.gc => 'GC',
TimelineStream.isolate => 'Isolate',
TimelineStream.vm => 'VM',
TimelineStream.compiler => 'Compiler',
TimelineStream.compilerVerbose => 'CompilerVerbose',
}).toList();
}

View File

@ -177,18 +177,12 @@ class _InternalCombinedCondition implements WaitCondition {
/// Parses a [WaitCondition] or its subclass from the given serializable [waitCondition].
WaitCondition deserializeCondition(SerializableWaitCondition waitCondition) {
final String conditionName = waitCondition.conditionName;
switch (conditionName) {
case 'NoTransientCallbacksCondition':
return _InternalNoTransientCallbacksCondition.deserialize(waitCondition);
case 'NoPendingFrameCondition':
return _InternalNoPendingFrameCondition.deserialize(waitCondition);
case 'FirstFrameRasterizedCondition':
return _InternalFirstFrameRasterizedCondition.deserialize(waitCondition);
case 'NoPendingPlatformMessagesCondition':
return _InternalNoPendingPlatformMessagesCondition.deserialize(waitCondition);
case 'CombinedCondition':
return _InternalCombinedCondition.deserialize(waitCondition);
}
throw SerializationException(
'Unsupported wait condition $conditionName in ${waitCondition.serialize()}');
return switch (conditionName) {
'NoTransientCallbacksCondition' => _InternalNoTransientCallbacksCondition.deserialize(waitCondition),
'NoPendingFrameCondition' => _InternalNoPendingFrameCondition.deserialize(waitCondition),
'FirstFrameRasterizedCondition' => _InternalFirstFrameRasterizedCondition.deserialize(waitCondition),
'NoPendingPlatformMessagesCondition' => _InternalNoPendingPlatformMessagesCondition.deserialize(waitCondition),
'CombinedCondition' => _InternalCombinedCondition.deserialize(waitCondition),
_ => throw SerializationException('Unsupported wait condition $conditionName in ${waitCondition.serialize()}'),
};
}

View File

@ -226,12 +226,10 @@ abstract class GlobalMaterialLocalizations implements MaterialLocalizations {
}
String? _formatDayPeriod(TimeOfDay timeOfDay) {
switch (timeOfDay.period) {
case DayPeriod.am:
return anteMeridiemAbbreviation;
case DayPeriod.pm:
return postMeridiemAbbreviation;
}
return switch (timeOfDay.period) {
DayPeriod.am => anteMeridiemAbbreviation,
DayPeriod.pm => postMeridiemAbbreviation,
};
}
/// The raw version of [dateRangeStartDateSemanticLabel], with `$formattedDate` verbatim

View File

@ -353,16 +353,14 @@ class TestDefaultBinaryMessenger extends BinaryMessenger {
final StreamController<Object?> controller = StreamController<Object?>();
addTearDown(controller.close);
setMockMethodCallHandler(MethodChannel(channel.name, channel.codec), (MethodCall call) async {
switch (call.method) {
case 'listen':
return handler.onListen(call.arguments, MockStreamHandlerEventSink(controller.sink));
case 'cancel':
return handler.onCancel(call.arguments);
default:
throw UnimplementedError('Method ${call.method} not implemented');
}
});
setMockMethodCallHandler(
MethodChannel(channel.name, channel.codec),
(MethodCall call) async => switch (call.method) {
'listen' => handler.onListen(call.arguments, MockStreamHandlerEventSink(controller.sink)),
'cancel' => handler.onCancel(call.arguments),
_ => throw UnimplementedError('Method ${call.method} not implemented'),
},
);
final StreamSubscription<Object?> sub = controller.stream.listen(
(Object? e) => handlePlatformMessage(

View File

@ -76,9 +76,7 @@ enum FlutterProjectType implements CliEnum {
static List<FlutterProjectType> get enabledValues {
return <FlutterProjectType>[
for (final FlutterProjectType value in values)
if (value == FlutterProjectType.packageFfi) ...<FlutterProjectType>[
if (featureFlags.isNativeAssetsEnabled) value
] else
if (value != FlutterProjectType.packageFfi || featureFlags.isNativeAssetsEnabled)
value,
];
}

View File

@ -206,16 +206,12 @@ class DriverTestMessage {
/// Return a DriverTestMessage depending on `status`.
static DriverTestMessage fromString(String status) {
switch (status) {
case 'error':
return DriverTestMessage.error();
case 'pending':
return DriverTestMessage.pending();
case 'complete':
return DriverTestMessage.complete();
default:
throw StateError('This type of status does not exist: $status');
}
return switch (status) {
'error' => DriverTestMessage.error(),
'pending' => DriverTestMessage.pending(),
'complete' => DriverTestMessage.complete(),
_ => throw StateError('This type of status does not exist: $status'),
};
}
}