[cfe] Introduce CatchVariable Kernel AST node

`CatchVariable`s are supposed to be used as parameters of the `catch`
block. In the CL they are emitted under an experimental flag.

Part of https://github.com/dart-lang/sdk/issues/61572

Change-Id: I6a486a63680fb484de7607fdebab8ba9dd975f5b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/482783
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Chloe Stefantsova
2026-02-24 04:01:49 -08:00
committed by Commit Queue
parent 1418cb1b9c
commit cf850ff4cc
18 changed files with 620 additions and 108 deletions
@@ -436,7 +436,6 @@ class PrimaryConstructorFieldDeclaration
}
@override
// Coverage-ignore(suite): Not run.
void setCovariantByClassInternal() {
_encoding.setCovariantByClass();
}
+37 -2
View File
@@ -5813,12 +5813,47 @@ class BodyBuilderImpl extends StackListenerImpl
// Coverage-ignore(suite): Not run.
stackTrace.kind == FormalParameterKind.optionalPositional,
);
CatchVariable? exceptionVariable;
if (exception?.variable
case VariableDeclaration exceptionVariableDeclaration) {
if (isClosureContextLoweringEnabled) {
// Coverage-ignore-block(suite): Not run.
// TODO(62743): Avoid the conversion when [FormalParameterBuilder]
// produces [CatchVariable]s directly.
exceptionVariable = new CatchVariable(
name: exceptionVariableDeclaration.name!,
type: exceptionVariableDeclaration.type,
isWildcard: exceptionVariableDeclaration.isWildcard,
);
} else {
exceptionVariable = exceptionVariableDeclaration;
}
}
CatchVariable? stackTraceVariable;
if (stackTrace?.variable
case VariableDeclaration stackTraceVariableDeclaration) {
if (isClosureContextLoweringEnabled) {
// Coverage-ignore-block(suite): Not run.
// TODO(62743): Avoid the conversion when [FormalParameterBuilder]
// produces [CatchVariable]s directly.
stackTraceVariable = new CatchVariable(
name: stackTraceVariableDeclaration.name!,
type: stackTraceVariableDeclaration.type,
isWildcard: stackTraceVariableDeclaration.isWildcard,
);
} else {
stackTraceVariable = stackTraceVariableDeclaration;
}
}
push(
forest.createCatch(
offsetForToken(onKeyword ?? catchKeyword),
exceptionType,
exception?.variable,
stackTrace?.variable,
exceptionVariable,
stackTraceVariable,
coreTypes.stackTraceRawType(Nullability.nonNullable),
body,
),
+2 -2
View File
@@ -450,8 +450,8 @@ class Forest {
Catch createCatch(
int fileOffset,
DartType exceptionType,
VariableDeclaration? exceptionParameter,
VariableDeclaration? stackTraceParameter,
CatchVariable? exceptionParameter,
CatchVariable? stackTraceParameter,
DartType stackTraceType,
Statement body,
) {
+48 -8
View File
@@ -1075,10 +1075,6 @@ class InternalPositionalParameter extends TreeNode
@override
final bool isLocalFunction;
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? contexts;
InternalPositionalParameter({
required this.astVariable,
required this.isImplicitlyTyped,
@@ -1086,6 +1082,30 @@ class InternalPositionalParameter extends TreeNode
this.isLocalFunction = false,
});
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? get contexts {
throw new UnsupportedError("${this.runtimeType}.contexts");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set contexts(List<VariableContext>? value) {
throw new UnsupportedError("${this.runtimeType}.contexts=");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
String get catchVariableName {
throw new UnsupportedError("${this.runtimeType}.catchVariableName");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set catchVariableName(String value) {
throw new UnsupportedError("${this.runtimeType}.catchVariableName=");
}
@override
R accept<R>(StatementVisitor<R> v) => v.visitPositionalParameter(astVariable);
@@ -1170,10 +1190,6 @@ class InternalNamedParameter extends TreeNode
@override
final bool isLocalFunction;
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? contexts;
InternalNamedParameter({
required this.astVariable,
required this.isImplicitlyTyped,
@@ -1181,6 +1197,30 @@ class InternalNamedParameter extends TreeNode
this.isLocalFunction = false,
});
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? get contexts {
throw new UnsupportedError("${this.runtimeType}.contexts");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set contexts(List<VariableContext>? value) {
throw new UnsupportedError("${this.runtimeType}.contexts=");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
String get catchVariableName {
throw new UnsupportedError("${this.runtimeType}.catchVariableName");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set catchVariableName(String value) {
throw new UnsupportedError("${this.runtimeType}.catchVariableName=");
}
@override
R accept<R>(StatementVisitor<R> v) => v.visitNamedParameter(astVariable);
@@ -1112,7 +1112,6 @@ extension CheckHelper on ProblemReporting {
nameToken.length,
);
} else {
// Coverage-ignore-block(suite): Not run.
addProblem(
diag.privateNamedParameter,
nameToken.charOffset,
@@ -3269,7 +3269,6 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
case ObjectAccessTargetKind.nullableInstanceMember:
kind = InstanceAccessKind.Nullable;
break;
// Coverage-ignore(suite): Not run.
case ObjectAccessTargetKind.objectMember:
kind = InstanceAccessKind.Object;
break;
@@ -3392,9 +3391,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
)..fileOffset = nullAwareAction.fileOffset,
);
} else if (nullAwareAction is DynamicInvocation &&
// Coverage-ignore(suite): Not run.
nullAwareAction.receiver == originalPropertyGet) {
// Coverage-ignore-block(suite): Not run.
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
new InstanceGetterInvocation(
@@ -2346,6 +2346,7 @@ popping
pops
populate
populated
populating
port
portion
position
+2 -2
View File
@@ -134,8 +134,8 @@ const Map<String?, Map<String, FieldRule?>> _fieldRuleMap = {
'SwitchStatement': {'cases': FieldRule(isDeclaration: true)},
'ContinueSwitchStatement': {'target': FieldRule(isDeclaration: false)},
'Catch': {
'exception': FieldRule(isDeclaration: true),
'stackTrace': FieldRule(isDeclaration: true),
'exceptionCatchVariable': FieldRule(isDeclaration: true),
'stackTraceCatchVariable': FieldRule(isDeclaration: true),
},
'FunctionDeclaration': {'variable': FieldRule(isDeclaration: true)},
'FunctionType': {'typeParameters': FieldRule(isDeclaration: true)},
+8
View File
@@ -374,6 +374,14 @@ final List<MapPatternEntry> emptyListOfMapPatternEntry =
final VariableDeclaration dummyVariableDeclaration =
new VariableDeclaration(null, isSynthesized: true);
/// Non-nullable [CatchVariable] dummy value.
///
/// This is used as the removal sentinel in [RemovingTransformer] and can be
/// used for instance as a dummy initial value for the `List.filled`
/// constructor.
final CatchVariable dummyCatchVariable =
new CatchVariable(name: "#dummy-catch-variable", type: const DynamicType());
/// Non-nullable [PositionalParameter] dummy value.
///
/// This is used as the removal sentinel in [RemovingTransformer] and can be
+3 -3
View File
@@ -188,9 +188,6 @@ class InvalidExpression extends Expression {
}
class VariableGet extends Expression {
/// The target variable as [VariableDeclaration].
VariableDeclaration get variable => expressionVariable as VariableDeclaration;
/// The target variable.
ExpressionVariable expressionVariable;
@@ -199,6 +196,9 @@ class VariableGet extends Expression {
VariableGet(this.expressionVariable, [this.promotedType]);
/// The target variable as [VariableDeclaration].
VariableDeclaration get variable => expressionVariable as VariableDeclaration;
@override
DartType getStaticType(StaticTypeContext context) =>
getStaticTypeInternal(context);
+63 -25
View File
@@ -1195,20 +1195,35 @@ class TryCatch extends Statement {
class Catch extends TreeNode implements ScopeProvider {
DartType guard; // Not null, defaults to dynamic.
VariableDeclaration? exception;
VariableDeclaration? stackTrace;
CatchVariable? exceptionCatchVariable;
CatchVariable? stackTraceCatchVariable;
Statement body;
@override
Scope? scope;
Catch(this.exception, this.body,
{this.guard = const DynamicType(), this.stackTrace}) {
exception?.parent = this;
stackTrace?.parent = this;
Catch(this.exceptionCatchVariable, this.body,
{this.guard = const DynamicType(), CatchVariable? stackTrace})
: stackTraceCatchVariable = stackTrace {
exceptionCatchVariable?.parent = this;
stackTraceCatchVariable?.parent = this;
body.parent = this;
}
VariableDeclaration? get exception =>
exceptionCatchVariable as VariableDeclaration?;
void set exception(VariableDeclaration? value) {
exceptionCatchVariable = value;
}
VariableDeclaration? get stackTrace =>
stackTraceCatchVariable as VariableDeclaration?;
void set stackTrace(VariableDeclaration? value) {
stackTraceCatchVariable = value;
}
@override
R accept<R>(TreeVisitor<R> v) => v.visitCatch(this);
@@ -1218,21 +1233,21 @@ class Catch extends TreeNode implements ScopeProvider {
@override
void visitChildren(Visitor v) {
guard.accept(v);
exception?.accept(v);
stackTrace?.accept(v);
exceptionCatchVariable?.accept(v);
stackTraceCatchVariable?.accept(v);
body.accept(v);
}
@override
void transformChildren(Transformer v) {
guard = v.visitDartType(guard);
if (exception != null) {
exception = v.transform(exception!);
exception?.parent = this;
if (exceptionCatchVariable != null) {
exceptionCatchVariable = v.transform(exceptionCatchVariable!);
exceptionCatchVariable?.parent = this;
}
if (stackTrace != null) {
stackTrace = v.transform(stackTrace!);
stackTrace?.parent = this;
if (stackTraceCatchVariable != null) {
stackTraceCatchVariable = v.transform(stackTraceCatchVariable!);
stackTraceCatchVariable?.parent = this;
}
body = v.transform(body);
body.parent = this;
@@ -1241,13 +1256,15 @@ class Catch extends TreeNode implements ScopeProvider {
@override
void transformOrRemoveChildren(RemovingTransformer v) {
guard = v.visitDartType(guard, cannotRemoveSentinel);
if (exception != null) {
exception = v.transformOrRemoveVariableDeclaration(exception!);
exception?.parent = this;
if (exceptionCatchVariable != null) {
exceptionCatchVariable =
v.transformOrRemoveCatchVariable(exceptionCatchVariable!);
exceptionCatchVariable?.parent = this;
}
if (stackTrace != null) {
stackTrace = v.transformOrRemoveVariableDeclaration(stackTrace!);
stackTrace?.parent = this;
if (stackTraceCatchVariable != null) {
stackTraceCatchVariable =
v.transformOrRemoveCatchVariable(stackTraceCatchVariable!);
stackTraceCatchVariable?.parent = this;
}
body = v.transform(body);
body.parent = this;
@@ -1425,7 +1442,8 @@ abstract interface class VariableDeclaration
Annotatable,
Statement,
ExpressionVariable,
VariableInitialization {
VariableInitialization,
CatchVariable {
/// The name of the variable as provided in the source code.
///
/// The name of a variable can only be omitted if the variable is synthesized.
@@ -1634,10 +1652,6 @@ class VariableStatement extends Statement implements VariableDeclaration {
@override
Expression? initializer; // May be null.
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? contexts;
VariableStatement(this._name,
{this.initializer,
this.type = const DynamicType(),
@@ -1707,6 +1721,30 @@ class VariableStatement extends Statement implements VariableDeclaration {
_name = value;
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? get contexts {
throw new UnsupportedError("${this.runtimeType}.contexts");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set contexts(List<VariableContext>? value) {
throw new UnsupportedError("${this.runtimeType}.contexts=");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
String get catchVariableName {
throw new UnsupportedError("${this.runtimeType}.catchVariableName");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set catchVariableName(String value) {
throw new UnsupportedError("${this.runtimeType}.catchVariableName=");
}
static const int FlagFinal = 1 << 0; // Must match serialized bit positions.
static const int FlagConst = 1 << 1;
static const int FlagHasDeclaredInitializer = 1 << 2;
+324 -8
View File
@@ -411,6 +411,282 @@ class LocalVariable extends ExpressionVariable {
bool get hasIsErroneouslyInitialized => false;
}
/// Since the `catch` block isn't invoked by the user code, but is redirected to
/// by the runtime, its parameters, the exception and the stack trace,
/// represented by `e` and `s` in the example below, are filled in by the
/// runtime too. The semantics of populating the variables makes them distinct
/// from function parameters, and they have a separate representation from them.
///
/// try {
/// foo();
/// } catch (e, s) {
/// bar();
/// }
class CatchVariable extends ExpressionVariable {
String catchVariableName;
@override
DartType type;
@override
List<Expression> annotations = const <Expression>[];
CatchVariable({
required String name,
required DartType? type,
bool isWildcard = false,
}) : catchVariableName = name,
type = type ?? const DynamicType() {
this.isWildcard = isWildcard;
}
@override
String? get cosmeticName => catchVariableName;
@override
void set cosmeticName(String? value) {
catchVariableName = value!;
}
@override
VariableInitialization? get variableInitialization {
throw new UnsupportedError("${this.runtimeType}.variableInitialization");
}
@override
void set variableInitialization(VariableInitialization? value) {
throw new UnsupportedError("${this.runtimeType}.variableInitialization=");
}
@override
void addAnnotation(Expression annotation) {
if (annotations.isEmpty) {
annotations = <Expression>[];
}
annotations.add(annotation..parent = this);
}
static const int FlagWildcard = 1 << 0;
@override
bool get isFinal => true;
@override
void set isFinal(bool value) {
throw new UnsupportedError("${this.runtimeType}.isFinal=");
}
@override
bool get isWildcard => flags & FlagWildcard != 0;
@override
void set isWildcard(bool value) {
flags = value ? (flags | FlagWildcard) : (flags & ~FlagWildcard);
}
@override
bool get isConst {
throw new UnsupportedError("${this.runtimeType}.isConst");
}
@override
void set isConst(bool value) {
throw new UnsupportedError("${this.runtimeType}.isConst=");
}
@override
bool get isLate {
throw new UnsupportedError("${this.runtimeType}.isLate");
}
@override
void set isLate(bool value) {
throw new UnsupportedError("${this.runtimeType}.isLate=");
}
@override
bool get isLowered {
throw new UnsupportedError("${this.runtimeType}.isLowered");
}
@override
void set isLowered(bool value) {
throw new UnsupportedError("${this.runtimeType}.isLowered=");
}
@override
bool get isHoisted {
throw new UnsupportedError("${this.runtimeType}.isHoisted");
}
@override
void set isHoisted(bool value) {
throw new UnsupportedError("${this.runtimeType}.isHoisted=");
}
@override
bool get isCovariantByClass {
throw new UnsupportedError("${this.runtimeType}.isCovariantByClass");
}
@override
void set isCovariantByClass(bool value) {
throw new UnsupportedError("${this.runtimeType}.isCovariantByClass=");
}
@override
bool get isCovariantByDeclaration {
throw new UnsupportedError("${this.runtimeType}.isCovariantByDeclaration");
}
@override
void set isCovariantByDeclaration(bool value) {
throw new UnsupportedError("${this.runtimeType}.isCovariantByDeclaration=");
}
@override
bool get isErroneouslyInitialized {
throw new UnsupportedError("${this.runtimeType}.isErroneouslyInitialized");
}
@override
void set isErroneouslyInitialized(bool value) {
throw new UnsupportedError("${this.runtimeType}.isErroneouslyInitialized=");
}
@override
bool get hasDeclaredInitializer {
throw new UnsupportedError("${this.runtimeType}.hasDeclaredInitializer");
}
@override
void set hasDeclaredInitializer(bool value) {
throw new UnsupportedError("${this.runtimeType}.hasDeclaredInitializer=");
}
@override
bool get isInitializingFormal {
throw new UnsupportedError("${this.runtimeType}.isInitializingFormal");
}
@override
void set isInitializingFormal(bool value) {
throw new UnsupportedError("${this.runtimeType}.isInitializingFormal=");
}
@override
bool get isRequired {
throw new UnsupportedError("${this.runtimeType}.isRequired");
}
@override
void set isRequired(bool value) {
throw new UnsupportedError("${this.runtimeType}.isRequired=");
}
@override
bool get isSuperInitializingFormal {
throw new UnsupportedError("${this.runtimeType}.isSuperInitializingFormal");
}
@override
void set isSuperInitializingFormal(bool value) {
throw new UnsupportedError(
"${this.runtimeType}.isSuperInitializingFormal=");
}
@override
bool get isSynthesized {
throw new UnsupportedError("${this.runtimeType}.isSynthesized");
}
@override
void set isSynthesized(bool value) {
throw new UnsupportedError("${this.runtimeType}.isSynthesized=");
}
@override
bool get isAssignable => false;
@override
R accept<R>(TreeVisitor<R> v) => v.visitCatchVariable(this);
@override
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) =>
v.visitCatchVariable(this, arg);
@override
void transformChildren(Transformer v) {}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
@override
void visitChildren(Visitor v) {}
@override
String toString() {
return "CatchVariable(${toStringInternal()})";
}
@override
void toTextInternal(AstPrinter printer) {
printer.writeExpressionVariable(this);
}
@override
Expression? get initializer {
throw new UnsupportedError("${this.runtimeType}.initializer");
}
@override
void set initializer(Expression? value) {
throw new UnsupportedError("${this.runtimeType}.initializer=");
}
@override
bool get hasIsFinal => false;
@override
bool get hasIsConst => false;
@override
bool get hasIsLate => false;
@override
bool get hasIsInitializingFormal => false;
@override
bool get hasIsSynthesized => false;
@override
bool get hasIsHoisted => false;
@override
bool get hasHasDeclaredInitializer => false;
@override
bool get hasIsCovariantByClass => false;
@override
bool get hasIsRequired => false;
@override
bool get hasIsCovariantByDeclaration => false;
@override
bool get hasIsLowered => false;
@override
bool get hasIsWildcard => false;
@override
bool get hasIsSuperInitializingFormal => false;
@override
bool get hasIsErroneouslyInitialized => false;
}
/// Abstract parameter class, the parent for positional and named parameters.
sealed class FunctionParameter extends ExpressionVariable
implements VariableDeclaration {
@@ -621,10 +897,6 @@ class PositionalParameter extends FunctionParameter {
@override
List<Expression> annotations = const <Expression>[];
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? contexts;
PositionalParameter({
this.cosmeticName,
required this.type,
@@ -640,6 +912,30 @@ class PositionalParameter extends FunctionParameter {
super.isWildcard = false,
});
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? get contexts {
throw new UnsupportedError("${this.runtimeType}.contexts");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set contexts(List<VariableContext>? value) {
throw new UnsupportedError("${this.runtimeType}.contexts=");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
String get catchVariableName {
throw new UnsupportedError("${this.runtimeType}.catchVariableName");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set catchVariableName(String value) {
throw new UnsupportedError("${this.runtimeType}.catchVariableName=");
}
@override
void addAnnotation(Expression annotation) {
if (annotations.isEmpty) {
@@ -757,10 +1053,6 @@ class NamedParameter extends FunctionParameter {
@override
List<Expression> annotations = const <Expression>[];
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? contexts;
NamedParameter(
{required this.parameterName,
required this.type,
@@ -775,6 +1067,30 @@ class NamedParameter extends FunctionParameter {
super.isSynthesized = false,
super.isWildcard = false});
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
List<VariableContext>? get contexts {
throw new UnsupportedError("${this.runtimeType}.contexts");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set contexts(List<VariableContext>? value) {
throw new UnsupportedError("${this.runtimeType}.contexts=");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
String get catchVariableName {
throw new UnsupportedError("${this.runtimeType}.catchVariableName");
}
@override
// TODO(62620): Conforming to [VariableDeclaration] interface. Remove this.
void set catchVariableName(String value) {
throw new UnsupportedError("${this.runtimeType}.catchVariableName=");
}
@override
void addAnnotation(Expression annotation) {
if (annotations.isEmpty) {
+7
View File
@@ -992,6 +992,12 @@ class CoverageVisitor implements Visitor<void> {
node.visitChildren(this);
}
@override
void visitCatchVariable(CatchVariable node) {
visited.add(NodeKind.CatchVariable);
node.visitChildren(this);
}
@override
void visitLocalVariable(LocalVariable node) {
visited.add(NodeKind.LocalVariable);
@@ -1327,6 +1333,7 @@ enum ConstantKind {
enum NodeKind {
Arguments,
Catch,
CatchVariable,
Class,
Combinator,
Component,
+86 -53
View File
@@ -850,6 +850,11 @@ class EquivalenceVisitor implements Visitor1<bool, Node> {
return strategy.checkCatch(this, node, other);
}
@override
bool visitCatchVariable(CatchVariable node, Node other) {
return strategy.checkCatchVariable(this, node, other);
}
@override
bool visitLocalVariable(LocalVariable node, Node other) {
return strategy.checkLocalVariable(this, node, other);
@@ -5392,9 +5397,6 @@ class EquivalenceStrategy {
if (!checkVariableStatement_initializer(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableStatement_contexts(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableStatement_fileOffset(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -5451,10 +5453,10 @@ class EquivalenceStrategy {
if (!checkCatch_guard(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatch_exception(visitor, node, other)) {
if (!checkCatch_exceptionCatchVariable(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatch_stackTrace(visitor, node, other)) {
if (!checkCatch_stackTraceCatchVariable(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatch_body(visitor, node, other)) {
@@ -5470,6 +5472,32 @@ class EquivalenceStrategy {
return result;
}
bool checkCatchVariable(
EquivalenceVisitor visitor, CatchVariable? node, Object? other) {
if (identical(node, other)) return true;
if (node is! CatchVariable) return false;
if (other is! CatchVariable) return false;
visitor.pushNodeState(node, other);
bool result = true;
if (!checkCatchVariable_catchVariableName(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatchVariable_type(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatchVariable_annotations(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatchVariable_flags(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkCatchVariable_fileOffset(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
visitor.popState();
return result;
}
bool checkLocalVariable(
EquivalenceVisitor visitor, LocalVariable? node, Object? other) {
if (identical(node, other)) return true;
@@ -5515,9 +5543,6 @@ class EquivalenceStrategy {
if (!checkPositionalParameter_annotations(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkPositionalParameter_contexts(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkPositionalParameter_binaryOffsetNoTag(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -5553,9 +5578,6 @@ class EquivalenceStrategy {
if (!checkNamedParameter_annotations(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkNamedParameter_contexts(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkNamedParameter_binaryOffsetNoTag(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -9902,12 +9924,6 @@ class EquivalenceStrategy {
node.initializer, other.initializer, 'initializer');
}
bool checkVariableStatement_contexts(EquivalenceVisitor visitor,
VariableStatement node, VariableStatement other) {
return visitor.checkLists(
node.contexts, other.contexts, visitor.checkNodes, 'contexts');
}
bool checkVariableStatement_fileOffset(EquivalenceVisitor visitor,
VariableStatement node, VariableStatement other) {
return checkStatement_fileOffset(visitor, node, other);
@@ -9948,14 +9964,16 @@ class EquivalenceStrategy {
return visitor.checkNodes(node.guard, other.guard, 'guard');
}
bool checkCatch_exception(
bool checkCatch_exceptionCatchVariable(
EquivalenceVisitor visitor, Catch node, Catch other) {
return visitor.checkNodes(node.exception, other.exception, 'exception');
return visitor.checkNodes(node.exceptionCatchVariable,
other.exceptionCatchVariable, 'exceptionCatchVariable');
}
bool checkCatch_stackTrace(
bool checkCatch_stackTraceCatchVariable(
EquivalenceVisitor visitor, Catch node, Catch other) {
return visitor.checkNodes(node.stackTrace, other.stackTrace, 'stackTrace');
return visitor.checkNodes(node.stackTraceCatchVariable,
other.stackTraceCatchVariable, 'stackTraceCatchVariable');
}
bool checkCatch_body(EquivalenceVisitor visitor, Catch node, Catch other) {
@@ -9971,6 +9989,53 @@ class EquivalenceStrategy {
return checkTreeNode_fileOffset(visitor, node, other);
}
bool checkCatchVariable_catchVariableName(
EquivalenceVisitor visitor, CatchVariable node, CatchVariable other) {
return visitor.checkValues(
node.catchVariableName, other.catchVariableName, 'catchVariableName');
}
bool checkCatchVariable_type(
EquivalenceVisitor visitor, CatchVariable node, CatchVariable other) {
return visitor.checkNodes(node.type, other.type, 'type');
}
bool checkCatchVariable_annotations(
EquivalenceVisitor visitor, CatchVariable node, CatchVariable other) {
return visitor.checkLists(
node.annotations, other.annotations, visitor.checkNodes, 'annotations');
}
bool checkVariable_flags(
EquivalenceVisitor visitor, Variable node, Variable other) {
return visitor.checkValues(node.flags, other.flags, 'flags');
}
bool checkExpressionVariable_flags(EquivalenceVisitor visitor,
ExpressionVariable node, ExpressionVariable other) {
return checkVariable_flags(visitor, node, other);
}
bool checkCatchVariable_flags(
EquivalenceVisitor visitor, CatchVariable node, CatchVariable other) {
return checkExpressionVariable_flags(visitor, node, other);
}
bool checkVariable_fileOffset(
EquivalenceVisitor visitor, Variable node, Variable other) {
return checkTreeNode_fileOffset(visitor, node, other);
}
bool checkExpressionVariable_fileOffset(EquivalenceVisitor visitor,
ExpressionVariable node, ExpressionVariable other) {
return checkVariable_fileOffset(visitor, node, other);
}
bool checkCatchVariable_fileOffset(
EquivalenceVisitor visitor, CatchVariable node, CatchVariable other) {
return checkExpressionVariable_fileOffset(visitor, node, other);
}
bool checkLocalVariable_cosmeticName(
EquivalenceVisitor visitor, LocalVariable node, LocalVariable other) {
return visitor.checkValues(
@@ -9994,31 +10059,11 @@ class EquivalenceStrategy {
node.annotations, other.annotations, visitor.checkNodes, 'annotations');
}
bool checkVariable_flags(
EquivalenceVisitor visitor, Variable node, Variable other) {
return visitor.checkValues(node.flags, other.flags, 'flags');
}
bool checkExpressionVariable_flags(EquivalenceVisitor visitor,
ExpressionVariable node, ExpressionVariable other) {
return checkVariable_flags(visitor, node, other);
}
bool checkLocalVariable_flags(
EquivalenceVisitor visitor, LocalVariable node, LocalVariable other) {
return checkExpressionVariable_flags(visitor, node, other);
}
bool checkVariable_fileOffset(
EquivalenceVisitor visitor, Variable node, Variable other) {
return checkTreeNode_fileOffset(visitor, node, other);
}
bool checkExpressionVariable_fileOffset(EquivalenceVisitor visitor,
ExpressionVariable node, ExpressionVariable other) {
return checkVariable_fileOffset(visitor, node, other);
}
bool checkLocalVariable_fileOffset(
EquivalenceVisitor visitor, LocalVariable node, LocalVariable other) {
return checkExpressionVariable_fileOffset(visitor, node, other);
@@ -10041,12 +10086,6 @@ class EquivalenceStrategy {
node.annotations, other.annotations, visitor.checkNodes, 'annotations');
}
bool checkPositionalParameter_contexts(EquivalenceVisitor visitor,
PositionalParameter node, PositionalParameter other) {
return visitor.checkLists(
node.contexts, other.contexts, visitor.checkNodes, 'contexts');
}
bool checkPositionalParameter_binaryOffsetNoTag(EquivalenceVisitor visitor,
PositionalParameter node, PositionalParameter other) {
return visitor.checkValues(
@@ -10107,12 +10146,6 @@ class EquivalenceStrategy {
node.annotations, other.annotations, visitor.checkNodes, 'annotations');
}
bool checkNamedParameter_contexts(
EquivalenceVisitor visitor, NamedParameter node, NamedParameter other) {
return visitor.checkLists(
node.contexts, other.contexts, visitor.checkNodes, 'contexts');
}
bool checkNamedParameter_binaryOffsetNoTag(
EquivalenceVisitor visitor, NamedParameter node, NamedParameter other) {
return visitor.checkValues(
+2
View File
@@ -329,6 +329,7 @@ class NodeCreator {
case NodeKind.PatternSwitchCase:
case NodeKind.SwitchExpressionCase:
case NodeKind.LocalVariable:
case NodeKind.CatchVariable:
case NodeKind.PositionalParameter:
case NodeKind.NamedParameter:
case NodeKind.SyntheticVariable:
@@ -1855,6 +1856,7 @@ class NodeCreator {
_createExpression())
..fileOffset = _needFileOffset();
case NodeKind.LocalVariable:
case NodeKind.CatchVariable:
case NodeKind.PositionalParameter:
case NodeKind.NamedParameter:
case NodeKind.SyntheticVariable:
+2
View File
@@ -224,6 +224,8 @@ class AstPrinter {
}
return _variableDeclarationNames[node] ??=
'#${_variableDeclarationNames.length}';
case CatchVariable(catchVariableName: var name):
return name;
}
}
+2
View File
@@ -1193,6 +1193,8 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
writeWord('synthetic-variable');
case VariableDeclaration():
writeWord('variable-declaration');
case CatchVariable():
writeWord('catch-variable');
}
// TODO(cstefantsova): Should [Variable]s have annotations?
+33
View File
@@ -824,6 +824,7 @@ abstract class TreeVisitor<R>
R visitComponent(Component node);
R visitTypeVariable(TypeVariable node);
R visitLocalVariable(LocalVariable node);
R visitCatchVariable(CatchVariable node);
R visitThisVariable(ThisVariable node);
R visitSyntheticVariable(SyntheticVariable node);
R visitVariableContext(VariableContext node);
@@ -887,6 +888,8 @@ mixin TreeVisitorDefaultMixin<R> implements TreeVisitor<R> {
@override
R visitLocalVariable(LocalVariable node) => defaultTreeNode(node);
@override
R visitCatchVariable(CatchVariable node) => defaultTreeNode(node);
@override
R visitThisVariable(ThisVariable node) => defaultTreeNode(node);
@override
R visitSyntheticVariable(SyntheticVariable node) => defaultTreeNode(node);
@@ -958,6 +961,7 @@ abstract class TreeVisitor1<R, A>
R visitComponent(Component node, A arg);
R visitTypeVariable(TypeVariable node, A arg);
R visitLocalVariable(LocalVariable node, A arg);
R visitCatchVariable(CatchVariable node, A arg);
R visitThisVariable(ThisVariable node, A arg);
R visitSyntheticVariable(SyntheticVariable node, A arg);
R visitVariableContext(VariableContext node, A arg);
@@ -1027,6 +1031,8 @@ mixin TreeVisitor1DefaultMixin<R, A> implements TreeVisitor1<R, A> {
@override
R visitLocalVariable(LocalVariable node, A arg) => defaultTreeNode(node, arg);
@override
R visitCatchVariable(CatchVariable node, A arg) => defaultTreeNode(node, arg);
@override
R visitThisVariable(ThisVariable node, A arg) => defaultTreeNode(node, arg);
@override
R visitSyntheticVariable(SyntheticVariable node, A arg) =>
@@ -2245,6 +2251,19 @@ class RemovingTransformer extends TreeVisitor1Default<TreeNode, TreeNode?> {
return transformOrRemove(node, dummyVariableDeclaration);
}
/// Visits [node], returning the transformation result. Removal of [node] is
/// supported with `null` as the result.
///
/// This is convenience method for calling [transformOrRemove] with removal
/// sentinel for [VariableDeclaration] nodes.
CatchVariable? transformOrRemoveCatchVariable(CatchVariable node) {
if (node is VariableDeclaration) {
return transformOrRemoveVariableDeclaration(node);
} else {
return transformOrRemove(node, dummyCatchVariable);
}
}
/// Visits [node] using [removalSentinel] as the removal sentinel.
///
/// If [removalSentinel] is the result of visiting [node], `null` is returned.
@@ -3432,6 +3451,13 @@ mixin TreeVisitorExperimentExclusionMixin<R> implements TreeVisitor<R> {
);
}
@override
R visitCatchVariable(CatchVariable node) {
throw StateError(
"${runtimeType}.visitCatchVariable isn't supported.",
);
}
@override
R visitThisVariable(ThisVariable node) {
throw StateError(
@@ -3497,6 +3523,13 @@ mixin TreeVisitor1ExperimentExclusionMixin<R, A> implements TreeVisitor1<R, A> {
);
}
@override
R visitCatchVariable(CatchVariable node, A arg) {
throw StateError(
"${runtimeType}.visitCatchVariable isn't supported.",
);
}
@override
R visitThisVariable(ThisVariable node, A arg) {
throw StateError(