Implementing control flow collections (#146601)

This pull request aims for improved readability, based on issue #146600.

```dart
// before
Set<Color> _distinctVisibleColors() {
  final Set<Color> distinctVisibleColors = <Color>{};
  if (top.style != BorderStyle.none) {
    distinctVisibleColors.add(top.color);
  }
  if (right.style != BorderStyle.none) {
    distinctVisibleColors.add(right.color);
  }
  if (bottom.style != BorderStyle.none) {
    distinctVisibleColors.add(bottom.color);
  }
  if (left.style != BorderStyle.none) {
    distinctVisibleColors.add(left.color);
  }
  return distinctVisibleColors;
}

// after
Set<Color> _distinctVisibleColors() {
  return <Color>{
    if (top.style != BorderStyle.none) top.color,
    if (right.style != BorderStyle.none) right.color,
    if (bottom.style != BorderStyle.none) bottom.color,
    if (left.style != BorderStyle.none) left.color,
  };
}
```

Most of the repo should be covered in this PR (aside from `flutter_tools/`, since there was a lot going on in there).
This commit is contained in:
Nate 2024-04-15 11:06:07 -05:00 committed by GitHub
parent 600787891a
commit 2e748e8598
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 276 additions and 494 deletions

View File

@ -11,30 +11,20 @@ import 'package:flutter/services.dart';
import 'package:microbenchmarks/common.dart';
List<Object?> _makeTestBuffer(int size) {
final List<Object?> answer = <Object?>[];
for (int i = 0; i < size; ++i) {
switch (i % 9) {
case 0:
answer.add(1);
case 1:
answer.add(math.pow(2, 65));
case 2:
answer.add(1234.0);
case 3:
answer.add(null);
case 4:
answer.add(<int>[1234]);
case 5:
answer.add(<String, int>{'hello': 1234});
case 6:
answer.add('this is a test');
case 7:
answer.add(true);
case 8:
answer.add(Uint8List(64));
}
}
return answer;
return <Object?>[
for (int i = 0; i < size; i++)
switch (i % 9) {
0 => 1,
1 => math.pow(2, 65),
2 => 1234.0,
3 => null,
4 => <int>[1234],
5 => <String, int>{'hello': 1234},
6 => 'this is a test',
7 => true,
_ => Uint8List(64),
},
];
}
Future<double> _runBasicStandardSmall(

View File

@ -139,28 +139,21 @@ Future<void> verifyExist(
String flutterRoot,
{@visibleForTesting ProcessManager processManager = const LocalProcessManager()
}) async {
final Set<String> foundFiles = <String>{};
final String cacheDirectory = path.join(flutterRoot, 'bin', 'cache');
for (final String binaryPath
in await findBinaryPaths(cacheDirectory, processManager: processManager)) {
if (binariesWithEntitlements(flutterRoot).contains(binaryPath)) {
foundFiles.add(binaryPath);
} else if (binariesWithoutEntitlements(flutterRoot).contains(binaryPath)) {
foundFiles.add(binaryPath);
} else {
throw Exception(
'Found unexpected binary in cache: $binaryPath');
}
}
final List<String> binaryPaths = await findBinaryPaths(
path.join(flutterRoot, 'bin', 'cache'),
processManager: processManager,
);
final List<String> allExpectedFiles = binariesWithEntitlements(flutterRoot) + binariesWithoutEntitlements(flutterRoot);
final Set<String> foundFiles = <String>{
for (final String binaryPath in binaryPaths)
if (allExpectedFiles.contains(binaryPath)) binaryPath
else throw Exception('Found unexpected binary in cache: $binaryPath'),
};
if (foundFiles.length < allExpectedFiles.length) {
final List<String> unfoundFiles = allExpectedFiles
.where(
(String file) => !foundFiles.contains(file),
)
.toList();
final List<String> unfoundFiles = <String>[
for (final String file in allExpectedFiles) if (!foundFiles.contains(file)) file,
];
print(
'Expected binaries not found in cache:\n\n${unfoundFiles.join('\n')}\n\n'
'If this commit is removing binaries from the cache, this test should be fixed by\n'

View File

@ -913,18 +913,14 @@ Future<void> _runFrameworkTests() async {
final Uint8List libappBytes = libapp.content as Uint8List; // bytes decompressed here
final String libappStrings = utf8.decode(libappBytes, allowMalformed: true);
await runCommand(flutter, <String>['clean'], workingDirectory: tracingDirectory);
final List<String> results = <String>[];
for (final String pattern in allowed) {
if (!libappStrings.contains(pattern)) {
results.add('When building with --$modeArgument, expected to find "$pattern" in libapp.so but could not find it.');
}
}
for (final String pattern in disallowed) {
if (libappStrings.contains(pattern)) {
results.add('When building with --$modeArgument, expected to not find "$pattern" in libapp.so but did find it.');
}
}
return results;
return <String>[
for (final String pattern in allowed)
if (!libappStrings.contains(pattern))
'When building with --$modeArgument, expected to find "$pattern" in libapp.so but could not find it.',
for (final String pattern in disallowed)
if (libappStrings.contains(pattern))
'When building with --$modeArgument, expected to not find "$pattern" in libapp.so but did find it.',
];
} catch (error, stackTrace) {
return <String>[
error.toString(),
@ -1332,11 +1328,9 @@ Future<void> _runDartTest(String workingDirectory, {
if (collectMetrics) {
try {
final List<String> testList = <String>[];
final Map<int, TestSpecs> allTestSpecs = test.allTestSpecs;
for (final TestSpecs testSpecs in allTestSpecs.values) {
testList.add(testSpecs.toJson());
}
final List<String> testList = <String>[
for (final TestSpecs testSpecs in test.allTestSpecs.values) testSpecs.toJson(),
];
if (testList.isNotEmpty) {
final String testJson = json.encode(testList);
final File testResults = fileSystem.file(

View File

@ -110,12 +110,10 @@ class NextContext extends Context {
break;
}
final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[];
for (final pb.Cherrypick cherrypick in state.engine.cherrypicks) {
if (!finishedStates.contains(cherrypick.state)) {
unappliedCherrypicks.add(cherrypick);
}
}
final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[
for (final pb.Cherrypick cherrypick in state.engine.cherrypicks)
if (!finishedStates.contains(cherrypick.state)) cherrypick,
];
if (unappliedCherrypicks.isEmpty) {
stdio.printStatus('All engine cherrypicks have been auto-applied by the conductor.\n');
@ -206,12 +204,10 @@ class NextContext extends Context {
);
}
final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[];
for (final pb.Cherrypick cherrypick in state.framework.cherrypicks) {
if (!finishedStates.contains(cherrypick.state)) {
unappliedCherrypicks.add(cherrypick);
}
}
final List<pb.Cherrypick> unappliedCherrypicks = <pb.Cherrypick>[
for (final pb.Cherrypick cherrypick in state.framework.cherrypicks)
if (!finishedStates.contains(cherrypick.state)) cherrypick,
];
if (state.framework.cherrypicks.isEmpty) {
stdio.printStatus(

View File

@ -183,15 +183,11 @@ abstract class Repository {
workingDirectory: (await checkoutDirectory).path,
);
final List<String> remoteBranches = <String>[];
for (final String line in output.split('\n')) {
final RegExpMatch? match = _lsRemotePattern.firstMatch(line);
if (match != null) {
remoteBranches.add(match.group(1)!);
}
}
return remoteBranches;
return <String>[
for (final String line in output.split('\n'))
if (_lsRemotePattern.firstMatch(line) case final RegExpMatch match)
match.group(1)!,
];
}
/// Ensure the repository is cloned to disk and initialized with proper state.

View File

@ -39,8 +39,8 @@ TaskFunction createMicrobenchmarkTask({
if (enableImpeller != null && !enableImpeller) '--no-enable-impeller',
'-d',
device.deviceId,
benchmarkPath,
];
options.add(benchmarkPath);
return startFlutter(
'run',
options: options,

View File

@ -154,14 +154,11 @@ class AndroidSemanticsNode {
if (actions == null) {
return const <AndroidSemanticsAction>[];
}
final List<AndroidSemanticsAction> convertedActions = <AndroidSemanticsAction>[];
for (final int id in actions) {
final AndroidSemanticsAction? action = AndroidSemanticsAction.deserialize(id);
if (action != null) {
convertedActions.add(action);
}
}
return convertedActions;
return <AndroidSemanticsAction>[
for (final int id in actions)
if (AndroidSemanticsAction.deserialize(id) case final AndroidSemanticsAction action)
action,
];
}
@override

View File

@ -121,10 +121,8 @@ class CalcExpression {
: this(<ExpressionToken>[], ExpressionState.Start);
CalcExpression.result(FloatToken result)
: _list = <ExpressionToken?>[],
state = ExpressionState.Result {
_list.add(result);
}
: _list = <ExpressionToken?>[result],
state = ExpressionState.Result;
/// The tokens comprising the expression.
final List<ExpressionToken?> _list;

View File

@ -84,15 +84,11 @@ class _CupertinoSearchTextFieldDemoState
Widget _buildPlatformList() {
if (_searchPlatform.isNotEmpty) {
final List<String> tempList = <String>[];
for (int i = 0; i < filteredPlatforms.length; i++) {
if (filteredPlatforms[i]
.toLowerCase()
.contains(_searchPlatform.toLowerCase())) {
tempList.add(filteredPlatforms[i]);
}
}
filteredPlatforms = tempList;
final String search = _searchPlatform.toLowerCase();
filteredPlatforms = <String>[
for (final String platform in filteredPlatforms)
if (platform.toLowerCase().contains(search)) platform
];
}
return ListView.builder(
itemCount: filteredPlatforms.length,

View File

@ -26,14 +26,10 @@ class _RestorableDessertSelections extends RestorableProperty<Set<int>> {
/// Takes a list of [_Dessert]s and saves the row indices of selected rows
/// into a [Set].
void setDessertSelections(List<_Dessert> desserts) {
final Set<int> updatedSet = <int>{};
for (int i = 0; i < desserts.length; i += 1) {
final _Dessert dessert = desserts[i];
if (dessert.selected) {
updatedSet.add(i);
}
}
_dessertSelections = updatedSet;
_dessertSelections = <int>{
for (final (int i, _Dessert dessert) in desserts.indexed)
if (dessert.selected) i,
};
notifyListeners();
}

View File

@ -116,19 +116,18 @@ Future<File> generateTest(Directory apiDir) async {
});
// Collect the examples, and import them all as separate symbols.
final List<String> imports = <String>[];
imports.add('''import 'package:flutter/widgets.dart';''');
imports.add('''import 'package:flutter/scheduler.dart';''');
imports.add('''import 'package:flutter_test/flutter_test.dart';''');
imports.add('''import 'package:integration_test/integration_test.dart';''');
final List<ExampleInfo> infoList = <ExampleInfo>[];
for (final File example in examples) {
final ExampleInfo info = ExampleInfo(example, examplesLibDir);
infoList.add(info);
imports.add('''import 'package:flutter_api_samples/${info.importPath}' as ${info.importName};''');
}
imports.sort();
final List<ExampleInfo> infoList = <ExampleInfo>[
for (final File example in examples) ExampleInfo(example, examplesLibDir),
];
infoList.sort((ExampleInfo a, ExampleInfo b) => a.importPath.compareTo(b.importPath));
final List<String> imports = <String>[
"import 'package:flutter/widgets.dart';",
"import 'package:flutter/scheduler.dart';",
"import 'package:flutter_test/flutter_test.dart';",
"import 'package:integration_test/integration_test.dart';",
for (final ExampleInfo info in infoList)
"import 'package:flutter_api_samples/${info.importPath}' as ${info.importName};"
]..sort();
final StringBuffer buffer = StringBuffer();
buffer.writeln('// Temporary generated file. Do not commit.');

View File

@ -388,15 +388,10 @@ bool testIsSuperset(Map<String, String> newCodepoints, Map<String, String> oldCo
@visibleForTesting
bool testIsStable(Map<String, String> newCodepoints, Map<String, String> oldCodepoints) {
final int oldCodepointsCount = oldCodepoints.length;
final List<String> unstable = <String>[];
oldCodepoints.forEach((String key, String value) {
if (newCodepoints.containsKey(key)) {
if (value != newCodepoints[key]) {
unstable.add(key);
}
}
});
final List<String> unstable = <String>[
for (final MapEntry<String, String>(:String key, :String value) in oldCodepoints.entries)
if (newCodepoints.containsKey(key) && value != newCodepoints[key]) key,
];
if (unstable.isNotEmpty) {
stderr.writeln('❌ out of $oldCodepointsCount existing codepoints, ${unstable.length} were unstable: $unstable');

View File

@ -1485,22 +1485,15 @@ class _CupertinoAlertActionSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<Widget> interactiveButtons = <Widget>[];
for (int i = 0; i < children.length; i += 1) {
interactiveButtons.add(
_PressableActionButton(
child: children[i],
),
);
}
return CupertinoScrollbar(
controller: scrollController,
child: SingleChildScrollView(
controller: scrollController,
child: _CupertinoDialogActionsRenderWidget(
actionButtons: interactiveButtons,
actionButtons: <Widget>[
for (final Widget child in children)
_PressableActionButton(child: child),
],
dividerThickness: _kDividerThickness,
hasCancelButton: hasCancelButton,
isActionSheet: isActionSheet,

View File

@ -311,12 +311,10 @@ final class _Float64ListChain {
/// are read back, they do not affect the timings of the work being
/// benchmarked.
List<double> extractElements() {
final List<double> result = <double>[];
_chain.forEach(result.addAll);
for (int i = 0; i < _pointer; i++) {
result.add(_slice[i]);
}
return result;
return <double>[
for (final Float64List list in _chain) ...list,
for (int i = 0; i < _pointer; i++) _slice[i],
];
}
}
@ -349,16 +347,11 @@ final class _StringListChain {
/// are read back, they do not affect the timings of the work being
/// benchmarked.
List<String> extractElements() {
final List<String> result = <String>[];
for (final List<String?> slice in _chain) {
for (final String? element in slice) {
result.add(element!);
}
}
for (int i = 0; i < _pointer; i++) {
result.add(_slice[i]!);
}
return result;
return <String>[
for (final List<String?> slice in _chain)
for (final String? value in slice) value!,
for (int i = 0; i < _pointer; i++) _slice[i]!,
];
}
}

View File

@ -2125,37 +2125,22 @@ class _LocalizedShortcutLabeler {
keySeparator = '+';
}
if (serialized.trigger != null) {
final List<String> modifiers = <String>[];
final LogicalKeyboardKey trigger = serialized.trigger!;
if (_usesSymbolicModifiers) {
// macOS/iOS platform convention uses this ordering, with always last.
if (serialized.control!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.control, localizations));
}
if (serialized.alt!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.alt, localizations));
}
if (serialized.shift!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.shift, localizations));
}
if (serialized.meta!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.meta, localizations));
}
} else {
// These should be in this order, to match the LogicalKeySet version.
if (serialized.alt!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.alt, localizations));
}
if (serialized.control!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.control, localizations));
}
if (serialized.meta!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.meta, localizations));
}
if (serialized.shift!) {
modifiers.add(_getModifierLabel(LogicalKeyboardKey.shift, localizations));
}
}
final List<String> modifiers = <String>[
if (_usesSymbolicModifiers) ...<String>[
// MacOS/iOS platform convention uses this ordering, with always last.
if (serialized.control!) _getModifierLabel(LogicalKeyboardKey.control, localizations),
if (serialized.alt!) _getModifierLabel(LogicalKeyboardKey.alt, localizations),
if (serialized.shift!) _getModifierLabel(LogicalKeyboardKey.shift, localizations),
if (serialized.meta!) _getModifierLabel(LogicalKeyboardKey.meta, localizations),
] else ...<String>[
// This order matches the LogicalKeySet version.
if (serialized.alt!) _getModifierLabel(LogicalKeyboardKey.alt, localizations),
if (serialized.control!) _getModifierLabel(LogicalKeyboardKey.control, localizations),
if (serialized.meta!) _getModifierLabel(LogicalKeyboardKey.meta, localizations),
if (serialized.shift!) _getModifierLabel(LogicalKeyboardKey.shift, localizations),
],
];
String? shortcutTrigger;
final int logicalKeyId = trigger.keyId;
if (_shortcutGraphicEquivalents.containsKey(trigger)) {

View File

@ -141,7 +141,6 @@ class NavigationDrawer extends StatelessWidget {
children.whereType<NavigationDrawerDestination>().toList().length;
int destinationIndex = 0;
final List<Widget> wrappedChildren = <Widget>[];
Widget wrapChild(Widget child, int index) => _SelectableAnimatedBuilder(
duration: const Duration(milliseconds: 500),
isSelected: index == selectedIndex,
@ -162,14 +161,11 @@ class NavigationDrawer extends StatelessWidget {
);
});
for (int i = 0; i < children.length; i++) {
if (children[i] is! NavigationDrawerDestination) {
wrappedChildren.add(children[i]);
} else {
wrappedChildren.add(wrapChild(children[i], destinationIndex));
destinationIndex += 1;
}
}
final List<Widget> wrappedChildren = <Widget>[
for (final Widget child in children)
if (child is! NavigationDrawerDestination) child
else wrapChild(child, destinationIndex++),
];
final NavigationDrawerThemeData navigationDrawerTheme = NavigationDrawerTheme.of(context);
return Drawer(

View File

@ -492,20 +492,12 @@ class Border extends BoxBorder {
}
Set<Color> _distinctVisibleColors() {
final Set<Color> distinctVisibleColors = <Color>{};
if (top.style != BorderStyle.none) {
distinctVisibleColors.add(top.color);
}
if (right.style != BorderStyle.none) {
distinctVisibleColors.add(right.color);
}
if (bottom.style != BorderStyle.none) {
distinctVisibleColors.add(bottom.color);
}
if (left.style != BorderStyle.none) {
distinctVisibleColors.add(left.color);
}
return distinctVisibleColors;
return <Color>{
if (top.style != BorderStyle.none) top.color,
if (right.style != BorderStyle.none) right.color,
if (bottom.style != BorderStyle.none) bottom.color,
if (left.style != BorderStyle.none) left.color,
};
}
// [BoxBorder.paintNonUniformBorder] is about 20% faster than [paintBorder],
@ -840,21 +832,12 @@ class BorderDirectional extends BoxBorder {
}
Set<Color> _distinctVisibleColors() {
final Set<Color> distinctVisibleColors = <Color>{};
if (top.style != BorderStyle.none) {
distinctVisibleColors.add(top.color);
}
if (end.style != BorderStyle.none) {
distinctVisibleColors.add(end.color);
}
if (bottom.style != BorderStyle.none) {
distinctVisibleColors.add(bottom.color);
}
if (start.style != BorderStyle.none) {
distinctVisibleColors.add(start.color);
}
return distinctVisibleColors;
return <Color>{
if (top.style != BorderStyle.none) top.color,
if (end.style != BorderStyle.none) end.color,
if (bottom.style != BorderStyle.none) bottom.color,
if (start.style != BorderStyle.none) start.color,
};
}

View File

@ -1260,19 +1260,13 @@ class RenderTable extends RenderBox {
return <DiagnosticsNode>[DiagnosticsNode.message('table is empty')];
}
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
for (int y = 0; y < rows; y += 1) {
for (int x = 0; x < columns; x += 1) {
final int xy = x + y * columns;
final RenderBox? child = _children[xy];
final String name = 'child ($x, $y)';
if (child != null) {
children.add(child.toDiagnosticsNode(name: name));
} else {
children.add(DiagnosticsProperty<Object>(name, null, ifNull: 'is null', showSeparator: false));
}
}
}
return children;
return <DiagnosticsNode>[
for (int y = 0; y < rows; y += 1)
for (int x = 0; x < columns; x += 1)
if (_children[x + y * columns] case final RenderBox child)
child.toDiagnosticsNode(name: 'child ($x, $y)')
else
DiagnosticsProperty<Object>('child ($x, $y)', null, ifNull: 'is null', showSeparator: false),
];
}
}

View File

@ -205,20 +205,15 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
// This is run in another isolate created by _addLicenses above.
static List<LicenseEntry> _parseLicenses(String rawLicenses) {
final String licenseSeparator = '\n${'-' * 80}\n';
final List<LicenseEntry> result = <LicenseEntry>[];
final List<String> licenses = rawLicenses.split(licenseSeparator);
for (final String license in licenses) {
final int split = license.indexOf('\n\n');
if (split >= 0) {
result.add(LicenseEntryWithLineBreaks(
license.substring(0, split).split('\n'),
license.substring(split + 2),
));
} else {
result.add(LicenseEntryWithLineBreaks(const <String>[], license));
}
}
return result;
return <LicenseEntry>[
for (final String license in rawLicenses.split(licenseSeparator))
if (license.indexOf('\n\n') case final int split when split >= 0)
LicenseEntryWithLineBreaks(
license.substring(0, split).split('\n'),
license.substring(split + 2),
)
else LicenseEntryWithLineBreaks(const <String>[], license),
];
}
@override

View File

@ -625,14 +625,13 @@ class HardwareKeyboard {
}
List<String> _debugPressedKeysDetails() {
if (_pressedKeys.isEmpty) {
return <String>['Empty'];
}
final List<String> details = <String>[];
for (final PhysicalKeyboardKey physicalKey in _pressedKeys.keys) {
details.add('$physicalKey: ${_pressedKeys[physicalKey]}');
}
return details;
return <String>[
if (_pressedKeys.isEmpty)
'Empty'
else
for (final PhysicalKeyboardKey physicalKey in _pressedKeys.keys)
'$physicalKey: ${_pressedKeys[physicalKey]}',
];
}
/// Process a new [KeyEvent] by recording the state changes and dispatching

View File

@ -180,20 +180,13 @@ class DefaultSpellCheckService implements SpellCheckService {
return null;
}
List<SuggestionSpan> suggestionSpans = <SuggestionSpan>[];
for (final dynamic result in rawResults) {
final Map<String, dynamic> resultMap =
Map<String,dynamic>.from(result as Map<dynamic, dynamic>);
suggestionSpans.add(
List<SuggestionSpan> suggestionSpans = <SuggestionSpan>[
for (final Map<dynamic, dynamic> resultMap in rawResults.cast<Map<dynamic, dynamic>>())
SuggestionSpan(
TextRange(
start: resultMap['startIndex'] as int,
end: resultMap['endIndex'] as int),
(resultMap['suggestions'] as List<dynamic>).cast<String>(),
)
);
}
TextRange(start: resultMap['startIndex'] as int, end: resultMap['endIndex'] as int),
(resultMap['suggestions'] as List<Object?>).cast<String>(),
),
];
if (lastSavedResults != null) {
// Merge current and previous spell check results if between requests,

View File

@ -1894,14 +1894,11 @@ class TextInput {
TextInput._instance._updateEditingValue(value, exclude: _PlatformTextInputControl.instance);
case 'TextInputClient.updateEditingStateWithDeltas':
assert(_currentConnection!._client is DeltaTextInputClient, 'You must be using a DeltaTextInputClient if TextInputConfiguration.enableDeltaModel is set to true');
final List<TextEditingDelta> deltas = <TextEditingDelta>[];
final Map<String, dynamic> encoded = args[1] as Map<String, dynamic>;
for (final dynamic encodedDelta in encoded['deltas'] as List<dynamic>) {
final TextEditingDelta delta = TextEditingDelta.fromJSON(encodedDelta as Map<String, dynamic>);
deltas.add(delta);
}
final List<TextEditingDelta> deltas = <TextEditingDelta>[
for (final dynamic encodedDelta in encoded['deltas'] as List<dynamic>)
TextEditingDelta.fromJSON(encodedDelta as Map<String, dynamic>)
];
(_currentConnection!._client as DeltaTextInputClient).updateEditingValueWithDeltas(deltas);
case 'TextInputClient.performAction':

View File

@ -6686,16 +6686,11 @@ class MouseRegion extends SingleChildRenderObjectWidget {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
final List<String> listeners = <String>[];
if (onEnter != null) {
listeners.add('enter');
}
if (onExit != null) {
listeners.add('exit');
}
if (onHover != null) {
listeners.add('hover');
}
final List<String> listeners = <String>[
if (onEnter != null) 'enter',
if (onExit != null) 'exit',
if (onHover != null) 'hover',
];
properties.add(IterableProperty<String>('listeners', listeners, ifEmpty: '<none>'));
properties.add(DiagnosticsProperty<MouseCursor>('cursor', cursor, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('opaque', opaque, defaultValue: true));
@ -7573,12 +7568,10 @@ class KeyedSubtree extends StatelessWidget {
return items;
}
final List<Widget> itemsWithUniqueKeys = <Widget>[];
int itemIndex = baseIndex;
for (final Widget item in items) {
itemsWithUniqueKeys.add(KeyedSubtree.wrap(item, itemIndex));
itemIndex += 1;
}
final List<Widget> itemsWithUniqueKeys = <Widget>[
for (final (int i, Widget item) in items.indexed)
KeyedSubtree.wrap(item, baseIndex + i),
];
assert(!debugItemsHaveDuplicateKeys(itemsWithUniqueKeys));
return itemsWithUniqueKeys;

View File

@ -909,17 +909,12 @@ class _DragAvatar<T extends Object> extends Drag {
Iterable<_DragTargetState<Object>> _getDragTargets(Iterable<HitTestEntry> path) {
// Look for the RenderBoxes that corresponds to the hit target (the hit target
// widgets build RenderMetaData boxes for us for this purpose).
final List<_DragTargetState<Object>> targets = <_DragTargetState<Object>>[];
for (final HitTestEntry entry in path) {
final HitTestTarget target = entry.target;
if (target is RenderMetaData) {
final dynamic metaData = target.metaData;
if (metaData is _DragTargetState && metaData.isExpectedDataType(data, T)) {
targets.add(metaData);
}
}
}
return targets;
return <_DragTargetState<Object>>[
for (final HitTestEntry entry in path)
if (entry.target case final RenderMetaData target)
if (target.metaData case final _DragTargetState<Object> metaData)
if (metaData.isExpectedDataType(data, T)) metaData,
];
}
void _leaveAllEntered() {

View File

@ -2035,15 +2035,11 @@ class _HighlightModeManager {
// Check to see if any of the early handlers handle the key. If so, then
// return early.
if (_earlyKeyEventHandlers.isNotEmpty) {
final List<KeyEventResult> results = <KeyEventResult>[];
// Copy the list before iteration to prevent problems if the list gets
// modified during iteration.
final List<OnKeyEventCallback> iterationList = _earlyKeyEventHandlers.toList();
for (final OnKeyEventCallback callback in iterationList) {
for (final KeyEvent event in message.events) {
results.add(callback(event));
}
}
final List<KeyEventResult> results = <KeyEventResult>[
// Make a copy to prevent problems if the list is modified during iteration.
for (final OnKeyEventCallback callback in _earlyKeyEventHandlers.toList())
for (final KeyEvent event in message.events) callback(event),
];
final KeyEventResult result = combineKeyEventResults(results);
switch (result) {
case KeyEventResult.ignored:
@ -2067,15 +2063,13 @@ class _HighlightModeManager {
FocusManager.instance.primaryFocus!,
...FocusManager.instance.primaryFocus!.ancestors,
]) {
final List<KeyEventResult> results = <KeyEventResult>[];
if (node.onKeyEvent != null) {
for (final KeyEvent event in message.events) {
results.add(node.onKeyEvent!(node, event));
}
}
if (node.onKey != null && message.rawEvent != null) {
results.add(node.onKey!(node, message.rawEvent!));
}
final List<KeyEventResult> results = <KeyEventResult>[
if (node.onKeyEvent != null)
for (final KeyEvent event in message.events)
node.onKeyEvent!(node, event),
if (node.onKey != null && message.rawEvent != null)
node.onKey!(node, message.rawEvent!),
];
final KeyEventResult result = combineKeyEventResults(results);
switch (result) {
case KeyEventResult.ignored:
@ -2095,15 +2089,11 @@ class _HighlightModeManager {
// Check to see if any late key event handlers want to handle the event.
if (!handled && _lateKeyEventHandlers.isNotEmpty) {
final List<KeyEventResult> results = <KeyEventResult>[];
// Copy the list before iteration to prevent problems if the list gets
// modified during iteration.
final List<OnKeyEventCallback> iterationList = _lateKeyEventHandlers.toList();
for (final OnKeyEventCallback callback in iterationList) {
for (final KeyEvent event in message.events) {
results.add(callback(event));
}
}
final List<KeyEventResult> results = <KeyEventResult>[
// Make a copy to prevent problems if the list is modified during iteration.
for (final OnKeyEventCallback callback in _lateKeyEventHandlers.toList())
for (final KeyEvent event in message.events) callback(event),
];
final KeyEventResult result = combineKeyEventResults(results);
switch (result) {
case KeyEventResult.ignored:

View File

@ -3194,14 +3194,11 @@ class BuildOwner {
keyStringCount[key] = 1;
}
}
final List<String> keyLabels = <String>[];
keyStringCount.forEach((String key, int count) {
if (count == 1) {
keyLabels.add(key);
} else {
keyLabels.add('$key ($count different affected keys had this toString representation)');
}
});
final List<String> keyLabels = <String>[
for (final MapEntry<String, int>(:String key, value: int count) in keyStringCount.entries)
if (count == 1) key
else '$key ($count different affected keys had this toString representation)',
];
final Iterable<Element> elements = _debugElementsThatWillNeedToBeRebuiltDueToGlobalKeyShenanigans!.keys;
final Map<String, int> elementStringCount = HashMap<String, int>();
for (final String element in elements.map<String>((Element element) => element.toString())) {
@ -3211,14 +3208,11 @@ class BuildOwner {
elementStringCount[element] = 1;
}
}
final List<String> elementLabels = <String>[];
elementStringCount.forEach((String element, int count) {
if (count == 1) {
elementLabels.add(element);
} else {
elementLabels.add('$element ($count different affected elements had this toString representation)');
}
});
final List<String> elementLabels = <String>[
for (final MapEntry<String, int>(key: String element, value: int count) in elementStringCount.entries)
if (count == 1) element
else '$element ($count different affected elements had this toString representation)',
];
assert(keyLabels.isNotEmpty);
final String the = keys.length == 1 ? ' the' : '';
final String s = keys.length == 1 ? '' : 's';

View File

@ -666,22 +666,12 @@ class PlatformMenuItemGroup extends PlatformMenuItem {
PlatformMenuDelegate delegate, {
required MenuItemSerializableIdGenerator getId,
}) {
final List<Map<String, Object?>> result = <Map<String, Object?>>[];
result.add(<String, Object?>{
_kIdKey: getId(group),
_kIsDividerKey: true,
});
for (final PlatformMenuItem item in group.members) {
result.addAll(item.toChannelRepresentation(
delegate,
getId: getId,
));
}
result.add(<String, Object?>{
_kIdKey: getId(group),
_kIsDividerKey: true,
});
return result;
return <Map<String, Object?>>[
<String, Object?>{_kIdKey: getId(group), _kIsDividerKey: true},
for (final PlatformMenuItem item in group.members)
...item.toChannelRepresentation(delegate, getId: getId),
<String, Object?>{_kIdKey: getId(group), _kIsDividerKey: true},
];
}
@override

View File

@ -729,13 +729,10 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
AxisDirection.right => (SemanticsAction.scrollLeft, SemanticsAction.scrollRight),
};
final Set<SemanticsAction> actions = <SemanticsAction>{};
if (pixels > minScrollExtent) {
actions.add(backward);
}
if (pixels < maxScrollExtent) {
actions.add(forward);
}
final Set<SemanticsAction> actions = <SemanticsAction>{
if (pixels > minScrollExtent) backward,
if (pixels < maxScrollExtent) forward,
};
if (setEquals<SemanticsAction>(actions, _semanticActions)) {
return;

View File

@ -2350,23 +2350,22 @@ class _HorizontalInnerDimensionState extends ScrollableState {
ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
RenderObject? targetRenderObject,
}) {
final List<Future<void>> newFutures = <Future<void>>[];
newFutures.add(position.ensureVisible(
object,
alignment: alignment,
duration: duration,
curve: curve,
alignmentPolicy: alignmentPolicy,
));
newFutures.add(verticalScrollable.position.ensureVisible(
object,
alignment: alignment,
duration: duration,
curve: curve,
alignmentPolicy: alignmentPolicy,
));
final List<Future<void>> newFutures = <Future<void>>[
position.ensureVisible(
object,
alignment: alignment,
duration: duration,
curve: curve,
alignmentPolicy: alignmentPolicy,
),
verticalScrollable.position.ensureVisible(
object,
alignment: alignment,
duration: duration,
curve: curve,
alignmentPolicy: alignmentPolicy,
),
];
return (newFutures, verticalScrollable);
}

View File

@ -2213,13 +2213,10 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai
/// Copies the selected contents of all [Selectable]s.
@override
SelectedContent? getSelectedContent() {
final List<SelectedContent> selections = <SelectedContent>[];
for (final Selectable selectable in selectables) {
final SelectedContent? data = selectable.getSelectedContent();
if (data != null) {
selections.add(data);
}
}
final List<SelectedContent> selections = <SelectedContent>[
for (final Selectable selectable in selectables)
if (selectable.getSelectedContent() case final SelectedContent data) data,
];
if (selections.isEmpty) {
return null;
}

View File

@ -254,18 +254,14 @@ class RenderTapRegionSurface extends RenderProxyBoxWithHitTestBehavior implement
// groups of regions that were not hit.
final Set<RenderTapRegion> hitRegions =
_getRegionsHit(_registeredRegions, result.path).cast<RenderTapRegion>().toSet();
final Set<RenderTapRegion> insideRegions = <RenderTapRegion>{};
assert(_tapRegionDebug('Tap event hit ${hitRegions.length} descendants.'));
for (final RenderTapRegion region in hitRegions) {
if (region.groupId == null) {
insideRegions.add(region);
continue;
}
// Add all grouped regions to the insideRegions so that groups act as a
// single region.
insideRegions.addAll(_groupIdToRegions[region.groupId]!);
}
final Set<RenderTapRegion> insideRegions = <RenderTapRegion>{
for (final RenderTapRegion region in hitRegions)
if (region.groupId == null) region
// Adding all grouped regions, so they act as a single region.
else ..._groupIdToRegions[region.groupId]!,
};
// If they're not inside, then they're outside.
final Set<RenderTapRegion> outsideRegions = _registeredRegions.difference(insideRegions);
@ -292,15 +288,12 @@ class RenderTapRegionSurface extends RenderProxyBoxWithHitTestBehavior implement
}
// Returns the registered regions that are in the hit path.
Iterable<HitTestTarget> _getRegionsHit(Set<RenderTapRegion> detectors, Iterable<HitTestEntry> hitTestPath) {
final Set<HitTestTarget> hitRegions = <HitTestTarget>{};
for (final HitTestEntry<HitTestTarget> entry in hitTestPath) {
final HitTestTarget target = entry.target;
if (_registeredRegions.contains(target)) {
hitRegions.add(target);
}
}
return hitRegions;
Set<HitTestTarget> _getRegionsHit(Set<RenderTapRegion> detectors, Iterable<HitTestEntry> hitTestPath) {
return <HitTestTarget>{
for (final HitTestEntry<HitTestTarget> entry in hitTestPath)
if (entry.target case final HitTestTarget target)
if (_registeredRegions.contains(target)) target,
};
}
}

View File

@ -699,17 +699,14 @@ class _MultiChildComponentElement extends Element {
@override
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (_childElement != null) {
children.add(_childElement!.toDiagnosticsNode());
}
for (int i = 0; i < _viewElements.length; i++) {
children.add(_viewElements[i].toDiagnosticsNode(
name: 'view ${i + 1}',
style: DiagnosticsTreeStyle.offstage,
));
}
return children;
return <DiagnosticsNode>[
if (_childElement != null) _childElement!.toDiagnosticsNode(),
for (int i = 0; i < _viewElements.length; i++)
_viewElements[i].toDiagnosticsNode(
name: 'view ${i + 1}',
style: DiagnosticsTreeStyle.offstage,
),
];
}
}

View File

@ -960,17 +960,11 @@ mixin WidgetInspectorService {
registerServiceExtension(
name: name,
callback: (Map<String, String> parameters) async {
final List<String> args = <String>[];
int index = 0;
while (true) {
final String name = 'arg$index';
if (parameters.containsKey(name)) {
args.add(parameters[name]!);
} else {
break;
}
index++;
}
int index;
final List<String> args = <String>[
for (index = 0; parameters['arg$index'] != null; index++)
parameters['arg$index']!,
];
// Verify that the only arguments other than perhaps 'isolateId' are
// arguments we have already handled.
assert(index == parameters.length || (index == parameters.length - 1 && parameters.containsKey('isolateId')));
@ -3408,27 +3402,16 @@ class _Location {
final String? name;
Map<String, Object?> toJsonMap() {
final Map<String, Object?> json = <String, Object?>{
return <String, Object?>{
'file': file,
'line': line,
'column': column,
if (name != null) 'name': name,
};
if (name != null) {
json['name'] = name;
}
return json;
}
@override
String toString() {
final List<String> parts = <String>[];
if (name != null) {
parts.add(name!);
}
parts.add(file);
parts..add('$line')..add('$column');
return parts.join(':');
}
String toString() => <String>[if (name != null) name!, file, '$line', '$column'].join(':');
}
bool _isDebugCreator(DiagnosticsNode node) => node is DiagnosticsDebugCreator;

View File

@ -204,12 +204,7 @@ void main() {
// Adding 7 more children overflows onto a third page.
setState(() {
children.add(const TestBox());
children.add(const TestBox());
children.add(const TestBox());
children.add(const TestBox());
children.add(const TestBox());
children.add(const TestBox());
children.addAll(List<TestBox>.filled(6, const TestBox()));
});
await tester.pumpAndSettle();
expect(find.byType(TestBox), findsNWidgets(7));

View File

@ -17,24 +17,15 @@ void main() {
/// Builds test button items for each of the suggestions provided.
List<ContextMenuButtonItem> buildSuggestionButtons(List<String> suggestions) {
final List<ContextMenuButtonItem> buttonItems = <ContextMenuButtonItem>[];
for (final String suggestion in suggestions) {
buttonItems.add(ContextMenuButtonItem(
onPressed: () {},
label: suggestion,
));
}
final ContextMenuButtonItem deleteButton =
return <ContextMenuButtonItem>[
for (final String suggestion in suggestions)
ContextMenuButtonItem(onPressed: () {}, label: suggestion),
ContextMenuButtonItem(
onPressed: () {},
type: ContextMenuButtonType.delete,
label: 'DELETE',
);
buttonItems.add(deleteButton);
return buttonItems;
),
];
}
/// Finds the container of the [SpellCheckSuggestionsToolbar] so that

View File

@ -338,14 +338,10 @@ void main() {
testWidgets('SliverFixedExtentList handles underflow when its children changes', (WidgetTester tester) async {
final List<String> items = <String>['1', '2', '3', '4', '5', '6'];
final List<String> initializedChild = <String>[];
List<Widget> children = <Widget>[];
for (final String item in items) {
children.add(
StateInitSpy(
item, () => initializedChild.add(item), key: ValueKey<String>(item),
),
);
}
List<Widget> children = <Widget>[
for (final String item in items)
StateInitSpy(item, () => initializedChild.add(item), key: ValueKey<String>(item)),
];
final ScrollController controller = ScrollController(initialScrollOffset: 5400);
addTearDown(controller.dispose);

View File

@ -106,16 +106,10 @@ class Response {
/// Create a list of Strings from [_failureDetails].
List<String> _failureDetailsAsString() {
final List<String> list = <String>[];
if (_failureDetails == null || _failureDetails.isEmpty) {
return list;
}
for (final Failure failure in _failureDetails) {
list.add(failure.toJson());
}
return list;
return <String>[
if (_failureDetails != null)
for (final Failure failure in _failureDetails) failure.toJson(),
];
}
/// Creates a [Failure] list using a json response.