Version 2.10.0-79.0.dev
Merge commit '69387f9d9337aed4ed9b5c73c9685064b1052f25' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 3284b6f..6d408cd 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -500,6 +500,7 @@
ImportLibrary.forType,
],
CompileTimeErrorCode.EXTENDS_NON_CLASS: [
+ DataDriven.newInstance,
ImportLibrary.forType,
],
CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS: [
@@ -509,6 +510,7 @@
AddMissingParameter.newInstance,
],
CompileTimeErrorCode.IMPLEMENTS_NON_CLASS: [
+ DataDriven.newInstance,
ImportLibrary.forType,
],
CompileTimeErrorCode.INVALID_ANNOTATION: [
@@ -519,6 +521,7 @@
DataDriven.newInstance,
],
CompileTimeErrorCode.MIXIN_OF_NON_CLASS: [
+ DataDriven.newInstance,
ImportLibrary.forType,
],
CompileTimeErrorCode.NEW_WITH_NON_TYPE: [
@@ -551,21 +554,25 @@
ImportLibrary.forType,
],
CompileTimeErrorCode.UNDEFINED_CLASS: [
+ DataDriven.newInstance,
ImportLibrary.forType,
],
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT: [
AddSuperConstructorInvocation.newInstance,
],
CompileTimeErrorCode.UNDEFINED_FUNCTION: [
+ DataDriven.newInstance,
ImportLibrary.forExtension,
ImportLibrary.forFunction,
ImportLibrary.forType,
],
CompileTimeErrorCode.UNDEFINED_GETTER: [
+ DataDriven.newInstance,
ImportLibrary.forTopLevelVariable,
ImportLibrary.forType,
],
CompileTimeErrorCode.UNDEFINED_IDENTIFIER: [
+ DataDriven.newInstance,
ImportLibrary.forExtension,
ImportLibrary.forFunction,
ImportLibrary.forTopLevelVariable,
@@ -579,6 +586,10 @@
CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER: [
ChangeArgumentName.newInstance,
],
+ CompileTimeErrorCode.UNDEFINED_SETTER: [
+ DataDriven.newInstance,
+ // TODO(brianwilkerson) Support ImportLibrary
+ ],
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS: [
DataDriven.newInstance,
],
@@ -597,6 +608,9 @@
HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: [
DataDriven.newInstance,
],
+ HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: [
+ DataDriven.newInstance,
+ ],
HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE: [
ImportLibrary.dartAsync,
],
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 8cd7bdb..cd29b71 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -5,6 +5,8 @@
import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'data_driven_test_support.dart';
@@ -12,12 +14,87 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(Rename_DeprecatedMemberUseTest);
+ defineReflectiveTests(Rename_ExtendsNonClassTest);
+ defineReflectiveTests(Rename_ImplementsNonClassTest);
+ defineReflectiveTests(Rename_MixinOfNonClassTest);
+ defineReflectiveTests(Rename_OverrideOnNonOverridingMethodTest);
+ defineReflectiveTests(Rename_UndefinedClassTest);
+ defineReflectiveTests(Rename_UndefinedFunctionTest);
+ defineReflectiveTests(Rename_UndefinedGetterTest);
+ defineReflectiveTests(Rename_UndefinedIdentifierTest);
+ defineReflectiveTests(Rename_UndefinedMethodTest);
});
}
@reflectiveTest
-class Rename_DeprecatedMemberUseTest extends DataDrivenFixProcessorTest {
- Future<void> test_class() async {
+class Rename_DeprecatedMemberUseTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_inExtends() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+class Old {}
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C extends Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C extends New {}
+''');
+ }
+
+ Future<void> test_class_reference_inImplements() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+class Old {}
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C implements Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C implements New {}
+''');
+ }
+
+ Future<void> test_class_reference_inOn() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+class Old {}
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+extension E on Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+extension E on New {}
+''');
+ }
+
+ Future<void> test_class_reference_inTypeAnnotation() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -39,7 +116,55 @@
''');
}
- Future<void> test_constructor_named() async {
+ Future<void> test_class_reference_inWith() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+class Old {}
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''');
+ }
+
+ Future<void> test_class_reference_staticField() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+class Old {
+ static String empty = '';
+}
+class New {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''');
+ }
+
+ Future<void> test_constructor_named_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -67,7 +192,7 @@
''');
}
- Future<void> test_constructor_unnamed() async {
+ Future<void> test_constructor_unnamed_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -97,7 +222,59 @@
''');
}
- Future<void> test_field_instance() async {
+ Future<void> test_extension_reference_override() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+extension Old on String {
+ int get double => length * 2;
+}
+extension New on String {
+ int get double => length * 2;
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var l = Old('a').double;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var l = New('a').double;
+''');
+ }
+
+ Future<void> test_extension_reference_staticField() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+extension Old on String {
+ static String empty = '';
+}
+extension New on String {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''');
+ }
+
+ Future<void> test_field_instance_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -125,7 +302,35 @@
''');
}
- Future<void> test_field_static() async {
+ Future<void> test_field_static_assignment() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+class C {
+ @deprecated
+ static int old;
+ static int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ C.old = 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new = 0;
+}
+''');
+ }
+
+ Future<void> test_field_static_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -153,7 +358,38 @@
''');
}
- Future<void> test_method_instance() async {
+ @failingTest
+ Future<void> test_method_instance_override() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+class C {
+ @deprecated
+ int old() => 0;
+ int new() => 0;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int old() => 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int new() => 0;
+}
+''');
+ }
+
+ Future<void> test_method_instance_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -181,7 +417,7 @@
''');
}
- Future<void> test_method_static() async {
+ Future<void> test_method_static_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -209,7 +445,29 @@
''');
}
- Future<void> test_topLevelFunction() async {
+ Future<void> test_mixin_reference_inWith() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+mixin Old {}
+mixin New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''');
+ }
+
+ Future<void> test_topLevelFunction_reference() async {
addMetaPackage();
setPackageContent('''
import 'package:meta/meta.dart';
@@ -235,6 +493,447 @@
''');
}
+ Future<void> test_typedef_reference() async {
+ addMetaPackage();
+ setPackageContent('''
+import 'package:meta/meta.dart';
+
+@deprecated
+typedef Old = int Function(int);
+typedef New = int Function(int);
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''');
+ }
+}
+
+@reflectiveTest
+class Rename_ExtendsNonClassTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_inExtends() async {
+ setPackageContent('''
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C extends Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C extends New {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_ImplementsNonClassTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_inImplements() async {
+ setPackageContent('''
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C implements Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C implements New {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_MixinOfNonClassTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_inWith() async {
+ setPackageContent('''
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_mixin_reference_inWith() async {
+ setPackageContent('''
+mixin New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_OverrideOnNonOverridingMethodTest extends _AbstractRenameTest {
+ Future<void> test_method_instance_override() async {
+ setPackageContent('''
+class C {
+ int new() => 0;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int old() => 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int new() => 0;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedClassTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_inOn() async {
+ setPackageContent('''
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+extension E on Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+extension E on New {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_class_reference_inTypeAnnotation() async {
+ setPackageContent('''
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_typedef_reference() async {
+ setPackageContent('''
+typedef New = int Function(int);
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedFunctionTest extends _AbstractRenameTest {
+ Future<void> test_constructor_unnamed_reference() async {
+ setPackageContent('''
+class New {
+ New();
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ Old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ New();
+}
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_extension_reference_override() async {
+ setPackageContent('''
+extension New on String {
+ int get double => length * 2;
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var l = Old('a').double;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var l = New('a').double;
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_field_instance_reference() async {
+ setPackageContent('''
+class C {
+ int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.old;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.new;
+}
+''');
+ }
+
+ Future<void> test_topLevelFunction_reference() async {
+ setPackageContent('''
+int new() {}
+''');
+ setPackageData(_rename(['old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ new();
+}
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedGetterTest extends _AbstractRenameTest {
+ Future<void> test_field_static_reference() async {
+ setPackageContent('''
+class C {
+ static int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ C.old;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedIdentifierTest extends _AbstractRenameTest {
+ Future<void> test_class_reference_staticField() async {
+ // CompileTimeErrorCode.UNDEFINED_IDENTIFIER
+ setPackageContent('''
+class New {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''', errorFilter: _ignoreUnusedImport);
+ }
+
+ Future<void> test_extension_reference_staticField() async {
+ setPackageContent('''
+extension New on String {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''', errorFilter: _ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedMethodTest extends _AbstractRenameTest {
+ Future<void> test_constructor_named_reference() async {
+ setPackageContent('''
+class C {
+ C.new();
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ C.old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new();
+}
+''');
+ }
+
+ Future<void> test_method_instance_reference() async {
+ setPackageContent('''
+class C {
+ int new() {}
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.new();
+}
+''');
+ }
+
+ Future<void> test_method_static_reference() async {
+ setPackageContent('''
+class C {
+ static int new() {}
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ C.old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new();
+}
+''');
+ }
+}
+
+@reflectiveTest
+class Rename_UndefinedSetterTest extends _AbstractRenameTest {
+ Future<void> test_field_static_assignment() async {
+ setPackageContent('''
+class C {
+ static int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ C.old = 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new = 0;
+}
+''');
+ }
+}
+
+class _AbstractRenameTest extends DataDrivenFixProcessorTest {
+ bool _ignoreUnusedImport(AnalysisError error) =>
+ error.errorCode != HintCode.UNUSED_IMPORT;
+
Transform _rename(List<String> components, String newName) => Transform(
title: 'title',
element: ElementDescriptor(
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index c37e6c6..54211be 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -834,13 +834,10 @@
checkIndexExpression(node.auxiliaryElements?.staticElement);
if (node.isNullAware) {
- var target = node.realTarget;
- if (_isExpressionWithType(target)) {
- _checkForUnnecessaryNullAware(
- target,
- node.question ?? node.period ?? node.leftBracket,
- );
- }
+ _checkForUnnecessaryNullAware(
+ node.realTarget,
+ node.question ?? node.period ?? node.leftBracket,
+ );
}
super.visitIndexExpression(node);
}
@@ -934,9 +931,7 @@
_checkForStaticAccessToInstanceMember(typeReference, methodName);
_checkForInstanceAccessToStaticMember(
typeReference, node.target, methodName);
- if (_isExpressionWithType(target)) {
- _checkForUnnecessaryNullAware(target, node.operator);
- }
+ _checkForUnnecessaryNullAware(target, node.operator);
} else {
_checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
}
@@ -1039,9 +1034,7 @@
_checkForStaticAccessToInstanceMember(typeReference, propertyName);
_checkForInstanceAccessToStaticMember(
typeReference, node.target, propertyName);
- if (_isExpressionWithType(target)) {
- _checkForUnnecessaryNullAware(target, node.operator);
- }
+ _checkForUnnecessaryNullAware(target, node.operator);
super.visitPropertyAccess(node);
}
@@ -4364,33 +4357,37 @@
var type = operator.type;
if (type == TokenType.QUESTION_PERIOD) {
var realTarget = target.realTarget;
- if (_isExpressionWithType(realTarget)) {
- return previousShortCircuitingOperator(realTarget) ?? operator;
- }
+ return previousShortCircuitingOperator(realTarget) ?? operator;
}
} else if (target is IndexExpression) {
if (target.question != null) {
var realTarget = target.realTarget;
- if (_isExpressionWithType(realTarget)) {
- return previousShortCircuitingOperator(realTarget) ??
- target.question;
- }
+ return previousShortCircuitingOperator(realTarget) ?? target.question;
}
} else if (target is MethodInvocation) {
var operator = target.operator;
var type = operator?.type;
if (type == TokenType.QUESTION_PERIOD) {
var realTarget = target.realTarget;
- if (_isExpressionWithType(realTarget)) {
- return previousShortCircuitingOperator(realTarget) ?? operator;
- }
- return operator;
+ return previousShortCircuitingOperator(realTarget) ?? operator;
}
}
return null;
}
- if (_typeSystem.isStrictlyNonNullable(target.staticType)) {
+ var targetType = target.staticType;
+ if (target is ExtensionOverride) {
+ var arguments = target.argumentList.arguments;
+ if (arguments.length == 1) {
+ targetType = arguments[0].staticType;
+ } else {
+ return;
+ }
+ } else if (targetType == null) {
+ return;
+ }
+
+ if (_typeSystem.isStrictlyNonNullable(targetType)) {
if (errorCode == StaticWarningCode.INVALID_NULL_AWARE_OPERATOR) {
var previousOperator = previousShortCircuitingOperator(target);
if (previousOperator != null) {
@@ -5331,20 +5328,6 @@
}
return null;
}
-
- static bool _isExpressionWithType(Expression node) {
- if (node is ExtensionOverride) {
- return false;
- }
-
- // For `foo?.bar`, `foo` must be an identifier with a value.
- if (node is Identifier) {
- var element = node.staticElement;
- return element is PropertyAccessorElement || element is VariableElement;
- }
-
- return true;
- }
}
/// A record of the elements that will be declared in some scope (block), but
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
index 3f27eb1..bce4df1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
@@ -89,6 +89,88 @@
@reflectiveTest
class InvalidNullAwareOperatorTest extends PubPackageResolutionTest
with WithNullSafetyMixin {
+ test_extensionOverride_assignmentExpression_indexExpression() async {
+ await assertErrorsInCode('''
+extension E on int {
+ operator[]=(int index, bool _) {}
+}
+
+void f(int? a, int b) {
+ E(a)?[0] = true;
+ E(b)?[0] = true;
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 109, 2),
+ ]);
+ }
+
+ test_extensionOverride_assignmentExpression_propertyAccess() async {
+ await assertErrorsInCode('''
+extension E on int {
+ set foo(bool _) {}
+}
+
+void f(int? a, int b) {
+ E(a)?.foo = true;
+ E(b)?.foo = true;
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 95, 2),
+ ]);
+ }
+
+ test_extensionOverride_indexExpression() async {
+ await assertErrorsInCode('''
+extension E on int {
+ bool operator[](int index) => true;
+}
+
+void f(int? a, int b) {
+ E(a)?[0];
+ E(b)?[0];
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 104, 2),
+ ]);
+ assertType(findNode.index('E(a)'), 'bool?');
+ assertType(findNode.index('E(b)'), 'bool?');
+ }
+
+ test_extensionOverride_methodInvocation() async {
+ await assertErrorsInCode('''
+extension E on int {
+ bool foo() => true;
+}
+
+void f(int? a, int b) {
+ E(a)?.foo();
+ E(b)?.foo();
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 91, 2),
+ ]);
+
+ assertType(findNode.methodInvocation('E(a)'), 'bool?');
+ assertType(findNode.methodInvocation('E(b)'), 'bool?');
+ }
+
+ test_extensionOverride_propertyAccess() async {
+ await assertErrorsInCode('''
+extension E on int {
+ bool get foo => true;
+}
+
+void f(int? a, int b) {
+ E(a)?.foo;
+ E(b)?.foo;
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 91, 2),
+ ]);
+ assertType(findNode.propertyAccess('E(a)'), 'bool?');
+ assertType(findNode.propertyAccess('E(b)'), 'bool?');
+ }
+
test_getter_class() async {
await assertNoErrorsInCode('''
class C {
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_non_null_assertion_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_non_null_assertion_test.dart
index a72ca9d..3104f05 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_non_null_assertion_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_non_null_assertion_test.dart
@@ -31,7 +31,33 @@
''');
}
- test_nonNull() async {
+ test_nonNull_function() async {
+ await assertErrorsInCode('''
+void g() {}
+
+void f() {
+ g!();
+}
+''', [
+ error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 27, 1),
+ ]);
+ }
+
+ test_nonNull_method() async {
+ await assertErrorsInCode('''
+class A {
+ static void foo() {}
+}
+
+void f() {
+ A.foo!();
+}
+''', [
+ error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 54, 1),
+ ]);
+ }
+
+ test_nonNull_parameter() async {
await assertErrorsInCode('''
f(int x) {
x!;
diff --git a/pkg/dartdev/README.md b/pkg/dartdev/README.md
index 25e92b1..7b9d987 100644
--- a/pkg/dartdev/README.md
+++ b/pkg/dartdev/README.md
@@ -6,11 +6,12 @@
Usage: dart [<vm-flags>] <command|dart-file> [<arguments>]
Global options:
--h, --help Print this usage information.
--v, --verbose Show additional command output.
- --version Print the Dart SDK version.
- --enable-analytics Enable anonymous analytics.
- --disable-analytics Disable anonymous analytics.
+-h, --help Print this usage information.
+-v, --verbose Show additional command output.
+ --version Print the Dart SDK version.
+ --enable-analytics Enable anonymous analytics.
+ --disable-analytics Disable anonymous analytics.
+ --enable-experiment=<experiment> Enable one or more experimental features (see dart.dev/go/experiments).
Available commands:
analyze Analyze the project's Dart code.
@@ -19,7 +20,7 @@
format Idiomatically formats Dart source code.
pub Work with packages.
run Run a Dart program.
- test Runs tests in this project.
+ test Run tests in this package.
Run "dart help <command>" for more information about a command.
```
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 72df662..b63580a 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -231,6 +231,10 @@
}
@override
+ String get usageFooter =>
+ 'See https://dart.dev/tools/dart-tool for detailed documentation.';
+
+ @override
String get invocation =>
'dart [<vm-flags>] <command|dart-file> [<arguments>]';
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 873680b..669d4be 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -28,7 +28,7 @@
abbr: 'o',
help: '''
Write the output to <file name>.
-This can be an absolute or reletive path.
+This can be an absolute or relative path.
''',
),
};
@@ -175,7 +175,7 @@
)
..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
-For example, 'dart compile $commandName -Da=1,b=2 main.dart'.''')
+For example: dart compile $commandName -Da=1,b=2 main.dart.''')
..addFlag('enable-asserts',
negatable: false, help: 'Enable assert statements.')
..addOption('packages',
@@ -184,7 +184,7 @@
help:
'''Get package locations from the specified file instead of .packages.
<path> can be relative or absolute.
-For example, 'dart compile $commandName --packages=/tmp/pkgs main.dart'.''')
+For example: dart compile $commandName --packages=/tmp/pkgs main.dart.''')
..addOption('save-debugging-info', abbr: 'S', valueHelp: 'path', help: '''
Remove debugging information from the output and save it separately to the specified file.
<path> can be relative or absolute.''');
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index b0296d4..8f28c9f 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -82,7 +82,7 @@
' when running with --enable-vm-service.',
)
..addSeparator(
- 'Other debugging options include:',
+ 'Other debugging options:',
)
..addFlag(
'pause-isolates-on-start',
diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart
index cfaf4f2..f655ed4 100644
--- a/pkg/dartdev/lib/src/commands/test.dart
+++ b/pkg/dartdev/lib/src/commands/test.dart
@@ -18,7 +18,7 @@
import '../vm_interop_handler.dart';
class TestCommand extends DartdevCommand<int> {
- TestCommand() : super('test', 'Runs tests in this project.') {
+ TestCommand() : super('test', 'Run tests in this package.') {
generateParser(argParser);
}
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index a42480f..be43698 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -8,7 +8,8 @@
dependencies:
analysis_server_client:
path: ../analysis_server_client
- analyzer: any
+ analyzer:
+ path: ../analyzer
args: ^1.6.0
cli_util: '>=0.1.4 <0.3.0'
dart2native:
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index 9dbb186..304f598 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -20,7 +20,7 @@
var result = p.runSync('test', ['--help']);
expect(result.exitCode, 0);
expect(result.stderr, isEmpty);
- expect(result.stdout, contains('Runs tests in this project.'));
+ expect(result.stdout, contains('Run tests in this package.'));
expect(result.stdout, contains('Usage: dart test [arguments]'));
expect(result.stdout, contains('======== Selecting Tests'));
});
diff --git a/pkg/dartfix/lib/src/migrate/apply.dart b/pkg/dartfix/lib/src/migrate/apply.dart
index 290c345..b4c7ab2 100644
--- a/pkg/dartfix/lib/src/migrate/apply.dart
+++ b/pkg/dartfix/lib/src/migrate/apply.dart
@@ -6,6 +6,8 @@
import '../util.dart';
+// TODO(devoncarew): This is only referenced from tests.
+
/// Perform the indicated source edits to the given source, returning the
/// resulting transformed text.
String applyEdits(SourceFileEdit sourceFileEdit, String source) {
diff --git a/pkg/dartfix/lib/src/migrate/display.dart b/pkg/dartfix/lib/src/migrate/display.dart
index d14fd8e..68561fb 100644
--- a/pkg/dartfix/lib/src/migrate/display.dart
+++ b/pkg/dartfix/lib/src/migrate/display.dart
@@ -6,6 +6,8 @@
import 'package:cli_util/cli_logging.dart';
import 'package:path/path.dart' as path;
+// TODO(devoncarew): This is only referenced from tests.
+
/// Given a Logger and an analysis issue, render the issue to the logger.
class IssueRenderer {
final Logger logger;
diff --git a/pkg/dartfix/lib/src/migrate/options.dart b/pkg/dartfix/lib/src/migrate/options.dart
index f19908d..e3c565e 100644
--- a/pkg/dartfix/lib/src/migrate/options.dart
+++ b/pkg/dartfix/lib/src/migrate/options.dart
@@ -8,6 +8,8 @@
import 'package:args/src/arg_parser.dart';
import 'package:path/path.dart' as path;
+// TODO(devoncarew): This class is unused.
+
class MigrateOptions {
static const applyChangesOption = 'apply-changes';
static const debugOption = 'debug';
@@ -62,8 +64,8 @@
ignoreErrorsOption,
defaultsTo: false,
negatable: false,
- help: 'Attempt to perform null safety analysis even if there are '
- 'analysis errors in the project.',
+ help: 'Attempt to perform null safety analysis even if the package has '
+ 'analysis errors.',
);
argParser.addOption(
sdkPathOption,
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index a8efa5e..26821cb 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -393,14 +393,12 @@
negatable: true,
help: 'Show an interactive preview of the proposed null safety changes '
'in a browser window.\n'
- 'With --no-web-preview, the proposed changes are instead printed to '
- 'the console.');
+ '--no-web-preview prints proposed changes to the console.');
parser.addOption(CommandLineOptions.sdkPathOption,
help: 'The path to the Dart SDK.', hide: hide);
parser.addOption(CommandLineOptions.summaryOption,
- help:
- 'Output path for a machine-readable summary of migration changes');
+ help: 'Output a machine-readable summary of migration changes.');
}
static void addCoreOptions(ArgParser parser, bool hide) {
@@ -412,8 +410,8 @@
CommandLineOptions.ignoreErrorsFlag,
defaultsTo: false,
negatable: false,
- help: 'Attempt to perform null safety analysis even if there are '
- 'analysis errors in the project.',
+ help: 'Attempt to perform null safety analysis even if the package has '
+ 'analysis errors.',
);
parser.addFlag(CommandLineOptions.ignoreExceptionsFlag,
defaultsTo: false,
@@ -424,7 +422,7 @@
parser.addFlag(CommandLineOptions.verboseFlag,
abbr: 'v',
defaultsTo: false,
- help: 'Verbose output.',
+ help: 'Show additional command output.',
negatable: false);
parser.addOption(CommandLineOptions.previewHostnameOption,
defaultsTo: 'localhost',
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index a376634..c61bc53 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -3371,6 +3371,13 @@
// Nothing else to do.
return;
}
+ } else if (destinationType.isDartCoreNull) {
+ // There's not really much we can infer from trying to assign a type to
+ // Null. We could say that the source of the assignment must be nullable,
+ // but that's not really useful because the nullability won't propagate
+ // anywhere. Besides, the code is probably erroneous (e.g. the user is
+ // trying to store a value into a `List<Null>`). So do nothing.
+ return;
} else if (destinationType is TypeParameterType) {
if (source.type is! TypeParameterType) {
// Assume an assignment to the type parameter's bound.
diff --git a/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
index 89f0f84..e6be786 100644
--- a/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/region_renderer.dart
@@ -36,10 +36,9 @@
path.Context get pathContext => migrationInfo.pathContext;
EditDetails render() {
- var unitDir = pathContext.dirname(pathMapper.map(unitInfo.path));
-
TargetLink linkForTarget(NavigationTarget target) {
- var relativePath = _relativePathToTarget(target, unitDir);
+ var relativePath =
+ _relativePathToTarget(target, pathContext.dirname(unitInfo.path));
var targetUri = _uriForPath(target.filePath, target);
return TargetLink(
path: relativePath,
diff --git a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
index 131fabf..ec45e53 100644
--- a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
@@ -65,7 +65,7 @@
/// Information about a hint found in a source file.
class HintComment {
- static final _alphaNumericRegexp = RegExp('[a-zA-Z0-9]');
+ static final _identifierCharRegexp = RegExp('[a-zA-Z0-9_]');
/// What kind of hint this is.
final HintCommentKind kind;
@@ -108,8 +108,8 @@
bool appendSpace = false;
var removeOffset = _removeOffset;
var removeEnd = _removeEnd;
- if (_isAlphaNumericBeforeOffset(sourceText, removeOffset) &&
- _isAlphaNumericAtOffset(sourceText, _keepOffset)) {
+ if (_isIdentifierCharBeforeOffset(sourceText, removeOffset) &&
+ _isIdentifierCharAtOffset(sourceText, _keepOffset)) {
if (sourceText[removeOffset] == ' ') {
// We can just keep this space.
removeOffset++;
@@ -117,8 +117,8 @@
prependSpace = true;
}
}
- if (_isAlphaNumericBeforeOffset(sourceText, _keepEnd) &&
- _isAlphaNumericAtOffset(sourceText, removeEnd)) {
+ if (_isIdentifierCharBeforeOffset(sourceText, _keepEnd) &&
+ _isIdentifierCharAtOffset(sourceText, removeEnd)) {
if (sourceText[removeEnd - 1] == ' ') {
// We can just keep this space.
removeEnd--;
@@ -143,8 +143,8 @@
{AtomicEditInfo info}) {
bool appendSpace = false;
var removeOffset = this._removeOffset;
- if (_isAlphaNumericBeforeOffset(sourceText, removeOffset) &&
- _isAlphaNumericAtOffset(sourceText, _removeEnd)) {
+ if (_isIdentifierCharBeforeOffset(sourceText, removeOffset) &&
+ _isIdentifierCharAtOffset(sourceText, _removeEnd)) {
if (sourceText[removeOffset] == ' ') {
// We can just keep this space.
removeOffset++;
@@ -173,13 +173,13 @@
};
}
- static bool _isAlphaNumericAtOffset(String sourceText, int offset) {
+ static bool _isIdentifierCharAtOffset(String sourceText, int offset) {
return offset < sourceText.length &&
- _alphaNumericRegexp.hasMatch(sourceText[offset]);
+ _identifierCharRegexp.hasMatch(sourceText[offset]);
}
- static bool _isAlphaNumericBeforeOffset(String sourceText, int offset) {
- return offset > 0 && _alphaNumericRegexp.hasMatch(sourceText[offset - 1]);
+ static bool _isIdentifierCharBeforeOffset(String sourceText, int offset) {
+ return offset > 0 && _identifierCharRegexp.hasMatch(sourceText[offset - 1]);
}
}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index a4ab81c..cbdf04c 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -1631,6 +1631,24 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_downcast_to_null() async {
+ // This probably doesn't arise too often for real-world code, since it is
+ // most likely a mistake. Still, we want to make sure we don't crash.
+ var content = '''
+test() {
+ var x = List.filled(3, null);
+ x[0] = 1;
+}
+''';
+ var expected = '''
+test() {
+ var x = List.filled(3, null);
+ x[0] = 1 as Null;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_downcast_type_argument_preserve_nullability() async {
// There are no examples in front of us yet where anyone downcasts a type
// with a nullable type parameter. This is maybe correct, maybe not, and it
@@ -3996,6 +4014,18 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_late_hint_followed_by_underscore() async {
+ var content = '''
+class _C {}
+/*late*/ _C c;
+''';
+ var expected = '''
+class _C {}
+late _C c;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_late_hint_instance_field_with_constructor() async {
var content = '''
class C {
diff --git a/pkg/nnbd_migration/test/front_end/region_renderer_test.dart b/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
index 9b2cd10..7fad2e6 100644
--- a/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
+++ b/pkg/nnbd_migration/test/front_end/region_renderer_test.dart
@@ -22,17 +22,9 @@
class RegionRendererTest extends NnbdMigrationTestBase {
PathMapper pathMapper;
- /// Returns the path of [testFile] used in traces.
- ///
- /// On Windows, we display the absolute path of the test file.
- /// On Posix, we display the path of the target file relative to the current
- /// file.
- // TODO(srawlins): I doubt this is intentional. While I don't see a bug,
- // the discrepancy could lead to confusion and may be an indicator of bugs.
- String get _testFilePathForTrace =>
- resourceProvider.pathContext.style == p.Style.windows
- ? testFile
- : resourceProvider.pathContext.basename(testFile);
+ /// Returns the basename of [testFile], used in traces.
+ String get _testFileBasename =>
+ resourceProvider.pathContext.basename(testFile);
/// Render the region at [offset], using a [MigrationInfo] which knows only
/// about the library at `infos.single`.
@@ -64,7 +56,7 @@
var trace = response.traces[0];
expect(trace.entries, hasLength(2));
expect(trace.entries[0].description,
- equals('parameter 0 of f ($_testFilePathForTrace:1:3)'));
+ equals('parameter 0 of f ($_testFileBasename:1:3)'));
expect(trace.entries[1].description, equals('data flow'));
}
@@ -80,7 +72,7 @@
expect(entry.link.href,
equals('$testFileUriPath?offset=2&line=1&authToken=AUTH_TOKEN'));
expect(entry.link.path,
- equals(resourceProvider.pathContext.toUri(_testFilePathForTrace).path));
+ equals(resourceProvider.pathContext.toUri(_testFileBasename).path));
}
Future<void>
@@ -151,11 +143,10 @@
var trace = response.traces[0];
expect(trace.description, equals('Nullability reason'));
expect(trace.entries, hasLength(4));
- expect(
- trace.entries[0].description, equals('a ($_testFilePathForTrace:1:1)'));
+ expect(trace.entries[0].description, equals('a ($_testFileBasename:1:1)'));
expect(trace.entries[1].description, equals('data flow'));
expect(trace.entries[2].description,
- equals('null literal ($_testFilePathForTrace:1:9)'));
+ equals('null literal ($_testFileBasename:1:9)'));
expect(trace.entries[3].description, equals('literal expression'));
}
diff --git a/pkg/test_runner/analysis_options.yaml b/pkg/test_runner/analysis_options.yaml
index 788c451..406b0a1 100644
--- a/pkg/test_runner/analysis_options.yaml
+++ b/pkg/test_runner/analysis_options.yaml
@@ -8,8 +8,6 @@
# - non_constant_identifier_names
# - only_throw_errors
# - prefer_interpolation_to_compose_strings
-# - prefer_is_empty
-# - prefer_is_not_empty
# - prefer_single_quotes
- avoid_bool_literals_in_conditional_expressions
- avoid_empty_else
@@ -60,6 +58,8 @@
- prefer_final_fields
- prefer_generic_function_type_aliases
- prefer_initializing_formals
+ - prefer_is_empty
+ - prefer_is_not_empty
- prefer_null_aware_operators
- prefer_typing_uninitialized_variables
- recursive_getters
diff --git a/pkg/test_runner/lib/src/android.dart b/pkg/test_runner/lib/src/android.dart
index 8f1c4d3..aa8fa5c 100644
--- a/pkg/test_runner/lib/src/android.dart
+++ b/pkg/test_runner/lib/src/android.dart
@@ -382,7 +382,7 @@
static Future<AdbDevicePool> create() async {
var names = await AdbHelper.listDevices();
var devices = names.map((id) => AdbDevice(id)).toList();
- if (devices.length == 0) {
+ if (devices.isEmpty) {
throw Exception('No android devices found. '
'Please make sure "adb devices" shows your device!');
}
diff --git a/pkg/test_runner/lib/src/browser.dart b/pkg/test_runner/lib/src/browser.dart
index 67238df..521e3c9 100644
--- a/pkg/test_runner/lib/src/browser.dart
+++ b/pkg/test_runner/lib/src/browser.dart
@@ -54,7 +54,7 @@
/// Escape [name] to make it into a valid identifier.
String _toJSIdentifier(String name) {
- if (name.length == 0) return r'$';
+ if (name.isEmpty) return r'$';
// Escape any invalid characters
StringBuffer buffer;
diff --git a/pkg/test_runner/lib/src/browser_controller.dart b/pkg/test_runner/lib/src/browser_controller.dart
index 75a89ad..708d185 100644
--- a/pkg/test_runner/lib/src/browser_controller.dart
+++ b/pkg/test_runner/lib/src/browser_controller.dart
@@ -1105,7 +1105,7 @@
}
void printDoubleReportingTests() {
- if (doubleReportingOutputs.length == 0) return;
+ if (doubleReportingOutputs.isEmpty) return;
// TODO(ricow): die on double reporting.
// Currently we just report this here, we could have a callback to the
// encapsulating environment.
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index c55896c..64996c0 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -969,6 +969,11 @@
class Dart2jsCompilerCommandOutput extends CompilationCommandOutput
with _StaticErrorOutput {
+ static void parseErrors(String stdout, List<StaticError> errors) {
+ _StaticErrorOutput._parseCfeErrors(
+ ErrorSource.web, _errorRegexp, stdout, errors);
+ }
+
/// Matches the location and message of a dart2js error message, which looks
/// like:
///
@@ -996,8 +1001,7 @@
@override
void _parseErrors() {
var errors = <StaticError>[];
- _StaticErrorOutput._parseCfeErrors(
- ErrorSource.web, _errorRegexp, decodeUtf8(stdout), errors);
+ parseErrors(decodeUtf8(stdout), errors);
errors.forEach(addError);
}
}
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 14eb334..3ebeaee 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -504,7 +504,7 @@
case _OptionValueType.string:
// Validate against the allowed values.
- if (!option.values.isEmpty) {
+ if (option.values.isNotEmpty) {
validate(String value) {
if (!option.values.contains(value)) {
_fail('Unknown value "$value" for option "$command".');
diff --git a/pkg/test_runner/lib/src/path.dart b/pkg/test_runner/lib/src/path.dart
index 5c9003d..ecf982f 100644
--- a/pkg/test_runner/lib/src/path.dart
+++ b/pkg/test_runner/lib/src/path.dart
@@ -200,7 +200,7 @@
var isAbs = isAbsolute;
var segs = segments();
String drive;
- if (isAbs && !segs.isEmpty && segs[0].length == 2 && segs[0][1] == ':') {
+ if (isAbs && segs.isNotEmpty && segs[0].length == 2 && segs[0][1] == ':') {
drive = segs[0];
segs.removeRange(0, 1);
}
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index 7be0d74..6d7a58c 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -405,7 +405,7 @@
void _tryRunNextCommand() {
_checkDone();
- if (_numProcesses < _maxProcesses && !_runQueue.isEmpty) {
+ if (_numProcesses < _maxProcesses && _runQueue.isNotEmpty) {
var command = _runQueue.removeFirst();
var isBrowserCommand = command is BrowserTestCommand;
diff --git a/pkg/test_runner/lib/src/reset_safari.dart b/pkg/test_runner/lib/src/reset_safari.dart
index 3d57910..212de21 100644
--- a/pkg/test_runner/lib/src/reset_safari.dart
+++ b/pkg/test_runner/lib/src/reset_safari.dart
@@ -143,7 +143,7 @@
if (result.exitCode == 0) {
var stdout = result.stdout as String;
var pids =
- stdout.split("\n").where((String line) => !line.isEmpty).toList();
+ stdout.split("\n").where((String line) => line.isNotEmpty).toList();
var timer = Timer(const Duration(seconds: 10), () {
print("Kill -9 Safari $pids");
kill(pids, force: true);
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index fb4a908..159b636 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -113,7 +113,7 @@
}
CommandOutput get lastCommandOutput {
- if (commandOutputs.length == 0) {
+ if (commandOutputs.isEmpty) {
throw Exception("CommandOutputs is empty, maybe no command was run? ("
"displayName: '$displayName', "
"configurationString: '$configurationString')");
@@ -122,7 +122,7 @@
}
Command get lastCommandExecuted {
- if (commandOutputs.length == 0) {
+ if (commandOutputs.isEmpty) {
throw Exception("CommandOutputs is empty, maybe no command was run? ("
"displayName: '$displayName', "
"configurationString: '$configurationString')");
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index 93de210..dbd8d79 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -254,7 +254,7 @@
}
// Start all the HTTP servers required before starting the process queue.
- if (!serverFutures.isEmpty) {
+ if (serverFutures.isNotEmpty) {
await Future.wait(serverFutures);
}
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 2a2bfb4..02d1f3e 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -595,14 +595,14 @@
var commonArguments = _commonArgumentsFromFile(testFile);
var vmOptionsList = getVmOptions(testFile);
- assert(!vmOptionsList.isEmpty);
+ assert(vmOptionsList.isNotEmpty);
for (var vmOptionsVariant = 0;
vmOptionsVariant < vmOptionsList.length;
vmOptionsVariant++) {
var vmOptions = vmOptionsList[vmOptionsVariant];
var allVmOptions = vmOptions;
- if (!extraVmOptions.isEmpty) {
+ if (extraVmOptions.isNotEmpty) {
allVmOptions = vmOptions.toList()..addAll(extraVmOptions);
}
@@ -623,7 +623,7 @@
var commonArguments = _commonArgumentsFromFile(testFile);
var vmOptionsList = getVmOptions(testFile);
- assert(!vmOptionsList.isEmpty);
+ assert(vmOptionsList.isNotEmpty);
var emitDdsTest = false;
for (var i = 0; i < 2; ++i) {
@@ -632,7 +632,7 @@
vmOptionsVariant++) {
var vmOptions = vmOptionsList[vmOptionsVariant];
var allVmOptions = vmOptions;
- if (!extraVmOptions.isEmpty) {
+ if (extraVmOptions.isNotEmpty) {
allVmOptions = vmOptions.toList()..addAll(extraVmOptions);
}
if (emitDdsTest) {
diff --git a/pkg/test_runner/lib/src/testing_servers.dart b/pkg/test_runner/lib/src/testing_servers.dart
index f46956c..5e9df68 100644
--- a/pkg/test_runner/lib/src/testing_servers.dart
+++ b/pkg/test_runner/lib/src/testing_servers.dart
@@ -241,7 +241,7 @@
Uri _getFileUriFromRequestUri(Uri request) {
// Go to the top of the file to see an explanation of the URL path scheme.
var pathSegments = request.normalizePath().pathSegments;
- if (pathSegments.length == 0) return null;
+ if (pathSegments.isEmpty) return null;
var packagesIndex = pathSegments.indexOf('packages');
if (packagesIndex != -1) {
var packageUri = Uri(
diff --git a/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart b/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart
index d3ca356..990dbf7 100644
--- a/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart
+++ b/pkg/test_runner/lib/src/vendored_pkg/args/src/parser.dart
@@ -50,7 +50,7 @@
});
// Parse the args.
- while (args.length > 0) {
+ while (args.isNotEmpty) {
if (current == '--') {
// Reached the argument terminator, so stop here.
args.removeAt(0);
@@ -98,7 +98,7 @@
/// that there is a valid value there.
void readNextArgAsValue(Option option) {
// Take the option argument from the next command line arg.
- validate(args.length > 0, 'Missing argument for "${option.name}".');
+ validate(args.isNotEmpty, 'Missing argument for "${option.name}".');
// Make sure it isn't an option itself.
validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current),
diff --git a/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart b/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart
index 27504f3..60d4a9e 100644
--- a/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart
+++ b/pkg/test_runner/lib/src/vendored_pkg/args/src/usage.dart
@@ -144,11 +144,11 @@
var lines = text.split('\n');
// Strip leading and trailing empty lines.
- while (lines.length > 0 && lines[0].trim() == '') {
+ while (lines.isNotEmpty && lines[0].trim() == '') {
lines.removeRange(0, 1);
}
- while (lines.length > 0 && lines[lines.length - 1].trim() == '') {
+ while (lines.isNotEmpty && lines[lines.length - 1].trim() == '') {
lines.removeLast();
}
diff --git a/pkg/test_runner/tool/update_static_error_tests.dart b/pkg/test_runner/tool/update_static_error_tests.dart
index eaa1bf8..de25ab3 100644
--- a/pkg/test_runner/tool/update_static_error_tests.dart
+++ b/pkg/test_runner/tool/update_static_error_tests.dart
@@ -19,7 +19,9 @@
const _usage =
"Usage: dart update_static_error_tests.dart [flags...] <path glob>";
-final String _analyzerPath = _findAnalyzer();
+final _dartPath = _findBinary("dart");
+final _analyzerPath = _findBinary("dartanalyzer");
+final _dart2jsPath = _findBinary("dart2js");
Future<void> main(List<String> args) async {
var sources = ErrorSource.all.map((e) => e.marker).toList();
@@ -176,11 +178,26 @@
}
}
- if (insert.contains(ErrorSource.cfe)) {
+ // If we're inserting web errors, we also need to gather the CFE errors to
+ // tell which web errors are web-specific.
+ List<StaticError> cfeErrors;
+ if (insert.contains(ErrorSource.cfe) || insert.contains(ErrorSource.web)) {
// Clear the previous line.
stdout.write("\r${file.path} ");
stdout.write("\r${file.path} (Running CFE...)");
- var fileErrors = await runCfe(file.absolute.path, options);
+ cfeErrors = await runCfe(file.absolute.path, options);
+ if (cfeErrors == null) {
+ print("Error: failed to update ${file.path}");
+ } else if (insert.contains(ErrorSource.cfe)) {
+ errors.addAll(cfeErrors);
+ }
+ }
+
+ if (insert.contains(ErrorSource.web)) {
+ // Clear the previous line.
+ stdout.write("\r${file.path} ");
+ stdout.write("\r${file.path} (Running dart2js...)");
+ var fileErrors = await runDart2js(file.absolute.path, options, cfeErrors);
if (fileErrors == null) {
print("Error: failed to update ${file.path}");
} else {
@@ -188,10 +205,6 @@
}
}
- if (insert.contains(ErrorSource.web)) {
- // TODO(rnystrom): Run DDC and collect web errors.
- }
-
errors = StaticError.simplify(errors);
var result = updateErrorExpectations(source, errors, remove: remove);
@@ -235,8 +248,7 @@
// TODO(rnystrom): Running the CFE command line each time is slow and wastes
// time generating code, which we don't care about. Import it as a library or
// at least run it in batch mode.
- var result = await Process.run(
- Platform.isWindows ? "sdk\\bin\\dart.bat" : "sdk/bin/dart", [
+ var result = await Process.run(_dartPath, [
"pkg/front_end/tool/_fasta/compile.dart",
...options,
"--verify",
@@ -260,33 +272,63 @@
return errors;
}
-/// Find the most recently-built analyzer.
-String _findAnalyzer() {
- String newestAnalyzer;
- DateTime newestAnalyzerTime;
+/// Invoke dart2js on [path] and gather all static errors it reports.
+Future<List<StaticError>> runDart2js(
+ String path, List<String> options, List<StaticError> cfeErrors) async {
+ var result = await Process.run(_dart2jsPath, [
+ ...options,
+ "-o",
+ "dev:null", // Output is only created for file URIs.
+ path,
+ ]);
+
+ var errors = <StaticError>[];
+ Dart2jsCompilerCommandOutput.parseErrors(result.stdout as String, errors);
+
+ // We only want the web-specific errors from dart2js, so filter out any errors
+ // that are also reported by the CFE.
+ errors.removeWhere((dart2jsError) {
+ return cfeErrors.any((cfeError) {
+ return dart2jsError.line == cfeError.line &&
+ dart2jsError.column == cfeError.column &&
+ dart2jsError.length == cfeError.length &&
+ dart2jsError.errorFor(ErrorSource.web) ==
+ cfeError.errorFor(ErrorSource.cfe);
+ });
+ });
+
+ return errors;
+}
+
+/// Find the most recently-built [binary] in any of the build directories.
+String _findBinary(String binary) {
+ if (Platform.isWindows) binary += ".bat";
+
+ String newestPath;
+ DateTime newestTime;
var buildDirectory = Directory(Platform.isMacOS ? "xcodebuild" : "out");
if (buildDirectory.existsSync()) {
for (var config in buildDirectory.listSync()) {
- var analyzerPath = p.join(config.path, "dart-sdk", "bin", "dartanalyzer");
+ var analyzerPath = p.join(config.path, "dart-sdk", "bin", binary);
var analyzerFile = File(analyzerPath);
if (!analyzerFile.existsSync()) continue;
var modified = analyzerFile.lastModifiedSync();
- if (newestAnalyzerTime == null || modified.isAfter(newestAnalyzerTime)) {
- newestAnalyzer = analyzerPath;
- newestAnalyzerTime = modified;
+ if (newestTime == null || modified.isAfter(newestTime)) {
+ newestPath = analyzerPath;
+ newestTime = modified;
}
}
}
- if (newestAnalyzer == null) {
+ if (newestPath == null) {
// Clear the current line since we're in the middle of a progress line.
print("");
- print("Could not find a built SDK with a dartanalyzer to run.");
+ print("Could not find a built SDK with a $binary to run.");
print("Make sure to build the Dart SDK before running this tool.");
exit(1);
}
- return newestAnalyzer;
+ return newestPath;
}
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 6c796d4..a0fc6dd 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -58,26 +58,6 @@
LibTest/html/Node/*: Skip # Not migrated to NNBD
LibTest/html/Window/*: Skip # Not migrated to NNBD
LibTest/io/RawDatagramSocket/*: Skip # https://github.com/dart-lang/co19/issues/195
-LibTest/typed_data/*: Skip # Not migrated to NNBD
-LibTest/typed_data/ByteBuffer/*: Skip # Not migrated to NNBD
-LibTest/typed_data/ByteData/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float32List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float32x4/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float32x4List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float64List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float64x2/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Float64x2List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int16List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int32List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int32x4/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int32x4List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int64List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Int8List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Uint16List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Uint32List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Uint64List/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Uint8ClampedList/*: Skip # Not migrated to NNBD
-LibTest/typed_data/Uint8List/*: Skip # Not migrated to NNBD
Utils/tests/Expect/*: Skip # Not migrated to NNBD
[ $compiler == dart2analyzer ]
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index fe8ad13..2cf6be3 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -33,6 +33,24 @@
LibTest/io/*: SkipByDesign # dart:io not supported.
LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
LibTest/mirrors/*: SkipByDesign # dart:mirrors is not supported
+LibTest/typed_data/ByteBuffer/*: SkipByDesign # not supported on the web
+LibTest/typed_data/ByteData/getInt64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/getInt64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getInt64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getUint64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/getUint64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getUint64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setInt64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/setInt64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setInt64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setUint64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/setUint64_A02_t01: Skip # Uint64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setUint64_A02_t02: Skip # Uint64 accessor not supported by dart2js
+LibTest/typed_data/Int32x4/operator_OR_A01_t01: Skip # Bitwise operations in JS are unsigned.
+LibTest/typed_data/Int32x4List/join_A01_t01: Skip # Differen string represrntation on VM and in JS
+LibTest/typed_data/Int32x4List/join_A01_t02: Skip # Differen string represrntation on VM and in JS
+LibTest/typed_data/Int64List/*: SkipByDesign # Int64List not supported on the web
+LibTest/typed_data/Uint64List/*: SkipByDesign # Uint64List not supported on the web
[ $compiler == dart2js && $runtime == d8 ]
LibTest/html/*: SkipByDesign # d8 is not a browser
diff --git a/tests/co19/co19-dartdevc.status b/tests/co19/co19-dartdevc.status
index 6388aaf..23dd0d4 100644
--- a/tests/co19/co19-dartdevc.status
+++ b/tests/co19/co19-dartdevc.status
@@ -106,4 +106,21 @@
LibTest/io/*: SkipByDesign # dart:io not supported.
LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
LibTest/mirrors/*: SkipByDesign # dart:mirrors is not supported
-
+LibTest/typed_data/ByteBuffer/*: SkipByDesign # not supported on the web
+LibTest/typed_data/ByteData/getInt64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/getInt64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getInt64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getUint64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/getUint64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/getUint64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setInt64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/setInt64_A02_t01: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setInt64_A02_t02: Skip # Int64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setUint64_A01_t01: Skip # Big integers cannot be represented in JS
+LibTest/typed_data/ByteData/setUint64_A02_t01: Skip # Uint64 accessor not supported by dart2js
+LibTest/typed_data/ByteData/setUint64_A02_t02: Skip # Uint64 accessor not supported by dart2js
+LibTest/typed_data/Int32x4/operator_OR_A01_t01: Skip # Bitwise operations in JS are unsigned.
+LibTest/typed_data/Int32x4List/join_A01_t01: Skip # Differen string represrntation on VM and in JS
+LibTest/typed_data/Int32x4List/join_A01_t02: Skip # Differen string represrntation on VM and in JS
+LibTest/typed_data/Int64List/*: SkipByDesign # Int64List not supported on the web
+LibTest/typed_data/Uint64List/*: SkipByDesign # Uint64List not supported on the web
diff --git a/tools/VERSION b/tools/VERSION
index 8359e44..2492ead 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 78
+PRERELEASE 79
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 5a01c59..d540f0f 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1373,7 +1373,7 @@
"co19"
],
"fileset": "vm-kernel",
- "shards": 4
+ "shards": 6
},
{
"name": "co19 nnbd tests in weak mode with asserts",
@@ -1382,7 +1382,7 @@
"co19"
],
"fileset": "vm-kernel",
- "shards": 4
+ "shards": 6
}
]
},