blob: e90516ef209bd2e979e6e696fa246f509cd29031 [file] [log] [blame]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
import 'package:_fe_analyzer_shared/src/type_inference/promotion_key_store.dart';
import 'package:kernel/ast.dart';
class AssignedVariablesImpl
implements AssignedVariables<TreeNode, ExpressionVariable> {
final AssignedVariables<TreeNode, ExpressionVariable> _delegate;
final AssignedVariables<TreeNode, ExpressionVariable>? _insideAsserts;
final AssignedVariables<TreeNode, ExpressionVariable>? _outsideAsserts;
int _assertDepth = 0;
final Map<AssignedVariablesNodeInfo, AssignedVariablesNodeInfo>?
_deferredInsideAssertsByDeferredDelegate;
final Map<AssignedVariablesNodeInfo, AssignedVariablesNodeInfo>?
_deferredOutsideAssertsByDeferredDelegate;
AssignedVariablesImpl(
this._delegate, {
required bool isClosureContextLoweringEnabled,
}) : _insideAsserts = isClosureContextLoweringEnabled
? new AssignedVariables<TreeNode, ExpressionVariable>()
: null,
_outsideAsserts = isClosureContextLoweringEnabled
? new AssignedVariables<TreeNode, ExpressionVariable>()
: null,
_deferredInsideAssertsByDeferredDelegate =
isClosureContextLoweringEnabled
? new Map<
AssignedVariablesNodeInfo,
AssignedVariablesNodeInfo
>.identity()
: null,
_deferredOutsideAssertsByDeferredDelegate =
isClosureContextLoweringEnabled
? new Map<
AssignedVariablesNodeInfo,
AssignedVariablesNodeInfo
>.identity()
: null;
bool get _isInsideAssert => _assertDepth > 0;
void enterAssert() {
_assertDepth++;
}
void exitAssert() {
_assertDepth--;
}
@override
AssignedVariablesNodeInfo get anywhere {
return _delegate.anywhere;
}
AssignedVariablesNodeInfo get insideAsserts {
return _insideAsserts!.anywhere;
}
AssignedVariablesNodeInfo get outsideAsserts {
return _outsideAsserts!.anywhere;
}
@override
void beginNode() {
_delegate.beginNode();
_insideAsserts?.beginNode();
_outsideAsserts?.beginNode();
}
@override
void declare(ExpressionVariable variable, {bool ignoreDuplicates = false}) {
_delegate.declare(variable, ignoreDuplicates: ignoreDuplicates);
_insideAsserts?.declare(variable, ignoreDuplicates: ignoreDuplicates);
_outsideAsserts?.declare(variable, ignoreDuplicates: ignoreDuplicates);
}
@override
AssignedVariablesNodeInfo deferNode({
bool isClosureOrLateVariableInitializer = false,
}) {
AssignedVariablesNodeInfo delegateDeferred = _delegate.deferNode(
isClosureOrLateVariableInitializer: isClosureOrLateVariableInitializer,
);
_deferredInsideAssertsByDeferredDelegate?[delegateDeferred] =
_insideAsserts!.deferNode(
isClosureOrLateVariableInitializer:
isClosureOrLateVariableInitializer,
);
_deferredOutsideAssertsByDeferredDelegate?[delegateDeferred] =
_outsideAsserts!.deferNode(
isClosureOrLateVariableInitializer:
isClosureOrLateVariableInitializer,
);
return delegateDeferred;
}
@override
void discardNode() {
_delegate.discardNode();
_insideAsserts
// Coverage-ignore(suite): Not run.
?.discardNode();
_outsideAsserts
// Coverage-ignore(suite): Not run.
?.discardNode();
}
@override
void endNode(
TreeNode node, {
bool isClosureOrLateVariableInitializer = false,
}) {
_delegate.endNode(
node,
isClosureOrLateVariableInitializer: isClosureOrLateVariableInitializer,
);
_insideAsserts?.endNode(
node,
isClosureOrLateVariableInitializer: isClosureOrLateVariableInitializer,
);
_outsideAsserts?.endNode(
node,
isClosureOrLateVariableInitializer: isClosureOrLateVariableInitializer,
);
}
@override
void finish() {
_delegate.finish();
_insideAsserts?.finish();
_outsideAsserts?.finish();
}
@override
AssignedVariablesNodeInfo getInfoForNode(TreeNode node) {
return _delegate.getInfoForNode(node);
}
@override
bool get isFinished {
return _delegate.isFinished;
}
@override
AssignedVariablesNodeInfo popNode() {
_insideAsserts?.popNode();
_outsideAsserts?.popNode();
return _delegate.popNode();
}
@override
PromotionKeyStore<ExpressionVariable> get promotionKeyStore {
return _delegate.promotionKeyStore;
}
@override
void pushNode(AssignedVariablesNodeInfo node) {
_delegate.pushNode(node);
_insideAsserts?.pushNode(node);
_outsideAsserts?.pushNode(node);
}
@override
void read(ExpressionVariable variable) {
_delegate.read(variable);
if (_isInsideAssert) {
_insideAsserts?.read(variable);
} else {
_outsideAsserts?.read(variable);
}
}
@override
void reassignInfo(TreeNode from, TreeNode to) {
_delegate.reassignInfo(from, to);
_insideAsserts
// Coverage-ignore(suite): Not run.
?.reassignInfo(from, to);
_outsideAsserts
// Coverage-ignore(suite): Not run.
?.reassignInfo(from, to);
}
@override
void storeInfo(TreeNode node, AssignedVariablesNodeInfo info) {
assert(_deferredInsideAssertsByDeferredDelegate?.containsKey(info) ?? true);
assert(
_deferredOutsideAssertsByDeferredDelegate?.containsKey(info) ?? true,
);
_delegate.storeInfo(node, info);
_insideAsserts?.storeInfo(
node,
_deferredInsideAssertsByDeferredDelegate!.remove(info)!,
);
_outsideAsserts?.storeInfo(
node,
_deferredOutsideAssertsByDeferredDelegate!.remove(info)!,
);
}
@override
void write(ExpressionVariable variable) {
_delegate.write(variable);
if (_isInsideAssert) {
// Coverage-ignore-block(suite): Not run.
_insideAsserts?.write(variable);
} else {
_outsideAsserts?.write(variable);
}
}
}