[cfe][InternalNodes] Add more internal nodes
This adds internal nodes for VariableStatement, VariableDeclaration, Let, and ForStatement. The prepares for separating Variable from InternalVariable and allows for the removal of Variable.asVariableDeclaration. Change-Id: Ib0593f64b3d22ce99c187ab4af32c8dc8cbea6e9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/509980 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
90d89a0ca1
commit
ac477b9233
@@ -3326,14 +3326,14 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
}
|
||||
pushNewLocalVariable(initializer, equalsToken: assignmentOperator);
|
||||
if (isLate) {
|
||||
VariableDeclaration node = peek() as VariableDeclaration;
|
||||
InternalVariableDeclaration node = peek() as InternalVariableDeclaration;
|
||||
// This is matched by the call to [beginNode] in
|
||||
// [beginVariableInitializer].
|
||||
|
||||
// TODO(62401): Remove the cast when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
assignedVariables.storeInfo(
|
||||
(node.variable as InternalVariable).astVariable,
|
||||
node.variable.astVariable,
|
||||
assignedVariablesInfo!,
|
||||
);
|
||||
}
|
||||
@@ -3384,7 +3384,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
name = createWildcardVariableName(wildcardVariableIndex);
|
||||
wildcardVariableIndex++;
|
||||
}
|
||||
VariableDeclaration variableDeclaration;
|
||||
InternalVariableDeclaration variableDeclaration;
|
||||
InternalVariable internalVariable;
|
||||
if (isLate) {
|
||||
internalVariable = intern.createLateVariable(
|
||||
@@ -3510,7 +3510,8 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
push(node);
|
||||
return;
|
||||
}
|
||||
VariableDeclaration declaration = node as VariableDeclaration;
|
||||
InternalVariableDeclaration declaration =
|
||||
node as InternalVariableDeclaration;
|
||||
declaration.variable.fileOffset = declaration.fileOffset =
|
||||
nameToken.charOffset;
|
||||
push(declaration);
|
||||
@@ -3520,7 +3521,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
// the scope.
|
||||
if (!(libraryFeatures.wildcardVariables.isEnabled &&
|
||||
declaration.variable.isWildcard)) {
|
||||
declareVariable(declaration.variable as InternalVariable, _localScope);
|
||||
declareVariable(declaration.variable, _localScope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3567,7 +3568,8 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
push(node);
|
||||
return;
|
||||
}
|
||||
VariableDeclaration declaration = node as VariableDeclaration;
|
||||
InternalVariableDeclaration declaration =
|
||||
node as InternalVariableDeclaration;
|
||||
if (annotations != null) {
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
declaration.variable.addAnnotation(annotations[i]);
|
||||
@@ -3578,11 +3580,11 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
// [endToken]?
|
||||
push(intern.createVariableStatement(declaration));
|
||||
} else {
|
||||
List<VariableDeclaration>? variables =
|
||||
const FixedNullableList<VariableDeclaration>().popNonNullable(
|
||||
List<InternalVariableDeclaration>? variables =
|
||||
const FixedNullableList<InternalVariableDeclaration>().popNonNullable(
|
||||
stack,
|
||||
count,
|
||||
dummyVariableDeclaration,
|
||||
dummyInternalVariableDeclaration,
|
||||
);
|
||||
constantContext = pop() as ConstantContext;
|
||||
currentLocalVariableType = pop(NullValues.Type) as DartType?;
|
||||
@@ -3593,7 +3595,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
return;
|
||||
}
|
||||
if (annotations != null) {
|
||||
VariableDeclaration first = variables.first;
|
||||
InternalVariableDeclaration first = variables.first;
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
first.variable.addAnnotation(annotations[i]);
|
||||
}
|
||||
@@ -3704,7 +3706,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
List<VariableDeclaration>? _buildForLoopVariableDeclarations(
|
||||
List<InternalVariableDeclaration>? _buildForLoopVariableDeclarations(
|
||||
variableOrExpression,
|
||||
) {
|
||||
// TODO(ahe): This can be simplified now that we have the events
|
||||
@@ -3712,16 +3714,16 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
if (variableOrExpression is Generator) {
|
||||
variableOrExpression = variableOrExpression.buildForEffect();
|
||||
}
|
||||
if (variableOrExpression is VariableStatement) {
|
||||
if (variableOrExpression is InternalVariableStatement) {
|
||||
// TODO(johnniwinther): Avoid parsing variable declarations initializers
|
||||
// in for statements as statements.
|
||||
VariableDeclaration variableDeclaration =
|
||||
InternalVariableDeclaration variableDeclaration =
|
||||
variableOrExpression.declaration;
|
||||
// Late for loop variables are not supported. An error has already been
|
||||
// reported by the parser.
|
||||
variableDeclaration.variable.isLate = false;
|
||||
return [variableDeclaration];
|
||||
} else if (variableOrExpression is VariableDeclaration) {
|
||||
} else if (variableOrExpression is InternalVariableDeclaration) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
// Late for loop variables are not supported. An error has already been
|
||||
// reported by the parser.
|
||||
@@ -3746,7 +3748,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
);
|
||||
} else if (variableOrExpression is List<Object>) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
List<VariableDeclaration> variables = [];
|
||||
List<InternalVariableDeclaration> variables = [];
|
||||
for (Object v in variableOrExpression) {
|
||||
variables.addAll(_buildForLoopVariableDeclarations(v)!);
|
||||
}
|
||||
@@ -3790,8 +3792,8 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
// If the declaration is of the form `for (final x in ...)`, then we may
|
||||
// have erroneously set the `isStaticLate` flag, so un-set it.
|
||||
Object? declaration = peek();
|
||||
if (declaration case VariableStatement(
|
||||
declaration: VariableDeclaration(:VariableDeclarationImpl variable),
|
||||
if (declaration case InternalVariableStatement(
|
||||
declaration: InternalVariableDeclaration(:InternalVariable variable),
|
||||
)) {
|
||||
variable.isStaticLate = false;
|
||||
}
|
||||
@@ -3967,8 +3969,8 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
.popNode();
|
||||
|
||||
Object? variableOrExpression = pop();
|
||||
List<VariableDeclaration>? variables;
|
||||
List<VariableDeclaration>? intermediateVariables;
|
||||
List<InternalVariableDeclaration>? variables;
|
||||
List<InternalVariableDeclaration>? intermediateVariables;
|
||||
if (variableOrExpression is InternalPatternVariableDeclaration) {
|
||||
variables = (pop() as List<InternalVariable>)
|
||||
.map(intern.createVariableDeclaration)
|
||||
@@ -4090,8 +4092,8 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
.deferNode();
|
||||
|
||||
Object? variableOrExpression = pop();
|
||||
List<VariableDeclaration>? variables;
|
||||
List<VariableDeclaration>? intermediateVariables;
|
||||
List<InternalVariableDeclaration>? variables;
|
||||
List<InternalVariableDeclaration>? intermediateVariables;
|
||||
if (variableOrExpression is InternalPatternVariableDeclaration) {
|
||||
variables = (pop() as List<InternalVariable>)
|
||||
.map(intern.createVariableDeclaration)
|
||||
@@ -4142,7 +4144,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
fileEndOffset: result.fileOffset,
|
||||
[
|
||||
variableOrExpression,
|
||||
for (VariableDeclaration intermediateVariable
|
||||
for (InternalVariableDeclaration intermediateVariable
|
||||
in intermediateVariables!)
|
||||
intern.createVariableStatement(intermediateVariable),
|
||||
result,
|
||||
@@ -8380,10 +8382,10 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
required Token inToken,
|
||||
required Object? lvalue,
|
||||
}) {
|
||||
if (lvalue is VariableStatement) {
|
||||
if (lvalue is InternalVariableStatement) {
|
||||
// TODO(johnniwinther): Avoid parsing variable declarations in
|
||||
// for-in statements as statements.
|
||||
VariableDeclaration declaration = lvalue.declaration;
|
||||
InternalVariableDeclaration declaration = lvalue.declaration;
|
||||
// Variable initializers are not supported. An error has already been
|
||||
// reported by the parser.
|
||||
declaration.variable.initializer = null;
|
||||
@@ -8407,7 +8409,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
variableDeclaration: declaration,
|
||||
error: error,
|
||||
);
|
||||
} else if (lvalue is VariableDeclaration) {
|
||||
} else if (lvalue is InternalVariableDeclaration) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
// Variable initializers are not supported. An error has already been
|
||||
// reported by the parser.
|
||||
|
||||
@@ -222,7 +222,7 @@ class ForElement extends ControlFlowElement
|
||||
implements ForElementBase {
|
||||
// May be empty, but not null.
|
||||
@override
|
||||
final List<VariableDeclaration> variables;
|
||||
final List<InternalVariableDeclaration> internalVariables;
|
||||
|
||||
@override
|
||||
Expression? condition; // May be null.
|
||||
@@ -233,8 +233,11 @@ class ForElement extends ControlFlowElement
|
||||
@override
|
||||
Expression body;
|
||||
|
||||
new(this.variables, this.condition, this.updates, this.body) {
|
||||
setParents(variables, this);
|
||||
@override
|
||||
late List<VariableDeclaration> variables;
|
||||
|
||||
new(this.internalVariables, this.condition, this.updates, this.body) {
|
||||
setParents(internalVariables, this);
|
||||
condition?.parent = this;
|
||||
setParents(updates, this);
|
||||
body.parent = this;
|
||||
@@ -252,7 +255,7 @@ class ForElement extends ControlFlowElement
|
||||
}
|
||||
if (bodyEntry == null) return null;
|
||||
ForMapEntry result = new ForMapEntry(
|
||||
variables,
|
||||
internalVariables,
|
||||
condition,
|
||||
updates,
|
||||
bodyEntry,
|
||||
@@ -270,12 +273,12 @@ class ForElement extends ControlFlowElement
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('for (');
|
||||
for (int index = 0; index < variables.length; index++) {
|
||||
for (int index = 0; index < internalVariables.length; index++) {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableDeclaration(
|
||||
variables[index],
|
||||
printer.writeVariableInitialization(
|
||||
internalVariables[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
@@ -307,7 +310,7 @@ class ForInElement extends ControlFlowElement
|
||||
/// [ScopeProvider] nodes in the output.
|
||||
Scope? scope;
|
||||
|
||||
Variable? variable;
|
||||
late Variable variable;
|
||||
|
||||
ForInEncoding? encoding;
|
||||
|
||||
@@ -318,7 +321,6 @@ class ForInElement extends ControlFlowElement
|
||||
required this.isAsync,
|
||||
required int fileOffset,
|
||||
required this.forOffset,
|
||||
this.variable,
|
||||
this.encoding,
|
||||
}) {
|
||||
this.fileOffset = fileOffset;
|
||||
@@ -354,7 +356,6 @@ class ForInElement extends ControlFlowElement
|
||||
isAsync: isAsync,
|
||||
fileOffset: fileOffset,
|
||||
forOffset: forOffset,
|
||||
variable: variable,
|
||||
encoding: encoding,
|
||||
);
|
||||
onConvertElement(this, result);
|
||||
@@ -457,24 +458,27 @@ class IfCaseElement extends ControlFlowElementImpl
|
||||
}
|
||||
|
||||
abstract interface class ForElementBase implements AuxiliaryExpression {
|
||||
List<VariableDeclaration> get variables;
|
||||
List<InternalVariableDeclaration> get internalVariables;
|
||||
|
||||
abstract Expression? condition;
|
||||
|
||||
List<Expression> get updates;
|
||||
|
||||
abstract Expression body;
|
||||
|
||||
/// [VariableDeclaration]s computed after inference of [internalVariables].
|
||||
abstract List<VariableDeclaration> variables;
|
||||
}
|
||||
|
||||
class PatternForElement extends ControlFlowElementImpl
|
||||
with ControlFlowElementMixin
|
||||
implements ForElementBase {
|
||||
InternalPatternVariableDeclaration internalPatternVariableDeclaration;
|
||||
List<VariableDeclaration> intermediateVariables;
|
||||
List<InternalVariableDeclaration> intermediateVariables;
|
||||
|
||||
// May be empty, but not null.
|
||||
@override
|
||||
final List<VariableDeclaration> variables;
|
||||
final List<InternalVariableDeclaration> internalVariables;
|
||||
|
||||
@override
|
||||
Expression? condition; // May be null.
|
||||
@@ -489,10 +493,13 @@ class PatternForElement extends ControlFlowElementImpl
|
||||
/// [internalPatternVariableDeclaration].
|
||||
late PatternVariableDeclaration patternVariableDeclaration;
|
||||
|
||||
@override
|
||||
late List<VariableDeclaration> variables;
|
||||
|
||||
new({
|
||||
required this.internalPatternVariableDeclaration,
|
||||
required this.intermediateVariables,
|
||||
required this.variables,
|
||||
required this.internalVariables,
|
||||
required this.condition,
|
||||
required this.updates,
|
||||
required this.body,
|
||||
@@ -511,12 +518,12 @@ class PatternForElement extends ControlFlowElementImpl
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
internalPatternVariableDeclaration.toTextInternal(printer);
|
||||
printer.write('for (');
|
||||
for (int index = 0; index < variables.length; index++) {
|
||||
for (int index = 0; index < internalVariables.length; index++) {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableDeclaration(
|
||||
variables[index],
|
||||
printer.writeVariableInitialization(
|
||||
internalVariables[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
@@ -683,13 +690,16 @@ class IfMapEntry extends TreeNode
|
||||
}
|
||||
|
||||
abstract interface class ForMapEntryBase implements TreeNode, MapLiteralEntry {
|
||||
List<VariableDeclaration> get variables;
|
||||
List<InternalVariableDeclaration> get internalVariables;
|
||||
|
||||
abstract Expression? condition;
|
||||
|
||||
List<Expression> get updates;
|
||||
|
||||
abstract MapLiteralEntry body;
|
||||
|
||||
/// [VariableDeclaration]s computed after inference of [internalVariables].
|
||||
abstract List<VariableDeclaration> variables;
|
||||
}
|
||||
|
||||
/// A 'for' element in a map literal.
|
||||
@@ -698,7 +708,7 @@ class ForMapEntry extends TreeNode
|
||||
implements ForMapEntryBase, ControlFlowMapEntry {
|
||||
// May be empty, but not null.
|
||||
@override
|
||||
final List<VariableDeclaration> variables;
|
||||
final List<InternalVariableDeclaration> internalVariables;
|
||||
|
||||
@override
|
||||
Expression? condition; // May be null.
|
||||
@@ -709,8 +719,11 @@ class ForMapEntry extends TreeNode
|
||||
@override
|
||||
MapLiteralEntry body;
|
||||
|
||||
new(this.variables, this.condition, this.updates, this.body) {
|
||||
setParents(variables, this);
|
||||
@override
|
||||
late List<VariableDeclaration> variables;
|
||||
|
||||
new(this.internalVariables, this.condition, this.updates, this.body) {
|
||||
setParents(internalVariables, this);
|
||||
condition?.parent = this;
|
||||
setParents(updates, this);
|
||||
body.parent = this;
|
||||
@@ -725,12 +738,12 @@ class ForMapEntry extends TreeNode
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('for (');
|
||||
for (int index = 0; index < variables.length; index++) {
|
||||
for (int index = 0; index < internalVariables.length; index++) {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableDeclaration(
|
||||
variables[index],
|
||||
printer.writeVariableInitialization(
|
||||
internalVariables[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
@@ -749,10 +762,10 @@ class PatternForMapEntry extends TreeNode
|
||||
with InternalTreeNode, ControlFlowMapEntryMixin
|
||||
implements ForMapEntryBase, ControlFlowMapEntry {
|
||||
InternalPatternVariableDeclaration internalPatternVariableDeclaration;
|
||||
List<VariableDeclaration> intermediateVariables;
|
||||
List<InternalVariableDeclaration> intermediateVariables;
|
||||
|
||||
@override
|
||||
final List<VariableDeclaration> variables;
|
||||
final List<InternalVariableDeclaration> internalVariables;
|
||||
|
||||
@override
|
||||
Expression? condition;
|
||||
@@ -767,10 +780,13 @@ class PatternForMapEntry extends TreeNode
|
||||
/// [internalPatternVariableDeclaration].
|
||||
late PatternVariableDeclaration patternVariableDeclaration;
|
||||
|
||||
@override
|
||||
late List<VariableDeclaration> variables;
|
||||
|
||||
new({
|
||||
required this.internalPatternVariableDeclaration,
|
||||
required this.intermediateVariables,
|
||||
required this.variables,
|
||||
required this.internalVariables,
|
||||
required this.condition,
|
||||
required this.updates,
|
||||
required this.body,
|
||||
@@ -781,12 +797,12 @@ class PatternForMapEntry extends TreeNode
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
internalPatternVariableDeclaration.toTextInternal(printer);
|
||||
printer.write('for (');
|
||||
for (int index = 0; index < variables.length; index++) {
|
||||
for (int index = 0; index < internalVariables.length; index++) {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableDeclaration(
|
||||
variables[index],
|
||||
printer.writeVariableInitialization(
|
||||
internalVariables[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
@@ -824,7 +840,7 @@ class ForInMapEntry extends TreeNode
|
||||
/// [ScopeProvider] nodes in the output.
|
||||
Scope? scope;
|
||||
|
||||
Variable? variable;
|
||||
late Variable variable;
|
||||
|
||||
ForInEncoding? encoding;
|
||||
|
||||
@@ -835,7 +851,6 @@ class ForInMapEntry extends TreeNode
|
||||
required this.isAsync,
|
||||
required int fileOffset,
|
||||
required this.forOffset,
|
||||
this.variable,
|
||||
this.encoding,
|
||||
}) {
|
||||
this.fileOffset = fileOffset;
|
||||
@@ -1020,7 +1035,7 @@ MapLiteralEntry convertToMapEntry(
|
||||
internalPatternVariableDeclaration:
|
||||
element.internalPatternVariableDeclaration,
|
||||
intermediateVariables: element.intermediateVariables,
|
||||
variables: element.variables,
|
||||
internalVariables: element.internalVariables,
|
||||
condition: element.condition,
|
||||
updates: element.updates,
|
||||
body: convertToMapEntry(
|
||||
@@ -1036,7 +1051,7 @@ MapLiteralEntry convertToMapEntry(
|
||||
|
||||
case ForElement():
|
||||
ForMapEntry result = new ForMapEntry(
|
||||
element.variables,
|
||||
element.internalVariables,
|
||||
element.condition,
|
||||
element.updates,
|
||||
convertToMapEntry(
|
||||
@@ -1064,7 +1079,6 @@ MapLiteralEntry convertToMapEntry(
|
||||
fileOffset: element.fileOffset,
|
||||
forOffset: element.forOffset,
|
||||
isAsync: element.isAsync,
|
||||
variable: element.variable,
|
||||
encoding: element.encoding,
|
||||
);
|
||||
onConvertElement(element, result);
|
||||
|
||||
@@ -297,10 +297,14 @@ EqualsNull createEqualsNull(Expression expression, {required int fileOffset}) {
|
||||
}
|
||||
|
||||
/// Creates an [ExpressionStatement] of [expression] using the file offset of
|
||||
/// [expression] for the file offset of the statement.
|
||||
ExpressionStatement createExpressionStatement(Expression expression) {
|
||||
/// [expression] for the file offset of the statement, unless provided directly
|
||||
/// through [fileOffset].
|
||||
ExpressionStatement createExpressionStatement(
|
||||
Expression expression, {
|
||||
int? fileOffset,
|
||||
}) {
|
||||
return new ExpressionStatement(expression)
|
||||
..fileOffset = expression.fileOffset;
|
||||
..fileOffset = fileOffset ?? expression.fileOffset;
|
||||
}
|
||||
|
||||
FieldInitializer createFieldInitializer(
|
||||
@@ -599,8 +603,9 @@ LateVariable createLateVariable({
|
||||
|
||||
/// Creates a [Let] of [variable] with the given [body] using
|
||||
/// `variable.fileOffset` as the file offset for the let.
|
||||
Let createLet(Variable variable, Expression body) {
|
||||
return new Let(variable, body)..fileOffset = variable.fileOffset;
|
||||
Let createLet(Variable variable, Expression body, {int? fileOffset}) {
|
||||
return new Let(variable, body)
|
||||
..fileOffset = fileOffset ?? variable.fileOffset;
|
||||
}
|
||||
|
||||
/// Creates a [Let] with the [effect] as the variable initializer and the
|
||||
@@ -1281,8 +1286,14 @@ Variable createVariableCache(Expression expression, DartType type) {
|
||||
..fileOffset = expression.fileOffset;
|
||||
}
|
||||
|
||||
VariableDeclaration createVariableDeclaration(Variable variable) {
|
||||
return new VariableDeclaration(variable)..fileOffset = variable.fileOffset;
|
||||
VariableDeclaration createVariableDeclaration(
|
||||
Variable variable, {
|
||||
List<VariableContext>? capturedContexts,
|
||||
int? fileOffset,
|
||||
}) {
|
||||
return new VariableDeclaration(variable)
|
||||
..capturedContexts = capturedContexts
|
||||
..fileOffset = fileOffset ?? variable.fileOffset;
|
||||
}
|
||||
|
||||
/// Creates a [VariableGet] of [variable] using `variable.fileOffset` as the
|
||||
@@ -1330,9 +1341,12 @@ Expression createVariableSet(
|
||||
}
|
||||
}
|
||||
|
||||
VariableStatement createVariableStatement(VariableDeclaration declaration) {
|
||||
VariableStatement createVariableStatement(
|
||||
VariableDeclaration declaration, {
|
||||
int? fileOffset,
|
||||
}) {
|
||||
return new VariableStatement(declaration)
|
||||
..fileOffset = declaration.fileOffset;
|
||||
..fileOffset = fileOffset ?? declaration.fileOffset;
|
||||
}
|
||||
|
||||
WildcardPattern createWildcardPattern({
|
||||
@@ -1354,3 +1368,16 @@ Catch createCatch({
|
||||
..scope = scope
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
ForStatement createForStatement({
|
||||
required List<VariableDeclaration> variables,
|
||||
required Expression? condition,
|
||||
required List<Expression> updates,
|
||||
required Statement body,
|
||||
required Scope? scope,
|
||||
required int fileOffset,
|
||||
}) {
|
||||
return new ForStatement(variables, condition, updates, body)
|
||||
..scope = scope
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
@@ -657,7 +657,7 @@ class Cascade extends InternalExpression {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('let ');
|
||||
printer.writeVariableInitialization(variable.asVariableDeclaration);
|
||||
printer.writeVariableInitialization(variable.astVariable);
|
||||
printer.write(' in cascade {');
|
||||
printer.incIndentation();
|
||||
for (Expression expression in expressions) {
|
||||
@@ -670,7 +670,7 @@ class Cascade extends InternalExpression {
|
||||
printer.newLine();
|
||||
}
|
||||
printer.write('} => ');
|
||||
printer.write(printer.getVariableName(variable.asVariableDeclaration));
|
||||
printer.write(printer.getVariableName(variable.astVariable));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,7 +713,7 @@ class AnonymousMethodExpression extends InternalExpression {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('let ');
|
||||
printer.writeVariableInitialization(variable.asVariableDeclaration);
|
||||
printer.writeVariableInitialization(variable.astVariable);
|
||||
printer.write(' in ');
|
||||
printer.writeExpression(body);
|
||||
}
|
||||
@@ -758,7 +758,7 @@ class AnonymousMethodBlock extends InternalExpression {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('let ');
|
||||
printer.writeVariableInitialization(variable.asVariableDeclaration);
|
||||
printer.writeVariableInitialization(variable.astVariable);
|
||||
printer.write(' in ');
|
||||
printer.writeStatement(body);
|
||||
}
|
||||
@@ -794,7 +794,7 @@ class DeferredCheck extends InternalExpression {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('let ');
|
||||
printer.writeVariableInitialization(variable.asVariableDeclaration);
|
||||
printer.writeVariableInitialization(variable.astVariable);
|
||||
printer.write(' in ');
|
||||
printer.writeExpression(expression);
|
||||
}
|
||||
@@ -1418,6 +1418,7 @@ class InternalLateVariable extends TreeNode
|
||||
variableDeclaration?.capturedContexts;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set capturedContexts(List<VariableContext>? value) {
|
||||
variableDeclaration!.capturedContexts = value;
|
||||
}
|
||||
@@ -1426,6 +1427,7 @@ class InternalLateVariable extends TreeNode
|
||||
int fileEqualsOffset = TreeNode.noOffset;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
Variable get variable => this;
|
||||
|
||||
@override
|
||||
@@ -1951,10 +1953,12 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
VariableDeclaration? get variableDeclaration =>
|
||||
astVariable.variableDeclaration;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set variableDeclaration(VariableDeclaration? value) {
|
||||
astVariable.variableDeclaration = value;
|
||||
}
|
||||
@@ -2049,6 +2053,7 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
return astVariable.accept1(v, arg);
|
||||
}
|
||||
|
||||
// Coverage-ignore(suite): Not run.
|
||||
String? get name => astVariable.cosmeticName;
|
||||
|
||||
// Coverage-ignore(suite): Not run.
|
||||
@@ -2268,9 +2273,6 @@ mixin InternalVariableMixin on TreeNode implements InternalVariable {
|
||||
|
||||
@override
|
||||
String? lateName;
|
||||
|
||||
@override
|
||||
Variable get asVariableDeclaration => this as Variable;
|
||||
}
|
||||
|
||||
/// Front end specific implementation of [LoadLibrary].
|
||||
@@ -6022,7 +6024,7 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
VariableDeclaration? _variableForSideEffect;
|
||||
|
||||
/// The declared variable.
|
||||
final VariableDeclaration variableDeclaration;
|
||||
final InternalVariableDeclaration variableDeclaration;
|
||||
|
||||
new({required this.variableDeclaration, required this.error});
|
||||
|
||||
@@ -6033,20 +6035,13 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
required int forOffset,
|
||||
required bool isClosureContextLoweringEnabled,
|
||||
}) {
|
||||
Variable loopVariable;
|
||||
Variable loopVariable = variableDeclaration.variable.astVariable;
|
||||
DartType loopVariableType;
|
||||
bool checkAssignment = true;
|
||||
if (variableDeclaration.variable case InternalVariable variable) {
|
||||
loopVariable = variable.astVariable;
|
||||
if (variable.isImplicitlyTyped) {
|
||||
loopVariableType = variable.type = type;
|
||||
checkAssignment = false;
|
||||
} else {
|
||||
loopVariableType = variable.type;
|
||||
}
|
||||
if (variableDeclaration.variable.isImplicitlyTyped) {
|
||||
loopVariableType = variableDeclaration.variable.type = type;
|
||||
checkAssignment = false;
|
||||
} else {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
loopVariable = variableDeclaration.variable;
|
||||
loopVariableType = variableDeclaration.variable.type;
|
||||
}
|
||||
if (checkAssignment) {
|
||||
@@ -6104,11 +6099,9 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.writeVariableInitialization(
|
||||
variableDeclaration.variable,
|
||||
variableDeclaration.variable.astVariable,
|
||||
includeInitializer: false,
|
||||
isImplicitlyTyped:
|
||||
variableDeclaration.variable is InternalVariable &&
|
||||
(variableDeclaration.variable as InternalVariable).isImplicitlyTyped,
|
||||
isImplicitlyTyped: variableDeclaration.variable.isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6127,7 +6120,7 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
/// `for (var a, b in [])`. This is an error case.
|
||||
class MultiVariableDeclarationForInElement extends _BaseForInElement {
|
||||
/// The declared variables.
|
||||
final List<VariableDeclaration> variableDeclarations;
|
||||
final List<InternalVariableDeclaration> variableDeclarations;
|
||||
|
||||
/// The error that should be emitted prior to the for-in statement.
|
||||
final InvalidExpression error;
|
||||
@@ -6138,21 +6131,18 @@ class MultiVariableDeclarationForInElement extends _BaseForInElement {
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
for (int i = 0; i < variableDeclarations.length; i++) {
|
||||
VariableDeclaration variableDeclaration = variableDeclarations[i];
|
||||
InternalVariableDeclaration variableDeclaration = variableDeclarations[i];
|
||||
if (i == 0) {
|
||||
printer.writeVariableInitialization(
|
||||
variableDeclaration.variable,
|
||||
variableDeclaration.variable.astVariable,
|
||||
includeModifiersAndType: true,
|
||||
includeInitializer: false,
|
||||
isImplicitlyTyped:
|
||||
variableDeclaration.variable is InternalVariable &&
|
||||
(variableDeclaration.variable as InternalVariable)
|
||||
.isImplicitlyTyped,
|
||||
isImplicitlyTyped: variableDeclaration.variable.isImplicitlyTyped,
|
||||
);
|
||||
} else {
|
||||
printer.write(', ');
|
||||
printer.writeVariableInitialization(
|
||||
variableDeclaration.variable,
|
||||
variableDeclaration.variable.astVariable,
|
||||
includeModifiersAndType: false,
|
||||
includeInitializer: false,
|
||||
);
|
||||
@@ -6172,8 +6162,14 @@ class MultiVariableDeclarationForInElement extends _BaseForInElement {
|
||||
return new ForInEncoding(
|
||||
preLoopError: error,
|
||||
bodyPrologue: extern.createBlock([
|
||||
for (VariableDeclaration variableDeclaration in variableDeclarations)
|
||||
extern.createVariableStatement(variableDeclaration),
|
||||
for (InternalVariableDeclaration variableDeclaration
|
||||
in variableDeclarations)
|
||||
extern.createVariableStatement(
|
||||
extern.createVariableDeclaration(
|
||||
variableDeclaration.variable.astVariable,
|
||||
fileOffset: variableDeclaration.fileOffset,
|
||||
),
|
||||
),
|
||||
], fileOffset: TreeNode.noOffset),
|
||||
);
|
||||
}
|
||||
@@ -8321,6 +8317,148 @@ class InternalCatch extends TreeNode with InternalTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Declaration of a variable with an initial value.
|
||||
class InternalVariableDeclaration extends TreeNode with InternalTreeNode {
|
||||
/// The declared variable.
|
||||
final InternalVariable variable;
|
||||
|
||||
new(this.variable) {
|
||||
variable.parent = this;
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
R accept<R>(TreeVisitor<R> v) {
|
||||
unsupported("${runtimeType}.accept on ${v.runtimeType}", -1, null);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
|
||||
unsupported("${runtimeType}.accept1 on ${v.runtimeType}", -1, null);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
variable.toTextInternal(printer);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => 'InternalVariableDeclaration(${toStringInternal()}';
|
||||
}
|
||||
|
||||
/// Declaration of a local variable.
|
||||
class InternalVariableStatement extends InternalStatement {
|
||||
/// The declared variable.
|
||||
final InternalVariableDeclaration declaration;
|
||||
|
||||
new(this.declaration) {
|
||||
declaration.parent = this;
|
||||
}
|
||||
|
||||
@override
|
||||
StatementInferenceResult acceptInference(InferenceVisitorImpl visitor) {
|
||||
return visitor.visitInternalVariableStatement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
declaration.toTextInternal(printer);
|
||||
printer.write(';');
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$runtimeType(${toStringInternal()})";
|
||||
}
|
||||
}
|
||||
|
||||
class InternalForStatement extends InternalStatement implements LoopStatement {
|
||||
// May be empty, but not null.
|
||||
final List<InternalVariableDeclaration> variables;
|
||||
final Expression? condition; // May be null.
|
||||
final List<Expression> updates; // May be empty, but not null.
|
||||
|
||||
@override
|
||||
Statement body;
|
||||
|
||||
new(this.variables, this.condition, this.updates, this.body) {
|
||||
setParents(variables, this);
|
||||
condition?.parent = this;
|
||||
setParents(updates, this);
|
||||
body.parent = this;
|
||||
}
|
||||
|
||||
@override
|
||||
StatementInferenceResult acceptInference(InferenceVisitorImpl visitor) {
|
||||
return visitor.visitInternalForStatement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('for (');
|
||||
for (int index = 0; index < variables.length; index++) {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableInitialization(
|
||||
variables[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
printer.write('; ');
|
||||
if (condition != null) {
|
||||
printer.writeExpression(condition!);
|
||||
}
|
||||
printer.write('; ');
|
||||
printer.writeExpressions(updates);
|
||||
printer.write(') ');
|
||||
printer.writeStatement(body);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$runtimeType(${toStringInternal()})";
|
||||
}
|
||||
}
|
||||
|
||||
/// Synthetic expression of form `let v = x in y`
|
||||
// TODO(johnniwinther): Can we avoid this?
|
||||
class InternalLet extends InternalExpression {
|
||||
final InternalVariable variable; // Must have an initializer.
|
||||
final Expression body;
|
||||
|
||||
new(this.variable, this.body) {
|
||||
variable.parent = this;
|
||||
body.parent = this;
|
||||
}
|
||||
|
||||
@override
|
||||
ExpressionInferenceResult acceptInference(
|
||||
InferenceVisitorImpl visitor,
|
||||
DartType typeContext,
|
||||
) {
|
||||
return visitor.visitInternalLet(this, typeContext);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('let ');
|
||||
printer.writeVariableInitialization(variable.astVariable);
|
||||
printer.write(' in ');
|
||||
printer.writeExpression(body);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "Let(${toStringInternal()})";
|
||||
}
|
||||
}
|
||||
|
||||
final InternalPattern dummyInternalPattern = new InternalConstantPattern(
|
||||
expression: dummyExpression,
|
||||
fileOffset: TreeNode.noOffset,
|
||||
@@ -8362,3 +8500,6 @@ final InternalVariable dummyInternalVariable = new VariableDeclarationImpl(
|
||||
fileOffset: TreeNode.noOffset,
|
||||
isSynthesized: true,
|
||||
);
|
||||
|
||||
final InternalVariableDeclaration dummyInternalVariableDeclaration =
|
||||
new InternalVariableDeclaration(dummyInternalVariable);
|
||||
|
||||
@@ -129,7 +129,7 @@ Block createBlock(
|
||||
Statement statement = statements[i];
|
||||
if (statement is _VariablesDeclaration) {
|
||||
copy ??= new List<Statement>.of(statements.getRange(0, i));
|
||||
for (VariableDeclaration declaration in statement.declarations) {
|
||||
for (InternalVariableDeclaration declaration in statement.declarations) {
|
||||
copy.add(createVariableStatement(declaration));
|
||||
}
|
||||
} else if (copy != null) {
|
||||
@@ -349,7 +349,7 @@ Statement createExpressionStatement(
|
||||
|
||||
ForElement createForElement(
|
||||
int fileOffset,
|
||||
List<VariableDeclaration> variables,
|
||||
List<InternalVariableDeclaration> variables,
|
||||
Expression? condition,
|
||||
List<Expression> updates,
|
||||
Expression body,
|
||||
@@ -410,7 +410,7 @@ ForInStatement createForInStatement(
|
||||
|
||||
ForMapEntry createForMapEntry(
|
||||
int fileOffset,
|
||||
List<VariableDeclaration> variables,
|
||||
List<InternalVariableDeclaration> variables,
|
||||
Expression? condition,
|
||||
List<Expression> updates,
|
||||
MapLiteralEntry body,
|
||||
@@ -422,12 +422,12 @@ ForMapEntry createForMapEntry(
|
||||
/// Return a representation of a for statement.
|
||||
Statement createForStatement(
|
||||
int fileOffset,
|
||||
List<VariableDeclaration>? variables,
|
||||
List<InternalVariableDeclaration>? variables,
|
||||
Expression? condition,
|
||||
List<Expression> updaters,
|
||||
Statement body,
|
||||
) {
|
||||
return new ForStatement(
|
||||
return new InternalForStatement(
|
||||
variables ?? // Coverage-ignore(suite): Not run.
|
||||
[],
|
||||
condition,
|
||||
@@ -694,18 +694,18 @@ InternalVariable createLateVariable({
|
||||
}
|
||||
}
|
||||
|
||||
Let createLetForEffect({
|
||||
InternalLet createLetForEffect({
|
||||
required bool isClosureContextLoweringEnabled,
|
||||
required Expression effect,
|
||||
required DartType effectType,
|
||||
required Expression expression,
|
||||
}) {
|
||||
return new Let(
|
||||
return new InternalLet(
|
||||
createSyntheticVariableForValue(
|
||||
effect,
|
||||
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
||||
type: effectType,
|
||||
).asVariableDeclaration,
|
||||
),
|
||||
expression,
|
||||
)..fileOffset = effect.fileOffset;
|
||||
}
|
||||
@@ -1099,8 +1099,8 @@ Expression createPatternAssignment(
|
||||
PatternForElement createPatternForElement(
|
||||
int fileOffset, {
|
||||
required InternalPatternVariableDeclaration patternVariableDeclaration,
|
||||
required List<VariableDeclaration> intermediateVariables,
|
||||
required List<VariableDeclaration> variables,
|
||||
required List<InternalVariableDeclaration> intermediateVariables,
|
||||
required List<InternalVariableDeclaration> variables,
|
||||
required Expression? condition,
|
||||
required List<Expression> updates,
|
||||
required Expression body,
|
||||
@@ -1108,7 +1108,7 @@ PatternForElement createPatternForElement(
|
||||
return new PatternForElement(
|
||||
internalPatternVariableDeclaration: patternVariableDeclaration,
|
||||
intermediateVariables: intermediateVariables,
|
||||
variables: variables,
|
||||
internalVariables: variables,
|
||||
condition: condition,
|
||||
updates: updates,
|
||||
body: body,
|
||||
@@ -1118,8 +1118,8 @@ PatternForElement createPatternForElement(
|
||||
PatternForMapEntry createPatternForMapEntry(
|
||||
int fileOffset, {
|
||||
required InternalPatternVariableDeclaration patternVariableDeclaration,
|
||||
required List<VariableDeclaration> intermediateVariables,
|
||||
required List<VariableDeclaration> variableInitializations,
|
||||
required List<InternalVariableDeclaration> intermediateVariables,
|
||||
required List<InternalVariableDeclaration> variableInitializations,
|
||||
required Expression? condition,
|
||||
required List<Expression> updates,
|
||||
required MapLiteralEntry body,
|
||||
@@ -1127,7 +1127,7 @@ PatternForMapEntry createPatternForMapEntry(
|
||||
return new PatternForMapEntry(
|
||||
internalPatternVariableDeclaration: patternVariableDeclaration,
|
||||
intermediateVariables: intermediateVariables,
|
||||
variables: variableInitializations,
|
||||
internalVariables: variableInitializations,
|
||||
condition: condition,
|
||||
updates: updates,
|
||||
body: body,
|
||||
@@ -1620,11 +1620,11 @@ UnaryExpression createUnary(
|
||||
return new UnaryExpression(unaryName, expression)..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
VariableDeclaration createVariableDeclaration(
|
||||
InternalVariableDeclaration createVariableDeclaration(
|
||||
InternalVariable variable, {
|
||||
int? fileOffset,
|
||||
}) {
|
||||
return new VariableDeclaration(variable.asVariableDeclaration)
|
||||
return new InternalVariableDeclaration(variable)
|
||||
..fileOffset = fileOffset ?? variable.fileOffset;
|
||||
}
|
||||
|
||||
@@ -1655,11 +1655,11 @@ InternalVariableSet createVariableSet(
|
||||
return new InternalVariableSet(variable, value)..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
VariableStatement createVariableStatement(
|
||||
VariableDeclaration declaration, {
|
||||
InternalVariableStatement createVariableStatement(
|
||||
InternalVariableDeclaration declaration, {
|
||||
int? fileOffset,
|
||||
}) {
|
||||
return new VariableStatement(declaration)
|
||||
return new InternalVariableStatement(declaration)
|
||||
..fileOffset = fileOffset ?? declaration.fileOffset;
|
||||
}
|
||||
|
||||
@@ -1714,13 +1714,13 @@ bool isThisExpression(Object node) =>
|
||||
bool isVariablesDeclaration(Object? node) => node is _VariablesDeclaration;
|
||||
|
||||
_VariablesDeclaration variablesDeclaration(
|
||||
List<VariableDeclaration> declarations,
|
||||
List<InternalVariableDeclaration> declarations,
|
||||
Uri uri,
|
||||
) {
|
||||
return new _VariablesDeclaration(declarations, uri);
|
||||
}
|
||||
|
||||
List<VariableDeclaration> variablesDeclarationExtractDeclarations(
|
||||
List<InternalVariableDeclaration> variablesDeclarationExtractDeclarations(
|
||||
Object? variablesDeclaration,
|
||||
) {
|
||||
return (variablesDeclaration as _VariablesDeclaration).declarations;
|
||||
@@ -1735,7 +1735,7 @@ Statement wrapVariables(Statement statement) {
|
||||
growable: true,
|
||||
),
|
||||
)..fileOffset = statement.fileOffset;
|
||||
} else if (statement is VariableStatement) {
|
||||
} else if (statement is InternalVariableStatement) {
|
||||
return new Block(<Statement>[statement])..fileOffset = statement.fileOffset;
|
||||
} else {
|
||||
return statement;
|
||||
@@ -1743,7 +1743,7 @@ Statement wrapVariables(Statement statement) {
|
||||
}
|
||||
|
||||
class _VariablesDeclaration extends AuxiliaryStatement {
|
||||
final List<VariableDeclaration> declarations;
|
||||
final List<InternalVariableDeclaration> declarations;
|
||||
final Uri uri;
|
||||
|
||||
new(this.declarations, this.uri) {
|
||||
@@ -1774,8 +1774,8 @@ class _VariablesDeclaration extends AuxiliaryStatement {
|
||||
if (index > 0) {
|
||||
printer.write(', ');
|
||||
}
|
||||
printer.writeVariableDeclaration(
|
||||
declarations[index],
|
||||
printer.writeVariableInitialization(
|
||||
declarations[index].variable.astVariable,
|
||||
includeModifiersAndType: index == 0,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,8 +95,9 @@ class MultipleStatementInferenceResult implements StatementInferenceResult {
|
||||
int get statementCount => statements.length;
|
||||
}
|
||||
|
||||
class VariableDeclarationInferenceResult {
|
||||
const new();
|
||||
sealed class VariableDeclarationInferenceResult {
|
||||
factory direct(VariableDeclaration declaration) =
|
||||
DirectVariableDeclarationInferenceResult;
|
||||
|
||||
factory effect([Expression? expression]) =
|
||||
EffectVariableDeclarationInferenceResult;
|
||||
@@ -107,10 +108,23 @@ class VariableDeclarationInferenceResult {
|
||||
required int fileOffset,
|
||||
}) = LateVariableDeclarationInferenceResult;
|
||||
|
||||
bool get hasChanged => false;
|
||||
StatementInferenceResult toStatementInferenceResult({
|
||||
required int fileOffset,
|
||||
});
|
||||
}
|
||||
|
||||
StatementInferenceResult toStatementInferenceResult() =>
|
||||
const StatementInferenceResult();
|
||||
class DirectVariableDeclarationInferenceResult
|
||||
implements VariableDeclarationInferenceResult {
|
||||
final VariableDeclaration declaration;
|
||||
|
||||
new(this.declaration);
|
||||
|
||||
@override
|
||||
StatementInferenceResult toStatementInferenceResult({
|
||||
required int fileOffset,
|
||||
}) => new StatementInferenceResult.single(
|
||||
createVariableStatement(declaration, fileOffset: fileOffset),
|
||||
);
|
||||
}
|
||||
|
||||
class EffectVariableDeclarationInferenceResult
|
||||
@@ -120,16 +134,13 @@ class EffectVariableDeclarationInferenceResult
|
||||
new([this.expression]);
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get hasChanged => true;
|
||||
|
||||
@override
|
||||
StatementInferenceResult toStatementInferenceResult() =>
|
||||
new StatementInferenceResult.single(
|
||||
expression != null
|
||||
? createExpressionStatement(expression!)
|
||||
: createEmptyStatement(),
|
||||
);
|
||||
StatementInferenceResult toStatementInferenceResult({
|
||||
required int fileOffset,
|
||||
}) => new StatementInferenceResult.single(
|
||||
expression != null
|
||||
? createExpressionStatement(expression!, fileOffset: fileOffset)
|
||||
: createEmptyStatement(fileOffset: fileOffset),
|
||||
);
|
||||
}
|
||||
|
||||
class LateVariableDeclarationInferenceResult
|
||||
@@ -145,16 +156,13 @@ class LateVariableDeclarationInferenceResult
|
||||
});
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get hasChanged => true;
|
||||
|
||||
@override
|
||||
StatementInferenceResult toStatementInferenceResult() =>
|
||||
new StatementInferenceResult.multiple(fileOffset, [
|
||||
for (VariableDeclaration variableDeclaration in variableDeclarations)
|
||||
createVariableStatement(variableDeclaration),
|
||||
...functionDeclarations,
|
||||
]);
|
||||
StatementInferenceResult toStatementInferenceResult({
|
||||
required int fileOffset,
|
||||
}) => new StatementInferenceResult.multiple(fileOffset, [
|
||||
for (VariableDeclaration variableDeclaration in variableDeclarations)
|
||||
createVariableStatement(variableDeclaration),
|
||||
...functionDeclarations,
|
||||
]);
|
||||
}
|
||||
|
||||
/// Tells the inferred type and how the code should be transformed.
|
||||
|
||||
@@ -2626,7 +2626,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
flowAnalysis.doStatement_bodyBegin(node);
|
||||
StatementInferenceResult bodyResult = inferStatement(node.body);
|
||||
if (bodyResult.hasChanged) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
node.body = bodyResult.statement..parent = node;
|
||||
}
|
||||
flowAnalysis.doStatement_conditionBegin();
|
||||
@@ -3452,17 +3451,29 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
StatementInferenceResult visitForStatement(ForStatement node) {
|
||||
_unhandledStatement(node);
|
||||
}
|
||||
|
||||
StatementInferenceResult visitInternalForStatement(
|
||||
InternalForStatement node,
|
||||
) {
|
||||
ScopeProviderInfo? scopeProviderInfo;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
scopeProviderInfo = _contextAllocationStrategy.enterScopeProvider(
|
||||
scopeProviderInfoKind: ScopeProviderInfoKind.Loop,
|
||||
);
|
||||
}
|
||||
List<VariableDeclaration> variables = new List.filled(
|
||||
node.variables.length,
|
||||
dummyVariableDeclaration,
|
||||
growable: true,
|
||||
);
|
||||
for (int index = 0; index < node.variables.length; index++) {
|
||||
VariableDeclaration variableDeclaration = node.variables[index];
|
||||
Variable variable = variableDeclaration.variable;
|
||||
if (variable.name == null) {
|
||||
InternalVariableDeclaration variableDeclaration = node.variables[index];
|
||||
InternalVariable variable = variableDeclaration.variable;
|
||||
if (variable.cosmeticName == null) {
|
||||
if (variable.initializer != null) {
|
||||
ExpressionInferenceResult result = inferExpression(
|
||||
variable.initializer!,
|
||||
@@ -3472,16 +3483,27 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
variable.initializer = result.expression..parent = variable;
|
||||
variable.type = result.inferredType;
|
||||
}
|
||||
variables[index] = extern.createVariableDeclaration(
|
||||
variable.astVariable,
|
||||
fileOffset: variableDeclaration.fileOffset,
|
||||
);
|
||||
} else {
|
||||
VariableDeclarationInferenceResult variableResult =
|
||||
inferVariableDeclaration(variableDeclaration);
|
||||
assert(
|
||||
!variableResult.hasChanged,
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
switch (variableResult) {
|
||||
case DirectVariableDeclarationInferenceResult():
|
||||
variables[index] = variableResult.declaration;
|
||||
// Coverage-ignore(suite): Not run.
|
||||
case EffectVariableDeclarationInferenceResult():
|
||||
case LateVariableDeclarationInferenceResult():
|
||||
throw new UnsupportedError(
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
flowAnalysis.for_conditionBegin(node);
|
||||
Expression? condition;
|
||||
if (node.condition != null) {
|
||||
InterfaceType expectedType = coreTypes.boolRawType(
|
||||
Nullability.nonNullable,
|
||||
@@ -3491,36 +3513,51 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
expectedType,
|
||||
isVoidAllowed: true,
|
||||
);
|
||||
Expression condition = ensureAssignableResult(
|
||||
condition = ensureAssignableResult(
|
||||
expectedType,
|
||||
conditionResult,
|
||||
).expression;
|
||||
node.condition = condition..parent = node;
|
||||
}
|
||||
|
||||
flowAnalysis.for_bodyBegin(node, switch (node.condition) {
|
||||
flowAnalysis.for_bodyBegin(node, switch (condition) {
|
||||
null => flowAnalysis.booleanLiteral(true),
|
||||
var condition => flowAnalysis.getExpressionInfo(condition),
|
||||
});
|
||||
StatementInferenceResult bodyResult = inferStatement(node.body);
|
||||
if (bodyResult.hasChanged) {
|
||||
node.body = bodyResult.statement..parent = node;
|
||||
}
|
||||
Statement body = bodyResult.hasChanged ? bodyResult.statement : node.body;
|
||||
flowAnalysis.for_updaterBegin();
|
||||
|
||||
List<Expression> updates = new List.filled(
|
||||
node.updates.length,
|
||||
dummyExpression,
|
||||
growable: true,
|
||||
);
|
||||
for (int index = 0; index < node.updates.length; index++) {
|
||||
ExpressionInferenceResult updateResult = inferExpression(
|
||||
node.updates[index],
|
||||
const UnknownType(),
|
||||
isVoidAllowed: true,
|
||||
);
|
||||
node.updates[index] = updateResult.expression..parent = node;
|
||||
updates[index] = updateResult.expression;
|
||||
}
|
||||
flowAnalysis.for_end();
|
||||
Scope? scope;
|
||||
if (scopeProviderInfo != null) {
|
||||
_contextAllocationStrategy.exitScopeProvider(scopeProviderInfo);
|
||||
node.scope = scopeProviderInfo.scope;
|
||||
scope = scopeProviderInfo.scope;
|
||||
}
|
||||
return const StatementInferenceResult();
|
||||
Statement replacement = extern.createForStatement(
|
||||
variables: variables,
|
||||
condition: condition,
|
||||
updates: updates,
|
||||
body: body,
|
||||
scope: scope,
|
||||
fileOffset: node.fileOffset,
|
||||
);
|
||||
libraryBuilder.loader.dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(node, replacement);
|
||||
return new StatementInferenceResult.single(replacement);
|
||||
}
|
||||
|
||||
LocalFunctionResult _visitInternalFunctionNode(
|
||||
@@ -4410,11 +4447,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
List<Variable> declaredVariables = pattern.declaredVariables;
|
||||
assert(declaredVariables.length == element.intermediateVariables.length);
|
||||
assert(declaredVariables.length == element.variables.length);
|
||||
assert(declaredVariables.length == element.internalVariables.length);
|
||||
for (int i = 0; i < declaredVariables.length; i++) {
|
||||
DartType type = declaredVariables[i].type;
|
||||
|
||||
Variable intermediateVariable = element.intermediateVariables[i].variable;
|
||||
Variable intermediateVariable =
|
||||
element.intermediateVariables[i].variable.astVariable;
|
||||
intermediateVariable.initializer = inferExpression(
|
||||
intermediateVariable.initializer!,
|
||||
type,
|
||||
@@ -4422,7 +4460,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
).expression..parent = intermediateVariable;
|
||||
intermediateVariable.type = type;
|
||||
|
||||
element.variables[i].variable.type = type;
|
||||
element.internalVariables[i].variable.type = type;
|
||||
}
|
||||
|
||||
return _inferForElementBase(
|
||||
@@ -4453,10 +4491,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
Map<TreeNode, DartType> inferredSpreadTypes,
|
||||
Map<Expression, DartType> inferredConditionTypes,
|
||||
) {
|
||||
for (int index = 0; index < element.variables.length; index++) {
|
||||
VariableDeclaration variableDeclaration = element.variables[index];
|
||||
Variable variable = variableDeclaration.variable;
|
||||
if (variable.name == null) {
|
||||
List<VariableDeclaration> variables = new List.filled(
|
||||
element.internalVariables.length,
|
||||
dummyVariableDeclaration,
|
||||
growable: true,
|
||||
);
|
||||
for (int index = 0; index < element.internalVariables.length; index++) {
|
||||
InternalVariableDeclaration variableDeclaration =
|
||||
element.internalVariables[index];
|
||||
InternalVariable variable = variableDeclaration.variable;
|
||||
if (variable.cosmeticName == null) {
|
||||
if (variable.initializer != null) {
|
||||
ExpressionInferenceResult initializerResult = inferExpression(
|
||||
variable.initializer!,
|
||||
@@ -4467,15 +4511,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
..parent = variable;
|
||||
variable.type = initializerResult.inferredType;
|
||||
}
|
||||
variables[index] = extern.createVariableDeclaration(
|
||||
variable.astVariable,
|
||||
fileOffset: variableDeclaration.fileOffset,
|
||||
);
|
||||
} else {
|
||||
VariableDeclarationInferenceResult variableResult =
|
||||
inferVariableDeclaration(variableDeclaration);
|
||||
assert(
|
||||
!variableResult.hasChanged,
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
switch (variableResult) {
|
||||
case DirectVariableDeclarationInferenceResult():
|
||||
variables[index] = variableResult.declaration;
|
||||
// Coverage-ignore(suite): Not run.
|
||||
case EffectVariableDeclarationInferenceResult():
|
||||
case LateVariableDeclarationInferenceResult():
|
||||
throw new UnsupportedError(
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
element.variables = variables;
|
||||
|
||||
flowAnalysis.for_conditionBegin(element);
|
||||
if (element.condition != null) {
|
||||
@@ -5353,9 +5408,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(element, loop);
|
||||
body.add(element.patternVariableDeclaration);
|
||||
for (VariableDeclaration intermediateVariable
|
||||
for (InternalVariableDeclaration intermediateVariable
|
||||
in element.intermediateVariables) {
|
||||
body.add(extern.createVariableStatement(intermediateVariable));
|
||||
body.add(
|
||||
extern.createVariableStatement(
|
||||
extern.createVariableDeclaration(
|
||||
intermediateVariable.variable.astVariable,
|
||||
fileOffset: intermediateVariable.fileOffset,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
body.add(loop);
|
||||
}
|
||||
@@ -5390,7 +5452,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
: _createBlock(statements);
|
||||
Statement loop = _createForInStatement(
|
||||
node.fileOffset,
|
||||
node.variable!,
|
||||
node.variable,
|
||||
node.iterable,
|
||||
loopBody,
|
||||
isAsync: node.isAsync,
|
||||
@@ -5976,9 +6038,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(entry, loop);
|
||||
body.add(entry.patternVariableDeclaration);
|
||||
for (VariableDeclaration intermediateVariable
|
||||
for (InternalVariableDeclaration intermediateVariable
|
||||
in entry.intermediateVariables) {
|
||||
body.add(extern.createVariableStatement(intermediateVariable));
|
||||
body.add(
|
||||
extern.createVariableStatement(
|
||||
extern.createVariableDeclaration(
|
||||
intermediateVariable.variable.astVariable,
|
||||
fileOffset: intermediateVariable.fileOffset,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
body.add(loop);
|
||||
}
|
||||
@@ -6013,7 +6082,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
: _createBlock(statements);
|
||||
Statement loop = _createForInStatement(
|
||||
node.fileOffset,
|
||||
node.variable!,
|
||||
node.variable,
|
||||
node.iterable,
|
||||
loopBody,
|
||||
isAsync: node.isAsync,
|
||||
@@ -7551,11 +7620,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
List<Variable> declaredVariables = pattern.declaredVariables;
|
||||
assert(declaredVariables.length == entry.intermediateVariables.length);
|
||||
assert(declaredVariables.length == entry.variables.length);
|
||||
assert(declaredVariables.length == entry.internalVariables.length);
|
||||
for (int i = 0; i < declaredVariables.length; i++) {
|
||||
DartType type = declaredVariables[i].type;
|
||||
|
||||
Variable intermediateVariable = entry.intermediateVariables[i].variable;
|
||||
InternalVariable intermediateVariable =
|
||||
entry.intermediateVariables[i].variable;
|
||||
intermediateVariable.initializer = inferExpression(
|
||||
intermediateVariable.initializer!,
|
||||
type,
|
||||
@@ -7563,7 +7633,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
).expression..parent = intermediateVariable;
|
||||
intermediateVariable.type = type;
|
||||
|
||||
entry.variables[i].variable.type = type;
|
||||
entry.internalVariables[i].variable.type = type;
|
||||
}
|
||||
|
||||
return _inferForMapEntryBase(
|
||||
@@ -7618,10 +7688,17 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
Map<Expression, DartType> inferredConditionTypes,
|
||||
_MapLiteralEntryOffsets offsets,
|
||||
) {
|
||||
for (int index = 0; index < entry.variables.length; index++) {
|
||||
VariableDeclaration variableDeclaration = entry.variables[index];
|
||||
Variable variable = variableDeclaration.variable;
|
||||
if (variable.name == null) {
|
||||
List<VariableDeclaration> variables = new List.filled(
|
||||
entry.internalVariables.length,
|
||||
dummyVariableDeclaration,
|
||||
growable: true,
|
||||
);
|
||||
for (int index = 0; index < entry.internalVariables.length; index++) {
|
||||
InternalVariableDeclaration variableDeclaration =
|
||||
entry.internalVariables[index];
|
||||
Variable variable = variableDeclaration.variable.astVariable;
|
||||
|
||||
if (variable.cosmeticName == null) {
|
||||
if (variable.initializer != null) {
|
||||
ExpressionInferenceResult result = inferExpression(
|
||||
variable.initializer!,
|
||||
@@ -7631,15 +7708,23 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
variable.initializer = result.expression..parent = variable;
|
||||
variable.type = result.inferredType;
|
||||
}
|
||||
variables[index] = createVariableDeclaration(variable);
|
||||
} else {
|
||||
VariableDeclarationInferenceResult variableResult =
|
||||
inferVariableDeclaration(variableDeclaration);
|
||||
assert(
|
||||
!variableResult.hasChanged,
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
switch (variableResult) {
|
||||
case DirectVariableDeclarationInferenceResult():
|
||||
variables[index] = variableResult.declaration;
|
||||
// Coverage-ignore(suite): Not run.
|
||||
case EffectVariableDeclarationInferenceResult():
|
||||
case LateVariableDeclarationInferenceResult():
|
||||
throw new UnsupportedError(
|
||||
"Unexpected variable declaration change.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.variables = variables;
|
||||
|
||||
flowAnalysis.for_conditionBegin(entry);
|
||||
if (entry.condition != null) {
|
||||
@@ -8395,22 +8480,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
internalPatternVariableDeclaration:
|
||||
entry.internalPatternVariableDeclaration,
|
||||
intermediateVariables: entry.intermediateVariables,
|
||||
variables: entry.variables,
|
||||
internalVariables: entry.internalVariables,
|
||||
condition: entry.condition,
|
||||
updates: entry.updates,
|
||||
body: convertToElement(entry.body, onConvertMapEntry),
|
||||
)
|
||||
..patternVariableDeclaration = entry.patternVariableDeclaration
|
||||
..variables = entry.variables
|
||||
..fileOffset = entry.fileOffset;
|
||||
onConvertMapEntry(entry, result);
|
||||
return result;
|
||||
case ForMapEntry():
|
||||
ForElement result = new ForElement(
|
||||
entry.variables,
|
||||
entry.condition,
|
||||
entry.updates,
|
||||
convertToElement(entry.body, onConvertMapEntry),
|
||||
)..fileOffset = entry.fileOffset;
|
||||
ForElement result =
|
||||
new ForElement(
|
||||
entry.internalVariables,
|
||||
entry.condition,
|
||||
entry.updates,
|
||||
convertToElement(entry.body, onConvertMapEntry),
|
||||
)
|
||||
..variables = entry.variables
|
||||
..fileOffset = entry.fileOffset;
|
||||
onConvertMapEntry(entry, result);
|
||||
return result;
|
||||
case ForInMapEntry():
|
||||
@@ -8421,9 +8510,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
isAsync: entry.isAsync,
|
||||
fileOffset: entry.fileOffset,
|
||||
forOffset: entry.forOffset,
|
||||
variable: entry.variable,
|
||||
encoding: entry.encoding,
|
||||
);
|
||||
)..variable = entry.variable;
|
||||
onConvertMapEntry(entry, result);
|
||||
return result;
|
||||
}
|
||||
@@ -11808,23 +11896,34 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
ExpressionInferenceResult visitLet(Let node, DartType typeContext) {
|
||||
_unhandledExpression(node, typeContext);
|
||||
}
|
||||
|
||||
ExpressionInferenceResult visitInternalLet(
|
||||
InternalLet node,
|
||||
DartType typeContext,
|
||||
) {
|
||||
DartType variableType = node.variable.type;
|
||||
ExpressionInferenceResult initializerResult = inferExpression(
|
||||
node.variable.initializer!,
|
||||
variableType,
|
||||
isVoidAllowed: true,
|
||||
);
|
||||
node.variable.initializer = initializerResult.expression
|
||||
..parent = node.variable;
|
||||
Variable variable = node.variable.astVariable;
|
||||
variable.initializer = initializerResult.expression..parent = variable;
|
||||
ExpressionInferenceResult bodyResult = inferExpression(
|
||||
node.body,
|
||||
typeContext,
|
||||
isVoidAllowed: true,
|
||||
);
|
||||
node.body = bodyResult.expression..parent = node;
|
||||
Expression body = bodyResult.expression..parent = node;
|
||||
DartType inferredType = bodyResult.inferredType;
|
||||
return new ExpressionInferenceResult(inferredType, node);
|
||||
return new ExpressionInferenceResult(
|
||||
inferredType,
|
||||
extern.createLet(variable, body, fileOffset: node.fileOffset),
|
||||
);
|
||||
}
|
||||
|
||||
ExpressionInferenceResult visitAnonymousMethodExpression(
|
||||
@@ -13154,6 +13253,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<SwitchExpressionCase> cases = new List.filled(
|
||||
node.cases.length,
|
||||
dummySwitchExpressionCase,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = node.cases.length - 1; i >= 0; i--) {
|
||||
cases[i] = popRewrite() as SwitchExpressionCase;
|
||||
@@ -13357,6 +13457,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<PatternSwitchCase> cases = new List.filled(
|
||||
node.cases.length,
|
||||
dummyPatternSwitchCase,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = node.cases.length - 1; i >= 0; i--) {
|
||||
cases[i] = popRewrite() as PatternSwitchCase;
|
||||
@@ -13547,11 +13648,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
}
|
||||
StatementInferenceResult bodyResult = inferStatement(node.body);
|
||||
Statement body = bodyResult.hasChanged
|
||||
?
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bodyResult.statement
|
||||
: node.body;
|
||||
Statement body = bodyResult.hasChanged ? bodyResult.statement : node.body;
|
||||
Scope? scope;
|
||||
if (scopeProviderInfo != null) {
|
||||
_contextAllocationStrategy.exitScopeProvider(scopeProviderInfo);
|
||||
@@ -13618,9 +13715,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
result = new TryFinally(
|
||||
result,
|
||||
finalizerResult!.hasChanged
|
||||
?
|
||||
// Coverage-ignore(suite): Not run.
|
||||
finalizerResult.statement
|
||||
? finalizerResult.statement
|
||||
: node.finallyBlock!,
|
||||
)..fileOffset = node.fileOffset;
|
||||
}
|
||||
@@ -13689,30 +13784,31 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
VariableDeclarationInferenceResult inferVariableDeclaration(
|
||||
VariableDeclaration node,
|
||||
InternalVariableDeclaration node,
|
||||
) {
|
||||
InternalVariable nodeVariable = node.variable as InternalVariable;
|
||||
VariableDeclarationInferenceResult variableDeclarationInferenceResult =
|
||||
_inferInternalExpressionVariableDeclaration(
|
||||
node,
|
||||
node.variable,
|
||||
nodeVariable,
|
||||
);
|
||||
node.variable = nodeVariable.astVariable;
|
||||
_inferInternalExpressionVariableDeclaration(node, node.variable);
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
node.variable,
|
||||
captureKind: _captureKindForVariable(node.variable),
|
||||
node.variable.astVariable,
|
||||
captureKind: _captureKindForVariable(node.variable.astVariable),
|
||||
);
|
||||
}
|
||||
return variableDeclarationInferenceResult;
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
StatementInferenceResult visitVariableStatement(VariableStatement node) {
|
||||
_unhandledStatement(node);
|
||||
}
|
||||
|
||||
StatementInferenceResult visitInternalVariableStatement(
|
||||
InternalVariableStatement node,
|
||||
) {
|
||||
return inferVariableDeclaration(
|
||||
node.declaration,
|
||||
).toStatementInferenceResult();
|
||||
).toStatementInferenceResult(fileOffset: node.fileOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -14607,6 +14703,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<Expression> expressions = new List.filled(
|
||||
case_.expressions.length,
|
||||
dummyExpression,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = case_.expressions.length - 1; i >= 0; i--) {
|
||||
expressions[i] = popRewrite() as Expression; // CaseHead
|
||||
@@ -14688,6 +14785,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<PatternGuard> patternGuards = new List.filled(
|
||||
case_.patternGuards.length,
|
||||
dummyPatternGuard,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = case_.patternGuards.length - 1; i >= 0; i--) {
|
||||
patternGuards[i] = popRewrite() as PatternGuard;
|
||||
@@ -15416,6 +15514,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<Pattern> patterns = new List.filled(
|
||||
node.patterns.length,
|
||||
dummyPattern,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = node.patterns.length - 1; i >= 0; i--) {
|
||||
Object? rewrite = popRewrite();
|
||||
@@ -15655,6 +15754,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<NamedPattern> fields = new List.filled(
|
||||
node.fields.length,
|
||||
dummyNamedPattern,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = node.fields.length - 1; i >= 0; i--) {
|
||||
InternalNamedPattern field = node.fields[i];
|
||||
@@ -16232,6 +16332,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
List<Pattern> patterns = new List.filled(
|
||||
node.patterns.length,
|
||||
dummyPattern,
|
||||
growable: true,
|
||||
);
|
||||
for (int i = node.patterns.length - 1; i >= 0; i--) {
|
||||
InternalPattern subPattern = node.patterns[i];
|
||||
@@ -17296,13 +17397,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
VariableDeclarationInferenceResult
|
||||
_inferInternalExpressionVariableDeclaration(
|
||||
VariableDeclaration variableDeclaration,
|
||||
Variable node,
|
||||
InternalVariable nodeVariable,
|
||||
InternalVariableDeclaration variableDeclaration,
|
||||
InternalVariable internalVariable,
|
||||
) {
|
||||
DartType declaredType = nodeVariable.isImplicitlyTyped
|
||||
DartType declaredType = internalVariable.isImplicitlyTyped
|
||||
? const UnknownType()
|
||||
: node.type;
|
||||
: internalVariable.type;
|
||||
DartType inferredType;
|
||||
ExpressionInferenceResult? initializerResult;
|
||||
|
||||
@@ -17310,10 +17410,11 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// for loops, const variables, and late variables. This logic turns them
|
||||
// into `ExpressionStatement`s or `EmptyStatement`s so the backends don't
|
||||
// need to allocate space for them.
|
||||
if (node.isWildcard &&
|
||||
!node.isConst &&
|
||||
node.parent?.parent is! ForStatement) {
|
||||
if (node.initializer case var initializer? when !node.isLate) {
|
||||
if (internalVariable.isWildcard &&
|
||||
!internalVariable.isConst &&
|
||||
internalVariable.parent?.parent is! InternalForStatement) {
|
||||
if (internalVariable.initializer case var initializer?
|
||||
when !internalVariable.isLate) {
|
||||
return new VariableDeclarationInferenceResult.effect(
|
||||
inferExpression(
|
||||
initializer,
|
||||
@@ -17325,88 +17426,97 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
return new VariableDeclarationInferenceResult.effect();
|
||||
}
|
||||
}
|
||||
if (node.initializer != null) {
|
||||
if (node.isLate && node.hasDeclaredInitializer) {
|
||||
List<VariableContext>? capturedContexts;
|
||||
if (internalVariable.initializer != null) {
|
||||
if (internalVariable.isLate && internalVariable.hasDeclaredInitializer) {
|
||||
// TODO(62401): Remove the cast when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
Variable variable = (node.variable as InternalVariable).astVariable;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
node.capturedContexts = _contextAllocationStrategy
|
||||
capturedContexts = _contextAllocationStrategy
|
||||
.computeCapturedVariableContexts(
|
||||
_capturedVariablesForNode(variable),
|
||||
_capturedVariablesForNode(internalVariable.astVariable),
|
||||
);
|
||||
}
|
||||
flowAnalysis.lateInitializer_begin(variable);
|
||||
flowAnalysis.lateInitializer_begin(internalVariable.astVariable);
|
||||
}
|
||||
initializerResult = inferExpression(
|
||||
node.initializer!,
|
||||
internalVariable.initializer!,
|
||||
declaredType,
|
||||
isVoidAllowed: true,
|
||||
);
|
||||
if (node.isLate && node.hasDeclaredInitializer) {
|
||||
if (internalVariable.isLate && internalVariable.hasDeclaredInitializer) {
|
||||
flowAnalysis.lateInitializer_end();
|
||||
}
|
||||
inferredType = inferDeclarationType(
|
||||
initializerResult.inferredType,
|
||||
forSyntheticVariable: node.name == null,
|
||||
forSyntheticVariable: internalVariable.cosmeticName == null,
|
||||
inferenceDefaultType: InferenceDefaultType.Dynamic,
|
||||
);
|
||||
} else {
|
||||
inferredType = const DynamicType();
|
||||
}
|
||||
if (nodeVariable.isImplicitlyTyped) {
|
||||
if (internalVariable.isImplicitlyTyped) {
|
||||
if (dataForTesting != null) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
dataForTesting!.typeInferenceResult.inferredVariableTypes[node] =
|
||||
dataForTesting!
|
||||
.typeInferenceResult
|
||||
.inferredVariableTypes[internalVariable] =
|
||||
inferredType;
|
||||
}
|
||||
node.type = inferredType;
|
||||
internalVariable.type = inferredType;
|
||||
}
|
||||
flowAnalysis.declare(
|
||||
nodeVariable.astVariable,
|
||||
new SharedTypeView(node.type),
|
||||
initialized: node.hasDeclaredInitializer,
|
||||
internalVariable.astVariable,
|
||||
new SharedTypeView(internalVariable.type),
|
||||
initialized: internalVariable.hasDeclaredInitializer,
|
||||
);
|
||||
if (initializerResult != null) {
|
||||
DartType initializerType = initializerResult.inferredType;
|
||||
flowAnalysis.initialize(
|
||||
nodeVariable.astVariable,
|
||||
internalVariable.astVariable,
|
||||
new SharedTypeView(initializerType),
|
||||
flowAnalysis.getExpressionInfo(initializerResult.expression),
|
||||
isFinal: node.isFinal,
|
||||
isLate: node.isLate,
|
||||
isImplicitlyTyped: nodeVariable.isImplicitlyTyped,
|
||||
isFinal: internalVariable.isFinal,
|
||||
isLate: internalVariable.isLate,
|
||||
isImplicitlyTyped: internalVariable.isImplicitlyTyped,
|
||||
);
|
||||
initializerResult = ensureAssignableResult(
|
||||
node.type,
|
||||
internalVariable.type,
|
||||
initializerResult,
|
||||
fileOffset: node.fileOffset,
|
||||
isVoidAllowed: node.type is VoidType,
|
||||
fileOffset: internalVariable.fileOffset,
|
||||
isVoidAllowed: internalVariable.type is VoidType,
|
||||
);
|
||||
Expression initializer = initializerResult.expression;
|
||||
node.initializer = initializer..parent = node;
|
||||
internalVariable.initializer = initializer..parent = internalVariable;
|
||||
}
|
||||
if (node.isLate &&
|
||||
if (internalVariable.isLate &&
|
||||
libraryBuilder.loader.target.backendTarget.isLateLocalLoweringEnabled(
|
||||
hasInitializer: node.hasDeclaredInitializer,
|
||||
isFinal: node.isFinal,
|
||||
isPotentiallyNullable: node.type.isPotentiallyNullable,
|
||||
hasInitializer: internalVariable.hasDeclaredInitializer,
|
||||
isFinal: internalVariable.isFinal,
|
||||
isPotentiallyNullable: internalVariable.type.isPotentiallyNullable,
|
||||
)) {
|
||||
int fileOffset = node.fileOffset;
|
||||
int fileOffset = internalVariable.fileOffset;
|
||||
|
||||
List<VariableDeclaration> variableDeclarations = [];
|
||||
List<FunctionDeclaration> functionDeclarations = [];
|
||||
variableDeclarations.add(variableDeclaration);
|
||||
variableDeclarations.add(
|
||||
extern.createVariableDeclaration(
|
||||
internalVariable.astVariable,
|
||||
fileOffset: variableDeclaration.fileOffset,
|
||||
),
|
||||
);
|
||||
|
||||
late_lowering.IsSetEncoding isSetEncoding = late_lowering
|
||||
.computeIsSetEncoding(
|
||||
node.type,
|
||||
internalVariable.type,
|
||||
late_lowering.computeIsSetStrategy(libraryBuilder),
|
||||
);
|
||||
Variable? isSetVariable;
|
||||
if (isSetEncoding == late_lowering.IsSetEncoding.useIsSetField) {
|
||||
isSetVariable = new Variable(
|
||||
late_lowering.computeLateLocalIsSetName(node.name!),
|
||||
late_lowering.computeLateLocalIsSetName(
|
||||
internalVariable.cosmeticName!,
|
||||
),
|
||||
initializer: new BoolLiteral(false)..fileOffset = fileOffset,
|
||||
type: coreTypes.boolRawType(Nullability.nonNullable),
|
||||
isLowered: true,
|
||||
@@ -17418,45 +17528,50 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
Expression createVariableRead({bool needsPromotion = false}) {
|
||||
if (needsPromotion) {
|
||||
return new VariableGet(node.variable, node.type)
|
||||
..fileOffset = fileOffset;
|
||||
return new VariableGet(
|
||||
internalVariable.variable,
|
||||
internalVariable.type,
|
||||
)..fileOffset = fileOffset;
|
||||
} else {
|
||||
return new VariableGet(node.variable)..fileOffset = fileOffset;
|
||||
return new VariableGet(internalVariable.variable)
|
||||
..fileOffset = fileOffset;
|
||||
}
|
||||
}
|
||||
|
||||
Expression createIsSetRead() =>
|
||||
new VariableGet(isSetVariable!)..fileOffset = fileOffset;
|
||||
Expression createVariableWrite(Expression value) =>
|
||||
new VariableSet(node.variable, value);
|
||||
new VariableSet(internalVariable.variable, value);
|
||||
Expression createIsSetWrite(Expression value) =>
|
||||
new VariableSet(isSetVariable!, value);
|
||||
|
||||
Variable getVariable = new Variable(
|
||||
late_lowering.computeLateLocalGetterName(node.name!),
|
||||
late_lowering.computeLateLocalGetterName(
|
||||
internalVariable.cosmeticName!,
|
||||
),
|
||||
isLowered: true,
|
||||
)..fileOffset = fileOffset;
|
||||
FunctionDeclaration getter = new FunctionDeclaration(
|
||||
getVariable,
|
||||
new FunctionNode(
|
||||
node.initializer == null
|
||||
internalVariable.initializer == null
|
||||
? late_lowering.createGetterBodyWithoutInitializer(
|
||||
coreTypes,
|
||||
fileOffset,
|
||||
node.name!,
|
||||
node.type,
|
||||
internalVariable.cosmeticName!,
|
||||
internalVariable.type,
|
||||
createVariableRead: createVariableRead,
|
||||
createIsSetRead: createIsSetRead,
|
||||
isSetEncoding: isSetEncoding,
|
||||
forField: false,
|
||||
)
|
||||
: (node.isFinal
|
||||
: (internalVariable.isFinal
|
||||
? late_lowering.createGetterWithInitializerWithRecheck(
|
||||
coreTypes,
|
||||
fileOffset,
|
||||
node.name!,
|
||||
node.type,
|
||||
node.initializer!,
|
||||
internalVariable.cosmeticName!,
|
||||
internalVariable.type,
|
||||
internalVariable.initializer!,
|
||||
createVariableRead: createVariableRead,
|
||||
createVariableWrite: createVariableWrite,
|
||||
createIsSetRead: createIsSetRead,
|
||||
@@ -17467,45 +17582,47 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
: late_lowering.createGetterWithInitializer(
|
||||
coreTypes,
|
||||
fileOffset,
|
||||
node.name!,
|
||||
node.type,
|
||||
node.initializer!,
|
||||
internalVariable.cosmeticName!,
|
||||
internalVariable.type,
|
||||
internalVariable.initializer!,
|
||||
createVariableRead: createVariableRead,
|
||||
createVariableWrite: createVariableWrite,
|
||||
createIsSetRead: createIsSetRead,
|
||||
createIsSetWrite: createIsSetWrite,
|
||||
isSetEncoding: isSetEncoding,
|
||||
)),
|
||||
returnType: node.type,
|
||||
),
|
||||
returnType: internalVariable.type,
|
||||
)..capturedContexts = capturedContexts,
|
||||
)..fileOffset = fileOffset;
|
||||
getVariable.type = getter.function.computeFunctionType(
|
||||
Nullability.nonNullable,
|
||||
);
|
||||
nodeVariable.lateGetter = getVariable;
|
||||
internalVariable.lateGetter = getVariable;
|
||||
functionDeclarations.add(getter);
|
||||
|
||||
if (!node.isFinal || node.initializer == null) {
|
||||
nodeVariable.isLateFinalWithoutInitializer =
|
||||
node.isFinal && node.initializer == null;
|
||||
if (!internalVariable.isFinal || internalVariable.initializer == null) {
|
||||
internalVariable.isLateFinalWithoutInitializer =
|
||||
internalVariable.isFinal && internalVariable.initializer == null;
|
||||
Variable setVariable = new Variable(
|
||||
late_lowering.computeLateLocalSetterName(node.name!),
|
||||
late_lowering.computeLateLocalSetterName(
|
||||
internalVariable.cosmeticName!,
|
||||
),
|
||||
isLowered: true,
|
||||
)..fileOffset = fileOffset;
|
||||
Variable setterParameter = new Variable(
|
||||
"${node.name}#param",
|
||||
type: node.type,
|
||||
"${internalVariable.cosmeticName}#param",
|
||||
type: internalVariable.type,
|
||||
)..fileOffset = fileOffset;
|
||||
FunctionDeclaration setter = new FunctionDeclaration(
|
||||
setVariable,
|
||||
new FunctionNode(
|
||||
node.isFinal
|
||||
internalVariable.isFinal
|
||||
? late_lowering.createSetterBodyFinal(
|
||||
coreTypes,
|
||||
fileOffset,
|
||||
node.name!,
|
||||
internalVariable.cosmeticName!,
|
||||
setterParameter,
|
||||
node.type,
|
||||
internalVariable.type,
|
||||
shouldReturnValue: true,
|
||||
createVariableRead: createVariableRead,
|
||||
createVariableWrite: createVariableWrite,
|
||||
@@ -17517,9 +17634,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
: late_lowering.createSetterBody(
|
||||
coreTypes,
|
||||
fileOffset,
|
||||
node.name!,
|
||||
internalVariable.cosmeticName!,
|
||||
setterParameter,
|
||||
node.type,
|
||||
internalVariable.type,
|
||||
shouldReturnValue: true,
|
||||
createVariableWrite: createVariableWrite,
|
||||
createIsSetWrite: createIsSetWrite,
|
||||
@@ -17535,34 +17652,43 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
setVariable.type = setter.function.computeFunctionType(
|
||||
Nullability.nonNullable,
|
||||
);
|
||||
nodeVariable.lateSetter = setVariable;
|
||||
internalVariable.lateSetter = setVariable;
|
||||
functionDeclarations.add(setter);
|
||||
}
|
||||
node.isLate = false;
|
||||
nodeVariable.lateType = node.type;
|
||||
internalVariable.isLate = false;
|
||||
internalVariable.lateType = internalVariable.type;
|
||||
if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
|
||||
node.initializer =
|
||||
internalVariable.initializer =
|
||||
new StaticInvocation(
|
||||
coreTypes.createSentinelMethod,
|
||||
new Arguments([], types: [node.type])..fileOffset = fileOffset,
|
||||
new Arguments([], types: [internalVariable.type])
|
||||
..fileOffset = fileOffset,
|
||||
)
|
||||
..fileOffset = fileOffset
|
||||
..parent = node;
|
||||
..parent = internalVariable;
|
||||
} else {
|
||||
node.initializer = null;
|
||||
internalVariable.initializer = null;
|
||||
}
|
||||
node.type = computeNullable(node.type);
|
||||
nodeVariable.lateName = node.name;
|
||||
node.isLowered = true;
|
||||
node.name = late_lowering.computeLateLocalName(node.name!);
|
||||
internalVariable.type = computeNullable(internalVariable.type);
|
||||
internalVariable.lateName = internalVariable.cosmeticName;
|
||||
internalVariable.isLowered = true;
|
||||
internalVariable.cosmeticName = late_lowering.computeLateLocalName(
|
||||
internalVariable.cosmeticName!,
|
||||
);
|
||||
|
||||
return new VariableDeclarationInferenceResult.late(
|
||||
variableDeclarations,
|
||||
functionDeclarations,
|
||||
fileOffset: node.fileOffset,
|
||||
fileOffset: internalVariable.fileOffset,
|
||||
);
|
||||
}
|
||||
return const VariableDeclarationInferenceResult();
|
||||
return new VariableDeclarationInferenceResult.direct(
|
||||
extern.createVariableDeclaration(
|
||||
internalVariable.astVariable,
|
||||
capturedContexts: capturedContexts,
|
||||
fileOffset: variableDeclaration.fileOffset,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -225,17 +225,31 @@ void main() {
|
||||
void _testVariableDeclarations() {
|
||||
testStatement(
|
||||
forest.variablesDeclaration([
|
||||
new VariableDeclaration(new Variable('a')),
|
||||
new VariableDeclaration(new Variable('b')),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('a', fileOffset: TreeNode.noOffset),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: TreeNode.noOffset),
|
||||
),
|
||||
], dummyUri),
|
||||
'''
|
||||
dynamic a, b;''',
|
||||
);
|
||||
testStatement(
|
||||
forest.variablesDeclaration([
|
||||
new VariableDeclaration(new Variable('a', type: const VoidType())),
|
||||
new VariableDeclaration(
|
||||
new Variable('b', initializer: new NullLiteral()),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'a',
|
||||
type: const VoidType(),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'b',
|
||||
initializer: new NullLiteral(),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
], dummyUri),
|
||||
'''
|
||||
@@ -378,7 +392,7 @@ void _testInternalForInStatement() {
|
||||
testStatement(
|
||||
new InternalForInStatement(
|
||||
new SingleVariableDeclarationForInElement(
|
||||
variableDeclaration: new VariableDeclaration(
|
||||
variableDeclaration: new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('e', fileOffset: -1),
|
||||
),
|
||||
error: null,
|
||||
@@ -396,7 +410,7 @@ for (var e in null) {}''',
|
||||
testStatement(
|
||||
new InternalForInStatement(
|
||||
new SingleVariableDeclarationForInElement(
|
||||
variableDeclaration: new VariableDeclaration(
|
||||
variableDeclaration: new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'e',
|
||||
type: const VoidType(),
|
||||
@@ -542,10 +556,10 @@ for (null in null) {}''',
|
||||
new InternalForInStatement(
|
||||
new MultiVariableDeclarationForInElement(
|
||||
variableDeclarations: [
|
||||
new VariableDeclaration(
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('a', fileOffset: -1),
|
||||
),
|
||||
new VariableDeclaration(
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: -1),
|
||||
),
|
||||
],
|
||||
@@ -565,14 +579,14 @@ for (var a, b in null) {}''',
|
||||
new InternalForInStatement(
|
||||
new MultiVariableDeclarationForInElement(
|
||||
variableDeclarations: [
|
||||
new VariableDeclaration(
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'a',
|
||||
type: const VoidType(),
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
new VariableDeclaration(
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: -1),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1482,8 +1482,6 @@ class VariableStatement extends Statement {
|
||||
..parent = this;
|
||||
}
|
||||
|
||||
/// Returns a possibly synthesized name for this variable, consistent with
|
||||
/// the names used across all [toString] calls.
|
||||
@override
|
||||
String toString() {
|
||||
return "VariableStatement(${toStringInternal()})";
|
||||
|
||||
@@ -71,7 +71,6 @@ abstract interface class IVariable implements TreeNode, Annotatable {
|
||||
bool get hasIsWildcard;
|
||||
bool get hasIsSuperInitializingFormal;
|
||||
bool get hasIsErroneouslyInitialized;
|
||||
Variable get asVariableDeclaration;
|
||||
}
|
||||
|
||||
/// The root of the sealed hierarchy of non-type variables.
|
||||
@@ -186,9 +185,6 @@ sealed class Variable extends VariableBase
|
||||
@override
|
||||
bool get isAssignable;
|
||||
|
||||
@override
|
||||
Variable get asVariableDeclaration => this;
|
||||
|
||||
abstract String? name;
|
||||
|
||||
@override
|
||||
@@ -646,9 +642,6 @@ class LegacyVariable extends TreeNode implements Variable, Annotatable {
|
||||
throw new UnsupportedError("${this.runtimeType}.context=");
|
||||
}
|
||||
|
||||
@override
|
||||
Variable get asVariableDeclaration => this;
|
||||
|
||||
@override
|
||||
Variable get variable => this;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user