Add SDK constraint checks for the constant update 2018 features
Change-Id: I308a32de5e73a93d8dead38ab45c130f88ef706d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97567
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index c4beb80..a41dc92 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -93,6 +93,12 @@
bool get isDartCoreNull;
/**
+ * Return `true` if this type represents the type 'String' defined in the
+ * dart:core library.
+ */
+ bool get isDartCoreString;
+
+ /**
* Return `true` if this type represents the type 'dynamic'.
*/
bool get isDynamic;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 8642f19..7c86f12 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -337,6 +337,11 @@
HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER,
HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT,
HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE,
+ HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT,
+ HintCode.SDK_VERSION_BOOL_OPERATOR,
+ HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT,
+ HintCode.SDK_VERSION_GT_GT_GT_OPERATOR,
+ HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT,
HintCode.SDK_VERSION_SET_LITERAL,
HintCode.SDK_VERSION_UI_AS_CODE,
HintCode.STRICT_RAW_TYPE,
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 5fbed4f..e2393ca 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1541,6 +1541,15 @@
}
@override
+ bool get isDartCoreString {
+ ClassElement element = this.element;
+ if (element == null) {
+ return false;
+ }
+ return element.name == "String" && element.library.isDartCore;
+ }
+
+ @override
bool get isObject => element.supertype == null && !element.isMixin;
@override
@@ -2825,6 +2834,9 @@
bool get isDartCoreNull => false;
@override
+ bool get isDartCoreString => false;
+
+ @override
bool get isDynamic => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 950e5ea..ef7f16c 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -550,6 +550,61 @@
"Try either importing 'dart:async' or updating the SDK constraints.");
/**
+ * An as expression being used in a const context is expected to run on
+ * versions of the SDK that did not support them.
+ */
+ static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT =
+ const HintCode(
+ 'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
+ "The use of an as expression in a constant expression wasn't "
+ "supported until version 2.2.2, but this code is required to be able "
+ "to run on earlier versions.",
+ correction: "Try updating the SDK constraints.");
+
+ /**
+ * The operator '&', '|' or '^' is being used on boolean values in code that
+ * is expected to run on versions of the SDK that did not support it.
+ */
+ static const HintCode SDK_VERSION_BOOL_OPERATOR = const HintCode(
+ 'SDK_VERSION_BOOL_OPERATOR',
+ "Using the operator '{0}' for 'bool's was not supported until version "
+ "2.2.2, but this code is required to be able to run on earlier versions.",
+ correction: "Try updating the SDK constraints.");
+
+ /**
+ * The operator '==' is being used on non-primitive values in code that
+ * is expected to run on versions of the SDK that did not support it.
+ */
+ static const HintCode SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT = const HintCode(
+ 'SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT',
+ "Using the operator '==' for non-primitive types was not supported until "
+ "version 2.2.2, but this code is required to be able to run on earlier "
+ "versions.",
+ correction: "Try updating the SDK constraints.");
+
+ /**
+ * The operator '>>>' is being used in code that is expected to run on
+ * versions of the SDK that did not support it.
+ */
+ static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = const HintCode(
+ 'SDK_VERSION_GT_GT_GT_OPERATOR',
+ "The operator '>>>' was not supported until version 2.2.2, but this code "
+ "is required to be able to run on earlier versions.",
+ correction: "Try updating the SDK constraints.");
+
+ /**
+ * An is expression being used in a const context is expected to run on
+ * versions of the SDK that did not support them.
+ */
+ static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT =
+ const HintCode(
+ 'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
+ "The use of an is expression in a constant expression wasn't "
+ "supported until version 2.2.2, but this code is required to be able "
+ "to run on earlier versions.",
+ correction: "Try updating the SDK constraints.");
+
+ /**
* A set literal is being used in code that is expected to run on versions of
* the SDK that did not support them.
*/
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index b7a9c21..c8b749c 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -3,9 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -26,6 +29,11 @@
/// The version constraint for the SDK.
final VersionConstraint _versionConstraint;
+ /// A cached flag indicating whether references to the constant-update-2018
+ /// features need to be checked. Use [checkConstantUpdate2018] to access this
+ /// field.
+ bool _checkConstantUpdate2018;
+
/// A cached flag indicating whether references to Future and Stream need to
/// be checked. Use [checkFutureAndStream] to access this field.
bool _checkFutureAndStream;
@@ -64,6 +72,11 @@
VersionRange get before_2_2_2 =>
new VersionRange(max: Version.parse('2.2.2'), includeMax: false);
+ /// Return `true` if references to the constant-update-2018 features need to
+ /// be checked.
+ bool get checkConstantUpdate2018 => _checkConstantUpdate2018 ??=
+ !before_2_2_2.intersect(_versionConstraint).isEmpty;
+
/// Return `true` if references to Future and Stream need to be checked.
bool get checkFutureAndStream => _checkFutureAndStream ??=
!before_2_1_0.intersect(_versionConstraint).isEmpty;
@@ -78,6 +91,51 @@
_checkUiAsCode ??= !before_2_2_2.intersect(_versionConstraint).isEmpty;
@override
+ void visitAsExpression(AsExpression node) {
+ if (checkConstantUpdate2018 &&
+ (node as AsExpressionImpl).inConstantContext) {
+ _errorReporter.reportErrorForNode(
+ HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT, node);
+ }
+ super.visitAsExpression(node);
+ }
+
+ @override
+ void visitBinaryExpression(BinaryExpression node) {
+ if (checkConstantUpdate2018) {
+ TokenType operatorType = node.operator.type;
+ if (operatorType == TokenType.GT_GT_GT) {
+ _errorReporter.reportErrorForToken(
+ HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, node.operator);
+ } else if (operatorType == TokenType.AMPERSAND ||
+ operatorType == TokenType.BAR ||
+ operatorType == TokenType.CARET) {
+ if (node.leftOperand.staticType.isDartCoreBool) {
+ _errorReporter.reportErrorForToken(HintCode.SDK_VERSION_BOOL_OPERATOR,
+ node.operator, [node.operator.lexeme]);
+ }
+ } else if (operatorType == TokenType.EQ_EQ &&
+ (node as BinaryExpressionImpl).inConstantContext) {
+ bool primitive(Expression node) {
+ DartType type = node.staticType;
+ return type.isDartCoreBool ||
+ type.isDartCoreDouble ||
+ type.isDartCoreInt ||
+ type.isDartCoreNull ||
+ type.isDartCoreString;
+ }
+
+ if (!primitive(node.leftOperand) || !primitive(node.rightOperand)) {
+ _errorReporter.reportErrorForToken(
+ HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT,
+ node.operator);
+ }
+ }
+ }
+ super.visitBinaryExpression(node);
+ }
+
+ @override
void visitForElement(ForElement node) {
_validateUiAsCode(node);
bool wasInUiAsCode = _inUiAsCode;
@@ -101,6 +159,25 @@
}
@override
+ void visitIsExpression(IsExpression node) {
+ if (checkConstantUpdate2018 &&
+ (node as IsExpressionImpl).inConstantContext) {
+ _errorReporter.reportErrorForNode(
+ HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT, node);
+ }
+ super.visitIsExpression(node);
+ }
+
+ @override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ if (checkConstantUpdate2018 && node.isOperator && node.name.name == '>>>') {
+ _errorReporter.reportErrorForNode(
+ HintCode.SDK_VERSION_GT_GT_GT_OPERATOR, node.name);
+ }
+ super.visitMethodDeclaration(node);
+ }
+
+ @override
void visitSetOrMapLiteral(SetOrMapLiteral node) {
if (node.isSet && checkSetLiterals && !_inSetLiteral) {
_errorReporter.reportErrorForNode(HintCode.SDK_VERSION_SET_LITERAL, node);
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index f9828f5..47659a8 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -143,9 +143,12 @@
void print(Object object) {}
-class bool extends Object {
+abstract class bool extends Object {
external const factory bool.fromEnvironment(String name,
{bool defaultValue: false});
+ bool operator &(bool other);
+ bool operator |(bool other);
+ bool operator ^(bool other);
}
abstract class Comparable<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart b/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart
index 81658b9..0624d6a 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_constraint_verifier_support.dart
@@ -7,9 +7,11 @@
import '../dart/resolution/driver_resolution.dart';
-/// A base class designed to be used by tests of the hints produced by an
+/// A base class designed to be used by tests of the hints produced by the
/// SdkConstraintVerifier.
class SdkConstraintVerifierTest extends DriverResolutionTest {
+ /// Verify that the [errorCodes] are produced if the [source] is analyzed in
+ /// a context that specifies the minimum SDK version to be [version].
verifyVersion(String version, String source,
{List<ErrorCode> errorCodes}) async {
driver.configure(
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
new file mode 100644
index 0000000..b63e481
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SdkVersionAsExpressionInConstContextTest);
+ });
+}
+
+@reflectiveTest
+class SdkVersionAsExpressionInConstContextTest
+ extends SdkConstraintVerifierTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+
+ test_equals() {
+ verifyVersion('2.2.2', '''
+const dynamic a = 2;
+const c = (a as int) + 2;
+''');
+ }
+
+ test_lessThan() {
+ verifyVersion('2.2.0', '''
+const dynamic a = 2;
+const c = (a as int) + 2;
+''', errorCodes: [HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
new file mode 100644
index 0000000..241e28f
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2019, 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/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SdkVersionBoolOperatorTest);
+ });
+}
+
+@reflectiveTest
+class SdkVersionBoolOperatorTest extends SdkConstraintVerifierTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+
+ test_and_const_equals() {
+ verifyVersion('2.2.2', '''
+const c = true & false;
+''');
+ }
+
+ test_and_const_lessThan() {
+ verifyVersion('2.2.0', '''
+const c = true & false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+
+ test_and_nonConst_equals() {
+ verifyVersion('2.2.2', '''
+var c = true & false;
+''');
+ }
+
+ test_and_nonConst_lessThan() {
+ verifyVersion('2.2.0', '''
+var c = true & false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+
+ test_or_const_equals() {
+ verifyVersion('2.2.2', '''
+const c = true | false;
+''');
+ }
+
+ test_or_const_lessThan() {
+ verifyVersion('2.2.0', '''
+const c = true | false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+
+ test_or_nonConst_equals() {
+ verifyVersion('2.2.2', '''
+var c = true | false;
+''');
+ }
+
+ test_or_nonConst_lessThan() {
+ verifyVersion('2.2.0', '''
+var c = true | false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+
+ test_xor_const_equals() {
+ verifyVersion('2.2.2', '''
+const c = true ^ false;
+''');
+ }
+
+ test_xor_const_lessThan() {
+ verifyVersion('2.2.0', '''
+const c = true ^ false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+
+ test_xor_nonConst_equals() {
+ verifyVersion('2.2.2', '''
+var c = true ^ false;
+''');
+ }
+
+ test_xor_nonConst_lessThan() {
+ verifyVersion('2.2.0', '''
+var c = true ^ false;
+''', errorCodes: [HintCode.SDK_VERSION_BOOL_OPERATOR]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
new file mode 100644
index 0000000..3d6b6ca
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2019, 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/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SdkVersionEqEqOperatorTest);
+ });
+}
+
+@reflectiveTest
+class SdkVersionEqEqOperatorTest extends SdkConstraintVerifierTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+
+ test_left_equals() {
+ verifyVersion('2.2.2', '''
+class A {
+ const A();
+}
+const A a = A();
+const c = a == null;
+''');
+ }
+
+ test_left_lessThan() {
+ verifyVersion('2.2.0', '''
+class A {
+ const A();
+}
+const A a = A();
+const c = a == null;
+''', errorCodes: [HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT]);
+ }
+
+ test_right_equals() {
+ verifyVersion('2.2.2', '''
+class A {
+ const A();
+}
+const A a = A();
+const c = null == a;
+''');
+ }
+
+ test_right_lessThan() {
+ verifyVersion('2.2.0', '''
+class A {
+ const A();
+}
+const A a = A();
+const c = null == a;
+''', errorCodes: [HintCode.SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
new file mode 100644
index 0000000..88ddc4e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, 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/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SdkVersionGtGtGtOperatorTest);
+ });
+}
+
+@reflectiveTest
+class SdkVersionGtGtGtOperatorTest extends SdkConstraintVerifierTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+
+ test_const_equals() {
+ // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
+ // UNDEFINED_OPERATOR when constant update is enabled by default.
+ verifyVersion('2.2.2', '''
+const a = 42 >>> 3;
+''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+ }
+
+ test_const_lessThan() {
+ // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
+ // UNDEFINED_OPERATOR when constant update is enabled by default.
+ verifyVersion('2.2.0', '''
+const a = 42 >>> 3;
+''', errorCodes: [
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ HintCode.SDK_VERSION_GT_GT_GT_OPERATOR
+ ]);
+ }
+
+ test_declaration_equals() {
+ verifyVersion('2.2.2', '''
+class A {
+ A operator >>>(A a) => this;
+}
+''');
+ }
+
+ test_declaration_lessThan() {
+ verifyVersion('2.2.0', '''
+class A {
+ A operator >>>(A a) => this;
+}
+''', errorCodes: [HintCode.SDK_VERSION_GT_GT_GT_OPERATOR]);
+ }
+
+ test_nonConst_equals() {
+ // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
+ // UNDEFINED_OPERATOR when constant update is enabled by default.
+ verifyVersion('2.2.2', '''
+var a = 42 >>> 3;
+''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+ }
+
+ test_nonConst_lessThan() {
+ // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
+ // UNDEFINED_OPERATOR when constant update is enabled by default.
+ verifyVersion('2.2.0', '''
+var a = 42 >>> 3;
+''', errorCodes: [
+ StaticTypeWarningCode.UNDEFINED_OPERATOR,
+ HintCode.SDK_VERSION_GT_GT_GT_OPERATOR
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
new file mode 100644
index 0000000..70778cf
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, 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/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'sdk_constraint_verifier_support.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SdkVersionIsExpressionInConstContextTest);
+ });
+}
+
+@reflectiveTest
+class SdkVersionIsExpressionInConstContextTest
+ extends SdkConstraintVerifierTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+
+ test_equals() {
+ verifyVersion('2.2.2', '''
+const dynamic a = 2;
+const c = a is int;
+''');
+ }
+
+ test_lessThan() {
+ verifyVersion('2.2.0', '''
+const dynamic a = 2;
+const c = a is int;
+''', errorCodes: [HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 357bdaa..6f6fe2a 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -67,8 +67,16 @@
as non_constant_spread_expression_from_deferred_library;
import 'not_iterable_spread_test.dart' as not_iterable_spread;
import 'not_map_spread_test.dart' as not_map_spread;
+import 'sdk_version_as_expression_in_const_context_test.dart'
+ as sdk_version_as_expression_in_const_context;
import 'sdk_version_async_exported_from_core_test.dart'
as sdk_version_async_exported_from_core;
+import 'sdk_version_bool_operator_test.dart' as sdk_version_bool_operator;
+import 'sdk_version_eq_eq_operator_test.dart' as sdk_version_eq_eq_operator;
+import 'sdk_version_gt_gt_gt_operator_test.dart'
+ as sdk_version_gt_gt_gt_operator;
+import 'sdk_version_is_expression_in_const_context_test.dart'
+ as sdk_version_is_expression_in_const_context;
import 'sdk_version_set_literal_test.dart' as sdk_version_set_literal;
import 'sdk_version_ui_as_code_test.dart' as sdk_version_ui_as_code;
import 'set_element_type_not_assignable_test.dart'
@@ -152,7 +160,12 @@
non_constant_spread_expression_from_deferred_library.main();
not_iterable_spread.main();
not_map_spread.main();
+ sdk_version_as_expression_in_const_context.main();
sdk_version_async_exported_from_core.main();
+ sdk_version_bool_operator.main();
+ sdk_version_eq_eq_operator.main();
+ sdk_version_gt_gt_gt_operator.main();
+ sdk_version_is_expression_in_const_context.main();
sdk_version_set_literal.main();
sdk_version_ui_as_code.main();
set_element_type_not_assignable.main();