diff --git a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart index a22ed55dc59..e5a435d2452 100644 --- a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart +++ b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart @@ -7,15 +7,11 @@ import 'type_analysis_result.dart'; import 'type_operations.dart'; /// Information supplied by the client to [TypeAnalyzer.analyzeSwitchExpression] -/// or [TypeAnalyzer.analyzeSwitchStatement] about a single case head. +/// or [TypeAnalyzer.analyzeSwitchStatement] about a single case head or +/// `default` clause. /// /// The client is free to `implement` or `extend` this class. -class CaseHeadInfo { - /// The AST node for this `case` or `default` clause. This is used for error - /// reporting, in case errors arise from mismatch among the variables bound by - /// various cases that share a body. - final Node node; - +class CaseHeadOrDefaultInfo { /// For a `case` clause, the case pattern. For a `default` clause, `null`. final Node? pattern; @@ -23,36 +19,34 @@ class CaseHeadInfo { /// `when`. Otherwise `null`. final Expression? guard; - CaseHeadInfo({required this.node, required this.pattern, this.guard}); + CaseHeadOrDefaultInfo({required this.pattern, this.guard}); } /// Information supplied by the client to [TypeAnalyzer.analyzeSwitchExpression] /// about an individual `case` or `default` clause. /// /// The client is free to `implement` or `extend` this class. -class ExpressionCaseInfo - extends CaseHeadInfo { - /// The body of the `case` or `default` clause. - final Expression body; +class SwitchExpressionMemberInfo { + /// The [CaseOrDefaultHead] associated with this clause. + final CaseHeadOrDefaultInfo head; - ExpressionCaseInfo( - {required super.node, - required super.pattern, - super.guard, - required this.body}); + /// The body of the `case` or `default` clause. + final Expression expression; + + SwitchExpressionMemberInfo({required this.head, required this.expression}); } /// Information supplied by the client to [TypeAnalyzer.analyzeSwitchStatement] /// about an individual `case` or `default` clause. /// /// The client is free to `implement` or `extend` this class. -class StatementCaseInfo { /// The list of case heads for this case. /// /// The reason this is a list rather than a single head is because the front /// end merges together cases that share a body at parse time. - final List> heads; + final List> heads; /// The labels preceding this `case` or `default` clause, if any. final List labels; @@ -63,7 +57,7 @@ class StatementCaseInfo body; - StatementCaseInfo(this.heads, this.body, {this.labels = const []}); + SwitchStatementMemberInfo(this.heads, this.body, {this.labels = const []}); } /// Type analysis logic to be shared between the analyzer and front end. The @@ -320,11 +314,11 @@ mixin TypeAnalyzer caseInfo = - getExpressionCaseInfo(node, i); + SwitchExpressionMemberInfo memberInfo = + getSwitchExpressionMemberInfo(node, i); flow?.switchStatement_beginCase(); Map> typeInfos = {}; - Node? pattern = caseInfo.pattern; + Node? pattern = memberInfo.head.pattern; if (pattern != null) { dispatchPattern(pattern).match( expressionType, @@ -334,7 +328,7 @@ mixin TypeAnalyzer caseInfo = - getStatementCaseInfo(node, i); - if (caseInfo.labels.isNotEmpty) { + SwitchStatementMemberInfo memberInfo = + getSwitchStatementMemberInfo(node, i); + if (memberInfo.labels.isNotEmpty) { hasLabels = true; } - List> heads = caseInfo.heads; + List> heads = memberInfo.heads; for (int j = 0; j < heads.length; j++) { - CaseHeadInfo head = heads[j]; + CaseHeadOrDefaultInfo head = heads[j]; Node? pattern = head.pattern; if (pattern != null) { dispatchPattern(pattern).match( @@ -429,7 +423,7 @@ mixin TypeAnalyzer getExpressionCaseInfo( + SwitchExpressionMemberInfo getSwitchExpressionMemberInfo( Expression node, int index); /// Returns a [StatementCaseInfo] object describing the [index]th `case` or @@ -569,8 +563,8 @@ mixin TypeAnalyzer getStatementCaseInfo( - Statement node, int caseIndex); + SwitchStatementMemberInfo + getSwitchStatementMemberInfo(Statement node, int caseIndex); /// Called after visiting a merged set of `case` / `default` clauses. /// diff --git a/pkg/_fe_analyzer_shared/test/mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart index a331a3e1c75..b2cafa574c0 100644 --- a/pkg/_fe_analyzer_shared/test/mini_ast.dart +++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart @@ -399,7 +399,9 @@ abstract class Expression extends Node { /// Representation of a single case clause in a switch expression. Use /// [caseExpr] to create instances of this class. class ExpressionCase extends Node - implements ExpressionCaseInfo { + implements + SwitchExpressionMemberInfo, + CaseHeadOrDefaultInfo { @override final Pattern? pattern; @@ -407,26 +409,26 @@ class ExpressionCase extends Node final Expression? guard; @override - final Expression body; + final Expression expression; - ExpressionCase._(this.pattern, this.guard, this.body, + ExpressionCase._(this.pattern, this.guard, this.expression, {required super.location}) : super._(); @override - Node get node => this; + CaseHeadOrDefaultInfo get head => this; String toString() => [ pattern == null ? 'default' : 'case $pattern', if (guard != null) ' when $guard', - ': $body' + ': $expression' ].join(''); void _preVisit(PreVisitor visitor) { var variableBinder = VariableBinder(visitor); pattern?.preVisit(visitor, variableBinder); variableBinder.finish(); - body.preVisit(visitor); + expression.preVisit(visitor); } } @@ -2447,18 +2449,19 @@ class _MiniAstTypeAnalyzer } @override - ExpressionCaseInfo getExpressionCaseInfo( + SwitchExpressionMemberInfo getSwitchExpressionMemberInfo( covariant _SwitchExpression node, int index) => node.cases[index]; @override - StatementCaseInfo getStatementCaseInfo( - covariant _SwitchStatement node, int caseIndex) { + SwitchStatementMemberInfo + getSwitchStatementMemberInfo( + covariant _SwitchStatement node, int caseIndex) { StatementCase case_ = node.cases[caseIndex]; - return StatementCaseInfo([ + return SwitchStatementMemberInfo([ for (var caseHead in case_._caseHeads._caseHeads) - CaseHeadInfo( - node: caseHead, pattern: caseHead._pattern, guard: caseHead._guard) + CaseHeadOrDefaultInfo( + pattern: caseHead._pattern, guard: caseHead._guard) ], case_._body.statements, labels: case_._caseHeads._labels); }