Skip to content

Commit

Permalink
refactor: Avoid nested conditional expressions whenever possible [DCM] (
Browse files Browse the repository at this point in the history
#2784)

I was playing around with the rule avoid-nested-conditional-expressions.
While I philosophically agree with the rule, sadly Dart's new switch-as-an-expression, while a much-needed improvement, still pales in comparison to Kotlin's powerful when, which makes it impossible to convert all cases of nested ternaries into something actually better. In some cases, given the tools that Dart provides, I think nested ternary is the best option.
Notwithstanding, I used the rule to catch many cases where the new switch expression can be used to vastly simplify our codebase, making it much more readable.
  • Loading branch information
luanpotter committed Oct 2, 2023
1 parent 71f7b47 commit 7b6a571
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ class ZigzagEffectController extends DurationEffectController {
// are 3 linear segments: at first it's y = x, for 0 ≤ x ≤ 1, then it's
// y = -x + 2, for 1 ≤ x ≤ 3, and finally it's y = x + (-4), for 3 ≤ x ≤ 4.
final x = timer / _quarterPeriod;
return x <= 1
? x
: x >= 3
? x - 4
: 2 - x;
return switch (x) {
<= 1 => x,
>= 3 => x - 4,
_ => 2 - x,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,12 @@ bool hasMouseDetectors(Game game) {
}

Widget applyMouseDetectors(Game game, Widget child) {
final mouseMoveFn = game is MouseMovementDetector
? game.onMouseMove
// ignore: deprecated_member_use_from_same_package
: (game is HasHoverables ? game.onMouseMove : null);
final mouseMoveFn = switch (game) {
MouseMovementDetector() => game.onMouseMove,
// ignore: deprecated_member_use_from_same_package
HasHoverables() => game.onMouseMove,
_ => null,
};
final mouseDetector = game.mouseDetector;
return Listener(
child: MouseRegion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ void main() {
expect(
ec.progress,
closeTo(
totalTime <= 1
? totalTime
: totalTime <= 3
? (totalTime - 1) / 2
: (totalTime - 3) / 3,
switch (totalTime) {
<= 1 => totalTime,
<= 3 => (totalTime - 1) / 2,
_ => (totalTime - 3) / 3,
},
1e-15,
),
);
Expand All @@ -84,11 +84,11 @@ void main() {
expect(
ec.progress,
closeTo(
totalTime <= 1
? totalTime
: totalTime <= 3
? (totalTime - 1) / 2
: (totalTime - 3) / 3,
switch (totalTime) {
<= 1 => totalTime,
<= 3 => (totalTime - 1) / 2,
_ => (totalTime - 3) / 3,
},
1e-14,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ abstract class Expression {

dynamic get value;

bool get isNumeric => false;
bool get isBoolean => false;
bool get isString => false;
bool get isNumeric => type == ExpressionType.numeric;
bool get isBoolean => type == ExpressionType.boolean;
bool get isString => type == ExpressionType.string;

ExpressionType get type {
return isNumeric
? ExpressionType.numeric
: isBoolean
? ExpressionType.boolean
: isString
? ExpressionType.string
: ExpressionType.unknown;
return switch (this) {
NumExpression() => ExpressionType.numeric,
BoolExpression() => ExpressionType.boolean,
StringExpression() => ExpressionType.string,
_ => ExpressionType.unknown,
};
}
}

Expand All @@ -30,27 +29,18 @@ abstract class NumExpression extends Expression {

@override
num get value;

@override
bool get isNumeric => true;
}

abstract class StringExpression extends Expression {
const StringExpression();

@override
String get value;

@override
bool get isString => true;
}

abstract class BoolExpression extends Expression {
const BoolExpression();

@override
bool get value;

@override
bool get isBoolean => true;
}
30 changes: 15 additions & 15 deletions packages/flame_jenny/jenny/lib/src/variable_storage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ class VariableStorage {

Expression getVariableAsExpression(String name) {
final dynamic value = variables[name];
if (value is String) {
return StringVariable(name, this);
}
if (value is num) {
return NumericVariable(name, this);
}
assert(value is bool);
return BooleanVariable(name, this);
return switch (value) {
String() => StringVariable(name, this),
num() => NumericVariable(name, this),
bool() => BooleanVariable(name, this),
_ => throw DialogueError(
'Cannot convert variable $name with type ${value.runtimeType} to '
'an expression',
),
};
}

ExpressionType getVariableType(String name) {
final dynamic value = variables[name];
return value is String
? ExpressionType.string
: value is num
? ExpressionType.numeric
: value is bool
? ExpressionType.boolean
: ExpressionType.unknown;
return switch (value) {
String() => ExpressionType.string,
num() => ExpressionType.numeric,
bool() => ExpressionType.boolean,
_ => ExpressionType.unknown,
};
}

void setVariable(String name, dynamic value) {
Expand Down

0 comments on commit 7b6a571

Please sign in to comment.