analyzer: expose canBeConst and computeConstantValue as public API
Work towards https://github.com/dart-lang/sdk/issues/50986
These utilities are used by a handful of lint rules, and the analysis
server, which makes me think they could be offered as public API.
Change-Id: I12415c2b86ca6fb96b03def4a304da73c6fb4cae
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430300
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_color.dart b/pkg/analysis_server/lib/src/computer/computer_color.dart
index 19061c1..0d8294e 100644
--- a/pkg/analysis_server/lib/src/computer/computer_color.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_color.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/constant/value.dart' show GenericState;
-import 'package:analyzer/src/lint/constants.dart';
import 'package:analyzer/src/utilities/extensions/flutter.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;
@@ -51,8 +50,12 @@
// Try to evaluate the constant target.
var colorConstResult = target.computeConstantValue();
- var colorConst = colorConstResult.value;
- if (colorConstResult.errors.isNotEmpty || colorConst == null) return false;
+ var colorConst = colorConstResult?.value;
+ if (colorConstResult == null ||
+ colorConstResult.diagnostics.isNotEmpty ||
+ colorConst == null) {
+ return false;
+ }
// If we want a specific member or swatch index, read that.
if (memberName != null) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/handler_editable_arguments.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/handler_editable_arguments.dart
index 7394ae8..1b60b1f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/handler_editable_arguments.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/editable_arguments/handler_editable_arguments.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/lint/constants.dart';
/// Information about the values for a parameter/argument.
typedef _Values = ({DartObject? parameterValue, DartObject? argumentValue});
@@ -147,7 +146,7 @@
Expression? argumentExpression,
) {
var parameterValue = parameter.computeConstantValue();
- var argumentValue = argumentExpression?.computeConstantValue().value;
+ var argumentValue = argumentExpression?.computeConstantValue()?.value;
return (parameterValue: parameterValue, argumentValue: argumentValue);
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart
index 145d59a..a325889 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_const.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/source/source_range.dart';
-import 'package:analyzer/src/lint/constants.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_decorated_box.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_decorated_box.dart
index 311f854..97cb76f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_decorated_box.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_decorated_box.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
diff --git a/pkg/analyzer/api.txt b/pkg/analyzer/api.txt
index 4f3d512..26a14d6 100644
--- a/pkg/analyzer/api.txt
+++ b/pkg/analyzer/api.txt
@@ -1058,12 +1058,14 @@
exportKeyword (getter: Token)
libraryExport (getter: LibraryExport?, experimental)
Expression (class extends Object implements CollectionElement):
+ canBeConst (getter: bool)
correspondingParameter (getter: FormalParameterElement?, experimental)
inConstantContext (getter: bool)
isAssignable (getter: bool)
precedence (getter: Precedence)
staticType (getter: DartType?)
unParenthesized (getter: Expression)
+ computeConstantValue (method: AttemptedConstantEvaluationResult? Function())
ExpressionFunctionBody (class extends Object implements FunctionBody):
expression (getter: Expression)
functionDefinition (getter: Token)
@@ -5106,6 +5108,10 @@
status (getter: FeatureStatus)
stringForValue (method: String Function(bool))
toString (method: String Function())
+package:analyzer/src/dart/ast/ast.dart:
+ AttemptedConstantEvaluationResult (class extends Object):
+ diagnostics (getter: List<Diagnostic>)
+ value (getter: DartObject?)
package:analyzer/src/dart/constant/evaluation.dart:
ConstantEvaluationTarget (class extends Object):
new (constructor: ConstantEvaluationTarget Function())
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index bb023ac..004133a 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -19,21 +19,31 @@
import 'package:analyzer/dart/ast/precedence.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/compute.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
+import 'package:analyzer/src/error/codes.g.dart';
import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
import 'package:analyzer/src/generated/inference_log.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/lint/constants.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
@@ -1865,6 +1875,21 @@
R? visitYieldStatement(YieldStatement node);
}
+/// The result of attempting to evaluate an expression as a constant.
+@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
+final class AttemptedConstantEvaluationResult {
+ /// The value of the expression, or `null` if has [diagnostics].
+ ///
+ /// If evaluating a constant expression yields diagnostics, then the value of
+ /// the constant expression cannot be calculated.
+ final DartObject? value;
+
+ /// The diagnostics reported during the evaluation.
+ final List<Diagnostic> diagnostics;
+
+ AttemptedConstantEvaluationResult._(this.value, this.diagnostics);
+}
+
/// The augmented expression.
///
/// It is created only inside an augmentation.
@@ -8007,6 +8032,12 @@
/// | [ThrowExpression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Expression implements CollectionElement {
+ /// Whether it would be valid for this expression to have a `const` keyword.
+ ///
+ /// Note that this method can cause constant evaluation to occur, which can be
+ /// computationally expensive.
+ bool get canBeConst;
+
/// The parameter element representing the parameter to which the value of
/// this expression is bound.
///
@@ -8064,6 +8095,14 @@
/// unwrapping the expression inside the parentheses. Otherwise, returns this
/// expression.
Expression get unParenthesized;
+
+ /// Computes the constant value of this expression, if it has one.
+ ///
+ /// Returns a [AttemptedConstantEvaluationResult], containing both the computed
+ /// constant value, and a list of errors that occurred during the computation.
+ ///
+ /// Returns `null` if this expression is not a constant expression.
+ AttemptedConstantEvaluationResult? computeConstantValue();
}
/// A function body consisting of a single expression.
@@ -8215,6 +8254,9 @@
implements CollectionElementImpl, Expression {
TypeImpl? _staticType;
+ @override
+ bool get canBeConst => false;
+
@experimental
@override
FormalParameterElementMixin? get correspondingParameter {
@@ -8264,6 +8306,53 @@
@override
ExpressionImpl get unParenthesized => this;
+ @override
+ AttemptedConstantEvaluationResult? computeConstantValue() {
+ var unitNode = thisOrAncestorOfType<CompilationUnitImpl>();
+ var unitFragment = unitNode?.declaredFragment;
+ if (unitFragment == null) {
+ throw ArgumentError('This AST structure has not yet been resolved.');
+ }
+
+ var libraryElement = unitFragment.element;
+ var declaredVariables = libraryElement.session.declaredVariables;
+
+ var evaluationEngine = ConstantEvaluationEngine(
+ declaredVariables: declaredVariables,
+ configuration: ConstantEvaluationConfiguration(),
+ );
+
+ var dependencies = <ConstantEvaluationTarget>[];
+ accept(ReferenceFinder(dependencies.add));
+
+ computeConstants(
+ declaredVariables: declaredVariables,
+ constants: dependencies,
+ featureSet: libraryElement.featureSet,
+ configuration: ConstantEvaluationConfiguration(),
+ );
+
+ var errorListener = RecordingErrorListener();
+ var visitor = ConstantVisitor(
+ evaluationEngine,
+ libraryElement,
+ ErrorReporter(errorListener, unitFragment.source),
+ );
+
+ var constant = visitor.evaluateAndReportInvalidConstant(this);
+ var isInvalidConstant = errorListener.errors.any(
+ (e) => e.errorCode == CompileTimeErrorCode.INVALID_CONSTANT,
+ );
+ if (isInvalidConstant) {
+ return null;
+ }
+
+ return AttemptedConstantEvaluationResult._(
+ constant is DartObjectImpl ? constant : null,
+ errorListener.errors,
+ );
+ }
+
/// Returns the [AstNode] that puts node into the constant context, and
/// the explicit `const` keyword of that node. The keyword might be absent
/// if the constness is implicit.
@@ -14057,6 +14146,25 @@
return constructorName.beginToken;
}
+ @override
+ bool get canBeConst {
+ var element = constructorName.element;
+ if (element == null || !element.isConst) return false;
+
+ // Ensure that dependencies (e.g. default parameter values) are computed.
+ element.baseElement.computeConstantDependencies();
+
+ // Verify that the evaluation of the constructor would not produce an
+ // exception.
+ var oldKeyword = keyword;
+ try {
+ keyword = KeywordToken(Keyword.CONST, offset);
+ return !hasConstantVerifierError;
+ } finally {
+ keyword = oldKeyword;
+ }
+ }
+
@generated
@override
ConstructorNameImpl get constructorName => _constructorName;
@@ -24541,6 +24649,17 @@
}
@override
+ bool get canBeConst {
+ var oldKeyword = constKeyword;
+ try {
+ constKeyword = KeywordToken(Keyword.CONST, offset);
+ return !hasConstantVerifierError;
+ } finally {
+ constKeyword = oldKeyword;
+ }
+ }
+
+ @override
bool get isConst {
return constKeyword != null || inConstantContext;
}
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index b1360ee..6c1639f 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -33,7 +33,6 @@
import 'package:analyzer/src/error/must_call_super_verifier.dart';
import 'package:analyzer/src/error/null_safe_api_verifier.dart';
import 'package:analyzer/src/error/widget_preview_verifier.dart';
-import 'package:analyzer/src/lint/constants.dart';
import 'package:analyzer/src/utilities/extensions/ast.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/workspace/workspace.dart';
@@ -873,7 +872,7 @@
var alreadySeen = <DartObject>{};
for (var expression in expressions) {
var constEvaluation = expression.computeConstantValue();
- if (constEvaluation.errors.isEmpty) {
+ if (constEvaluation != null && constEvaluation.diagnostics.isEmpty) {
var value = constEvaluation.value;
if (value != null && !alreadySeen.add(value)) {
var errorCode =
diff --git a/pkg/analyzer/lib/src/lint/constants.dart b/pkg/analyzer/lib/src/lint/constants.dart
index 9f2aae2..1bbe1b8 100644
--- a/pkg/analyzer/lib/src/lint/constants.dart
+++ b/pkg/analyzer/lib/src/lint/constants.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
@@ -15,21 +14,8 @@
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/potentially_constant.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
-import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/error/codes.dart';
-/// The result of attempting to evaluate an expression as a constant.
-final class LinterConstantEvaluationResult {
- /// The value of the expression, or `null` if has [errors].
- final DartObject? value;
-
- /// The errors reported during the evaluation.
- // TODO(srawlins): Rename to `diagnostics`.
- final List<Diagnostic> errors;
-
- LinterConstantEvaluationResult._(this.value, this.errors);
-}
-
/// An error listener that only records whether any constant related errors have
/// been reported.
class _ConstantAnalysisErrorListener extends AnalysisErrorListener {
@@ -39,9 +25,9 @@
@override
void onError(Diagnostic error) {
- DiagnosticCode errorCode = error.errorCode;
- if (errorCode is CompileTimeErrorCode) {
- switch (errorCode) {
+ DiagnosticCode diagnosticCode = error.errorCode;
+ if (diagnosticCode is CompileTimeErrorCode) {
+ switch (diagnosticCode) {
case CompileTimeErrorCode
.CONST_CONSTRUCTOR_CONSTANT_FROM_DEFERRED_LIBRARY:
case CompileTimeErrorCode
@@ -85,7 +71,7 @@
}
}
-extension on AstNode {
+extension AstNodeExtension on AstNode {
/// Whether [ConstantVerifier] reports an error when computing the value of
/// `this` as a constant.
bool get hasConstantVerifierError {
@@ -134,88 +120,3 @@
}
}
}
-
-extension ExpressionExtension on Expression {
- /// Whether it would be valid for this expression to have a `const` keyword.
- ///
- /// Note that this method can cause constant evaluation to occur, which can be
- /// computationally expensive.
- bool get canBeConst {
- var self = this;
- return switch (self) {
- InstanceCreationExpressionImpl() => _canBeConstInstanceCreation(self),
- TypedLiteralImpl() => _canBeConstTypedLiteral(self),
- _ => false,
- };
- }
-
- /// Computes the constant value of `this`, if it has one.
- ///
- /// Returns a [LinterConstantEvaluationResult], containing both the computed
- /// constant value, and a list of errors that occurred during the computation.
- LinterConstantEvaluationResult computeConstantValue() {
- var unitNode = thisOrAncestorOfType<CompilationUnitImpl>();
- var unitFragment = unitNode?.declaredFragment;
- if (unitFragment == null) {
- return LinterConstantEvaluationResult._(null, []);
- }
-
- var libraryElement = unitFragment.element;
- var declaredVariables = libraryElement.session.declaredVariables;
-
- var evaluationEngine = ConstantEvaluationEngine(
- declaredVariables: declaredVariables,
- configuration: ConstantEvaluationConfiguration(),
- );
-
- var dependencies = <ConstantEvaluationTarget>[];
- accept(ReferenceFinder(dependencies.add));
-
- computeConstants(
- declaredVariables: declaredVariables,
- constants: dependencies,
- featureSet: libraryElement.featureSet,
- configuration: ConstantEvaluationConfiguration(),
- );
-
- var errorListener = RecordingErrorListener();
- var visitor = ConstantVisitor(
- evaluationEngine,
- libraryElement,
- ErrorReporter(errorListener, unitFragment.source),
- );
-
- var constant = visitor.evaluateAndReportInvalidConstant(this);
- var dartObject = constant is DartObjectImpl ? constant : null;
- return LinterConstantEvaluationResult._(dartObject, errorListener.errors);
- }
-
- bool _canBeConstInstanceCreation(InstanceCreationExpressionImpl node) {
- var element = node.constructorName.element;
- if (element == null || !element.isConst) return false;
-
- // Ensure that dependencies (e.g. default parameter values) are computed.
- var implElement = element.baseElement;
- implElement.computeConstantDependencies();
-
- // Verify that the evaluation of the constructor would not produce an
- // exception.
- var oldKeyword = node.keyword;
- try {
- node.keyword = KeywordToken(Keyword.CONST, offset);
- return !hasConstantVerifierError;
- } finally {
- node.keyword = oldKeyword;
- }
- }
-
- bool _canBeConstTypedLiteral(TypedLiteralImpl node) {
- var oldKeyword = node.constKeyword;
- try {
- node.constKeyword = KeywordToken(Keyword.CONST, offset);
- return !hasConstantVerifierError;
- } finally {
- node.constKeyword = oldKeyword;
- }
- }
-}
diff --git a/pkg/analyzer/lib/utilities/extensions/ast.dart b/pkg/analyzer/lib/utilities/extensions/ast.dart
index 9edf319..9a90ef7 100644
--- a/pkg/analyzer/lib/utilities/extensions/ast.dart
+++ b/pkg/analyzer/lib/utilities/extensions/ast.dart
@@ -2,7 +2,7 @@
// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
@Deprecated('Use the method defined on `CompilationUnit` instead.')
extension AstNodeExtension on AstNode {
diff --git a/pkg/analyzer/test/src/dart/ast/ast_test.dart b/pkg/analyzer/test/src/dart/ast/ast_test.dart
index fc46945..926e521 100644
--- a/pkg/analyzer/test/src/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/ast_test.dart
@@ -13,6 +13,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(CompilationUnitImplTest);
+ defineReflectiveTests(EvaluateExpressionTest);
defineReflectiveTests(ExpressionImplTest);
defineReflectiveTests(InstanceCreationExpressionImplTest);
defineReflectiveTests(IntegerLiteralImplTest);
@@ -108,6 +109,108 @@
}
@reflectiveTest
+class EvaluateExpressionTest extends PubPackageResolutionTest {
+ test_hasError_listLiteral_forElement() async {
+ await resolveTestCode('''
+var x = const [for (var i = 0; i < 4; i++) i];
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isNotEmpty);
+ expect(result.value, isNull);
+ }
+
+ test_hasError_mapLiteral_forElement() async {
+ await resolveTestCode('''
+var x = const {for (var i = 0; i < 4; i++) i: 0};
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result?.diagnostics, isNotEmpty);
+ expect(result?.value, isNull);
+ }
+
+ test_hasError_methodInvocation() async {
+ await resolveTestCode('''
+var x = 42.abs();
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isNotEmpty);
+ expect(result.value, isNull);
+ }
+
+ test_hasError_setLiteral_forElement() async {
+ await resolveTestCode('''
+var x = const {for (var i = 0; i < 4; i++) i};
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isNotEmpty);
+ expect(result.value, isNull);
+ }
+
+ test_hasValue_binaryExpression() async {
+ await resolveTestCode('''
+var x = 1 + 2;
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isEmpty);
+ expect(result.value!.toIntValue(), 3);
+ }
+
+ test_hasValue_constantReference() async {
+ await resolveTestCode('''
+const a = 42;
+var x = a;
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isEmpty);
+ expect(result.value!.toIntValue(), 42);
+ }
+
+ test_hasValue_constantReference_imported() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+const a = 42;
+''');
+ await resolveTestCode('''
+import 'a.dart';
+var x = a;
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isEmpty);
+ expect(result.value!.toIntValue(), 42);
+ }
+
+ test_hasValue_intLiteral() async {
+ await resolveTestCode('''
+var x = 42;
+''');
+ var result = _evaluateX();
+ expect(result, isNotNull);
+ expect(result!.diagnostics, isEmpty);
+ expect(result.value!.toIntValue(), 42);
+ }
+
+ test_nonConstant() async {
+ await resolveTestCode('''
+var a = 42;
+var x = a;
+''');
+ var result = _evaluateX();
+ expect(result, isNull);
+ }
+
+ AttemptedConstantEvaluationResult? _evaluateX() {
+ var node = findNode.topVariableDeclarationByName('x').initializer!;
+ return node.computeConstantValue();
+ }
+}
+
+@reflectiveTest
class ExpressionImplTest extends ParserTestCase {
late final String testSource;
late final CompilationUnitImpl testUnit;
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 13878ec..dc1a9bb 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -19,7 +19,6 @@
defineReflectiveTests(CanBeConstConstructorTest);
defineReflectiveTests(CanBeConstInstanceCreationTest);
defineReflectiveTests(CanBeConstTypedLiteralTest);
- defineReflectiveTests(EvaluateExpressionTest);
defineReflectiveTests(PubDependencyTest);
});
}
@@ -512,91 +511,6 @@
}
@reflectiveTest
-class EvaluateExpressionTest extends AbstractLinterContextTest {
- test_hasError_listLiteral_forElement() async {
- await resolve('''
-var x = const [for (var i = 0; i < 4; i++) i];
-''');
- var result = _evaluateX();
- expect(result.errors, isNotEmpty);
- expect(result.value, isNull);
- }
-
- test_hasError_mapLiteral_forElement() async {
- await resolve('''
-var x = const {for (var i = 0; i < 4; i++) i: 0};
-''');
- var result = _evaluateX();
- expect(result.errors, isNotEmpty);
- expect(result.value, isNull);
- }
-
- test_hasError_methodInvocation() async {
- await resolve('''
-var x = 42.abs();
-''');
- var result = _evaluateX();
- expect(result.errors, isNotEmpty);
- expect(result.value, isNull);
- }
-
- test_hasError_setLiteral_forElement() async {
- await resolve('''
-var x = const {for (var i = 0; i < 4; i++) i};
-''');
- var result = _evaluateX();
- expect(result.errors, isNotEmpty);
- expect(result.value, isNull);
- }
-
- test_hasValue_binaryExpression() async {
- await resolve('''
-var x = 1 + 2;
-''');
- var result = _evaluateX();
- expect(result.errors, isEmpty);
- expect(result.value!.toIntValue(), 3);
- }
-
- test_hasValue_constantReference() async {
- await resolve('''
-const a = 42;
-var x = a;
-''');
- var result = _evaluateX();
- expect(result.errors, isEmpty);
- expect(result.value!.toIntValue(), 42);
- }
-
- test_hasValue_constantReference_imported() async {
- newFile('$testPackageLibPath/a.dart', r'''
-const a = 42;
-''');
- await resolve('''
-import 'a.dart';
-var x = a;
-''');
- var result = _evaluateX();
- expect(result.errors, isEmpty);
- expect(result.value!.toIntValue(), 42);
- }
-
- test_hasValue_intLiteral() async {
- await resolve('''
-var x = 42;
-''');
- var result = _evaluateX();
- expect(result.errors, isEmpty);
- expect(result.value!.toIntValue(), 42);
- }
-
- LinterConstantEvaluationResult _evaluateX() {
- var node = findNode.topVariableDeclarationByName('x').initializer!;
- return node.computeConstantValue();
- }
-}
-
-@reflectiveTest
class PubDependencyTest extends AbstractLinterContextTest {
test_dependencies() async {
newPubspecYamlFile(testPackageRootPath, '''
diff --git a/pkg/linter/lib/src/ast.dart b/pkg/linter/lib/src/ast.dart
index 64a4731..5063ecd 100644
--- a/pkg/linter/lib/src/ast.dart
+++ b/pkg/linter/lib/src/ast.dart
@@ -12,8 +12,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor2.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/lint/constants.dart' // ignore: implementation_imports
- show ExpressionExtension;
import 'package:analyzer/workspace/workspace.dart';
import 'package:path/path.dart' as path;
@@ -125,7 +123,7 @@
_getWriteElement(node) ?? node.element;
bool hasConstantError(Expression node) =>
- node.computeConstantValue().errors.isNotEmpty;
+ node.computeConstantValue()?.diagnostics.isNotEmpty ?? true;
/// Returns `true` if this element is the `==` method declaration.
bool isEquals(ClassMember element) =>
@@ -317,7 +315,7 @@
if (expression is IntegerLiteral) {
value = expression.value;
} else if (expression is SimpleIdentifier && context != null) {
- value = expression.computeConstantValue().value?.toIntValue();
+ value = expression.computeConstantValue()?.value?.toIntValue();
}
if (value is! int) return null;
diff --git a/pkg/linter/lib/src/rules/avoid_redundant_argument_values.dart b/pkg/linter/lib/src/rules/avoid_redundant_argument_values.dart
index 79643e1..6c7fe0e 100644
--- a/pkg/linter/lib/src/rules/avoid_redundant_argument_values.dart
+++ b/pkg/linter/lib/src/rules/avoid_redundant_argument_values.dart
@@ -7,8 +7,6 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart' // ignore: implementation_imports
- show ExpressionExtension;
import 'package:collection/collection.dart';
import '../analyzer.dart';
@@ -76,7 +74,7 @@
// rule.reportLint(arg);
// } else ...
if (value != null && value.hasKnownValue) {
- var expressionValue = arg.computeConstantValue().value;
+ var expressionValue = arg.computeConstantValue()?.value;
if ((expressionValue?.hasKnownValue ?? false) &&
expressionValue == value) {
rule.reportAtNode(arg);
diff --git a/pkg/linter/lib/src/rules/no_duplicate_case_values.dart b/pkg/linter/lib/src/rules/no_duplicate_case_values.dart
index 8de516a..1f86c20 100644
--- a/pkg/linter/lib/src/rules/no_duplicate_case_values.dart
+++ b/pkg/linter/lib/src/rules/no_duplicate_case_values.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart'; // ignore: implementation_imports
import '../analyzer.dart';
@@ -41,7 +40,7 @@
var expression = member.expression;
var result = expression.computeConstantValue();
- var value = result.value;
+ var value = result?.value;
if (value == null || !value.hasKnownValue) {
continue;
diff --git a/pkg/linter/lib/src/rules/prefer_const_constructors.dart b/pkg/linter/lib/src/rules/prefer_const_constructors.dart
index df87946..054a79f 100644
--- a/pkg/linter/lib/src/rules/prefer_const_constructors.dart
+++ b/pkg/linter/lib/src/rules/prefer_const_constructors.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart'; // ignore: implementation_imports
import '../analyzer.dart';
import '../extensions.dart';
diff --git a/pkg/linter/lib/src/rules/prefer_const_literals_to_create_immutables.dart b/pkg/linter/lib/src/rules/prefer_const_literals_to_create_immutables.dart
index 2844d6f..ec84223 100644
--- a/pkg/linter/lib/src/rules/prefer_const_literals_to_create_immutables.dart
+++ b/pkg/linter/lib/src/rules/prefer_const_literals_to_create_immutables.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart'; // ignore: implementation_imports
import '../analyzer.dart';
diff --git a/pkg/linter/lib/src/rules/use_build_context_synchronously.dart b/pkg/linter/lib/src/rules/use_build_context_synchronously.dart
index 26e73fb..a56f6ad 100644
--- a/pkg/linter/lib/src/rules/use_build_context_synchronously.dart
+++ b/pkg/linter/lib/src/rules/use_build_context_synchronously.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart'; // ignore: implementation_imports
-import 'package:analyzer/src/lint/constants.dart'; // ignore: implementation_imports
import 'package:analyzer/src/lint/linter.dart'; // ignore: implementation_imports
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
@@ -1445,7 +1444,7 @@
}
extension on Expression {
- bool? get constantBoolValue => computeConstantValue().value?.toBoolValue();
+ bool? get constantBoolValue => computeConstantValue()?.value?.toBoolValue();
}
@visibleForTesting
diff --git a/pkg/linter/lib/src/rules/use_named_constants.dart b/pkg/linter/lib/src/rules/use_named_constants.dart
index 709d8d8..27c0169 100644
--- a/pkg/linter/lib/src/rules/use_named_constants.dart
+++ b/pkg/linter/lib/src/rules/use_named_constants.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/constants.dart'; // ignore: implementation_imports
import '../analyzer.dart';
@@ -57,7 +56,7 @@
var library =
(node.root as CompilationUnit).declaredFragment?.element.library2;
if (library == null) return;
- var value = node.computeConstantValue().value;
+ var value = node.computeConstantValue()?.value;
for (var field in element.fields.where(
(e) => e.isStatic && e.isConst,
)) {