From ac04a4e4e2ca1911058cd63a72ec12ea195b873b Mon Sep 17 00:00:00 2001 From: Kallen Tu Date: Thu, 7 Sep 2023 21:08:49 +0000 Subject: [PATCH] [analyzer] Remove generated constant evaluator and its tests. The generated constant evaluator is not being used and is removed by this CL. All imports of the deleted evaluator will import the more direct dependency and tests are moved to `evaluation_test.dart`. Change-Id: Ie435d289bd85256419f67407b36af0375661f335 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/324342 Reviewed-by: Konstantin Shcheglov Commit-Queue: Kallen Tu Reviewed-by: Brian Wilkerson --- pkg/analyzer/lib/src/context/context.dart | 2 +- .../lib/src/dart/constant/evaluation.dart | 5 +- pkg/analyzer/lib/src/dart/constant/value.dart | 36 +- .../src/error/best_practices_verifier.dart | 3 +- .../lib/src/error/dead_code_verifier.dart | 3 +- pkg/analyzer/lib/src/generated/constant.dart | 132 -- pkg/analyzer/lib/src/generated/engine.dart | 2 +- .../lib/src/generated/exhaustiveness.dart | 3 +- .../from_environment_evaluator_test.dart | 3 +- .../test/generated/constant_test.dart | 1073 -------------- pkg/analyzer/test/generated/test_all.dart | 2 - .../src/dart/constant/evaluation_test.dart | 1229 ++++++++++++++++- .../test/src/dart/constant/value_test.dart | 2 +- .../dart/resolution/dart_object_printer.dart | 44 + 14 files changed, 1255 insertions(+), 1284 deletions(-) delete mode 100644 pkg/analyzer/lib/src/generated/constant.dart delete mode 100644 pkg/analyzer/test/generated/constant_test.dart diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart index 654270685f6..90a059fc075 100644 --- a/pkg/analyzer/lib/src/context/context.dart +++ b/pkg/analyzer/lib/src/context/context.dart @@ -2,9 +2,9 @@ // 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/analysis/declared_variables.dart'; import 'package:analyzer/src/dart/element/type_provider.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/source.dart'; diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart index 16b1d3dd0af..9b42a567f87 100644 --- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart +++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart @@ -4,10 +4,12 @@ import 'dart:collection'; +import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/syntactic_entity.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -20,6 +22,8 @@ import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart'; import 'package:analyzer/src/dart/constant/has_type_parameter_reference.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/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart'; import 'package:analyzer/src/dart/element/type.dart'; @@ -27,7 +31,6 @@ import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl; import 'package:analyzer/src/diagnostic/diagnostic.dart'; import 'package:analyzer/src/error/codes.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/task/api/model.dart'; diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart index ab6c10534b1..dac6ce854fd 100644 --- a/pkg/analyzer/lib/src/dart/constant/value.dart +++ b/pkg/analyzer/lib/src/dart/constant/value.dart @@ -904,7 +904,7 @@ class DartObjectImpl implements DartObject, Constant { Map? toMapValue() { final state = this.state; if (state is MapState) { - return state._entries; + return state.entries; } return null; } @@ -913,7 +913,7 @@ class DartObjectImpl implements DartObject, Constant { Set? toSetValue() { final state = this.state; if (state is SetState) { - return state._elements; + return state.elements; } return null; } @@ -2491,16 +2491,16 @@ class ListState extends InstanceState { /// The state of an object representing a map. class MapState extends InstanceState { /// The entries in the map. - final Map _entries; + final Map entries; /// Initialize a newly created state to represent a map with the given /// [entries]. - MapState(this._entries); + MapState(this.entries); @override int get hashCode { int value = 0; - for (DartObjectImpl key in _entries.keys.toSet()) { + for (DartObjectImpl key in entries.keys.toSet()) { value = (value << 3) ^ key.hashCode; } return value; @@ -2512,15 +2512,15 @@ class MapState extends InstanceState { @override bool operator ==(Object other) { if (other is MapState) { - Map otherElements = other._entries; - int count = _entries.length; + Map otherElements = other.entries; + int count = entries.length; if (otherElements.length != count) { return false; } else if (count == 0) { return true; } - for (DartObjectImpl key in _entries.keys) { - var value = _entries[key]; + for (DartObjectImpl key in entries.keys) { + var value = entries[key]; var otherValue = otherElements[key]; if (value != otherValue) { return false; @@ -2552,7 +2552,7 @@ class MapState extends InstanceState { StringBuffer buffer = StringBuffer(); buffer.write('{'); bool first = true; - _entries.forEach((DartObjectImpl key, DartObjectImpl value) { + entries.forEach((DartObjectImpl key, DartObjectImpl value) { if (first) { first = false; } else { @@ -2763,16 +2763,16 @@ class RecordState extends InstanceState { /// The state of an object representing a set. class SetState extends InstanceState { /// The elements of the set. - final Set _elements; + final Set elements; /// Initialize a newly created state to represent a set with the given /// [elements]. - SetState(this._elements); + SetState(this.elements); @override int get hashCode { int value = 0; - for (DartObjectImpl element in _elements) { + for (DartObjectImpl element in elements) { value = (value << 3) ^ element.hashCode; } return value; @@ -2784,16 +2784,16 @@ class SetState extends InstanceState { @override bool operator ==(Object other) { if (other is SetState) { - List elements = _elements.toList(); - List otherElements = other._elements.toList(); - int count = elements.length; + List currentElements = elements.toList(); + List otherElements = other.elements.toList(); + int count = currentElements.length; if (otherElements.length != count) { return false; } else if (count == 0) { return true; } for (int i = 0; i < count; i++) { - if (elements[i] != otherElements[i]) { + if (currentElements[i] != otherElements[i]) { return false; } } @@ -2823,7 +2823,7 @@ class SetState extends InstanceState { StringBuffer buffer = StringBuffer(); buffer.write('{'); bool first = true; - for (var element in _elements) { + for (var element in elements) { if (first) { first = false; } else { diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart index ed23922fd76..65a31d4da52 100644 --- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart +++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart @@ -4,10 +4,12 @@ import 'dart:collection'; +import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/syntactic_entity.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; @@ -32,7 +34,6 @@ import 'package:analyzer/src/error/doc_comment_verifier.dart'; import 'package:analyzer/src/error/error_handler_verifier.dart'; import 'package:analyzer/src/error/must_call_super_verifier.dart'; import 'package:analyzer/src/error/null_safe_api_verifier.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/lint/linter.dart'; import 'package:analyzer/src/workspace/workspace.dart'; diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart index 646303dd77e..abb808957a6 100644 --- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart +++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart @@ -11,12 +11,13 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/source/source_range.dart'; +import 'package:analyzer/src/dart/constant/evaluation.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; import 'package:analyzer/src/dart/resolver/exit_detector.dart'; import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart'; import 'package:analyzer/src/dart/resolver/scope.dart'; import 'package:analyzer/src/error/codes.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:collection/collection.dart'; typedef _CatchClausesVerifierReporter = void Function( diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart deleted file mode 100644 index f01b81b7988..00000000000 --- a/pkg/analyzer/lib/src/generated/constant.dart +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2014, 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:analyzer/dart/analysis/declared_variables.dart'; -import 'package:analyzer/dart/analysis/features.dart'; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/error/error.dart'; -import 'package:analyzer/error/listener.dart'; -import 'package:analyzer/src/dart/constant/evaluation.dart'; -import 'package:analyzer/src/dart/constant/value.dart'; -import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/generated/source.dart' show Source; - -export 'package:analyzer/dart/analysis/declared_variables.dart'; -export 'package:analyzer/dart/constant/value.dart'; -export 'package:analyzer/src/dart/constant/evaluation.dart'; -export 'package:analyzer/src/dart/constant/utilities.dart'; -export 'package:analyzer/src/dart/constant/value.dart'; - -/// Instances of the class [ConstantEvaluator] evaluate constant expressions to -/// produce their compile-time value. -/// -/// According to the Dart Language Specification: -/// -/// > A constant expression is one of the following: -/// > -/// > * A literal number. -/// > * A literal boolean. -/// > * A literal string where any interpolated expression is a compile-time -/// > constant that evaluates to a numeric, string or boolean value or to -/// > **null**. -/// > * A literal symbol. -/// > * **null**. -/// > * A qualified reference to a static constant variable. -/// > * An identifier expression that denotes a constant variable, class or type -/// > alias. -/// > * A constant constructor invocation. -/// > * A constant list literal. -/// > * A constant map literal. -/// > * A simple or qualified identifier denoting a top-level function or a -/// > static method. -/// > * A parenthesized expression _(e)_ where _e_ is a constant expression. -/// > * -/// > An expression of the form identical(e1, e2) -/// > where e1 and e2 are constant -/// > expressions and identical() is statically bound to the predefined -/// > dart function identical() discussed above. -/// > -/// > * -/// > An expression of one of the forms e1 == e2 -/// > or e1 != e2 where e1 and -/// > e2 are constant expressions that evaluate to a -/// > numeric, string or boolean value. -/// > -/// > * -/// > An expression of one of the forms !e, e1 && -/// > e2 or e1 || e2, where -/// > e, e1 and e2 are constant -/// > expressions that evaluate to a boolean value. -/// > -/// > * -/// > An expression of one of the forms ~e, e1 ^ -/// > e2, e1 & e2, -/// > e1 | e2, e1 >> -/// > e2 or e1 << e2, where -/// > e, e1 and e2 are constant -/// > expressions that evaluate to an integer value or to null. -/// > -/// > * -/// > An expression of one of the forms -e, e1 + -/// > e2, e1 -e2, -/// > e1 * e2, e1 / -/// > e2, e1 ~/ e2, -/// > e1 > e2, e1 < -/// > e2, e1 >= e2, -/// > e1 <= e2 or e1 % -/// > e2, where e, e1 and -/// > e2 are constant expressions that evaluate to a numeric -/// > value or to null. -/// > -/// > * -/// > An expression of the form e1 ? e2 : -/// > e3 where e1, e2 and -/// > e3 are constant expressions, and e1 -/// > evaluates to a boolean value. -/// > -/// -/// The values returned by instances of this class are therefore `null` and -/// instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and -/// `DartObject`. -/// -/// In addition, this class defines several values that can be returned to -/// indicate various conditions encountered during evaluation. These are -/// documented with the static fields that define those values. -class ConstantEvaluator { - /// The source containing the expression(s) that will be evaluated. - final Source _source; - - /// The library containing the expression(s) that will be evaluated. - final LibraryElementImpl _library; - - ConstantEvaluator(this._source, this._library); - - EvaluationResult evaluate(Expression expression) { - RecordingErrorListener errorListener = RecordingErrorListener(); - ErrorReporter errorReporter = ErrorReporter( - errorListener, - _source, - isNonNullableByDefault: _library.isNonNullableByDefault, - ); - var result = expression.accept(ConstantVisitor( - ConstantEvaluationEngine( - declaredVariables: DeclaredVariables(), - isNonNullableByDefault: - _library.featureSet.isEnabled(Feature.non_nullable), - configuration: ConstantEvaluationConfiguration(), - ), - _library, - errorReporter)); - List errors = errorListener.errors; - if (errors.isNotEmpty) { - return EvaluationResult.forErrors(errors); - } - if (result is DartObjectImpl) { - return EvaluationResult.forValue(result); - } - // We should not get here. Either there should be a valid value or there - // should be an error explaining why a value could not be generated. - return EvaluationResult.forErrors(errors); - } -} diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart index d19a4adc60a..e689d81a71e 100644 --- a/pkg/analyzer/lib/src/generated/engine.dart +++ b/pkg/analyzer/lib/src/generated/engine.dart @@ -7,6 +7,7 @@ import 'dart:typed_data'; import 'package:_fe_analyzer_shared/src/scanner/string_canonicalizer.dart'; import 'package:analyzer/dart/analysis/analysis_options.dart'; import 'package:analyzer/dart/analysis/code_style_options.dart'; +import 'package:analyzer/dart/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/instrumentation/instrumentation.dart'; @@ -14,7 +15,6 @@ import 'package:analyzer/source/error_processor.dart'; import 'package:analyzer/src/analysis_options/code_style_options.dart'; import 'package:analyzer/src/dart/analysis/experiments.dart'; import 'package:analyzer/src/dart/sdk/sdk.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/services/lint.dart'; import 'package:analyzer/src/summary/api_signature.dart'; diff --git a/pkg/analyzer/lib/src/generated/exhaustiveness.dart b/pkg/analyzer/lib/src/generated/exhaustiveness.dart index e2244a33690..1b7eb730da8 100644 --- a/pkg/analyzer/lib/src/generated/exhaustiveness.dart +++ b/pkg/analyzer/lib/src/generated/exhaustiveness.dart @@ -11,17 +11,18 @@ import 'package:_fe_analyzer_shared/src/exhaustiveness/space.dart'; import 'package:_fe_analyzer_shared/src/exhaustiveness/static_type.dart'; import 'package:_fe_analyzer_shared/src/exhaustiveness/types.dart'; import 'package:analyzer/dart/analysis/features.dart'; +import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; 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/dart/ast/extensions.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/replacement_visitor.dart'; import 'package:analyzer/src/dart/element/type_algebra.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; import 'package:analyzer/src/dart/resolver/variance.dart'; -import 'package:analyzer/src/generated/constant.dart'; /// The buffer that accumulates types and elements as is, so that they /// can be written latter into Dart code that considers imports. It also diff --git a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart index 44891cf70f2..cb08f4c095c 100644 --- a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart +++ b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart @@ -2,10 +2,11 @@ // 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/analysis/declared_variables.dart'; import 'package:analyzer/dart/element/type_provider.dart'; import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart deleted file mode 100644 index 533f4eee520..00000000000 --- a/pkg/analyzer/test/generated/constant_test.dart +++ /dev/null @@ -1,1073 +0,0 @@ -// Copyright (c) 2016, 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. - -@deprecated -library analyzer.test.constant_test; - -import 'package:analyzer/dart/analysis/results.dart'; -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/error/syntactic_errors.dart'; -import 'package:analyzer/src/error/codes.dart'; -import 'package:analyzer/src/generated/constant.dart'; -import 'package:analyzer/src/test_utilities/find_element.dart'; -import 'package:test/test.dart'; -import 'package:test_reflective_loader/test_reflective_loader.dart'; - -import '../src/dart/resolution/context_collection_resolution.dart'; - -main() { - defineReflectiveSuite(() { - defineReflectiveTests(ConstantEvaluatorTest); - }); -} - -@reflectiveTest -class ConstantEvaluatorTest extends PubPackageResolutionTest { - void assertTypeArguments(DartObject value, List? typeArgumentNames) { - var typeArguments = (value as DartObjectImpl).typeArguments; - if (typeArguments == null) { - expect(typeArguments, typeArgumentNames); - return; - } - expect( - typeArguments.map((arg) => arg.getDisplayString(withNullability: true)), - equals(typeArgumentNames), - ); - } - - test_bitAnd_int_int() async { - await _assertValueInt(74 & 42, "74 & 42"); - } - - test_bitNot() async { - await _assertValueInt(~42, "~42"); - } - - test_bitOr_int_int() async { - await _assertValueInt(74 | 42, "74 | 42"); - } - - test_bitXor_int_int() async { - await _assertValueInt(74 ^ 42, "74 ^ 42"); - } - - /// See https://github.com/dart-lang/sdk/issues/50045 - test_bool_fromEnvironment_dartLibraryJsUtil() async { - await resolveTestCode(''' -const x = bool.fromEnvironment('dart.library.js_util'); -'''); - - _assertTopVarConstValue('x', r''' - bool - variable: self::@variable::x -'''); - } - - test_constructorInvocation_fieldInitializer() async { - var result = await _getExpressionValue("const C(2)", context: ''' -class C { - final int x; - const C(this.x); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C'); - DartObject x = value.getField('x')!; - assertType(x.type, 'int'); - expect(x.toIntValue(), 2); - } - - test_constructorInvocation_noArgs() async { - var result = await _getExpressionValue( - "const C()", - context: 'class C {const C();}', - ); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C'); - } - - test_constructorInvocation_noConstConstructor() async { - var result = await _getExpressionValue( - "const C()", - context: 'class C {}', - ); - expect(result.isValid, isFalse); - var value = result.value; - expect(value, isNull); - } - - test_constructorInvocation_simpleArgs() async { - var result = await _getExpressionValue("const C(1)", context: ''' -class C { - const C(int x); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C'); - } - - test_constructorReference_generic_named() async { - var result = await _getExpressionValue("C.foo", context: ''' -class C { - C.foo(); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C Function()'); - } - - test_constructorReference_generic_unnamed() async { - var result = await _getExpressionValue("C.new", context: ''' -class C { - C.new(); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C Function()'); - } - - test_constructorReference_nonGeneric_named() async { - var result = await _getExpressionValue("C.foo", context: ''' -class C { - const C.foo(); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C Function()'); - } - - test_constructorReference_nonGeneric_unnamed() async { - var result = await _getExpressionValue("C.new", context: ''' -class C { - const C(); -} -'''); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, 'C Function()'); - } - - test_divide_double_double() async { - await _assertValueDouble(3.2 / 2.3, "3.2 / 2.3"); - } - - test_divide_double_double_byZero() async { - var result = await _getExpressionValue("3.2 / 0.0"); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, "double"); - expect(value.toDoubleValue()!.isInfinite, isTrue); - } - - test_divide_int_int() async { - await _assertValueDouble(1.5, "3 / 2"); - } - - test_divide_int_int_byZero() async { - var result = await _getExpressionValue("3 / 0"); - expect(result.isValid, isTrue); - } - - test_equal_boolean_boolean() async { - await _assertValueBool(false, "true == false"); - } - - test_equal_int_int() async { - await _assertValueBool(false, "2 == 3"); - } - - test_equal_invalidLeft() async { - var result = await _getExpressionValue("a == 3"); - expect(result.isValid, isFalse); - } - - test_equal_invalidRight() async { - var result = await _getExpressionValue("2 == a"); - expect(result.isValid, isFalse); - } - - test_equal_string_string() async { - await _assertValueBool(false, "'a' == 'b'"); - } - - test_greaterThan_int_int() async { - await _assertValueBool(false, "2 > 3"); - } - - test_greaterThanOrEqual_int_int() async { - await _assertValueBool(false, "2 >= 3"); - } - - @failingTest - test_identifier_class() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_identifier_function() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_identifier_static() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_identifier_staticMethod() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_identifier_topLevel() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_identifier_typeParameter() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - test_lessThan_int_int() async { - await _assertValueBool(true, "2 < 3"); - } - - test_lessThanOrEqual_int_int() async { - await _assertValueBool(true, "2 <= 3"); - } - - test_literal_boolean_false() async { - await _assertValueBool(false, "false"); - } - - test_literal_boolean_true() async { - await _assertValueBool(true, "true"); - } - - test_literal_list() async { - var result = await _getExpressionValue("const ['a', 'b', 'c']"); - expect(result.isValid, isTrue); - } - - test_literal_list_explicitType() async { - var result = await _getExpressionValue("const ['a', 'b', 'c']"); - expect(result.isValid, isTrue); - } - - test_literal_list_explicitType_functionType() async { - var result = await _getExpressionValue("const []"); - expect(result.isValid, isTrue); - } - - test_literal_list_forElement() async { - var result = await _getExpressionValue(''' -const [for (var i = 0; i < 4; i++) i] -'''); - expect(result.isValid, isFalse); - expect(result.errors, isNotEmpty); - } - - test_literal_map() async { - var result = await _getExpressionValue( - "const {'a' : 'm', 'b' : 'n', 'c' : 'o'}", - ); - expect(result.isValid, isTrue); - var map = result.value!.toMapValue()!; - expect(map.keys.map((k) => k!.toStringValue()), ['a', 'b', 'c']); - } - - test_literal_null() async { - var result = await _getExpressionValue("null"); - expect(result.isValid, isTrue); - DartObject value = result.value!; - expect(value.isNull, isTrue); - } - - test_literal_number_double() async { - await _assertValueDouble(3.45, "3.45"); - } - - test_literal_number_integer() async { - await _assertValueInt(42, "42"); - } - - test_literal_string_adjacent() async { - await _assertValueString("abcdef", "'abc' 'def'"); - } - - test_literal_string_interpolation_invalid() async { - var result = await _getExpressionValue("'a\${f()}c'"); - expect(result.isValid, isFalse); - } - - test_literal_string_interpolation_valid() async { - await _assertValueString("a3c", "'a\${3}c'"); - } - - test_literal_string_simple() async { - await _assertValueString("abc", "'abc'"); - } - - test_logicalAnd() async { - await _assertValueBool(false, "true && false"); - } - - test_logicalNot() async { - await _assertValueBool(false, "!true"); - } - - test_logicalOr() async { - await _assertValueBool(true, "true || false"); - } - - test_minus_double_double() async { - await _assertValueDouble(3.2 - 2.3, "3.2 - 2.3"); - } - - test_minus_int_int() async { - await _assertValueInt(1, "3 - 2"); - } - - test_negated_boolean() async { - var result = await _getExpressionValue("-true"); - expect(result.isValid, isFalse); - } - - test_negated_double() async { - await _assertValueDouble(-42.3, "-42.3"); - } - - test_negated_integer() async { - await _assertValueInt(-42, "-42"); - } - - /// Even though it is an error to specify a default value for a required - /// parameter, we still can evaluate it. - test_normalParameter_requiredNamed_hasDefault() async { - final a = newFile('$testPackageLibPath/a.dart', r''' -class A { - A({required int x = 42}); -} -'''); - - final unitResult = await _getUnitElement(a); - final x = unitResult.findElement.parameter('x'); - assertDartObjectText( - x.computeConstantValue(), - r''' -int 42 -''', - libraryElement: unitResult.library, - ); - } - - /// Even though it is an error to specify a default value for a required - /// parameter, we still can evaluate it. - test_normalParameter_requiredNamed_noDefault() async { - final a = newFile('$testPackageLibPath/a.dart', r''' -class A { - A({required int? x}); -} -'''); - - final unitResult = await _getUnitElement(a); - final x = unitResult.findElement.parameter('x'); - assertDartObjectText( - x.computeConstantValue(), - r''' -Null null -''', - libraryElement: unitResult.library, - ); - } - - test_notEqual_boolean_boolean() async { - await _assertValueBool(true, "true != false"); - } - - test_notEqual_int_int() async { - await _assertValueBool(true, "2 != 3"); - } - - test_notEqual_invalidLeft() async { - var result = await _getExpressionValue("a != 3"); - expect(result.isValid, isFalse); - } - - test_notEqual_invalidRight() async { - var result = await _getExpressionValue("2 != a"); - expect(result.isValid, isFalse); - } - - test_notEqual_string_string() async { - await _assertValueBool(true, "'a' != 'b'"); - } - - test_object_enum() async { - await resolveTestCode(''' -enum E { v1, v2 } -const x1 = E.v1; -const x2 = E.v2; -'''); - - _assertTopVarConstValue('x1', r''' -E - _name: String v1 - index: int 0 - variable: self::@variable::x1 -'''); - - _assertTopVarConstValue('x2', r''' -E - _name: String v2 - index: int 1 - variable: self::@variable::x2 -'''); - } - - /// Enum constants can reference other constants. - test_object_enum_enhanced_constants() async { - await assertNoErrorsInCode(''' -enum E { - v1(42), v2(v1); - final Object? a; - const E([this.a]); -} -'''); - - assertDartObjectText(findElement.field('v2').evaluationResult.value, r''' -E - _name: String v2 - a: E - _name: String v1 - a: int 42 - index: int 0 - variable: self::@enum::E::@field::v1 - index: int 1 - variable: self::@enum::E::@field::v2 -'''); - } - - test_object_enum_enhanced_named() async { - await resolveTestCode(''' -enum E { - v1.named(10), - v2.named(20); - final T f; - const E.named(this.f); -} - -const x1 = E.v1; -const x2 = E.v2; -'''); - - _assertTopVarConstValue('x1', r''' -E - _name: String v1 - f: double 10.0 - index: int 0 - variable: self::@variable::x1 -'''); - - _assertTopVarConstValue('x2', r''' -E - _name: String v2 - f: int 20 - index: int 1 - variable: self::@variable::x2 -'''); - } - - test_object_enum_enhanced_unnamed() async { - await resolveTestCode(''' -enum E { - v1(10), - v2(20), - v3('abc'); - final T f; - const E(this.f); -} - -const x1 = E.v1; -const x2 = E.v2; -const x3 = E.v3; -'''); - - _assertTopVarConstValue('x1', r''' -E - _name: String v1 - f: int 10 - index: int 0 - variable: self::@variable::x1 -'''); - - _assertTopVarConstValue('x2', r''' -E - _name: String v2 - f: int 20 - index: int 1 - variable: self::@variable::x2 -'''); - - _assertTopVarConstValue('x3', r''' -E - _name: String v3 - f: String abc - index: int 2 - variable: self::@variable::x3 -'''); - } - - test_parenthesizedExpression() async { - await _assertValueString("a", "('a')"); - } - - test_plus_double_double() async { - await _assertValueDouble(2.3 + 3.2, "2.3 + 3.2"); - } - - test_plus_int_int() async { - await _assertValueInt(5, "2 + 3"); - } - - test_plus_string_string() async { - await _assertValueString("ab", "'a' + 'b'"); - } - - @failingTest - test_prefixedIdentifier_invalid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_prefixedIdentifier_valid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_propertyAccess_invalid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_propertyAccess_valid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - test_record_mixed() async { - await assertNoErrorsInCode(r''' -const x = (0, f1: 10, f2: 2.3); -'''); - - final value = _topVarConstValue('x'); - assertDartObjectText(value, r''' -Record(int, {int f1, double f2}) - positionalFields - $1: int 0 - namedFields - f1: int 10 - f2: double 2.3 - variable: self::@variable::x -'''); - } - - test_record_named() async { - await assertNoErrorsInCode(r''' -const x = (f1: 10, f2: -3); -'''); - - final value = _topVarConstValue('x'); - assertDartObjectText(value, r''' -Record({int f1, int f2}) - namedFields - f1: int 10 - f2: int -3 - variable: self::@variable::x -'''); - } - - test_record_positional() async { - await assertNoErrorsInCode(r''' -const x = (20, 0, 7); -'''); - - final value = _topVarConstValue('x'); - assertDartObjectText(value, r''' -Record(int, int, int) - positionalFields - $1: int 20 - $2: int 0 - $3: int 7 - variable: self::@variable::x -'''); - } - - @failingTest - test_simpleIdentifier_invalid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - @failingTest - test_simpleIdentifier_valid() async { - var result = await _getExpressionValue("?"); - expect(result.isValid, isTrue); - var value = result.value; - expect(value, null); - } - - test_stringLength_complex() async { - await _assertValueInt(6, "('qwe' + 'rty').length"); - } - - test_stringLength_simple() async { - await _assertValueInt(6, "'Dvorak'.length"); - } - - test_superFormalParameter_explicitSuper_hasNamedArgument_requiredNamed() async { - await assertNoErrorsInCode(''' -class A { - final int a; - final int b; - const A({required this.a, required this.b}); -} - -class B extends A { - final int c; - const B(this.c, {required super.b}) : super(a: 1); -} - -const x = B(3, b: 2); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - c: int 3 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_explicitSuper_hasNamedArgument_requiredPositional() async { - await assertNoErrorsInCode(''' -class A { - final int a; - final int b; - const A(this.a, {required this.b}); -} - -class B extends A { - final int c; - const B(super.a, {required this.c}) : super(b: 2); -} - -const x = B(1, c: 3); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - c: int 3 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_explicitSuper_requiredNamed() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A({required this.a}); -} - -class B extends A { - final int b; - const B(this.b, {required super.a}) : super(); -} - -const x = B(2, a: 1); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_explicitSuper_requiredNamed_generic() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A({required this.a}); -} - -class B extends A { - final int b; - const B(this.b, {required super.a}) : super(); -} - -const x = B(2, a: 1); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_explicitSuper_requiredPositional() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A(this.a); -} - -class B extends A { - final int b; - const B(super.a, this.b) : super(); -} - -const x = B(1, 2); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_explicitSuper_requiredPositional_generic() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A(this.a); -} - -class B extends A { - final int b; - const B(super.a, this.b) : super(); -} - -const x = B(1, 2); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_implicitSuper_requiredNamed() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A({required this.a}); -} - -class B extends A { - final int b; - const B(this.b, {required super.a}); -} - -const x = B(2, a: 1); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_implicitSuper_requiredNamed_generic() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A({required this.a}); -} - -class B extends A { - final int b; - const B(this.b, {required super.a}); -} - -const x = B(2, a: 1); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_implicitSuper_requiredPositional() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A(this.a); -} - -class B extends A { - final int b; - const B(super.a, this.b); -} - -const x = B(1, 2); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_superFormalParameter_implicitSuper_requiredPositional_generic() async { - await assertNoErrorsInCode(''' -class A { - final int a; - const A(this.a); -} - -class B extends A { - final int b; - const B(super.a, this.b); -} - -const x = B(1, 2); -'''); - - var value = findElement.topVar('x').evaluationResult.value; - assertDartObjectText(value, r''' -B - (super): A - a: int 1 - b: int 2 - variable: self::@variable::x -'''); - } - - test_unknownConstuctor() async { - await assertErrorsInCode(''' -class C { - const C.named(); -} - -const x = C.(); -''', [ - // TODO(https://github.com/dart-lang/sdk/issues/50441): This should not be - // reported. - error(CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER, - 45, 8), - error(ParserErrorCode.MISSING_IDENTIFIER, 52, 1), - ]); - - var result = findElement.topVar('x').evaluationResult; - assertDartObjectText(result.value, r''' - -'''); - } - - test_variable_alias() async { - await resolveTestCode(''' -const a = 42; -const b = a; -'''); - - final a_result = findElement.topVar('a').evaluationResult; - assertDartObjectText(a_result.value, r''' -int 42 - variable: self::@variable::a -'''); - - final b_result = findElement.topVar('b').evaluationResult; - assertDartObjectText(b_result.value, r''' -int 42 - variable: self::@variable::b -'''); - } - - test_variable_list_elements() async { - await resolveTestCode(''' -const a = 0; -const b = 2; -const c = [a, 1, b]; -'''); - - final b_result = findElement.topVar('c').evaluationResult; - assertDartObjectText(b_result.value, r''' -List - elementType: int - elements - int 0 - variable: self::@variable::a - int 1 - int 2 - variable: self::@variable::b - variable: self::@variable::c -'''); - } - - void _assertTopVarConstValue(String name, String expected) { - assertDartObjectText(_topVarConstResult(name).value, expected); - } - - Future _assertValueBool(bool expectedValue, String contents) async { - var result = await _getExpressionValue(contents); - DartObject value = result.value!; - assertType(value.type, "bool"); - expect(value.toBoolValue(), expectedValue); - } - - Future _assertValueDouble(double expectedValue, String contents) async { - var result = await _getExpressionValue(contents); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, "double"); - expect(value.toDoubleValue(), expectedValue); - } - - Future _assertValueInt(int expectedValue, String contents) async { - var result = await _getExpressionValue(contents); - expect(result.isValid, isTrue); - DartObject value = result.value!; - assertType(value.type, "int"); - expect(value.toIntValue(), expectedValue); - } - - Future _assertValueString(String expectedValue, String contents) async { - var result = await _getExpressionValue(contents); - DartObject value = result.value!; - assertType(value.type, 'String'); - } - - Future _getExpressionValue(String expressionCode, - {String context = ''}) async { - await resolveTestCode(''' -var x = $expressionCode; - -$context -'''); - - var expression = findNode.variableDeclaration('x =').initializer!; - - var file = getFile(result.path); - var evaluator = ConstantEvaluator( - file.createSource(result.uri), - result.libraryElement as LibraryElementImpl, - ); - - return evaluator.evaluate(expression); - } - - Future<_UnitElementResult> _getUnitElement(File file) async { - final analysisSession = contextFor(file).currentSession; - final unitResult = await analysisSession.getUnitElement(file.path); - unitResult as UnitElementResult; - return _UnitElementResult(unitResult.element); - } - - EvaluationResultImpl _topVarConstResult(String name) { - var element = findElement.topVar(name) as ConstTopLevelVariableElementImpl; - return element.evaluationResult!; - } - - DartObjectImpl _topVarConstValue(String name) { - return _topVarConstResult(name).value!; - } -} - -class _UnitElementResult { - final CompilationUnitElement element; - - _UnitElementResult(this.element); - - PartFindElement get findElement { - return PartFindElement(element); - } - - LibraryElement get library => element.library; -} - -extension on VariableElement { - EvaluationResultImpl get evaluationResult { - var constVariable = this as ConstVariableElement; - var evaluationResult = constVariable.evaluationResult; - if (evaluationResult == null) { - fail('Not evaluated: $this'); - } - return evaluationResult; - } -} diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart index 0281d0e025a..931d89ab955 100644 --- a/pkg/analyzer/test/generated/test_all.dart +++ b/pkg/analyzer/test/generated/test_all.dart @@ -9,7 +9,6 @@ import 'class_member_parser_test.dart' as class_member_parser; import 'collection_literal_parser_test.dart' as collection_literal_parser; import 'complex_parser_test.dart' as complex_parser; // ignore: deprecated_member_use_from_same_package -import 'constant_test.dart' as constant_test; import 'element_resolver_test.dart' as element_resolver_test; import 'error_parser_test.dart' as error_parser; import 'error_suppression_test.dart' as error_suppression; @@ -51,7 +50,6 @@ main() { class_member_parser.main(); collection_literal_parser.main(); complex_parser.main(); - constant_test.main(); element_resolver_test.main(); error_parser.main(); error_suppression.main(); diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart index b5630278553..2d96b5ed6c7 100644 --- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart +++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart @@ -2,14 +2,17 @@ // 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/analysis/declared_variables.dart'; import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/error/error.dart'; import 'package:analyzer/error/listener.dart'; +import 'package:analyzer/src/dart/constant/evaluation.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/error/syntactic_errors.dart'; import 'package:analyzer/src/error/codes.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -36,6 +39,135 @@ const int x = 'foo'; ]); } + /// Enum constants can reference other constants. + test_enum_enhanced_constants() async { + await assertNoErrorsInCode(''' +enum E { + v1(42), v2(v1); + final Object? a; + const E([this.a]); +} +'''); + assertDartObjectText(_field('v2'), r''' +E + _name: String v2 + a: E + _name: String v1 + a: int 42 + index: int 0 + variable: self::@enum::E::@field::v1 + index: int 1 + variable: self::@enum::E::@field::v2 +'''); + } + + test_enum_enhanced_named() async { + await resolveTestCode(''' +enum E { + v1.named(10), + v2.named(20); + final T f; + const E.named(this.f); +} + +const x1 = E.v1; +const x2 = E.v2; +'''); + assertDartObjectText(_topLevelVar('x1'), r''' +E + _name: String v1 + f: double 10.0 + index: int 0 + variable: self::@variable::x1 +'''); + assertDartObjectText(_topLevelVar('x2'), r''' +E + _name: String v2 + f: int 20 + index: int 1 + variable: self::@variable::x2 +'''); + } + + test_enum_enhanced_unnamed() async { + await resolveTestCode(''' +enum E { + v1(10), + v2(20), + v3('abc'); + final T f; + const E(this.f); +} + +const x1 = E.v1; +const x2 = E.v2; +const x3 = E.v3; +'''); + assertDartObjectText(_topLevelVar('x1'), r''' +E + _name: String v1 + f: int 10 + index: int 0 + variable: self::@variable::x1 +'''); + assertDartObjectText(_topLevelVar('x2'), r''' +E + _name: String v2 + f: int 20 + index: int 1 + variable: self::@variable::x2 +'''); + assertDartObjectText(_topLevelVar('x3'), r''' +E + _name: String v3 + f: String abc + index: int 2 + variable: self::@variable::x3 +'''); + } + + test_enum_simple() async { + await resolveTestCode(''' +enum E { v1, v2 } +const x1 = E.v1; +const x2 = E.v2; +'''); + assertDartObjectText(_topLevelVar('x1'), r''' +E + _name: String v1 + index: int 0 + variable: self::@variable::x1 +'''); + assertDartObjectText(_topLevelVar('x2'), r''' +E + _name: String v2 + index: int 1 + variable: self::@variable::x2 +'''); + } + + test_equalEqual_bool_bool_false() async { + await assertNoErrorsInCode(''' +const v = true == false; +'''); + final result = _topLevelVar('v'); + assertDartObjectText(result, ''' +bool false + variable: self::@variable::v +'''); + } + + test_equalEqual_bool_bool_true() async { + await assertNoErrorsInCode(''' +const v = true == true; +'''); + final result = _topLevelVar('v'); + assertDartObjectText(result, ''' +bool true + variable: self::@variable::v +'''); + } + test_equalEqual_double_object() async { await assertNoErrorsInCode(''' const v = 1.2 == Object(); @@ -107,6 +239,26 @@ bool false '''); } + test_equalEqual_invalidLeft() async { + await assertErrorsInCode(''' +const v = a == 1; +''', [ + error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 10, + 1), + ]); + } + + test_equalEqual_invalidRight() async { + await assertErrorsInCode(''' +const v = 1 == a; +''', [ + error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 15, 1), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 15, + 1), + ]); + } + test_equalEqual_null_object() async { await assertNoErrorsInCode(''' const Object? a = null; @@ -573,6 +725,28 @@ const v2 = v1 + v1; _assertNull(result); } + test_visitBinaryExpression_gt_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 > 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool false + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_gte_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 >= 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool false + variable: self::@variable::c +'''); + } + test_visitBinaryExpression_gtGtGt_negative_fewerBits() async { await assertNoErrorsInCode(''' const c = 0xFFFFFFFF >>> 8; @@ -685,6 +859,28 @@ int 0xff '''); } + test_visitBinaryExpression_lt_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 < 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_lte_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 <= 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + test_visitBinaryExpression_questionQuestion_invalid_notNull() async { await assertErrorsInCode(''' final x = 0; @@ -834,6 +1030,40 @@ class A { ]); } + test_visitConstructorReference_generic_named() async { + await assertNoErrorsInCode(''' +class C { + C.foo(); +} +const c = C.foo; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +C Function() + element: self::@class::C::@constructor::foo + typeArguments + int + variable: self::@variable::c +'''); + } + + test_visitConstructorReference_generic_unnamed() async { + await assertNoErrorsInCode(''' +class C { + C(); +} +const c = C.new; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +C Function() + element: self::@class::C::@constructor::new + typeArguments + int + variable: self::@variable::c +'''); + } + test_visitConstructorReference_identical_aliasIsNotGeneric() async { await assertNoErrorsInCode(''' class C {} @@ -1109,6 +1339,40 @@ bool false '''); } + test_visitConstructorReference_nonGeneric_named() async { + await assertNoErrorsInCode(''' +class C { + const C.foo(); +} +const c = C.foo; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +C Function() + element: self::@class::C::@constructor::foo + typeArguments + int + variable: self::@variable::c +'''); + } + + test_visitConstructorReference_nonGeneric_unnamed() async { + await assertNoErrorsInCode(''' +class C { + const C(); +} +const c = C.new; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +C Function() + element: self::@class::C::@constructor::new + typeArguments + int + variable: self::@variable::c +'''); + } + test_visitFunctionReference_defaultConstructorValue() async { await assertErrorsInCode(r''' void f(T t) => t; @@ -1476,6 +1740,61 @@ bool true '''); } + test_visitInstanceCreationExpression_noArgs() async { + await assertNoErrorsInCode(''' +class A { + const A(); +} +const a = A(); +'''); + final result = _topLevelVar('a'); + assertDartObjectText(result, r''' +A + variable: self::@variable::a +'''); + } + + test_visitInstanceCreationExpression_noConstConstructor() async { + await assertErrorsInCode(''' +class A {} +const a = A(); +''', [ + error(CompileTimeErrorCode.CONST_WITH_NON_CONST, 21, 3), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 21, + 3), + ]); + } + + test_visitInstanceCreationExpression_simpleArgs() async { + await assertNoErrorsInCode(''' +class A { + const A(int x); +} +const a = A(1); +'''); + final result = _topLevelVar('a'); + assertDartObjectText(result, r''' +A + variable: self::@variable::a +'''); + } + + test_visitInstanceCreationExpression_unknown() async { + await assertErrorsInCode(''' +class C { + const C.named(); +} + +const x = C.(); +''', [ + // TODO(https://github.com/dart-lang/sdk/issues/50441): This should not be + // reported. + error(CompileTimeErrorCode.CLASS_INSTANTIATION_ACCESS_TO_UNKNOWN_MEMBER, + 45, 8), + error(ParserErrorCode.MISSING_IDENTIFIER, 52, 1), + ]); + } + test_visitInterpolationExpression_list() async { await assertErrorsInCode(r''' const x = '${const [2]}'; @@ -1656,6 +1975,70 @@ const x = [1, if (1) 2 else 3, 4]; _assertNull(result); } + test_visitListLiteral_listElement_explicitType() async { + await assertNoErrorsInCode(r''' +const x = ['a', 'b', 'c']; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +List + elementType: String + elements + String a + String b + String c + variable: self::@variable::x +'''); + } + + test_visitListLiteral_listElement_explicitType_functionType() async { + await assertNoErrorsInCode(r''' +const x = []; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +List + elementType: void Function() + variable: self::@variable::x +'''); + } + + test_visitListLiteral_listElement_simple() async { + await assertNoErrorsInCode(r''' +const x = ['a', 'b', 'c']; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +List + elementType: String + elements + String a + String b + String c + variable: self::@variable::x +'''); + } + + test_visitListLiteral_listElement_variableElements() async { + await assertNoErrorsInCode(r''' +const a = 0; +const b = 2; +const c = [a, 1, b]; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +List + elementType: int + elements + int 0 + variable: self::@variable::a + int 1 + int 2 + variable: self::@variable::b + variable: self::@variable::c +'''); + } + test_visitListLiteral_spreadElement() async { await assertErrorsInCode(r''' const dynamic a = 5; @@ -1778,40 +2161,7 @@ void Function(T) '''); } - test_visitPrefixExpression_extensionMethod() async { - await assertErrorsInCode(''' -extension on Object { - int operator -() => 0; -} - -const Object v1 = 1; -const v2 = -v1; -''', [ - error(CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD, 82, 3), - ]); - final result = _topLevelVar('v2'); - _assertNull(result); - } - - test_visitPropertyAccess_genericFunction_instantiated() async { - await assertNoErrorsInCode(''' -import '' as self; -class C { - static void f(T a) {} -} -const void Function(int) g = self.C.f; -'''); - final result = _topLevelVar('g'); - assertDartObjectText(result, ''' -void Function(int) - element: self::@class::C::@method::f - typeArguments - int - variable: self::@variable::g -'''); - } - - test_visitPropertyAccess_length_invalidTarget() async { + test_visitPrefixedIdentifier_length_invalidTarget() async { await assertErrorsInCode(''' void main() { const RequiresNonEmptyList([1]); @@ -1834,6 +2184,144 @@ class RequiresNonEmptyList { ]); } + test_visitPrefixExpression_bitNot() async { + await assertNoErrorsInCode(''' +const c = ~42; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, ''' +int -43 + variable: self::@variable::c +'''); + } + + test_visitPrefixExpression_extensionMethod() async { + await assertErrorsInCode(''' +extension on Object { + int operator -() => 0; +} + +const Object v1 = 1; +const v2 = -v1; +''', [ + error(CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD, 82, 3), + ]); + final result = _topLevelVar('v2'); + _assertNull(result); + } + + test_visitPrefixExpression_logicalNot() async { + await assertNoErrorsInCode(''' +const c = !true; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool false + variable: self::@variable::c +'''); + } + + test_visitPrefixExpression_negated_bool() async { + await assertErrorsInCode(''' +const c = -true; +''', [ + error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 10, 1), + error(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM, 10, 5), + ]); + } + + test_visitPrefixExpression_negated_double() async { + await assertNoErrorsInCode(''' +const c = -42.3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double -42.3 + variable: self::@variable::c +'''); + } + + test_visitPrefixExpression_negated_int() async { + await assertNoErrorsInCode(''' +const c = -42; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +int -42 + variable: self::@variable::c +'''); + } + + test_visitPropertyAccess_genericFunction_instantiated() async { + await assertNoErrorsInCode(''' +import '' as self; +class C { + static void f(T a) {} +} +const void Function(int) g = self.C.f; +'''); + final result = _topLevelVar('g'); + assertDartObjectText(result, ''' +void Function(int) + element: self::@class::C::@method::f + typeArguments + int + variable: self::@variable::g +'''); + } + + test_visitPropertyAccess_length_complex() async { + await assertNoErrorsInCode(''' +const x = ('qwe' + 'rty').length; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +int 6 + variable: self::@variable::x +'''); + } + + test_visitPropertyAccess_length_simple() async { + await assertNoErrorsInCode(''' +const x = 'Dvorak'.length; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +int 6 + variable: self::@variable::x +'''); + } + + test_visitRecordLiteral_mixedTypes() async { + await assertNoErrorsInCode(r''' +const x = (0, f1: 10, f2: 2.3); +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +Record(int, {int f1, double f2}) + positionalFields + $1: int 0 + namedFields + f1: int 10 + f2: double 2.3 + variable: self::@variable::x +'''); + } + + test_visitRecordLiteral_named() async { + await assertNoErrorsInCode(r''' +const x = (f1: 10, f2: -3); +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +Record({int f1, int f2}) + namedFields + f1: int 10 + f2: int -3 + variable: self::@variable::x +'''); + } + test_visitRecordLiteral_objectField_generic() async { await assertNoErrorsInCode(r''' class A { @@ -1854,6 +2342,21 @@ A '''); } + test_visitRecordLiteral_positional() async { + await assertNoErrorsInCode(r''' +const x = (20, 0, 7); +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +Record(int, int, int) + positionalFields + $1: int 20 + $2: int 0 + $3: int 7 + variable: self::@variable::x +'''); + } + test_visitRecordLiteral_withoutEnvironment() async { await assertNoErrorsInCode(r''' const a = (1, 'b', c: false); @@ -1870,19 +2373,28 @@ Record(int, String, {bool c}) '''); } - test_visitSetOrMapLiteral_double_zeros() async { + test_visitSetOrMapLiteral_map_complexKey() async { await assertNoErrorsInCode(r''' -class C { - final double x; - const C(this.x); -} - -const cp0 = C(0.0); -const cm0 = C(-0.0); - -main(){ - print(const{cp0, cm0}); +class A { + final int x; + const A(this.x); } +void fn() => 2; +const x = {A(0): 1, fn: 2}; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, r''' +Map + entries + entry + key: A + x: int 0 + value: int 1 + entry + key: void Function() + element: self::@function::fn + value: int 2 + variable: self::@variable::x '''); } @@ -1921,6 +2433,53 @@ const c = const {if (nonBool) 'a' : 1}; _assertNull(result); } + test_visitSetOrMapLiteral_map_mapElement() async { + await assertNoErrorsInCode(r''' +const x = {'a' : 'm', 'b' : 'n', 'c' : 'o'}; +'''); + final result = _topLevelVar('x'); + assertDartObjectText(result, ''' +Map + entries + entry + key: String a + value: String m + entry + key: String b + value: String n + entry + key: String c + value: String o + variable: self::@variable::x +'''); + } + + test_visitSetOrMapLiteral_set_double_zeros() async { + await assertNoErrorsInCode(r''' +class C { + final double x; + const C(this.x); +} + +const cp0 = C(0.0); +const cm0 = C(-0.0); + +const a = {cp0, cm0}; +'''); + final result = _topLevelVar('a'); + assertDartObjectText(result, ''' +Set + elements + C + x: double 0.0 + variable: self::@variable::cp0 + C + x: double -0.0 + variable: self::@variable::cm0 + variable: self::@variable::a +'''); + } + test_visitSetOrMapLiteral_set_forElement() async { await assertErrorsInCode(r''' const Set set = {}; @@ -2295,6 +2854,17 @@ const c = {1, ...{2, 3}, 4}; expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 3, 4]); } + test_visitAdjacentInterpolation_simple() async { + await assertNoErrorsInCode(''' +const c = 'abc' 'def'; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, ''' +String abcdef + variable: self::@variable::c +'''); + } + test_visitAsExpression_instanceOfSameClass() async { await resolveTestCode(''' const a = const A(); @@ -2371,6 +2941,50 @@ class MyClass { '''); } + test_visitBinaryExpression_add_double_double() async { + await assertNoErrorsInCode(''' +const c = 2.3 + 3.2; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double 5.5 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_add_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 + 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +int 5 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_add_string_string() async { + await assertNoErrorsInCode(''' +const c = 'a' + 'b'; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +String ab + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_and_bool_bool() async { + await assertNoErrorsInCode(''' +const c = true && false; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool false + variable: self::@variable::c +'''); + } + test_visitBinaryExpression_and_bool_false_invalid() async { await assertErrorsInCode(''' final a = false; @@ -2451,11 +3065,14 @@ const c = a & b; } test_visitBinaryExpression_and_int() async { - await resolveTestCode(''' -const c = 3 & 5; + await assertNoErrorsInCode(''' +const c = 74 & 42; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +int 10 + variable: self::@variable::c '''); - DartObjectImpl result = _evaluateConstant('c'); - expect(result.type, typeProvider.intType); } test_visitBinaryExpression_and_mixed() async { @@ -2467,6 +3084,125 @@ const c = 3 & false; ]); } + test_visitBinaryExpression_divide_double_double() async { + await assertNoErrorsInCode(''' +const c = 3.2 / 2.3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double 1.3913043478260871 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_divide_double_double_byZero() async { + await assertNoErrorsInCode(''' +const c = 3.2 / 0.0; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double Infinity + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_divide_int_int() async { + await assertNoErrorsInCode(''' +const c = 3 / 2; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double 1.5 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_divide_int_int_byZero() async { + await assertNoErrorsInCode(''' +const c = 3 / 0; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double Infinity + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_minus_double_double() async { + await assertNoErrorsInCode(''' +const c = 3.2 - 2.3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double 0.9000000000000004 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_minus_int_int() async { + await assertNoErrorsInCode(''' +const c = 3 - 2; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +int 1 + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_notEqual_bool_bool() async { + await assertNoErrorsInCode(''' +const c = true != false; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_notEqual_int_int() async { + await assertNoErrorsInCode(''' +const c = 2 != 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + + test_visitBinaryExpression_notEqual_invalidLeft() async { + await assertErrorsInCode(''' +const c = a != 3; +''', [ + error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 10, + 1), + ]); + } + + test_visitBinaryExpression_notEqual_invalidRight() async { + await assertErrorsInCode(''' +const c = 2 != a; +''', [ + error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 15, 1), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 15, + 1), + ]); + } + + test_visitBinaryExpression_notEqual_string_string() async { + await assertNoErrorsInCode(''' +const c = 'a' != 'b'; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + test_visitBinaryExpression_or_bool_false_invalid() async { await assertErrorsInCode(''' final a = false; @@ -2554,6 +3290,19 @@ const c = 3 | 5; expect(result.type, typeProvider.intType); } + test_visitBinaryExpression_or_known_known() async { + await assertErrorsInCode(''' +const c = true || false; +''', [ + error(WarningCode.DEAD_CODE, 15, 8), + ]); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + test_visitBinaryExpression_or_mixed() async { await assertErrorsInCode(''' const c = 3 | false; @@ -2652,6 +3401,30 @@ const c = 3 ^ false; ]); } + test_visitBoolLiteral_false() async { + await assertNoErrorsInCode(''' +const c = false; +'''); + final result = _topLevelVar('c'); + dartObjectPrinterConfiguration.withHexIntegers = true; + assertDartObjectText(result, r''' +bool false + variable: self::@variable::c +'''); + } + + test_visitBoolLiteral_true() async { + await assertNoErrorsInCode(''' +const c = true; +'''); + final result = _topLevelVar('c'); + dartObjectPrinterConfiguration.withHexIntegers = true; + assertDartObjectText(result, r''' +bool true + variable: self::@variable::c +'''); + } + test_visitConditionalExpression_eager_false_int_int() async { await assertErrorsInCode(''' const c = false ? 1 : 0; @@ -2797,7 +3570,18 @@ const c = identical(0, 0.0) ? 1 : new Object(); ]); } - test_visitIntegerLiteral() async { + test_visitDoubleLiteral() async { + await assertNoErrorsInCode(''' +const c = 3.45; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +double 3.45 + variable: self::@variable::c +'''); + } + + test_visitIntegerLiteral_doubleType() async { await resolveTestCode(''' const double d = 3; '''); @@ -2806,6 +3590,17 @@ const double d = 3; expect(result.toDoubleValue(), 3.0); } + test_visitIntegerLiteral_integer() async { + await assertNoErrorsInCode(''' +const c = 3; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +int 3 + variable: self::@variable::c +'''); + } + test_visitIsExpression_is_functionType_badTypes() async { await assertNoErrorsInCode(''' void foo(int a) {} @@ -2931,6 +3726,28 @@ bool true '''); } + test_visitNullLiteral_null() async { + await assertNoErrorsInCode(''' +const c = null; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, ''' +Null null + variable: self::@variable::c +'''); + } + + test_visitParenthesizedExpression_string() async { + await assertNoErrorsInCode(''' +const a = ('a'); +'''); + final result = _topLevelVar('a'); + assertDartObjectText(result, r''' +String a + variable: self::@variable::a +'''); + } + test_visitPropertyAccess_length_extension() async { await assertErrorsInCode(''' extension ExtObject on Object { @@ -3019,6 +3836,18 @@ int 3 '''); } + test_visitSimpleIdentifier_variable() async { + await assertNoErrorsInCode(''' +const a = 42; +const b = a; +'''); + final result = _topLevelVar('b'); + assertDartObjectText(result, ''' +int 42 + variable: self::@variable::b +'''); + } + test_visitSimpleIdentifier_withoutEnvironment() async { await assertNoErrorsInCode(r''' const a = b; @@ -3027,6 +3856,38 @@ const b = 3;'''); assertDartObjectText(result, r''' int 3 variable: self::@variable::a +'''); + } + + test_visitSimpleStringLiteral_valid() async { + await assertNoErrorsInCode(r''' +const c = 'abc'; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, ''' +String abc + variable: self::@variable::c +'''); + } + + test_visitStringInterpolation_invalid() async { + await assertErrorsInCode(r''' +const c = 'a${f()}c'; +''', [ + error(CompileTimeErrorCode.UNDEFINED_FUNCTION, 14, 1), + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 14, + 3), + ]); + } + + test_visitStringInterpolation_valid() async { + await assertNoErrorsInCode(r''' +const c = 'a${3}c'; +'''); + final result = _topLevelVar('c'); + assertDartObjectText(result, r''' +String a3c + variable: self::@variable::c '''); } } @@ -3456,6 +4317,18 @@ A '''); } + /// See https://github.com/dart-lang/sdk/issues/50045 + test_bool_fromEnvironment_dartLibraryJsUtil() async { + await resolveTestCode(''' +const a = bool.fromEnvironment('dart.library.js_util'); +'''); + + assertDartObjectText(_topLevelVar('a'), ''' + bool + variable: self::@variable::a +'''); + } + test_fieldInitializer_functionReference_withTypeParameter() async { await assertNoErrorsInCode(''' void g(U a) {} @@ -3603,6 +4476,260 @@ A '''); } + test_superInitializer_formalParameter_explicitSuper_hasNamedArgument_requiredNamed() async { + await assertNoErrorsInCode(''' +class A { + final int a; + final int b; + const A({required this.a, required this.b}); +} + +class B extends A { + final int c; + const B(this.c, {required super.b}) : super(a: 1); +} + +const x = B(3, b: 2); +'''); + + var result = _topLevelVar('x'); + assertDartObjectText(result, r''' +B + (super): A + a: int 1 + b: int 2 + c: int 3 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_explicitSuper_hasNamedArgument_requiredPositional() async { + await assertNoErrorsInCode(''' +class A { + final int a; + final int b; + const A(this.a, {required this.b}); +} + +class B extends A { + final int c; + const B(super.a, {required this.c}) : super(b: 2); +} + +const x = B(1, c: 3); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + c: int 3 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_explicitSuper_requiredNamed() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A({required this.a}); +} + +class B extends A { + final int b; + const B(this.b, {required super.a}) : super(); +} + +const x = B(2, a: 1); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_explicitSuper_requiredNamed_generic() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A({required this.a}); +} + +class B extends A { + final int b; + const B(this.b, {required super.a}) : super(); +} + +const x = B(2, a: 1); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_explicitSuper_requiredPositional() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A(this.a); +} + +class B extends A { + final int b; + const B(super.a, this.b) : super(); +} + +const x = B(1, 2); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_explicitSuper_requiredPositional_generic() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A(this.a); +} + +class B extends A { + final int b; + const B(super.a, this.b) : super(); +} + +const x = B(1, 2); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_implicitSuper_requiredNamed() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A({required this.a}); +} + +class B extends A { + final int b; + const B(this.b, {required super.a}); +} + +const x = B(2, a: 1); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_implicitSuper_requiredNamed_generic() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A({required this.a}); +} + +class B extends A { + final int b; + const B(this.b, {required super.a}); +} + +const x = B(2, a: 1); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_implicitSuper_requiredPositional() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A(this.a); +} + +class B extends A { + final int b; + const B(super.a, this.b); +} + +const x = B(1, 2); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + + test_superInitializer_formalParameter_implicitSuper_requiredPositional_generic() async { + await assertNoErrorsInCode(''' +class A { + final int a; + const A(this.a); +} + +class B extends A { + final int b; + const B(super.a, this.b); +} + +const x = B(1, 2); +'''); + + var value = _topLevelVar('x'); + assertDartObjectText(value, r''' +B + (super): A + a: int 1 + b: int 2 + variable: self::@variable::x +'''); + } + test_superInitializer_paramTypeMismatch_indirect() async { await assertErrorsInCode(''' class C { diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart index bc874e3ba4f..030358055af 100644 --- a/pkg/analyzer/test/src/dart/constant/value_test.dart +++ b/pkg/analyzer/test/src/dart/constant/value_test.dart @@ -6,8 +6,8 @@ import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type_provider.dart'; +import 'package:analyzer/src/dart/constant/value.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; -import 'package:analyzer/src/generated/constant.dart'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; diff --git a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart index 0a242358e5f..9a5811f6749 100644 --- a/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart +++ b/pkg/analyzer/test/src/dart/resolution/dart_object_printer.dart @@ -48,8 +48,12 @@ class DartObjectPrinter { _writeGenericState(type, state); } else if (state is ListState) { _writeListState(state); + } else if (state is MapState) { + _writeMapState(state); } else if (state is RecordState) { _writeRecordState(type, state); + } else if (state is SetState) { + _writeSetState(state); } else if (state is TypeState) { _sink.write('Type '); _sink.writeln(state); @@ -122,6 +126,30 @@ class DartObjectPrinter { } } + void _writeMapState(MapState state) { + _sink.writeln('Map'); + _sink.withIndent(() { + final entries = state.entries; + if (entries.isNotEmpty) { + _sink.writelnWithIndent('entries'); + _sink.withIndent(() { + for (final entry in entries.entries) { + _sink.writelnWithIndent('entry'); + _sink.withIndent(() { + _sink.writeIndent(); + _sink.write('key: '); + write(entry.key); + + _sink.writeIndent(); + _sink.write('value: '); + write(entry.value); + }); + } + }); + } + }); + } + void _writeRecordState(DartType type, RecordState state) { _sink.write('Record'); _elementPrinter.writeType(type); @@ -154,6 +182,22 @@ class DartObjectPrinter { }); } + void _writeSetState(SetState state) { + _sink.writeln('Set'); + _sink.withIndent(() { + final elements = state.elements; + if (elements.isNotEmpty) { + _sink.writelnWithIndent('elements'); + _sink.withIndent(() { + for (final element in elements) { + _sink.writeIndent(); + write(element); + } + }); + } + }); + } + void _writeString(DartObjectImpl object) { _sink.write('String ');