Don't use variableElement.computeConstantValue() in ConstantVisitor.
...when we are using Analysis Driver.
This method causes switching to the task-model based way of computing
constants. And so filling SdkAnalysisContext with data. And because
SDK instances are long-lived, we were keeping this data as well.
R=brianwilkerson@google.com
Change-Id: Ie6f4a4ce8a05238b9640aef961af394d64373573
Reviewed-on: https://dart-review.googlesource.com/c/78420
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index f28c8c5..bdd8592 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -60,7 +60,7 @@
final List<UsedImportedElements> _usedImportedElementsList = [];
final List<UsedLocalElements> _usedLocalElementsList = [];
final Map<FileState, List<PendingError>> _fileToPendingErrors = {};
- final List<ConstantEvaluationTarget> _constants = [];
+ final Set<ConstantEvaluationTarget> _constants = new Set();
LibraryAnalyzer(
this._analysisOptions,
@@ -162,7 +162,8 @@
void _computeConstantErrors(
ErrorReporter errorReporter, CompilationUnit unit) {
ConstantVerifier constantVerifier = new ConstantVerifier(
- errorReporter, _libraryElement, _typeProvider, _declaredVariables);
+ errorReporter, _libraryElement, _typeProvider, _declaredVariables,
+ forAnalysisDriver: true);
unit.accept(constantVerifier);
}
@@ -172,7 +173,7 @@
void _computeConstants() {
ConstantEvaluationEngine evaluationEngine = new ConstantEvaluationEngine(
_typeProvider, _declaredVariables,
- typeSystem: _context.typeSystem);
+ forAnalysisDriver: true, typeSystem: _context.typeSystem);
List<_ConstantNode> nodes = [];
Map<ConstantEvaluationTarget, _ConstantNode> nodeMap = {};
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 2b66eb0..d333f97 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -51,17 +51,23 @@
/// The current library that is being analyzed.
final LibraryElement _currentLibrary;
+ ConstantEvaluationEngine _evaluationEngine;
+
/// Initialize a newly created constant verifier.
///
/// @param errorReporter the error reporter by which errors will be reported
ConstantVerifier(this._errorReporter, LibraryElement currentLibrary,
- this._typeProvider, this.declaredVariables)
+ this._typeProvider, this.declaredVariables,
+ {bool forAnalysisDriver: false})
: _currentLibrary = currentLibrary,
_typeSystem = currentLibrary.context.typeSystem {
this._boolType = _typeProvider.boolType;
this._intType = _typeProvider.intType;
this._numType = _typeProvider.numType;
this._stringType = _typeProvider.stringType;
+ this._evaluationEngine = new ConstantEvaluationEngine(
+ _typeProvider, declaredVariables,
+ forAnalysisDriver: forAnalysisDriver, typeSystem: _typeSystem);
}
@override
@@ -123,12 +129,9 @@
// evaluation.
ConstructorElement constructor = node.staticElement;
if (constructor != null) {
- ConstantEvaluationEngine evaluationEngine =
- new ConstantEvaluationEngine(_typeProvider, declaredVariables,
- typeSystem: _typeSystem);
ConstantVisitor constantVisitor =
- new ConstantVisitor(evaluationEngine, _errorReporter);
- evaluationEngine.evaluateConstructorCall(
+ new ConstantVisitor(_evaluationEngine, _errorReporter);
+ _evaluationEngine.evaluateConstructorCall(
node,
node.argumentList.arguments,
constructor,
@@ -204,10 +207,8 @@
AnalysisErrorListener.NULL_LISTENER;
ErrorReporter subErrorReporter =
new ErrorReporter(errorListener, _errorReporter.source);
- DartObjectImpl result = key.accept(new ConstantVisitor(
- new ConstantEvaluationEngine(_typeProvider, declaredVariables,
- typeSystem: _typeSystem),
- subErrorReporter));
+ DartObjectImpl result = key
+ .accept(new ConstantVisitor(_evaluationEngine, subErrorReporter));
if (result != null) {
if (keys.contains(result)) {
invalidKeys.add(key);
@@ -444,10 +445,8 @@
RecordingErrorListener errorListener = new RecordingErrorListener();
ErrorReporter subErrorReporter =
new ErrorReporter(errorListener, _errorReporter.source);
- DartObjectImpl result = expression.accept(new ConstantVisitor(
- new ConstantEvaluationEngine(_typeProvider, declaredVariables,
- typeSystem: _typeSystem),
- subErrorReporter));
+ DartObjectImpl result = expression
+ .accept(new ConstantVisitor(_evaluationEngine, subErrorReporter));
_reportErrors(errorListener.errors, errorCode);
return result;
}
@@ -545,10 +544,8 @@
AnalysisErrorListener.NULL_LISTENER;
ErrorReporter subErrorReporter =
new ErrorReporter(errorListener, _errorReporter.source);
- DartObjectImpl result = initializer.accept(new ConstantVisitor(
- new ConstantEvaluationEngine(_typeProvider, declaredVariables,
- typeSystem: _typeSystem),
- subErrorReporter));
+ DartObjectImpl result = initializer.accept(
+ new ConstantVisitor(_evaluationEngine, subErrorReporter));
if (result == null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode
@@ -574,9 +571,8 @@
ErrorReporter subErrorReporter =
new ErrorReporter(errorListener, _errorReporter.source);
DartObjectImpl result = expression.accept(
- new _ConstantVerifier_validateInitializerExpression(_typeProvider,
- subErrorReporter, this, parameterElements, declaredVariables,
- typeSystem: _typeSystem));
+ new _ConstantVerifier_validateInitializerExpression(_typeSystem,
+ _evaluationEngine, subErrorReporter, this, parameterElements));
_reportErrors(errorListener.errors,
CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER);
if (result != null) {
@@ -606,24 +602,18 @@
}
class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor {
+ final TypeSystem typeSystem;
final ConstantVerifier verifier;
List<ParameterElement> parameterElements;
- TypeSystem _typeSystem;
-
_ConstantVerifier_validateInitializerExpression(
- TypeProvider typeProvider,
+ this.typeSystem,
+ ConstantEvaluationEngine evaluationEngine,
ErrorReporter errorReporter,
this.verifier,
- this.parameterElements,
- DeclaredVariables declaredVariables,
- {TypeSystem typeSystem})
- : _typeSystem = typeSystem ?? new StrongTypeSystemImpl(typeProvider),
- super(
- new ConstantEvaluationEngine(typeProvider, declaredVariables,
- typeSystem: typeSystem),
- errorReporter);
+ this.parameterElements)
+ : super(evaluationEngine, errorReporter);
@override
DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
@@ -637,20 +627,20 @@
if (type.isDynamic) {
return new DartObjectImpl(
verifier._typeProvider.objectType, DynamicState.DYNAMIC_STATE);
- } else if (_typeSystem.isSubtypeOf(type, verifier._boolType)) {
+ } else if (typeSystem.isSubtypeOf(type, verifier._boolType)) {
return new DartObjectImpl(
verifier._typeProvider.boolType, BoolState.UNKNOWN_VALUE);
- } else if (_typeSystem.isSubtypeOf(
+ } else if (typeSystem.isSubtypeOf(
type, verifier._typeProvider.doubleType)) {
return new DartObjectImpl(
verifier._typeProvider.doubleType, DoubleState.UNKNOWN_VALUE);
- } else if (_typeSystem.isSubtypeOf(type, verifier._intType)) {
+ } else if (typeSystem.isSubtypeOf(type, verifier._intType)) {
return new DartObjectImpl(
verifier._typeProvider.intType, IntState.UNKNOWN_VALUE);
- } else if (_typeSystem.isSubtypeOf(type, verifier._numType)) {
+ } else if (typeSystem.isSubtypeOf(type, verifier._numType)) {
return new DartObjectImpl(
verifier._typeProvider.numType, NumState.UNKNOWN_VALUE);
- } else if (_typeSystem.isSubtypeOf(type, verifier._stringType)) {
+ } else if (typeSystem.isSubtypeOf(type, verifier._stringType)) {
return new DartObjectImpl(
verifier._typeProvider.stringType, StringState.UNKNOWN_VALUE);
}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 80330a4..c016009 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -90,6 +90,11 @@
final ConstantEvaluationValidator validator;
/**
+ * Whether this engine is used inside Analysis Driver.
+ */
+ final bool forAnalysisDriver;
+
+ /**
* Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
* is used to access known types. [_declaredVariables] is the set of
* variables declared on the command line using '-D'. The [validator], if
@@ -97,7 +102,9 @@
* tests.
*/
ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
- {ConstantEvaluationValidator validator, TypeSystem typeSystem})
+ {ConstantEvaluationValidator validator,
+ TypeSystem typeSystem,
+ this.forAnalysisDriver: false})
: typeProvider = typeProvider,
validator =
validator ?? new ConstantEvaluationValidator_ForProduction(),
@@ -1070,7 +1077,7 @@
/**
* Convenience getter to gain access to the [evaluationEngine]'s type system.
*/
- TypeSystem get _typeSystem => evaluationEngine.typeSystem;
+ TypeSystem get typeSystem => evaluationEngine.typeSystem;
/**
* Given a [type] that may contain free type variables, evaluate them against
@@ -1211,8 +1218,8 @@
}
ParameterizedType thenType = thenResult.type;
ParameterizedType elseType = elseResult.type;
- return new DartObjectImpl.validWithUnknownValue(_typeSystem
- .getLeastUpperBound(thenType, elseType) as ParameterizedType);
+ return new DartObjectImpl.validWithUnknownValue(
+ typeSystem.getLeastUpperBound(thenType, elseType) as ParameterizedType);
}
@override
@@ -1502,11 +1509,23 @@
Element variableElement =
element is PropertyAccessorElement ? element.variable : element;
if (variableElement is VariableElementImpl) {
- evaluationEngine.validator.beforeGetEvaluationResult(variableElement);
- variableElement.computeConstantValue();
- EvaluationResultImpl value = variableElement.evaluationResult;
- if (variableElement.isConst && value != null) {
- return value.value;
+ // We access values of constant variables here in two cases: when we
+ // compute values of other constant variables, or when we compute values
+ // and errors for other constant expressions. In any case, with Analysis
+ // Driver, we compute values of all dependencies first (or detect cycle).
+ // So, the value has already been computed. Just return it.
+ if (evaluationEngine.forAnalysisDriver) {
+ if (variableElement.isConst) {
+ return variableElement.evaluationResult.value;
+ }
+ } else {
+ // TODO(scheglov) Once we remove task model, we can remove this code.
+ evaluationEngine.validator.beforeGetEvaluationResult(variableElement);
+ variableElement.computeConstantValue();
+ EvaluationResultImpl value = variableElement.evaluationResult;
+ if (variableElement.isConst && value != null) {
+ return value.value;
+ }
}
} else if (variableElement is ExecutableElement) {
ExecutableElement function = element;
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 81f3e41..50480ad 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -164,6 +164,10 @@
if (node.isConst) {
_find(node);
} else {
+ // Values of keys are computed to check that they are unique.
+ for (var entry in node.entries) {
+ _find(entry.key);
+ }
super.visitMapLiteral(node);
}
}
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 679ca15..e4e4784 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -5555,6 +5555,24 @@
verify([source]);
}
+ test_recursiveCompileTimeConstant_fromMapLiteral() async {
+ resourceProvider.newFile(
+ resourceProvider.convertPath('/constants.dart'),
+ r'''
+const int x = y;
+const int y = x;
+''',
+ );
+ Source source = addSource(r'''
+import 'constants.dart';
+final z = {x: 0, y: 1};
+''');
+ await computeAnalysisResult(source);
+ // No errors, because the cycle is not in this source.
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_recursiveCompileTimeConstant_initializer_after_toplevel_var() async {
Source source = addSource('''
const y = const C();
@@ -5587,6 +5605,28 @@
verify([source]);
}
+ test_recursiveCompileTimeConstant_singleVariable_fromConstList() async {
+ Source source = addSource(r'''
+const elems = const [
+ const [
+ 1, elems, 3,
+ ],
+];
+''');
+ await computeAnalysisResult(source);
+ if (!enableNewAnalysisDriver) {
+ assertErrors(source, [
+ CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
+ ]);
+ } else {
+ assertErrors(source, [
+ CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT,
+ StrongModeCode.TOP_LEVEL_CYCLE,
+ ]);
+ }
+ verify([source]);
+ }
+
test_recursiveConstructorRedirect() async {
Source source = addSource(r'''
class A {