Version 2.14.0-293.0.dev
Merge commit '99704187c1c5c433695fb4ddb8bfecd6588a1363' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb04160..04485aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -105,6 +105,14 @@
* The `dartanalyzer` command's JSON output mode has been changed to emit the JSON
output on stdout instead of stderr.
+#### dart format
+
+* Simplify and optimize cascade formatting.
+ See: https://github.com/dart-lang/dart_style/pull/1033
+* Don't unnecessarily split argument lists with `/* */` comments.
+* Return correct exit code from `FormatCommand` when formatting stdin.
+* Split empty catch blocks with finally clauses or catches after them.
+
#### Linter
Updated the Linter to `1.7.0`, which includes changes that
diff --git a/DEPS b/DEPS
index 3cf9187..ccced0b 100644
--- a/DEPS
+++ b/DEPS
@@ -103,7 +103,7 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_rev": "f17c23e0eea9a870601c19d904e2a9c1a7c81470",
+ "dart_style_rev": "0fe592042eda5d9eea6fc240a8ee0fe531bb0794",
"dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
"devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart
new file mode 100644
index 0000000..19764bb
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_initializing_formal.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2021, 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:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertToInitializingFormal extends CorrectionProducer {
+ @override
+ // The fix isn't able to remove the initializer list / block function body in
+ // the case where multiple initializers / statements are being removed.
+ bool get canBeAppliedInBulk => false;
+
+ @override
+ FixKind get fixKind => DartFixKind.CONVERT_TO_INITIALIZING_FORMAL;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var node = this.node;
+ var constructor = node.thisOrAncestorOfType<ConstructorDeclaration>();
+ if (constructor == null) {
+ return;
+ }
+ if (node is AssignmentExpression) {
+ var statement = node.parent;
+ if (statement is! ExpressionStatement) {
+ return;
+ }
+ var block = statement.parent;
+ if (block is! Block) {
+ return;
+ }
+ var right = node.rightHandSide;
+ if (right is! SimpleIdentifier) {
+ return;
+ }
+ var parameterElement = right.staticElement;
+ var parameter = _parameterForElement(constructor, parameterElement);
+ if (parameter is! SimpleFormalParameter) {
+ return;
+ }
+ var name = parameter.identifier?.name;
+ if (name == null) {
+ return;
+ }
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.node(parameter), 'this.$name');
+ var statements = block.statements;
+ var functionBody = block.parent;
+ if (statements.length == 1 && functionBody is BlockFunctionBody) {
+ builder.addSimpleReplacement(
+ range.endEnd(constructor.parameters, functionBody), ';');
+ } else {
+ builder.addDeletion(range.nodeInList(statements, statement));
+ }
+ });
+ } else if (node is ConstructorFieldInitializer) {
+ var right = node.expression;
+ if (right is! SimpleIdentifier) {
+ return;
+ }
+ var parameterElement = right.staticElement;
+ var parameter = _parameterForElement(constructor, parameterElement);
+ if (parameter is! SimpleFormalParameter) {
+ return;
+ }
+ var name = parameter.identifier?.name;
+ if (name == null) {
+ return;
+ }
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.node(parameter), 'this.$name');
+ var initializers = constructor.initializers;
+ if (initializers.length == 1) {
+ builder.addDeletion(range.endEnd(constructor.parameters, node));
+ } else {
+ builder.addDeletion(range.nodeInList(initializers, node));
+ }
+ });
+ }
+ }
+
+ FormalParameter? _parameterForElement(
+ ConstructorDeclaration constructor, Element? parameterElement) {
+ for (var parameter in constructor.parameters.parameters) {
+ if (parameter.declaredElement == parameterElement) {
+ return parameter;
+ }
+ }
+ return null;
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static ConvertToInitializingFormal newInstance() =>
+ ConvertToInitializingFormal();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_Null_with_void.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_Null_with_void.dart
new file mode 100644
index 0000000..1c4fa5c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_Null_with_void.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, 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:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ReplaceNullWithVoid extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REPLACE_NULL_WITH_VOID;
+
+ @override
+ FixKind? get multiFixKind => DartFixKind.REPLACE_NULL_WITH_VOID_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final diagnostic = this.diagnostic;
+ if (diagnostic is AnalysisError) {
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.error(diagnostic), 'void');
+ });
+ }
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static ReplaceNullWithVoid newInstance() => ReplaceNullWithVoid();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 50b36bd..c8c725d 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -5,108 +5,26 @@
import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
import 'package:analysis_server/src/services/completion/dart/extension_cache.dart';
import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
-import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
-/// Return true if this [errorCode] is likely to have a fix associated with it.
-bool hasFix(ErrorCode errorCode) =>
- errorCode == CompileTimeErrorCode.CAST_TO_NON_TYPE ||
- errorCode == CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER ||
- errorCode == CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE ||
- errorCode == CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER ||
- errorCode == CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION ||
- errorCode == CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR ||
- errorCode ==
- CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE ||
- errorCode ==
- CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO ||
- errorCode ==
- CompileTimeErrorCode
- .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE ||
- errorCode ==
- CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR ||
- errorCode ==
- CompileTimeErrorCode
- .NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS ||
- errorCode == CompileTimeErrorCode.NON_TYPE_AS_TYPE_ARGUMENT ||
- errorCode == CompileTimeErrorCode.TYPE_TEST_WITH_UNDEFINED_NAME ||
- errorCode == CompileTimeErrorCode.FINAL_NOT_INITIALIZED ||
- errorCode == CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 ||
- errorCode == CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 ||
- errorCode ==
- CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS ||
- errorCode == CompileTimeErrorCode.UNDEFINED_IDENTIFIER ||
- errorCode ==
- CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE ||
- errorCode == CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE ||
- errorCode == CompileTimeErrorCode.INVALID_ANNOTATION ||
- errorCode == CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT ||
- errorCode == CompileTimeErrorCode.PART_OF_NON_PART ||
- errorCode == CompileTimeErrorCode.UNDEFINED_ANNOTATION ||
- errorCode == CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN ||
- errorCode ==
- CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT ||
- errorCode == CompileTimeErrorCode.UNDEFINED_FUNCTION ||
- errorCode == CompileTimeErrorCode.UNDEFINED_GETTER ||
- errorCode == CompileTimeErrorCode.UNDEFINED_METHOD ||
- errorCode == CompileTimeErrorCode.UNDEFINED_SETTER ||
- errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST ||
- errorCode == CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED ||
- errorCode == HintCode.CAN_BE_NULL_AFTER_NULL_AWARE ||
- errorCode == HintCode.DEAD_CODE ||
- errorCode == HintCode.DIVISION_OPTIMIZATION ||
- errorCode == HintCode.TYPE_CHECK_IS_NOT_NULL ||
- errorCode == HintCode.TYPE_CHECK_IS_NULL ||
- errorCode == HintCode.UNNECESSARY_CAST ||
- errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
- errorCode == HintCode.UNUSED_CATCH_STACK ||
- errorCode == HintCode.UNUSED_IMPORT ||
- errorCode == ParserErrorCode.EXPECTED_TOKEN ||
- errorCode == ParserErrorCode.GETTER_WITH_PARAMETERS ||
- errorCode == ParserErrorCode.VAR_AS_TYPE_NAME ||
- errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER ||
- (errorCode is LintCode &&
- (errorCode.name == LintNames.always_require_non_null_named_parameters ||
- errorCode.name == LintNames.annotate_overrides ||
- errorCode.name == LintNames.avoid_annotating_with_dynamic ||
- errorCode.name == LintNames.avoid_empty_else ||
- errorCode.name == LintNames.avoid_init_to_null ||
- errorCode.name == LintNames.avoid_redundant_argument_values ||
- errorCode.name == LintNames.avoid_return_types_on_setters ||
- errorCode.name == LintNames.avoid_types_on_closure_parameters ||
- errorCode.name == LintNames.await_only_futures ||
- errorCode.name == LintNames.empty_catches ||
- errorCode.name == LintNames.empty_constructor_bodies ||
- errorCode.name == LintNames.empty_statements ||
- errorCode.name == LintNames.no_duplicate_case_values ||
- errorCode.name == LintNames.non_constant_identifier_names ||
- errorCode.name == LintNames.null_closures ||
- errorCode.name == LintNames.prefer_collection_literals ||
- errorCode.name == LintNames.prefer_conditional_assignment ||
- errorCode.name == LintNames.prefer_const_constructors ||
- errorCode.name ==
- LintNames.prefer_const_constructors_in_immutables ||
- errorCode.name == LintNames.prefer_const_declarations ||
- errorCode.name == LintNames.prefer_equal_for_default_values ||
- errorCode.name == LintNames.prefer_final_fields ||
- errorCode.name == LintNames.prefer_final_locals ||
- errorCode.name == LintNames.prefer_final_parameters ||
- errorCode.name == LintNames.prefer_is_not_empty ||
- errorCode.name == LintNames.type_init_formals ||
- errorCode.name == LintNames.unawaited_futures ||
- errorCode.name == LintNames.unnecessary_brace_in_string_interps ||
- errorCode.name == LintNames.unnecessary_const ||
- errorCode.name == LintNames.unnecessary_lambdas ||
- errorCode.name == LintNames.unnecessary_new ||
- errorCode.name == LintNames.unnecessary_overrides ||
- errorCode.name == LintNames.unnecessary_this ||
- errorCode.name == LintNames.use_rethrow_when_possible));
+/// Return `true` if this [errorCode] is likely to have a fix associated with
+/// it.
+bool hasFix(ErrorCode errorCode) {
+ if (errorCode is LintCode) {
+ var lintName = errorCode.name;
+ return FixProcessor.lintProducerMap.containsKey(lintName);
+ }
+ // TODO(brianwilkerson) Either deprecate the part of the protocol supported by
+ // this function, or handle error codes associated with non-dart files.
+ return FixProcessor.nonLintProducerMap.containsKey(errorCode) ||
+ FixProcessor.nonLintMultiProducerMap.containsKey(errorCode);
+}
/// An enumeration of quick fix kinds for the errors found in an analysis
/// options file.
@@ -316,6 +234,10 @@
'dart.fix.convert.toIfNull.multi',
DartFixKindPriority.IN_FILE,
"Convert to '??'s everywhere in file");
+ static const CONVERT_TO_INITIALIZING_FORMAL = FixKind(
+ 'dart.fix.convert.toInitializingFormal',
+ DartFixKindPriority.DEFAULT,
+ 'Convert to an initializing formal parameter');
static const CONVERT_TO_INT_LITERAL = FixKind('dart.fix.convert.toIntLiteral',
DartFixKindPriority.DEFAULT, 'Convert to an int literal');
static const CONVERT_TO_INT_LITERAL_MULTI = FixKind(
@@ -802,6 +724,12 @@
'dart.fix.replace.finalWithVar.multi',
DartFixKindPriority.IN_FILE,
"Replace 'final' with 'var' where possible in file");
+ static const REPLACE_NULL_WITH_VOID = FixKind('dart.fix.replace.nullWithVoid',
+ DartFixKindPriority.DEFAULT, "Replace 'Null' with 'void'");
+ static const REPLACE_NULL_WITH_VOID_MULTI = FixKind(
+ 'dart.fix.replace.nullWithVoid.multi',
+ DartFixKindPriority.DEFAULT,
+ "Replace 'Null' with 'void' everywhere in file");
static const REPLACE_RETURN_TYPE_FUTURE = FixKind(
'dart.fix.replace.returnTypeFuture',
DartFixKindPriority.DEFAULT,
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 ee44e16..fc14455 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -48,6 +48,7 @@
import 'package:analysis_server/src/services/correction/dart/convert_to_for_loop.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_if_null.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_initializing_formal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
@@ -129,6 +130,7 @@
import 'package:analysis_server/src/services/correction/dart/remove_unused_local_variable.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unused_parameter.dart';
import 'package:analysis_server/src/services/correction/dart/rename_to_camel_case.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_Null_with_void.dart';
import 'package:analysis_server/src/services/correction/dart/replace_boolean_with_bool.dart';
import 'package:analysis_server/src/services/correction/dart/replace_cascade_with_dot.dart';
import 'package:analysis_server/src/services/correction/dart/replace_colon_with_equals.dart';
@@ -468,6 +470,9 @@
LintNames.prefer_if_elements_to_conditional_expressions: [
ConvertConditionalExpressionToIfElement.newInstance,
],
+ LintNames.prefer_initializing_formals: [
+ ConvertToInitializingFormal.newInstance,
+ ],
LintNames.prefer_is_empty: [
ReplaceWithIsEmpty.newInstance,
],
@@ -509,6 +514,9 @@
LintNames.prefer_typing_uninitialized_variables: [
AddTypeAnnotation.newInstance,
],
+ LintNames.prefer_void_to_null: [
+ ReplaceNullWithVoid.newInstance,
+ ],
LintNames.slash_for_doc_comments: [
ConvertDocumentationIntoLine.newInstance,
],
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 4677b02..1af10454 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -76,6 +76,8 @@
static const String prefer_if_elements_to_conditional_expressions =
'prefer_if_elements_to_conditional_expressions';
static const String prefer_if_null_operators = 'prefer_if_null_operators';
+ static const String prefer_initializing_formals =
+ 'prefer_initializing_formals';
static const String prefer_inlined_adds = 'prefer_inlined_adds';
static const String prefer_int_literals = 'prefer_int_literals';
static const String prefer_interpolation_to_compose_strings =
@@ -91,6 +93,7 @@
static const String prefer_spread_collections = 'prefer_spread_collections';
static const String prefer_typing_uninitialized_variables =
'prefer_typing_uninitialized_variables';
+ static const String prefer_void_to_null = 'prefer_void_to_null';
static const String slash_for_doc_comments = 'slash_for_doc_comments';
static const String sort_child_properties_last = 'sort_child_properties_last';
static const String sort_constructors_first = 'sort_constructors_first';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_initializing_formal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_initializing_formal_test.dart
new file mode 100644
index 0000000..8270691
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_initializing_formal_test.dart
@@ -0,0 +1,94 @@
+// 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:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertToInitializingFormalTest);
+ });
+}
+
+@reflectiveTest
+class ConvertToInitializingFormalTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.CONVERT_TO_INITIALIZING_FORMAL;
+
+ @override
+ String get lintCode => LintNames.prefer_initializing_formals;
+
+ Future<void> test_assignment_emptyAfterRemoval() async {
+ await resolveTestCode('''
+class C {
+ int a = 0;
+ C(int a) {
+ this.a = a;
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ int a = 0;
+ C(this.a);
+}
+''');
+ }
+
+ Future<void> test_assignment_notEmptyAfterRemoval() async {
+ await resolveTestCode('''
+class C {
+ int a = 0;
+ C(int a) {
+ this.a = a;
+ print(a);
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ int a = 0;
+ C(this.a) {
+ print(a);
+ }
+}
+''');
+ }
+
+ Future<void> test_initializer_emptyAfterRemoval() async {
+ await resolveTestCode('''
+class C {
+ int a;
+ C(int a) : this.a = a;
+}
+''');
+ await assertHasFix('''
+class C {
+ int a;
+ C(this.a);
+}
+''');
+ }
+
+ Future<void> test_initializer_notEmptyAfterRemoval() async {
+ await resolveTestCode('''
+class C {
+ int a;
+ int b;
+ C(int a) : this.a = a, this.b = 2;
+}
+''');
+ await assertHasFix('''
+class C {
+ int a;
+ int b;
+ C(this.a) : this.b = 2;
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_Null_with_void_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_Null_with_void_test.dart
new file mode 100644
index 0000000..871972b
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_Null_with_void_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2021, 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:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ReplaceNullWithVoidTest);
+ defineReflectiveTests(ReplaceNullWithVoidBulkTest);
+ });
+}
+
+@reflectiveTest
+class ReplaceNullWithVoidBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.prefer_void_to_null;
+
+ Future<void> test_singleFile() async {
+ await resolveTestCode('''
+Future<Null> f() async {
+ await Future.value();
+}
+
+Future<Null>? future_null;
+''');
+ await assertHasFix('''
+Future<void> f() async {
+ await Future.value();
+}
+
+Future<void>? future_null;
+''');
+ }
+}
+
+@reflectiveTest
+class ReplaceNullWithVoidTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_NULL_WITH_VOID;
+
+ @override
+ String get lintCode => LintNames.prefer_void_to_null;
+
+ Future<void> test_simple() async {
+ await resolveTestCode('''
+Future<Null> f() async {
+ await Future.value();
+}
+''');
+ await assertHasFix('''
+Future<void> f() async {
+ await Future.value();
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index b3e369d..fec18cc 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -55,6 +55,8 @@
as convert_to_generic_function_syntax;
import 'convert_to_if_element_test.dart' as convert_to_if_element;
import 'convert_to_if_null_test.dart' as convert_to_if_null;
+import 'convert_to_initializing_formal_test.dart'
+ as convert_to_initializing_formal;
import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
@@ -154,6 +156,7 @@
import 'remove_unused_local_variable_test.dart' as remove_unused_local_variable;
import 'remove_unused_parameter_test.dart' as remove_unused_parameter;
import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
+import 'replace_Null_with_void_test.dart' as replace_null_with_void;
import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
import 'replace_cascade_with_dot_test.dart' as replace_cascade_with_dot;
import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
@@ -233,6 +236,7 @@
convert_to_generic_function_syntax.main();
convert_to_if_element.main();
convert_to_if_null.main();
+ convert_to_initializing_formal.main();
convert_to_int_literal.main();
convert_to_list_literal.main();
convert_to_map_literal.main();
@@ -331,6 +335,7 @@
replace_final_with_var.main();
replace_new_with_const.main();
replace_null_with_closure.main();
+ replace_null_with_void.main();
replace_return_type_future.main();
replace_var_with_dynamic.main();
replace_with_brackets.main();
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 5a83702..f80936d 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -75,18 +75,14 @@
var isDill = resolvedUri.path.endsWith('.dill');
void inferNullSafetyMode(bool isSound) {
- if (isSound) assert(_options.enableNonNullable);
if (_options.nullSafetyMode == NullSafetyMode.unspecified) {
_options.nullSafetyMode =
isSound ? NullSafetyMode.sound : NullSafetyMode.unsound;
}
}
- void validateNullSafety() {
+ void validateNullSafetyMode() {
assert(_options.nullSafetyMode != NullSafetyMode.unspecified);
- if (_options.nullSafetyMode == NullSafetyMode.sound) {
- assert(_options.enableNonNullable);
- }
}
if (isDill) {
@@ -111,7 +107,7 @@
"safety and is incompatible with the '$option' option");
}
inferNullSafetyMode(isStrongDill);
- validateNullSafety();
+ validateNullSafetyMode();
if (_options.dillDependencies != null) {
// Modular compiles do not include the platform on the input dill
@@ -157,7 +153,7 @@
..verbosity = verbosity;
bool isLegacy =
await fe.uriUsesLegacyLanguageVersion(resolvedUri, options);
- inferNullSafetyMode(_options.enableNonNullable && !isLegacy);
+ inferNullSafetyMode(!isLegacy);
List<Uri> dependencies = [];
if (_options.platformBinaries != null) {
@@ -183,7 +179,7 @@
component = await fe.compile(initializedCompilerState, verbose,
fileSystem, onDiagnostic, resolvedUri);
if (component == null) return null;
- validateNullSafety();
+ validateNullSafetyMode();
}
if (_options.cfeOnly) {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 5c89ed6..91fad6a 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -204,11 +204,6 @@
fe.isExperimentEnabled(fe.ExperimentalFlag.variance,
explicitExperimentalFlags: explicitExperimentalFlags);
- /// Whether `--enable-experiment=non-nullable` is provided.
- bool get enableNonNullable =>
- fe.isExperimentEnabled(fe.ExperimentalFlag.nonNullable,
- explicitExperimentalFlags: explicitExperimentalFlags);
-
/// A possibly null state object for kernel compilation.
fe.InitializedCompilerState kernelInitializedCompilerState;
@@ -493,7 +488,7 @@
bool get useLegacySubtyping {
assert(nullSafetyMode != NullSafetyMode.unspecified,
"Null safety mode unspecified");
- return !enableNonNullable || (nullSafetyMode == NullSafetyMode.unsound);
+ return nullSafetyMode == NullSafetyMode.unsound;
}
/// If specified, a bundle of optimizations to enable (or disable).
@@ -674,10 +669,6 @@
throw ArgumentError("'${Flags.soundNullSafety}' incompatible with "
"'${Flags.noSoundNullSafety}'");
}
- if (!enableNonNullable && _soundNullSafety) {
- throw ArgumentError("'${Flags.soundNullSafety}' requires the "
- "'non-nullable' experiment to be enabled");
- }
if (nativeNullAssertions && _noNativeNullAssertions) {
throw ArgumentError("'${Flags.nativeNullAssertions}' incompatible with "
"'${Flags.noNativeNullAssertions}'");
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index cfc2b0d..c0240ca 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -170,12 +170,10 @@
"null safety and is incompatible with the '$option' option");
}
- if (component.mode == ir.NonNullableByDefaultCompiledMode.Strong) {
- assert(_options.enableNonNullable);
- _options.nullSafetyMode = NullSafetyMode.sound;
- } else {
- _options.nullSafetyMode = NullSafetyMode.unsound;
- }
+ _options.nullSafetyMode =
+ component.mode == ir.NonNullableByDefaultCompiledMode.Strong
+ ? NullSafetyMode.sound
+ : NullSafetyMode.unsound;
}
Future<ir.Component> deserializeComponentAndUpdateOptions() async {
diff --git a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
index 7799b9e..8c545e2 100644
--- a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
+++ b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
@@ -436,12 +436,39 @@
TargetEntry findEnclosingFunction(
String sources, SourceFile file, int start, SingleMapping mapping) {
if (sources == null) return null;
- int index = sources.lastIndexOf(': function(', start);
- if (index < 0) return null;
- index += 2;
- var line = file.getLine(index);
- var lineEntry = _findLineInternal(mapping, line);
- return _findColumn(line, file.getColumn(index), lineEntry);
+ var index = start;
+ while (true) {
+ index = nextDeclarationCandidate(sources, index);
+ if (index < 0) return null;
+ var line = file.getLine(index);
+ var lineEntry = _findLineInternal(mapping, line);
+ var result = _findColumn(line, file.getColumn(index), lineEntry);
+ if (result?.column == file.getColumn(index)) return result;
+ index--;
+ }
+}
+
+/// Returns the index of a candidate location of a enclosing function
+/// declaration. We try to find the beginning of a `function` keyword or the
+/// `(` of an ES6 method definition, but the search contains some false
+/// positives. To rule out false positives, [findEnclosingFunction]
+/// validates that the returned location contains a source-map entry, searching
+/// for another candidate if not.
+int nextDeclarationCandidate(String sources, int start) {
+ var indexForFunctionKeyword = sources.lastIndexOf('function', start);
+ // We attempt to identify potential method definitions by looking for any '('
+ // that precedes a '{'. This method will fail if 1) Dart2JS starts emitting
+ // functions with initializers or 2) sourcemap boundaries appear at '(' for
+ // non-method-definition constructs.
+ var indexForMethodDefinition = sources.lastIndexOf('{', start);
+ if (indexForFunctionKeyword > indexForMethodDefinition ||
+ indexForFunctionKeyword < 0) {
+ return indexForFunctionKeyword;
+ }
+ indexForMethodDefinition = sources.lastIndexOf('(', indexForMethodDefinition);
+ return indexForFunctionKeyword > indexForMethodDefinition
+ ? indexForFunctionKeyword
+ : indexForMethodDefinition;
}
Map<int, List<FrameEntry>> _loadInlinedFrameData(
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index a8b539a..c9fb518 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -562,7 +562,9 @@
return CompareImmediate(reg, Immediate(immediate), width);
}
- void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
+ void testl(Register reg, const Immediate& imm) {
+ testq(reg, Immediate(imm.value() & 0xFFFFFFFF));
+ }
void testb(const Address& address, const Immediate& imm);
void testb(const Address& address, Register reg);
diff --git a/tools/VERSION b/tools/VERSION
index cd931f8..a78b319 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 292
+PRERELEASE 293
PRERELEASE_PATCH 0
\ No newline at end of file