| // Copyright (c) 2018, 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/util/dependency_walker.dart' as graph |
| show DependencyWalker, Node; |
| import 'package:analyzer/dart/analysis/declared_variables.dart'; |
| import 'package:analyzer/dart/analysis/features.dart'; |
| import 'package:analyzer/src/dart/constant/evaluation.dart'; |
| import 'package:analyzer/src/dart/element/element.dart'; |
| |
| /// Compute values of the given [constants] with correct ordering. |
| void computeConstants(DeclaredVariables declaredVariables, |
| List<ConstantEvaluationTarget> constants, FeatureSet featureSet) { |
| var walker = _ConstantWalker(declaredVariables, featureSet); |
| |
| for (var constant in constants) { |
| walker.walk(walker._getNode(constant)); |
| } |
| } |
| |
| /// [graph.Node] that is used to compute constants in dependency order. |
| class _ConstantNode extends graph.Node<_ConstantNode> { |
| final _ConstantWalker walker; |
| final ConstantEvaluationTarget constant; |
| |
| _ConstantNode(this.walker, this.constant); |
| |
| @override |
| bool get isEvaluated => constant.isConstantEvaluated; |
| |
| @override |
| List<_ConstantNode> computeDependencies() { |
| return walker._computeDependencies(this); |
| } |
| } |
| |
| /// [graph.DependencyWalker] for computing constants and detecting cycles. |
| class _ConstantWalker extends graph.DependencyWalker<_ConstantNode> { |
| final DeclaredVariables declaredVariables; |
| final FeatureSet featureSet; |
| final Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {}; |
| |
| _ConstantWalker(this.declaredVariables, this.featureSet); |
| |
| @override |
| void evaluate(_ConstantNode node) { |
| _getEvaluationEngine(node).computeConstantValue(node.constant); |
| } |
| |
| @override |
| void evaluateScc(List<_ConstantNode> scc) { |
| var constantsInCycle = scc.map((node) => node.constant); |
| for (var node in scc) { |
| var constant = node.constant; |
| if (constant is ConstructorElementImpl) { |
| constant.isCycleFree = false; |
| } |
| _getEvaluationEngine(node).generateCycleError(constantsInCycle, constant); |
| } |
| } |
| |
| List<_ConstantNode> _computeDependencies(_ConstantNode node) { |
| var evaluationEngine = _getEvaluationEngine(node); |
| var targets = <ConstantEvaluationTarget>[]; |
| evaluationEngine.computeDependencies(node.constant, targets.add); |
| return targets.map(_getNode).toList(); |
| } |
| |
| ConstantEvaluationEngine _getEvaluationEngine(_ConstantNode node) { |
| return ConstantEvaluationEngine( |
| declaredVariables: declaredVariables, |
| isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable), |
| ); |
| } |
| |
| _ConstantNode _getNode(ConstantEvaluationTarget constant) { |
| return nodeMap.putIfAbsent( |
| constant, |
| () => _ConstantNode(this, constant), |
| ); |
| } |
| } |