Skip to content

Commit

Permalink
Implementing null-aware operators throughout the repository (#143804)
Browse files Browse the repository at this point in the history
This pull request fixes #143803 by taking advantage of Dart's null-aware operators.

And unlike `switch` expressions ([9 PRs](flutter/flutter#143634) and counting), the Flutter codebase is already fantastic when it comes to null-aware coding. After refactoring the entire repo, all the changes involving `?.` and `??` can fit into a single pull request.
  • Loading branch information
nate-thegrate authored Feb 23, 2024
1 parent 39585e6 commit c53a18f
Show file tree
Hide file tree
Showing 55 changed files with 93 additions and 365 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,7 @@ Iterable<InlineSpanSemanticsInformation> combineSemanticsInfoSyncStar(List<Inlin
workingText += info.text;
workingLabel ??= '';
final String? infoSemanticsLabel = info.semanticsLabel;
if (infoSemanticsLabel != null) {
workingLabel += infoSemanticsLabel;
} else {
workingLabel += info.text;
}
workingLabel += infoSemanticsLabel ?? info.text;
}
}
assert(workingLabel != null);
Expand All @@ -115,11 +111,7 @@ Iterable<InlineSpanSemanticsInformation> combineSemanticsInfoList(List<InlineSpa
workingText += info.text;
workingLabel ??= '';
final String? infoSemanticsLabel = info.semanticsLabel;
if (infoSemanticsLabel != null) {
workingLabel += infoSemanticsLabel;
} else {
workingLabel += info.text;
}
workingLabel += infoSemanticsLabel ?? info.text;
}
}
assert(workingLabel != null);
Expand Down
11 changes: 2 additions & 9 deletions dev/bots/tool_subsharding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,13 @@ class TestSpecs {
int startTime;
int? _endTime;

int get milliseconds {
return endTime - startTime;
}
int get milliseconds => endTime - startTime;

set endTime(int value) {
_endTime = value;
}

int get endTime {
if (_endTime == null) {
return 0;
}
return _endTime!;
}
int get endTime => _endTime ?? 0;

String toJson() {
return json.encode(
Expand Down
11 changes: 4 additions & 7 deletions dev/conductor/core/lib/src/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,10 @@ class Version {
int nextZ = previousVersion.z;
int? nextM = previousVersion.m;
int? nextN = previousVersion.n;
if (nextVersionType == null) {
if (previousVersion.type == VersionType.latest || previousVersion.type == VersionType.gitDescribe) {
nextVersionType = VersionType.development;
} else {
nextVersionType = previousVersion.type;
}
}
nextVersionType ??= switch (previousVersion.type) {
VersionType.stable => VersionType.stable,
VersionType.latest || VersionType.gitDescribe || VersionType.development => VersionType.development,
};

switch (increment) {
case 'x':
Expand Down
6 changes: 1 addition & 5 deletions dev/devicelab/bin/tasks/flavors_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ Future<void> main() async {
final TaskResult? firstInstallFailure = testResults
.firstWhereOrNull((TaskResult element) => element.failed);

if (firstInstallFailure != null) {
return firstInstallFailure;
}

return TaskResult.success(null);
return firstInstallFailure ?? TaskResult.success(null);
},
);

Expand Down
6 changes: 1 addition & 5 deletions dev/devicelab/bin/tasks/flavors_test_ios.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ Future<void> main() async {
final TaskResult? firstInstallFailure = testResults
.firstWhereOrNull((TaskResult element) => element.failed);

if (firstInstallFailure != null) {
return firstInstallFailure;
}

return TaskResult.success(null);
return firstInstallFailure ?? TaskResult.success(null);
},
);

Expand Down
7 changes: 1 addition & 6 deletions dev/devicelab/lib/framework/browser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -572,12 +572,7 @@ class BlinkTraceEvent {
/// Returns null if the value is null.
int? _readInt(Map<String, dynamic> json, String key) {
final num? jsonValue = json[key] as num?;

if (jsonValue == null) {
return null;
}

return jsonValue.toInt();
return jsonValue?.toInt();
}

/// Used by [Chrome.launch] to detect a glibc bug and retry launching the
Expand Down
6 changes: 1 addition & 5 deletions dev/devicelab/lib/tasks/perf_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1290,11 +1290,7 @@ class PerfTest {
}) {
return inDirectory<TaskResult>(testDirectory, () async {
late Device selectedDevice;
if (device != null) {
selectedDevice = device!;
} else {
selectedDevice = await devices.workingDevice;
}
selectedDevice = device ?? await devices.workingDevice;
await selectedDevice.unlock();
final String deviceId = selectedDevice.deviceId;
final String? localEngine = localEngineFromEnv;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,7 @@ class _AndroidSemanticsMatcher extends Matcher {
Description describeMismatch(dynamic item, Description mismatchDescription,
Map<dynamic, dynamic> matchState, bool verbose) {
final String? failure = matchState['failure'] as String?;
if (failure == null) {
return mismatchDescription.add('hasAndroidSemantics matcher does not complete successfully');
}
return mismatchDescription.add(failure);
return mismatchDescription.add(failure ?? 'hasAndroidSemantics matcher does not complete successfully');
}

bool _failWithMessage(String value, Map<dynamic, dynamic> matchState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,8 @@ class AppStateModel extends Model {

// Adds a product to the cart.
void addProductToCart(int productId) {
final int? value = _productsInCart[productId];
if (value == null) {
_productsInCart[productId] = 1;
} else {
_productsInCart[productId] = value+1;
}
final int value = _productsInCart[productId] ?? 0;
_productsInCart[productId] = value + 1;

notifyListeners();
}
Expand Down
4 changes: 1 addition & 3 deletions dev/tools/gen_defaults/bin/gen_defaults.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,7 @@ Future<void> main(List<String> args) async {
final Map<String, dynamic> tokenFileTokens = _readTokenFile(tokenFile as File);
final String version = tokenFileTokens['version'] as String;
tokenFileTokens.remove('version');
if (versionMap[version] == null) {
versionMap[version] = List<String>.empty(growable: true);
}
versionMap[version] ??= <String>[];
versionMap[version]!.add(tokenFile.uri.pathSegments.last);

tokens.addAll(tokenFileTokens);
Expand Down
3 changes: 0 additions & 3 deletions packages/flutter/lib/src/cupertino/colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -953,9 +953,6 @@ class CupertinoDynamicColor extends Color with Diagnosticable {
/// * [resolve], which is similar to this function, but returns a
/// non-nullable value, and does not allow a null `resolvable` color.
static Color? maybeResolve(Color? resolvable, BuildContext context) {
if (resolvable == null) {
return null;
}
return (resolvable is CupertinoDynamicColor)
? resolvable.resolveFrom(context)
: resolvable;
Expand Down
6 changes: 2 additions & 4 deletions packages/flutter/lib/src/cupertino/date_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -684,10 +684,8 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {

// Lazily calculate the column width of the column being displayed only.
double _getEstimatedColumnWidth(_PickerColumnType columnType) {
if (estimatedColumnWidths[columnType.index] == null) {
estimatedColumnWidths[columnType.index] =
CupertinoDatePicker._getColumnWidth(columnType, localizations, context, widget.showDayOfWeek);
}
estimatedColumnWidths[columnType.index] ??=
CupertinoDatePicker._getColumnWidth(columnType, localizations, context, widget.showDayOfWeek);

return estimatedColumnWidths[columnType.index]!;
}
Expand Down
5 changes: 1 addition & 4 deletions packages/flutter/lib/src/cupertino/interface_level.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ class CupertinoUserInterfaceLevel extends InheritedWidget {
/// [CupertinoUserInterfaceLevel] encloses the given context.
static CupertinoUserInterfaceLevelData? maybeOf(BuildContext context) {
final CupertinoUserInterfaceLevel? query = context.dependOnInheritedWidgetOfExactType<CupertinoUserInterfaceLevel>();
if (query != null) {
return query._data;
}
return null;
return query?._data;
}

@override
Expand Down
5 changes: 1 addition & 4 deletions packages/flutter/lib/src/foundation/diagnostics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2257,10 +2257,7 @@ class EnumProperty<T extends Enum?> extends DiagnosticsProperty<T> {

@override
String valueToString({ TextTreeConfiguration? parentConfiguration }) {
if (value == null) {
return value.toString();
}
return value!.name;
return value?.name ?? 'null';
}
}

Expand Down
6 changes: 1 addition & 5 deletions packages/flutter/lib/src/foundation/persistent_hash_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,9 @@ class PersistentHashMap<K extends Object, V> {
/// is not in the map.
@pragma('dart2js:as:trust')
V? operator[](K key) {
if (_root == null) {
return null;
}

// Unfortunately can not use unsafeCast<V?>(...) here because it leads
// to worse code generation on VM.
return _root.get(0, key, key.hashCode) as V?;
return _root?.get(0, key, key.hashCode) as V?;
}
}

Expand Down
5 changes: 1 addition & 4 deletions packages/flutter/lib/src/gestures/recognizer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
}

GestureArenaEntry _addPointerToArena(int pointer) {
if (_team != null) {
return _team!.add(pointer, this);
}
return GestureBinding.instance.gestureArena.add(pointer, this);
return _team?.add(pointer, this) ?? GestureBinding.instance.gestureArena.add(pointer, this);
}

/// Causes events related to the given pointer ID to be routed to this recognizer.
Expand Down
6 changes: 2 additions & 4 deletions packages/flutter/lib/src/material/drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -560,10 +560,8 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro

double get _width {
final RenderBox? box = _drawerKey.currentContext?.findRenderObject() as RenderBox?;
if (box != null) {
return box.size.width;
}
return _kWidth; // drawer not being shown currently
// return _kWidth if drawer not being shown currently
return box?.size.width ?? _kWidth;
}

bool _previouslyOpened = false;
Expand Down
5 changes: 1 addition & 4 deletions packages/flutter/lib/src/material/popup_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,7 @@ class _RenderMenuItem extends RenderShiftedBox {

@override
Size computeDryLayout(BoxConstraints constraints) {
if (child == null) {
return Size.zero;
}
return child!.getDryLayout(constraints);
return child?.getDryLayout(constraints) ?? Size.zero;
}

@override
Expand Down
6 changes: 2 additions & 4 deletions packages/flutter/lib/src/material/stepper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,8 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
if (isActive) MaterialState.selected else MaterialState.disabled,
};
final Color? resolvedConnectorColor = widget.connectorColor?.resolve(states);
if (resolvedConnectorColor != null) {
return resolvedConnectorColor;
}
return isActive ? colorScheme.primary : Colors.grey.shade400;

return resolvedConnectorColor ?? (isActive ? colorScheme.primary : Colors.grey.shade400);
}

Widget _buildLine(bool visible, bool isActive) {
Expand Down
8 changes: 1 addition & 7 deletions packages/flutter/lib/src/painting/border_radius.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,7 @@ abstract class BorderRadiusGeometry {
if (visual != null && logical != null) {
return '$visual + $logical';
}
if (visual != null) {
return visual;
}
if (logical != null) {
return logical;
}
return 'BorderRadius.zero';
return visual ?? logical ?? 'BorderRadius.zero';
}

@override
Expand Down
16 changes: 2 additions & 14 deletions packages/flutter/lib/src/painting/borders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -510,13 +510,7 @@ abstract class ShapeBorder {
if (identical(a, b)) {
return a;
}
ShapeBorder? result;
if (b != null) {
result = b.lerpFrom(a, t);
}
if (result == null && a != null) {
result = a.lerpTo(b, t);
}
final ShapeBorder? result = b?.lerpFrom(a, t) ?? a?.lerpTo(b, t);
return result ?? (t < 0.5 ? a : b);
}

Expand Down Expand Up @@ -700,13 +694,7 @@ abstract class OutlinedBorder extends ShapeBorder {
if (identical(a, b)) {
return a;
}
ShapeBorder? result;
if (b != null) {
result = b.lerpFrom(a, t);
}
if (result == null && a != null) {
result = a.lerpTo(b, t);
}
final ShapeBorder? result = b?.lerpFrom(a, t) ?? a?.lerpTo(b, t);
return result as OutlinedBorder? ?? (t < 0.5 ? a : b);
}
}
Expand Down
20 changes: 4 additions & 16 deletions packages/flutter/lib/src/rendering/proxy_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -468,43 +468,31 @@ class RenderAspectRatio extends RenderProxyBox {
if (height.isFinite) {
return height * _aspectRatio;
}
if (child != null) {
return child!.getMinIntrinsicWidth(height);
}
return 0.0;
return child?.getMinIntrinsicWidth(height) ?? 0.0;
}

@override
double computeMaxIntrinsicWidth(double height) {
if (height.isFinite) {
return height * _aspectRatio;
}
if (child != null) {
return child!.getMaxIntrinsicWidth(height);
}
return 0.0;
return child?.getMaxIntrinsicWidth(height) ?? 0.0;
}

@override
double computeMinIntrinsicHeight(double width) {
if (width.isFinite) {
return width / _aspectRatio;
}
if (child != null) {
return child!.getMinIntrinsicHeight(width);
}
return 0.0;
return child?.getMinIntrinsicHeight(width) ?? 0.0;
}

@override
double computeMaxIntrinsicHeight(double width) {
if (width.isFinite) {
return width / _aspectRatio;
}
if (child != null) {
return child!.getMaxIntrinsicHeight(width);
}
return 0.0;
return child?.getMaxIntrinsicHeight(width) ?? 0.0;
}

Size _applyAspectRatio(BoxConstraints constraints) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,7 @@ class DisposableBuildContext<T extends State> {
/// Otherwise, asserts the [_state] is still mounted and returns its context.
BuildContext? get context {
assert(_debugValidate());
if (_state == null) {
return null;
}
return _state!.context;
return _state?.context;
}

/// Called from asserts or tests to determine whether this object is in a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,10 +1039,7 @@ class DraggableScrollableActuator extends StatefulWidget {
/// otherwise.
static bool reset(BuildContext context) {
final _InheritedResetNotifier? notifier = context.dependOnInheritedWidgetOfExactType<_InheritedResetNotifier>();
if (notifier == null) {
return false;
}
return notifier._sendReset();
return notifier?._sendReset() ?? false;
}

@override
Expand Down
5 changes: 1 addition & 4 deletions packages/flutter/lib/src/widgets/navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -578,10 +578,7 @@ abstract class Route<T> {
/// rendered. It is even possible for the route to be active but for the stateful
/// widgets within the route to not be instantiated. See [ModalRoute.maintainState].
bool get isActive {
if (_navigator == null) {
return false;
}
return _navigator!._firstRouteEntryWhereOrNull(_RouteEntry.isRoutePredicate(this))?.isPresent ?? false;
return _navigator?._firstRouteEntryWhereOrNull(_RouteEntry.isRoutePredicate(this))?.isPresent ?? false;
}
}

Expand Down
Loading

0 comments on commit c53a18f

Please sign in to comment.