Version 2.12.0-22.0.dev
Merge commit '221c697f312ee20cf9e145ff0f2a12f2c498a27d' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart b/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart
index 90a50c5..be324d4 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart
@@ -13,6 +13,12 @@
class SurroundWith extends MultiCorrectionProducer {
@override
Iterable<CorrectionProducer> get producers sync* {
+ // If the node is the CompilationUnit, the selected statements must span multiple
+ // top level items and cannot be surrounded with anything.
+ if (node is CompilationUnit) {
+ return;
+ }
+
// prepare selected statements
var selectionAnalyzer = StatementAnalyzer(
resolvedResult, SourceRange(selectionOffset, selectionLength));
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 7fb93d9..2520805 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -3,6 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart' show ClassElement;
+import 'package:analyzer/dart/element/type.dart';
import 'package:meta/meta.dart';
/// The path to an element.
@@ -27,4 +30,128 @@
/// Return `true` if the described element is a constructor.
bool get isConstructor => kind == ElementKind.constructorKind;
+
+ /// Return `true` if the given [node] appears to be consistent with this kind
+ /// of element.
+ bool matches(AstNode node) {
+ // TODO(brianwilkerson) Check the resolved element if one exists for more
+ // accurate results.
+ switch (kind) {
+ case ElementKind.classKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.constantKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.constructorKind:
+ if (node is Annotation) {
+ var className = _nameFromIdentifier(node.name);
+ var constructorName = node.constructorName ?? '';
+ if (components[0] == className && components[1] == constructorName) {
+ return true;
+ }
+ } else if (node is InstanceCreationExpression) {
+ var name = node.constructorName;
+ var className = _nameFromIdentifier(name.type.name);
+ var constructorName = name.name?.name ?? '';
+ if (components[0] == className && components[1] == constructorName) {
+ return true;
+ }
+ } else if (node is MethodInvocation) {
+ var target = node.target;
+ if (target == null) {
+ if (components[0] == node.methodName.name && components[1] == '') {
+ return true;
+ }
+ } else if (target is Identifier) {
+ var className = _nameFromIdentifier(target);
+ var constructorName = node.methodName.name;
+ if (components[0] == className &&
+ components[1] == constructorName) {
+ return true;
+ }
+ }
+ }
+ return false;
+ case ElementKind.enumKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.extensionKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.fieldKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.functionKind:
+ if (node is MethodInvocation) {
+ if (node.realTarget == null &&
+ components[0] == node.methodName.name) {
+ return true;
+ }
+ }
+ return false;
+ case ElementKind.getterKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.methodKind:
+ if (node is MethodInvocation) {
+ if (components[1] == node.methodName.name) {
+ var target = node.realTarget;
+ if (target == null) {
+ // TODO(brianwilkerson) If `node.target == null` then the invocation
+ // should be in a subclass of the element's class.
+ return true;
+ } else {
+ var type = target.staticType;
+ if (type == null && target is SimpleIdentifier) {
+ var element = target.staticElement;
+ // TODO(brianwilkerson) Handle more than `ClassElement`.
+ if (element is ClassElement) {
+ type = element.thisType;
+ }
+ }
+ if (type == null) {
+ // We can't get more specific type information, so we assume
+ // that the method might have been in the element's class.
+ return true;
+ }
+ if (components[0] == type.element.name) {
+ return true;
+ }
+ if (type is InterfaceType) {
+ for (var supertype in type.allSupertypes) {
+ if (components[0] == supertype.element.name) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ case ElementKind.mixinKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.setterKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.typedefKind:
+ // TODO: Handle this case.
+ return false;
+ case ElementKind.variableKind:
+ // TODO: Handle this case.
+ return false;
+ }
+ return false;
+ }
+
+ String _nameFromIdentifier(Identifier identifier) {
+ if (identifier is SimpleIdentifier) {
+ return identifier.name;
+ } else if (identifier is PrefixedIdentifier) {
+ return identifier.identifier.name;
+ }
+ throw StateError(
+ 'Unexpected class of identifier: ${identifier.runtimeType}');
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename_parameter.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename_parameter.dart
new file mode 100644
index 0000000..97065b7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename_parameter.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2020, 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/data_driven.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:meta/meta.dart';
+
+/// The data related to a parameter that has been renamed.
+class RenameParameter extends Change<_Data> {
+ /// The old name of the parameter.
+ final String oldName;
+
+ /// The new name of the parameter.
+ final String newName;
+
+ /// Initialize a newly created transform to describe a renaming of a parameter
+ /// from the [oldName] to the [newName].
+ RenameParameter({@required this.newName, @required this.oldName});
+
+ @override
+ void apply(DartFileEditBuilder builder, DataDrivenFix fix, _Data data) {
+ if (data is _InvocationData) {
+ builder.addSimpleReplacement(range.node(data.nameNode), newName);
+ } else if (data is _OverrideData) {
+ var declaration = data.methodDeclaration;
+ var parameter = declaration.parameterNamed(oldName);
+ if (parameter != null) {
+ var overriddenMethod = declaration.overriddenElement();
+ var overriddenParameter = overriddenMethod?.parameterNamed(oldName);
+ if (overriddenParameter == null) {
+ // If the overridden parameter has already been removed, then just
+ // rename the old parameter to have the new name.
+ builder.addSimpleReplacement(
+ range.node(parameter.identifier), newName);
+ } else {
+ // If the overridden parameter still exists, then mark it as
+ // deprecated (if it isn't already) and add a declaration of the new
+ // parameter.
+ builder.addInsertion(parameter.offset, (builder) {
+ var parameterElement = parameter.declaredElement;
+ builder.writeParameter(newName,
+ isCovariant: parameterElement.isCovariant,
+ isRequiredNamed: parameterElement.isRequiredNamed,
+ type: parameterElement.type);
+ builder.write(', ');
+ if (!parameterElement.hasDeprecated) {
+ builder.write('@deprecated ');
+ }
+ });
+ }
+ }
+ }
+ }
+
+ @override
+ _Data validate(DataDrivenFix fix) {
+ var node = fix.node;
+ if (node is SimpleIdentifier) {
+ var parent = node.parent;
+ if (node.name == oldName &&
+ parent is Label &&
+ parent.parent is NamedExpression) {
+ var invocation = parent.parent.parent.parent;
+ if (fix.element.matches(invocation)) {
+ return _InvocationData(node);
+ }
+ } else if (parent is MethodDeclaration) {
+ return _OverrideData(parent);
+ }
+ }
+ return const _IgnoredData();
+ }
+}
+
+/// The data returned from `validate`.
+abstract class _Data {
+ const _Data();
+}
+
+/// The data returned when the change doesn't apply.
+class _IgnoredData extends _Data {
+ const _IgnoredData();
+}
+
+/// The data returned when updating an invocation site.
+class _InvocationData extends _Data {
+ /// The node representing the name to be replaced.
+ final SimpleIdentifier nameNode;
+
+ /// Initialize newly created data about an invocation site.
+ _InvocationData(this.nameNode);
+}
+
+/// The data returned when updating an override site.
+class _OverrideData extends _Data {
+ /// The node representing the overriding method.
+ final MethodDeclaration methodDeclaration;
+
+ /// Initialize newly created data about an override site.
+ _OverrideData(this.methodDeclaration);
+}
+
+extension on MethodDeclaration {
+ /// Return the parameter of this method whose name matches the given [name],
+ /// or `null` if there is no such parameter.
+ FormalParameter parameterNamed(String name) {
+ for (var parameter in parameters.parameters) {
+ if (parameter.declaredElement.name == name) {
+ return parameter;
+ }
+ }
+ return null;
+ }
+
+ /// Return the element that this method overrides, or `null` if this method
+ /// doesn't override any inherited member.
+ ExecutableElement overriddenElement() {
+ var element = declaredElement;
+ var enclosingElement = element.enclosingElement;
+ if (enclosingElement is ClassElement) {
+ var name = Name(enclosingElement.library.source.uri, element.name);
+ return InheritanceManager3().getInherited2(enclosingElement, name);
+ }
+ return null;
+ }
+}
+
+extension on ExecutableElement {
+ /// Return the parameter of this executable element whose name matches the
+ /// given [name], or `null` if there is no such parameter.
+ ParameterElement parameterNamed(String name) {
+ for (var parameter in parameters) {
+ if (parameter.name == name) {
+ return parameter;
+ }
+ }
+ return null;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index e7b8a24..ef73836 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -11,6 +11,7 @@
import 'package:analysis_server/src/services/correction/fix/data_driven/modify_parameters.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/rename_parameter.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
@@ -61,6 +62,7 @@
static const String _mixinKey = 'mixin';
static const String _nameKey = 'name';
static const String _newNameKey = 'newName';
+ static const String _oldNameKey = 'oldName';
static const String _setterKey = 'setter';
static const String _statementsKey = 'statements';
static const String _styleKey = 'style';
@@ -90,6 +92,7 @@
static const String _importKind = 'import';
static const String _removeParameterKind = 'removeParameter';
static const String _renameKind = 'rename';
+ static const String _renameParameterKind = 'renameParameter';
/// The valid values for the [_styleKey] in an [_addParameterKind] change.
static const List<String> validStyles = [
@@ -420,12 +423,15 @@
return null;
} else if (kind == _renameKind) {
return _translateRenameChange(node);
+ } else if (kind == _renameParameterKind) {
+ return _translateRenameParameterChange(node);
}
return _reportInvalidValueOneOf(kindNode, kindContext, [
_addParameterKind,
_addTypeParameterKind,
_removeParameterKind,
_renameKind,
+ _renameParameterKind,
]);
} else {
return _reportInvalidValue(node, context, 'Map');
@@ -718,11 +724,27 @@
var newName = _translateString(node.valueAt(_newNameKey),
ErrorContext(key: _newNameKey, parentNode: node));
if (newName == null) {
+ // The error has already been reported.
return null;
}
return Rename(newName: newName);
}
+ /// Translate the [node] into a rename parameter change. Return the resulting
+ /// change, or `null` if the [node] does not represent a valid rename change.
+ RenameParameter _translateRenameParameterChange(YamlMap node) {
+ _reportUnsupportedKeys(node, const {_kindKey, _newNameKey, _oldNameKey});
+ var oldName = _translateString(node.valueAt(_oldNameKey),
+ ErrorContext(key: _oldNameKey, parentNode: node));
+ var newName = _translateString(node.valueAt(_newNameKey),
+ ErrorContext(key: _newNameKey, parentNode: node));
+ if (oldName == null || newName == null) {
+ // The error has already been reported.
+ return null;
+ }
+ return RenameParameter(newName: newName, oldName: oldName);
+ }
+
/// Translate the [node] into a string. Return the resulting string, or `null`
/// if the [node] does not represent a valid string. If the [node] is not
/// valid, use the [context] to report the error.
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_surround_with_set_state_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_surround_with_set_state_test.dart
index 3445e2c..d13bb22 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_surround_with_set_state_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_surround_with_set_state_test.dart
@@ -27,6 +27,23 @@
);
}
+ Future<void> test_noParentNode() async {
+ // This code selects the `CompilationUnit` node which has previously
+ // caused errors in code assuming the node would have a parent.
+ await resolveTestCode('''
+main() {
+// start
+ print(0);
+}
+
+other() {
+ print(1);
+// end
+}
+''');
+ await assertNoAssist();
+ }
+
Future<void> test_outsideState() async {
await resolveTestCode('''
import 'package:flutter/widgets.dart';
@@ -34,7 +51,7 @@
class Stateless {
int _count1;
int _count2;
-
+
void increment() {
// start
++_count1;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
index 4c619b7..b065182 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
@@ -675,6 +675,287 @@
''');
}
+ Future<void> test_material_TextTheme_copyWith_deprecated() async {
+ setPackageContent('''
+class TextTheme {
+ TextTheme copyWith({TextStyle headline1, TextStyle headline2,
+ TextStyle headline3, TextStyle headline4, TextStyle headline5,
+ TextStyle headline6, TextStyle subtitle1, TextStyle subtitle2,
+ TextStyle bodyText1, TextStyle bodyText2, TextStyle caption,
+ TextStyle button, TextStyle overline,
+ @deprecated TextStyle display4, @deprecated TextStyle display3,
+ @deprecated TextStyle display2, @deprecated TextStyle display1,
+ @deprecated TextStyle headline, @deprecated TextStyle title,
+ @deprecated TextStyle subhead, @deprecated TextStyle subtitle,
+ @deprecated TextStyle body2, @deprecated TextStyle body1}) {}
+}
+class TextStyle {}
+''');
+ addPackageDataFile('''
+version: 1
+transforms:
+ - title: 'Rename arguments'
+ date: 2020-09-24
+ element:
+ uris: ['$importUri']
+ method: 'copyWith'
+ inClass: 'TextTheme'
+ changes:
+ - kind: 'renameParameter'
+ oldName: 'display4'
+ newName: 'headline1'
+ - kind: 'renameParameter'
+ oldName: 'display3'
+ newName: 'headline2'
+ - kind: 'renameParameter'
+ oldName: 'display2'
+ newName: 'headline3'
+ - kind: 'renameParameter'
+ oldName: 'display1'
+ newName: 'headline4'
+ - kind: 'renameParameter'
+ oldName: 'headline'
+ newName: 'headline5'
+ - kind: 'renameParameter'
+ oldName: 'title'
+ newName: 'headline6'
+ - kind: 'renameParameter'
+ oldName: 'subhead'
+ newName: 'subtitle1'
+ - kind: 'renameParameter'
+ oldName: 'subtitle'
+ newName: 'subtitle2'
+ - kind: 'renameParameter'
+ oldName: 'body2'
+ newName: 'bodytext1'
+ - kind: 'renameParameter'
+ oldName: 'body1'
+ newName: 'bodytext2'
+''');
+ await resolveTestCode('''
+import '$importUri';
+
+void f(TextTheme t, TextStyle s) {
+ t.copyWith(display2: s);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(TextTheme t, TextStyle s) {
+ t.copyWith(headline3: s);
+}
+''');
+ }
+
+ Future<void> test_material_TextTheme_copyWith_removed() async {
+ setPackageContent('''
+class TextTheme {
+ TextTheme copyWith({TextStyle headline1, TextStyle headline2,
+ TextStyle headline3, TextStyle headline4, TextStyle headline5,
+ TextStyle headline6, TextStyle subtitle1, TextStyle subtitle2,
+ TextStyle bodyText1, TextStyle bodyText2, TextStyle caption,
+ TextStyle button, TextStyle overline}) {}
+}
+class TextStyle {}
+''');
+ addPackageDataFile('''
+version: 1
+transforms:
+ - title: 'Rename arguments'
+ date: 2020-09-24
+ element:
+ uris: ['$importUri']
+ method: 'copyWith'
+ inClass: 'TextTheme'
+ changes:
+ - kind: 'renameParameter'
+ oldName: 'display4'
+ newName: 'headline1'
+ - kind: 'renameParameter'
+ oldName: 'display3'
+ newName: 'headline2'
+ - kind: 'renameParameter'
+ oldName: 'display2'
+ newName: 'headline3'
+ - kind: 'renameParameter'
+ oldName: 'display1'
+ newName: 'headline4'
+ - kind: 'renameParameter'
+ oldName: 'headline'
+ newName: 'headline5'
+ - kind: 'renameParameter'
+ oldName: 'title'
+ newName: 'headline6'
+ - kind: 'renameParameter'
+ oldName: 'subhead'
+ newName: 'subtitle1'
+ - kind: 'renameParameter'
+ oldName: 'subtitle'
+ newName: 'subtitle2'
+ - kind: 'renameParameter'
+ oldName: 'body2'
+ newName: 'bodytext1'
+ - kind: 'renameParameter'
+ oldName: 'body1'
+ newName: 'bodytext2'
+''');
+ await resolveTestCode('''
+import '$importUri';
+
+void f(TextTheme t, TextStyle s) {
+ t.copyWith(subtitle: s);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(TextTheme t, TextStyle s) {
+ t.copyWith(subtitle2: s);
+}
+''');
+ }
+
+ Future<void> test_material_TextTheme_defaultConstructor_deprecated() async {
+ setPackageContent('''
+class TextTheme {
+ TextTheme({TextStyle headline1, TextStyle headline2, TextStyle headline3,
+ TextStyle headline4, TextStyle headline5, TextStyle headline6,
+ TextStyle subtitle1, TextStyle subtitle2, TextStyle bodyText1,
+ TextStyle bodyText2, TextStyle caption, TextStyle button, TextStyle overline,
+ @deprecated TextStyle display4, @deprecated TextStyle display3,
+ @deprecated TextStyle display2, @deprecated TextStyle display1,
+ @deprecated TextStyle headline, @deprecated TextStyle title,
+ @deprecated TextStyle subhead, @deprecated TextStyle subtitle,
+ @deprecated TextStyle body2, @deprecated TextStyle body1}) {}
+}
+class TextStyle {}
+''');
+ addPackageDataFile('''
+version: 1
+transforms:
+ - title: 'Rename arguments'
+ date: 2020-09-24
+ element:
+ uris: ['$importUri']
+ constructor: ''
+ inClass: 'TextTheme'
+ changes:
+ - kind: 'renameParameter'
+ oldName: 'display4'
+ newName: 'headline1'
+ - kind: 'renameParameter'
+ oldName: 'display3'
+ newName: 'headline2'
+ - kind: 'renameParameter'
+ oldName: 'display2'
+ newName: 'headline3'
+ - kind: 'renameParameter'
+ oldName: 'display1'
+ newName: 'headline4'
+ - kind: 'renameParameter'
+ oldName: 'headline'
+ newName: 'headline5'
+ - kind: 'renameParameter'
+ oldName: 'title'
+ newName: 'headline6'
+ - kind: 'renameParameter'
+ oldName: 'subhead'
+ newName: 'subtitle1'
+ - kind: 'renameParameter'
+ oldName: 'subtitle'
+ newName: 'subtitle2'
+ - kind: 'renameParameter'
+ oldName: 'body2'
+ newName: 'bodytext1'
+ - kind: 'renameParameter'
+ oldName: 'body1'
+ newName: 'bodytext2'
+''');
+ await resolveTestCode('''
+import '$importUri';
+
+void f(TextStyle s) {
+ TextTheme(display4: s);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(TextStyle s) {
+ TextTheme(headline1: s);
+}
+''');
+ }
+
+ Future<void> test_material_TextTheme_defaultConstructor_removed() async {
+ setPackageContent('''
+class TextTheme {
+ TextTheme({TextStyle headline1, TextStyle headline2, TextStyle headline3,
+ TextStyle headline4, TextStyle headline5, TextStyle headline6,
+ TextStyle subtitle1, TextStyle subtitle2, TextStyle bodyText1,
+ TextStyle bodyText2, TextStyle caption, TextStyle button, TextStyle overline,
+ }) {}
+}
+class TextStyle {}
+''');
+ addPackageDataFile('''
+version: 1
+transforms:
+ - title: 'Rename arguments'
+ date: 2020-09-24
+ element:
+ uris: ['$importUri']
+ constructor: ''
+ inClass: 'TextTheme'
+ changes:
+ - kind: 'renameParameter'
+ oldName: 'display4'
+ newName: 'headline1'
+ - kind: 'renameParameter'
+ oldName: 'display3'
+ newName: 'headline2'
+ - kind: 'renameParameter'
+ oldName: 'display2'
+ newName: 'headline3'
+ - kind: 'renameParameter'
+ oldName: 'display1'
+ newName: 'headline4'
+ - kind: 'renameParameter'
+ oldName: 'headline'
+ newName: 'headline5'
+ - kind: 'renameParameter'
+ oldName: 'title'
+ newName: 'headline6'
+ - kind: 'renameParameter'
+ oldName: 'subhead'
+ newName: 'subtitle1'
+ - kind: 'renameParameter'
+ oldName: 'subtitle'
+ newName: 'subtitle2'
+ - kind: 'renameParameter'
+ oldName: 'body2'
+ newName: 'bodytext1'
+ - kind: 'renameParameter'
+ oldName: 'body1'
+ newName: 'bodytext2'
+''');
+ await resolveTestCode('''
+import '$importUri';
+
+void f(TextStyle s) {
+ TextTheme(display3: s);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(TextStyle s) {
+ TextTheme(headline2: s);
+}
+''');
+ }
+
Future<void> test_material_TextTheme_display4_deprecated() async {
setPackageContent('''
class TextTheme {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
new file mode 100644
index 0000000..eca3df1
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
@@ -0,0 +1,341 @@
+// Copyright (c) 2020, 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/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/rename_parameter.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'data_driven_test_support.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RenameParameterInConstructorTest);
+ defineReflectiveTests(RenameParameterInMethodTest);
+ defineReflectiveTests(RenameParameterInTopLevelFunctionTest);
+ });
+}
+
+@reflectiveTest
+class RenameParameterInConstructorTest extends _AbstractRenameParameterInTest {
+ @override
+ String get _kind => 'constructor';
+
+ Future<void> test_named_deprecated() async {
+ setPackageContent('''
+class C {
+ C.named({int b, @deprecated int a});
+}
+''');
+ setPackageData(_rename(['C', 'named'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C.named(a: 0);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.named(b: 0);
+}
+''');
+ }
+
+ Future<void> test_named_removed() async {
+ setPackageContent('''
+class C {
+ C.named({int b});
+}
+''');
+ setPackageData(_rename(['C', 'named'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C.named(a: 0);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.named(b: 0);
+}
+''');
+ }
+
+ Future<void> test_unnamed_deprecated() async {
+ setPackageContent('''
+class C {
+ C({int b, @deprecated int a});
+}
+''');
+ setPackageData(_rename(['C', ''], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C(a: 0);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C(b: 0);
+}
+''');
+ }
+
+ Future<void> test_unnamed_removed() async {
+ setPackageContent('''
+class C {
+ C({int b});
+}
+''');
+ setPackageData(_rename(['C', ''], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C(a: 0);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C(b: 0);
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RenameParameterInMethodTest extends _AbstractRenameParameterInTest {
+ @override
+ String get _kind => 'method';
+
+ Future<void> test_differentMethod() async {
+ setPackageContent('''
+class C {
+ int m({int b, @deprecated int a}) => 0;
+}
+''');
+ setPackageData(_rename(['D', 'm'], 'a', 'nbew'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f(C c) {
+ c.m(a: 1);
+}
+''');
+ await assertNoFix();
+ }
+
+ Future<void> test_instance_override_deprecated() async {
+ setPackageContent('''
+class C {
+ int m({int b, @deprecated int a}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int m({int a}) => 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int m({int b, @deprecated int a}) => 0;
+}
+''');
+ }
+
+ Future<void> test_instance_override_removed() async {
+ setPackageContent('''
+class C {
+ int m({int b}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int m({int a}) => 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int m({int b}) => 0;
+}
+''');
+ }
+
+ Future<void> test_instance_reference_deprecated() async {
+ setPackageContent('''
+class C {
+ int m({int b, @deprecated int a}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f(C c) {
+ c.m(a: 1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m(b: 1);
+}
+''');
+ }
+
+ Future<void> test_instance_reference_removed() async {
+ setPackageContent('''
+class C {
+ int m({int b}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f(C c) {
+ c.m(a: 1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m(b: 1);
+}
+''');
+ }
+
+ Future<void> test_static_deprecated() async {
+ setPackageContent('''
+class C {
+ static int m({int b, @deprecated int a}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C.m(a: 1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.m(b: 1);
+}
+''');
+ }
+
+ Future<void> test_static_removed() async {
+ setPackageContent('''
+class C {
+ static int m({int b}) => 0;
+}
+''');
+ setPackageData(_rename(['C', 'm'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+void f() {
+ C.m(a: 1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.m(b: 1);
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RenameParameterInTopLevelFunctionTest
+ extends _AbstractRenameParameterInTest {
+ @override
+ String get _kind => 'function';
+
+ Future<void> test_deprecated() async {
+ setPackageContent('''
+int f({int b, @deprecated int a}) => 0;
+''');
+ setPackageData(_rename(['f'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+var x = f(a: 1);
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var x = f(b: 1);
+''');
+ }
+
+ Future<void> test_removed() async {
+ setPackageContent('''
+int f({int b}) => 0;
+''');
+ setPackageData(_rename(['f'], 'a', 'b'));
+ await resolveTestCode('''
+import '$importUri';
+
+var x = f(a: 1);
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var x = f(b: 1);
+''');
+ }
+}
+
+abstract class _AbstractRenameParameterInTest
+ extends DataDrivenFixProcessorTest {
+ /// Return the kind of element containing the parameter being renamed.
+ String get _kind;
+
+ Transform _rename(List<String> components, String oldName, String newName) =>
+ Transform(
+ title: 'title',
+ element: ElementDescriptor(
+ libraryUris: [Uri.parse(importUri)],
+ kind: ElementKindUtilities.fromName(_kind),
+ components: components),
+ bulkApply: false,
+ changes: [
+ RenameParameter(newName: newName, oldName: oldName),
+ ]);
+}
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 8430c1a..2578b5b 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
@@ -361,23 +361,23 @@
setPackageContent('''
class C {
@deprecated
- C.old();
- C.new();
+ C.a();
+ C.b();
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old();
+ C.a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new();
+ C.b();
}
''');
}
@@ -385,22 +385,22 @@
Future<void> test_named_named_removed() async {
setPackageContent('''
class C {
- C.new();
+ C.b();
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old();
+ C.a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new();
+ C.b();
}
''');
}
@@ -458,10 +458,10 @@
class C {
@deprecated
C();
- C.new();
+ C.a();
}
''');
- setPackageData(_rename(['C', ''], 'new'));
+ setPackageData(_rename(['C', ''], 'a'));
await resolveTestCode('''
import '$importUri';
@@ -473,7 +473,7 @@
import '$importUri';
void f() {
- C.new();
+ C.a();
}
''');
}
@@ -481,10 +481,10 @@
Future<void> test_unnamed_named_removed() async {
setPackageContent('''
class C {
- C.new();
+ C.a();
}
''');
- setPackageData(_rename(['C', ''], 'new'));
+ setPackageData(_rename(['C', ''], 'a'));
await resolveTestCode('''
import '$importUri';
@@ -496,7 +496,7 @@
import '$importUri';
void f() {
- C.new();
+ C.a();
}
''');
}
@@ -601,23 +601,23 @@
setPackageContent('''
class C {
@deprecated
- int old;
- int new;
+ int a;
+ int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old;
+ c.a;
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new;
+ c.b;
}
''');
}
@@ -625,22 +625,22 @@
Future<void> test_instance_reference_removed() async {
setPackageContent('''
class C {
- int new;
+ int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old;
+ c.a;
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new;
+ c.b;
}
''');
}
@@ -649,23 +649,23 @@
setPackageContent('''
class C {
@deprecated
- static int old;
- static int new;
+ static int a;
+ static int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old = 0;
+ C.a = 0;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new = 0;
+ C.b = 0;
}
''');
}
@@ -673,22 +673,22 @@
Future<void> test_static_assignment_removed() async {
setPackageContent('''
class C {
- static int new;
+ static int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old = 0;
+ C.a = 0;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new = 0;
+ C.b = 0;
}
''');
}
@@ -697,23 +697,23 @@
setPackageContent('''
class C {
@deprecated
- static int old;
- static int new;
+ static int a;
+ static int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old;
+ C.a;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new;
+ C.b;
}
''');
}
@@ -721,22 +721,22 @@
Future<void> test_static_reference_removed() async {
setPackageContent('''
class C {
- static int new;
+ static int b;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old;
+ C.a;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new;
+ C.b;
}
''');
}
@@ -794,23 +794,23 @@
setPackageContent('''
class C {
@deprecated
- int get old => 0;
- int get new => 1;
+ int get a => 0;
+ int get b => 1;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old;
+ c.a;
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new;
+ c.b;
}
''');
}
@@ -818,22 +818,22 @@
Future<void> test_instance_reference_direct_removed() async {
setPackageContent('''
class C {
- int get new => 1;
+ int get b => 1;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old;
+ c.a;
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new;
+ c.b;
}
''');
}
@@ -842,26 +842,26 @@
setPackageContent('''
class C {
@deprecated
- int get old => 0;
- int get new => 1;
+ int get a => 0;
+ int get b => 1;
}
class D {
C c() => C();
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(D d) {
- print(d.c().old);
+ print(d.c().a);
}
''');
await assertHasFix('''
import '$importUri';
void f(D d) {
- print(d.c().new);
+ print(d.c().b);
}
''');
}
@@ -869,25 +869,25 @@
Future<void> test_instance_reference_indirect_removed() async {
setPackageContent('''
class C {
- int get new => 1;
+ int get b => 1;
}
class D {
C c() => C();
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(D d) {
- print(d.c().old);
+ print(d.c().a);
}
''');
await assertHasFix('''
import '$importUri';
void f(D d) {
- print(d.c().new);
+ print(d.c().b);
}
''');
}
@@ -895,43 +895,43 @@
Future<void> test_topLevel_reference_deprecated() async {
setPackageContent('''
@deprecated
-int get old => 0;
-int get new => 1;
+int get a => 0;
+int get b => 1;
''');
- setPackageData(_rename(['old'], 'new'));
+ setPackageData(_rename(['a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- old;
+ a;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- new;
+ b;
}
''');
}
Future<void> test_topLevel_reference_removed() async {
setPackageContent('''
-int get new => 1;
+int get b => 1;
''');
- setPackageData(_rename(['old'], 'new'));
+ setPackageData(_rename(['a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- old;
+ a;
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- new;
+ b;
}
''', errorFilter: ignoreUnusedImport);
}
@@ -947,17 +947,17 @@
setPackageContent('''
class C {
@deprecated
- int old() => 0;
- int new() => 0;
+ int a() => 0;
+ int b() => 0;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
class D extends C {
@override
- int old() => 0;
+ int a() => 0;
}
''');
await assertHasFix('''
@@ -965,7 +965,7 @@
class D extends C {
@override
- int new() => 0;
+ int b() => 0;
}
''');
}
@@ -973,16 +973,16 @@
Future<void> test_instance_override_removed() async {
setPackageContent('''
class C {
- int new() => 0;
+ int b() => 0;
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
class D extends C {
@override
- int old() => 0;
+ int a() => 0;
}
''');
await assertHasFix('''
@@ -990,7 +990,7 @@
class D extends C {
@override
- int new() => 0;
+ int b() => 0;
}
''');
}
@@ -999,23 +999,23 @@
setPackageContent('''
class C {
@deprecated
- int old() {}
- int new() {}
+ int a() {}
+ int b() {}
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old();
+ c.a();
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new();
+ c.b();
}
''');
}
@@ -1023,22 +1023,22 @@
Future<void> test_instance_reference_removed() async {
setPackageContent('''
class C {
- int new() {}
+ int b() {}
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f(C c) {
- c.old();
+ c.a();
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- c.new();
+ c.b();
}
''');
}
@@ -1047,23 +1047,23 @@
setPackageContent('''
class C {
@deprecated
- static int old() {}
- static int new() {}
+ static int a() {}
+ static int b() {}
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old();
+ C.a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new();
+ C.b();
}
''');
}
@@ -1071,22 +1071,22 @@
Future<void> test_static_reference_removed() async {
setPackageContent('''
class C {
- static int new() {}
+ static int b() {}
}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['C', 'a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- C.old();
+ C.a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new();
+ C.b();
}
''');
}
@@ -1142,43 +1142,43 @@
Future<void> test_deprecated() async {
setPackageContent('''
@deprecated
-int old() {}
-int new() {}
+int a() {}
+int b() {}
''');
- setPackageData(_rename(['old'], 'new'));
+ setPackageData(_rename(['a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- old();
+ a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- new();
+ b();
}
''');
}
Future<void> test_removed() async {
setPackageContent('''
-int new() {}
+int b() {}
''');
- setPackageData(_rename(['old'], 'new'));
+ setPackageData(_rename(['a'], 'b'));
await resolveTestCode('''
import '$importUri';
void f() {
- old();
+ a();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- new();
+ b();
}
''', errorFilter: ignoreUnusedImport);
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
index 28ee44c..4eb8242 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
@@ -4,27 +4,29 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'add_type_parameter_test.dart' as add_type_parameter_change;
+import 'add_type_parameter_test.dart' as add_type_parameter;
import 'code_fragment_parser_test.dart' as code_fragment_parser;
import 'code_template_test.dart' as code_template;
import 'diagnostics/test_all.dart' as diagnostics;
import 'end_to_end_test.dart' as end_to_end;
import 'flutter_use_case_test.dart' as flutter_use_case;
import 'modify_parameters_test.dart' as modify_parameters;
-import 'rename_test.dart' as rename_change;
+import 'rename_parameter_test.dart' as rename_parameter;
+import 'rename_test.dart' as rename;
import 'transform_set_manager_test.dart' as transform_set_manager;
import 'transform_set_parser_test.dart' as transform_set_parser;
void main() {
defineReflectiveSuite(() {
- add_type_parameter_change.main();
+ add_type_parameter.main();
code_fragment_parser.main();
code_template.main();
diagnostics.main();
end_to_end.main();
flutter_use_case.main();
modify_parameters.main();
- rename_change.main();
+ rename_parameter.main();
+ rename.main();
transform_set_manager.main();
transform_set_parser.main();
});
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index a9eae73..60447c0 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -342,9 +342,51 @@
* Parameters:
* 0: the name of the diagnostic being ignored
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a diagnostic name appears in an
+ // `ignore` comment, but the diagnostic is already being ignored, either
+ // because it's already included in the same `ignore` comment or because it
+ // appears in an `ignore-in-file` comment.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the diagnostic named
+ // `unused_local_variable` is already being ignored for the whole file so it
+ // doesn't need to be ignored on a specific line:
+ //
+ // ```dart
+ // // ignore_for_file: unused_local_variable
+ // void f() {
+ // // ignore: [!unused_local_variable!]
+ // var x = 0;
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because the diagnostic named
+ // `unused_local_variable` is being ignored twice on the same line:
+ //
+ // ```dart
+ // void f() {
+ // // ignore: unused_local_variable, [!unused_local_variable!]
+ // var x = 0;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the ignore comment, or remove the unnecessary diagnostic name if the
+ // ignore comment is ignoring more than one diagnostic:
+ //
+ // ```dart
+ // // ignore_for_file: unused_local_variable
+ // void f() {
+ // var x = 0;
+ // }
+ // ```
static const HintCode DUPLICATE_IGNORE = HintCode(
'DUPLICATE_IGNORE',
- "The diagnostic '{0}' does not need to be ignored here because it is "
+ "The diagnostic '{0}' doesn't need to be ignored here because it's "
"already being ignored.",
correction:
"Try removing the name from the list, or removing the whole comment "
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index d7a5519..ed2da59 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -25,6 +25,53 @@
/**
* No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a field that has the `abstract`
+ // modifier also has an initializer.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `f` is marked as
+ // `abstract` and has an initializer:
+ //
+ // ```dart
+ // %experiments=non-nullable
+ // abstract class C {
+ // abstract int [!f!] = 0;
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because `f` is marked as
+ // `abstract` and there's an initializer in the constructor:
+ //
+ // ```dart
+ // %experiments=non-nullable
+ // abstract class C {
+ // abstract int f;
+ //
+ // C() : [!f!] = 0;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the field must be abstract, then remove the initializer:
+ //
+ // ```dart
+ // %experiments=non-nullable
+ // abstract class C {
+ // abstract int f;
+ // }
+ // ```
+ //
+ // If the field isn't required to be abstract, then remove the keyword:
+ //
+ // ```dart
+ // abstract class C {
+ // int f = 0;
+ // }
+ // ```
static const CompileTimeErrorCode ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER =
CompileTimeErrorCodeWithUniqueName(
'ABSTRACT_FIELD_INITIALIZER',
@@ -80,16 +127,56 @@
hasPublishedDocs: true);
/**
- * 14.2 Exports: It is a compile-time error if a name <i>N</i> is re-exported
- * by a library <i>L</i> and <i>N</i> is introduced into the export namespace
- * of <i>L</i> by more than one export, unless each all exports refer to same
- * declaration for the name N.
- *
* Parameters:
* 0: the name of the ambiguous element
* 1: the name of the first library in which the type is found
* 2: the name of the second library in which the type is found
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when two or more export directives
+ // cause the same name to be exported from multiple libraries.
+ //
+ // #### Example
+ //
+ // Given a file named `a.dart` containing
+ //
+ // ```dart
+ // %uri="lib/a.dart"
+ // class C {}
+ // ```
+ //
+ // And a file named `b.dart` containing
+ //
+ // ```dart
+ // %uri="lib/b.dart"
+ // class C {}
+ // ```
+ //
+ // The following code produces this diagnostic because the name `C` is being
+ // exported from both `a.dart` and `b.dart`:
+ //
+ // ```dart
+ // export 'a.dart';
+ // export [!'b.dart'!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If none of the names in one of the libraries needs to be exported, then
+ // remove the unnecessary export directives:
+ //
+ // ```dart
+ // export 'a.dart';
+ // ```
+ //
+ // If all of the export directives are needed, then hide the name in all
+ // except one of the directives:
+ //
+ // ```dart
+ // export 'a.dart';
+ // export 'b.dart' hide C;
+ // ```
static const CompileTimeErrorCode AMBIGUOUS_EXPORT = CompileTimeErrorCode(
'AMBIGUOUS_EXPORT',
"The name '{0}' is defined in the libraries '{1}' and '{2}'.",
@@ -472,17 +559,103 @@
"'{1}'.",
hasPublishedDocs: true);
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a redirecting constructor (a
+ // constructor that redirects to another constructor in the same class) has an
+ // assert in the initializer list.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the unnamed constructor
+ // is a redirecting constructor and also has an assert in the initializer
+ // list:
+ //
+ // ```dart
+ // class C {
+ // C(int x) : [!assert(x > 0)!], this.name();
+ // C.name() {}
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the assert isn't needed, then remove it:
+ //
+ // ```dart
+ // class C {
+ // C(int x) : this.name();
+ // C.name() {}
+ // }
+ // ```
+ //
+ // If the assert is needed, then convert the constructor into a factory
+ // constructor:
+ //
+ // ```dart
+ // class C {
+ // factory C(int x) {
+ // assert(x > 0);
+ // return C.name();
+ // }
+ // C.name() {}
+ // }
+ // ```
static const CompileTimeErrorCode ASSERT_IN_REDIRECTING_CONSTRUCTOR =
CompileTimeErrorCode('ASSERT_IN_REDIRECTING_CONSTRUCTOR',
"A redirecting constructor can't have an 'assert' initializer.");
/**
- * 5 Variables: Attempting to assign to a final variable elsewhere will cause
- * a NoSuchMethodError to be thrown, because no setter is defined for it. The
- * assignment will also give rise to a static warning for the same reason.
- *
- * A constant variable is always implicitly final.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when it finds an assignment to a
+ // top-level variable, a static field, or a local variable that has the
+ // `const` modifier. The value of a compile-time constant can't be changed at
+ // runtime.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `c` is being assigned a
+ // value even though it has the `const` modifier:
+ //
+ // ```dart
+ // const c = 0;
+ //
+ // void f() {
+ // [!c!] = 1;
+ // print(c);
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the variable must be assignable, then remove the `const` modifier:
+ //
+ // ```dart
+ // var c = 0;
+ //
+ // void f() {
+ // c = 1;
+ // print(c);
+ // }
+ // ```
+ //
+ // If the constant shouldn't be changed, then either remove the assignment or
+ // use a local variable in place of references to the constant:
+ //
+ // ```dart
+ // const c = 0;
+ //
+ // void f() {
+ // var v = 1;
+ // print(v);
+ // }
+ // ```
static const CompileTimeErrorCode ASSIGNMENT_TO_CONST = CompileTimeErrorCode(
'ASSIGNMENT_TO_CONST', "Constant variables can't be assigned a value.",
correction: "Try removing the assignment, or "
@@ -2001,9 +2174,51 @@
isUnresolvedIdentifier: true);
/**
- * 16.12.2 Const: If <i>T</i> is a parameterized type, it is a compile-time
- * error if <i>T</i> includes a type variable among its type arguments.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a type parameter is used as a
+ // type argument in a `const` invocation of a constructor. This isn't allowed
+ // because the value of the type parameter (the actual type that will be used
+ // at runtime) can't be known at compile time.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the type parameter `T`
+ // is being used as a type argument when creating a constant:
+ //
+ // ```dart
+ // class C<T> {
+ // const C();
+ // }
+ //
+ // C<T> newC<T>() => const C<[!T!]>();
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the type that will be used for the type parameter can be known at
+ // compile time, then remove the use of the type parameter:
+ //
+ // ```dart
+ // class C<T> {
+ // const C();
+ // }
+ //
+ // C<int> newC() => const C<int>();
+ // ```
+ //
+ // If the type that will be used for the type parameter can't be known until
+ // runtime, then remove the keyword `const`:
+ //
+ // ```dart
+ // class C<T> {
+ // const C();
+ // }
+ //
+ // C<T> newC<T>() => C<T>();
+ // ```
static const CompileTimeErrorCode CONST_WITH_TYPE_PARAMETERS =
CompileTimeErrorCode('CONST_WITH_TYPE_PARAMETERS',
"A constant creation can't use a type parameter as a type argument.",
@@ -2379,17 +2594,47 @@
hasPublishedDocs: true);
/**
- * 18.3 Parts: It's a compile-time error if the same library contains two part
- * directives with the same URI.
- *
* Parameters:
* 0: the URI of the duplicate part
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a single file is referenced in
+ // multiple part directives.
+ //
+ // #### Example
+ //
+ // Given a file named `part.dart` containing
+ //
+ // ```dart
+ // %uri="lib/part.dart"
+ // part of lib;
+ // ```
+ //
+ // The following code produces this diagnostic because the file `part.dart` is
+ // included multiple times:
+ //
+ // ```dart
+ // library lib;
+ //
+ // part 'part.dart';
+ // part [!'part.dart'!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove all except the first of the duplicated part directives:
+ //
+ // ```dart
+ // library lib;
+ //
+ // part 'part.dart';
+ // ```
static const CompileTimeErrorCode DUPLICATE_PART = CompileTimeErrorCode(
'DUPLICATE_PART',
- "The library already contains a part with the uri '{0}'.",
+ "The library already contains a part with the URI '{0}'.",
correction:
- "Try removing all but one of the duplicated part directives.");
+ "Try removing all except one of the duplicated part directives.");
static const CompileTimeErrorCode ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING =
CompileTimeErrorCode('ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING',
@@ -2476,42 +2721,93 @@
hasPublishedDocs: true);
/**
- * 12.7 Lists: A fresh instance (7.6.1) <i>a</i>, of size <i>n</i>, whose
- * class implements the built-in class <i>List<E></i> is allocated.
- *
* Parameters:
* 0: the number of provided type arguments
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a list literal has more than one
+ // type argument.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the list literal has
+ // two type arguments when it can have at most one:
+ //
+ // ```dart
+ // var l = [!<int, int>!][];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove all except one of the type arguments:
+ //
+ // ```dart
+ // var l = <int>[];
+ // ```
static const CompileTimeErrorCode EXPECTED_ONE_LIST_TYPE_ARGUMENTS =
- CompileTimeErrorCode(
- 'EXPECTED_ONE_LIST_TYPE_ARGUMENTS',
- "List literals require exactly one type argument or none, "
- "but {0} found.",
+ CompileTimeErrorCode('EXPECTED_ONE_LIST_TYPE_ARGUMENTS',
+ "List literals require one type argument or none, but {0} found.",
correction: "Try adjusting the number of type arguments.");
/**
* Parameters:
* 0: the number of provided type arguments
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a set literal has more than one
+ // type argument.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the set literal has
+ // three type arguments when it can have at most one:
+ //
+ // ```dart
+ // var s = [!<int, String, int>!]{0, 'a', 1};
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove all except one of the type arguments:
+ //
+ // ```dart
+ // var s = <int>{0, 1};
+ // ```
static const CompileTimeErrorCode EXPECTED_ONE_SET_TYPE_ARGUMENTS =
- CompileTimeErrorCode(
- 'EXPECTED_ONE_SET_TYPE_ARGUMENTS',
- "Set literals require exactly one type argument or none, "
- "but {0} found.",
+ CompileTimeErrorCode('EXPECTED_ONE_SET_TYPE_ARGUMENTS',
+ "Set literals require one type argument or none, but {0} were found.",
correction: "Try adjusting the number of type arguments.");
/**
- * 12.8 Maps: A fresh instance (7.6.1) <i>m</i>, of size <i>n</i>, whose class
- * implements the built-in class <i>Map<K, V></i> is allocated.
- *
* Parameters:
* 0: the number of provided type arguments
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a map literal has either one or
+ // more than two type arguments.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the map literal has
+ // three type arguments when it can have either two or zero:
+ //
+ // ```dart
+ // var m = [!<int, String, int>!]{};
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove all except two of the type arguments:
+ //
+ // ```dart
+ // var m = <int, String>{};
+ // ```
static const CompileTimeErrorCode EXPECTED_TWO_MAP_TYPE_ARGUMENTS =
- CompileTimeErrorCode(
- 'EXPECTED_TWO_MAP_TYPE_ARGUMENTS',
- "Map literals require exactly two type arguments or none, "
- "but {0} found.",
+ CompileTimeErrorCode('EXPECTED_TWO_MAP_TYPE_ARGUMENTS',
+ "Map literals require two type arguments or none, but {0} found.",
correction: "Try adjusting the number of type arguments.");
/**
@@ -2583,12 +2879,36 @@
hasPublishedDocs: true);
/**
- * 14.2 Exports: It is a compile-time error if the compilation unit found at
- * the specified URI is not a library declaration.
- *
* Parameters:
* 0: the uri pointing to a non-library declaration
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an export directive references a
+ // part rather than a library.
+ //
+ // #### Example
+ //
+ // Given a file named `part.dart` containing
+ //
+ // ```dart
+ // %uri="lib/part.dart"
+ // part of lib;
+ // ```
+ //
+ // The following code produces this diagnostic because the file `part.dart` is
+ // a part, and only libraries can be exported:
+ //
+ // ```dart
+ // library lib;
+ //
+ // export [!'part.dart'!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Either remove the export directive, or change the URI to be the URI of the
+ // library containing the part.
static const CompileTimeErrorCode EXPORT_OF_NON_LIBRARY =
CompileTimeErrorCode('EXPORT_OF_NON_LIBRARY',
"The exported library '{0}' can't have a part-of directive.",
@@ -3743,9 +4063,38 @@
correction: "Try making the deferred import non-deferred.");
/**
- * It is a compile-time error if the declared return type of a function marked
- * 'async*' is not a supertype of 'Stream<T>' for some type 'T'.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the body of a function has the
+ // `async*` modifier even though the return type of the function isn't either
+ // `Stream` or a supertype of `Stream`.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the body of the
+ // function `f` has the 'async*' modifier even though the return type `int`
+ // isn't a supertype of `Stream`:
+ //
+ // ```dart
+ // [!int!] f() async* {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the function should be asynchronous, then change the return type to be
+ // either `Stream` or a supertype of `Stream`:
+ //
+ // ```dart
+ // Stream<int> f() async* {}
+ // ```
+ //
+ // If the function should be synchronous, then remove the `async*` modifier:
+ //
+ // ```dart
+ // int f() => 0;
+ // ```
static const CompileTimeErrorCode ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE =
CompileTimeErrorCode(
'ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE',
@@ -3789,9 +4138,7 @@
// If the function should be synchronous, then remove the `async` modifier:
//
// ```dart
- // int f() {
- // return 0;
- // }
+ // int f() => 0;
// ```
static const CompileTimeErrorCode ILLEGAL_ASYNC_RETURN_TYPE =
CompileTimeErrorCode(
@@ -3803,9 +4150,39 @@
hasPublishedDocs: true);
/**
- * It is a compile-time error if the declared return type of a function marked
- * 'sync*' is not a supertype of 'Iterable<T>' for some type 'T'.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the body of a function has the
+ // `sync*` modifier even though the return type of the function isn't either
+ // `Iterable` or a supertype of `Iterable`.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the body of the
+ // function `f` has the 'sync*' modifier even though the return type `int`
+ // isn't a supertype of `Iterable`:
+ //
+ // ```dart
+ // [!int!] f() sync* {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the function should return an iterable, then change the return type to
+ // be either `Iterable` or a supertype of `Iterable`:
+ //
+ // ```dart
+ // Iterable<int> f() sync* {}
+ // ```
+ //
+ // If the function should return a single value, then remove the `sync*`
+ // modifier:
+ //
+ // ```dart
+ // int f() => 0;
+ // ```
static const CompileTimeErrorCode ILLEGAL_SYNC_GENERATOR_RETURN_TYPE =
CompileTimeErrorCode(
'ILLEGAL_SYNC_GENERATOR_RETURN_TYPE',
@@ -3915,16 +4292,48 @@
hasPublishedDocs: true);
/**
- * 7.10 Superinterfaces: It is a compile-time error if the superclass of a
- * class <i>C</i> appears in the implements clause of <i>C</i>.
- *
* Parameters:
* 0: the name of the class that appears in both "extends" and "implements"
* clauses
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when one class is listed in both the
+ // `extends` and `implements` clauses of another class.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the class `A` is used
+ // in both the `extends` and `implements` clauses for the class `B`:
+ //
+ // ```dart
+ // class A {}
+ //
+ // class B extends A implements [!A!] {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you want to inherit the implementation from the class, then remove the
+ // class from the `implements` clause:
+ //
+ // ```dart
+ // class A {}
+ //
+ // class B extends A {}
+ // ```
+ //
+ // If you don't want to inherit the implementation from the class, then remove
+ // the `extends` clause:
+ //
+ // ```dart
+ // class A {}
+ //
+ // class B implements A {}
+ // ```
static const CompileTimeErrorCode IMPLEMENTS_SUPER_CLASS =
CompileTimeErrorCode('IMPLEMENTS_SUPER_CLASS',
- "'{0}' can't be used in both 'extends' and 'implements' clauses.",
+ "'{0}' can't be used in both the 'extends' and 'implements' clauses.",
correction: "Try removing one of the occurrences.");
/**
@@ -4500,11 +4909,37 @@
"Try using the BigInt class, or switch to the closest valid "
"double: {1}");
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an integer literal has a value
+ // that is too large (positive) or too small (negative) to be represented in a
+ // 64-bit word.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the value can't be
+ // represented in 64 bits:
+ //
+ // ```dart
+ // var x = [!9223372036854775810!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you need to represent the current value, then wrap it in an instance of
+ // the class `BigInt`:
+ //
+ // ```dart
+ // var x = BigInt.parse('9223372036854775810');
+ // ```
static const CompileTimeErrorCode INTEGER_LITERAL_OUT_OF_RANGE =
CompileTimeErrorCode('INTEGER_LITERAL_OUT_OF_RANGE',
"The integer literal {0} can't be represented in 64 bits.",
correction:
- "Try using the BigInt class if you need an integer larger than "
+ "Try using the 'BigInt' class if you need an integer larger than "
"9,223,372,036,854,775,807 or less than "
"-9,223,372,036,854,775,808.");
@@ -5018,17 +5453,97 @@
"Invalid reference to 'this' expression.",
hasPublishedDocs: true);
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the initializer list of a
+ // constructor contains an invocation of a constructor in the superclass, but
+ // the invocation isn't the last item in the initializer list.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the invocation of the
+ // superclass' constructor isn't the last item in the initializer list:
+ //
+ // ```dart
+ // class A {
+ // A(int x);
+ // }
+ //
+ // class B extends A {
+ // B(int x) : [!super!](x), assert(x >= 0);
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Move the invocation of the superclass' constructor to the end of the
+ // initializer list:
+ //
+ // ```dart
+ // class A {
+ // A(int x);
+ // }
+ //
+ // class B extends A {
+ // B(int x) : assert(x >= 0), super(x);
+ // }
+ // ```
static const CompileTimeErrorCode INVALID_SUPER_INVOCATION =
CompileTimeErrorCode('INVALID_SUPER_INVOCATION',
- "The super call must be last in an initializer list: '{0}'.");
+ "The superclass call must be last in an initializer list: '{0}'.");
/**
- * 12.6 Lists: It is a compile time error if the type argument of a constant
- * list literal includes a type parameter.
- *
* Parameters:
* 0: the name of the type parameter
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a type parameter is used as a
+ // type argument in a list, map, or set literal that is prefixed by `const`.
+ // This isn't allowed because the value of the type parameter (the actual type
+ // that will be used at runtime) can't be known at compile time.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the type parameter `T`
+ // is being used as a type argument when creating a constant list:
+ //
+ // ```dart
+ // List<T> newList<T>() => const <[!T!]>[];
+ // ```
+ //
+ // The following code produces this diagnostic because the type parameter `T`
+ // is being used as a type argument when creating a constant map:
+ //
+ // ```dart
+ // Map<String, T> newSet<T>() => const <String, [!T!]>{};
+ // ```
+ //
+ // The following code produces this diagnostic because the type parameter `T`
+ // is being used as a type argument when creating a constant set:
+ //
+ // ```dart
+ // Set<T> newSet<T>() => const <[!T!]>{};
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the type that will be used for the type parameter can be known at
+ // compile time, then remove the type parameter:
+ //
+ // ```dart
+ // List<int> newList() => const <int>[];
+ // ```
+ //
+ // If the type that will be used for the type parameter can't be known until
+ // runtime, then remove the keyword `const`:
+ //
+ // ```dart
+ // List<T> newList<T>() => <T>[];
+ // ```
static const CompileTimeErrorCode INVALID_TYPE_ARGUMENT_IN_CONST_LIST =
CompileTimeErrorCodeWithUniqueName(
'INVALID_TYPE_ARGUMENT_IN_CONST_LITERAL',
@@ -5039,9 +5554,6 @@
"Try replacing the type parameter with a different type.");
/**
- * 12.7 Maps: It is a compile time error if the type arguments of a constant
- * map literal include a type parameter.
- *
* Parameters:
* 0: the name of the type parameter
*/
@@ -5276,17 +5788,67 @@
hasPublishedDocs: true);
/**
- * 13.13 Break: It is a compile-time error if no such statement
- * <i>s<sub>E</sub></i> exists within the innermost function in which
- * <i>s<sub>b</sub></i> occurs.
- *
- * 13.14 Continue: It is a compile-time error if no such statement or case
- * clause <i>s<sub>E</sub></i> exists within the innermost function in which
- * <i>s<sub>c</sub></i> occurs.
- *
* Parameters:
* 0: the name of the unresolvable label
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a `break` or `continue`
+ // statement references a label that is declared in a method or function
+ // containing the function in which the `break` or `continue` statement
+ // appears. The `break` and `continue` statements can't be used to transfer
+ // control outside the function that contains them.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the label `loop` is
+ // declared outside the local function `g`:
+ //
+ // ```dart
+ // void f() {
+ // loop:
+ // while (true) {
+ // void g() {
+ // break [!loop!];
+ // }
+ //
+ // g();
+ // }
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Try rewriting the code so that it isn't necessary to transfer control
+ // outside the local function, possibly by inlining the local function:
+ //
+ // ```dart
+ // void f() {
+ // loop:
+ // while (true) {
+ // break loop;
+ // }
+ // }
+ // ```
+ //
+ // If that isn't possible, then try rewriting the local function so that a
+ // value returned by the function can be used to determine whether control is
+ // transferred:
+ //
+ // ```dart
+ // void f() {
+ // loop:
+ // while (true) {
+ // bool g() {
+ // return true;
+ // }
+ //
+ // if (g()) {
+ // break loop;
+ // }
+ // }
+ // }
+ // ```
static const CompileTimeErrorCode LABEL_IN_OUTER_SCOPE = CompileTimeErrorCode(
'LABEL_IN_OUTER_SCOPE',
"Can't reference label '{0}' declared in an outer method.");
@@ -5466,6 +6028,9 @@
"The element type '{0}' can't be assigned to the list type '{1}'.",
hasPublishedDocs: true);
+ /**
+ * No parameters.
+ */
static const CompileTimeErrorCode MAIN_FIRST_POSITIONAL_PARAMETER_TYPE =
CompileTimeErrorCode(
'MAIN_FIRST_POSITIONAL_PARAMETER_TYPE',
@@ -5474,6 +6039,9 @@
correction: "Try changing the type of the parameter.",
);
+ /**
+ * No parameters.
+ */
static const CompileTimeErrorCode MAIN_HAS_REQUIRED_NAMED_PARAMETERS =
CompileTimeErrorCode(
'MAIN_HAS_REQUIRED_NAMED_PARAMETERS',
@@ -5482,6 +6050,9 @@
"or removing the 'required' modifier.",
);
+ /**
+ * No parameters.
+ */
static const CompileTimeErrorCode
MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS = CompileTimeErrorCode(
'MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS',
@@ -5490,6 +6061,32 @@
"or removing extra parameters.",
);
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a library contains a declaration
+ // of the name `main` that isn't the declaration of a top-level function.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the name `main` is
+ // being used to declare a top-level variable:
+ //
+ // ```dart
+ // %experiments=non-nullable
+ // var [!main!] = 3;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Use a different name for the declaration:
+ //
+ // ```dart
+ // %experiments=non-nullable
+ // var mainIndex = 3;
+ // ```
static const CompileTimeErrorCode MAIN_IS_NOT_FUNCTION = CompileTimeErrorCode(
'MAIN_IS_NOT_FUNCTION',
"The declaration named 'main' must be a function.",
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 8e9e71c..cd29202 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -257,6 +257,11 @@
static T checkNotNull<T>(T argument, [String, name]) => argument;
}
+// In the SDK this is an abstract class.
+class BigInt implements Comparable<BigInt> {
+ static BigInt parse(String source, {int radix}) => BigInt();
+}
+
abstract class bool extends Object {
external const factory bool.fromEnvironment(String name,
{bool defaultValue: false});
@@ -1100,18 +1105,21 @@
///
/// [nullSafePackages], if supplied, is a list of packages names that should
/// be included in the null safety allow list.
+ ///
+ /// [sdkVersion], if supplied will override the version stored in the mock
+ /// SDK's `version` file.
MockSdk({
@required this.resourceProvider,
List<MockSdkLibrary> additionalLibraries = const [],
List<String> nullSafePackages = const [],
+ String sdkVersion,
}) {
+ sdkVersion ??= '${ExperimentStatus.currentVersion.major}.'
+ '${ExperimentStatus.currentVersion.minor}.0';
_versionFile = resourceProvider
.getFolder(resourceProvider.convertPath(sdkRoot))
.getChildAssumingFile('version');
- _versionFile.writeAsStringSync(
- '${ExperimentStatus.currentVersion.major}.'
- '${ExperimentStatus.currentVersion.minor}.0',
- );
+ _versionFile.writeAsStringSync(sdkVersion);
for (MockSdkLibrary library in _LIBRARIES) {
var convertedLibrary = library._toProvider(resourceProvider);
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 7b12549..5b680ce 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -234,6 +234,55 @@
doesn't conform to the language specification or
that might work in unexpected ways.
+### abstract_field_initializer
+
+_Abstract fields can't have initializers._
+
+#### Description
+
+The analyzer produces this diagnostic when a field that has the `abstract`
+modifier also has an initializer.
+
+#### Example
+
+The following code produces this diagnostic because `f` is marked as
+`abstract` and has an initializer:
+
+{% prettify dart tag=pre+code %}
+abstract class C {
+ abstract int [!f!] = 0;
+}
+{% endprettify %}
+
+The following code produces this diagnostic because `f` is marked as
+`abstract` and there's an initializer in the constructor:
+
+{% prettify dart tag=pre+code %}
+abstract class C {
+ abstract int f;
+
+ C() : [!f!] = 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field must be abstract, then remove the initializer:
+
+{% prettify dart tag=pre+code %}
+abstract class C {
+ abstract int f;
+}
+{% endprettify %}
+
+If the field isn't required to be abstract, then remove the keyword:
+
+{% prettify dart tag=pre+code %}
+abstract class C {
+ int f = 0;
+}
+{% endprettify %}
+
### abstract_super_member_reference
_The {0} '{1}' is always abstract in the supertype._
@@ -263,6 +312,54 @@
Remove the invocation of the abstract member, possibly replacing it with an
invocation of a concrete member.
+### ambiguous_export
+
+_The name '{0}' is defined in the libraries '{1}' and '{2}'._
+
+#### Description
+
+The analyzer produces this diagnostic when two or more export directives
+cause the same name to be exported from multiple libraries.
+
+#### Example
+
+Given a file named `a.dart` containing
+
+{% prettify dart tag=pre+code %}
+class C {}
+{% endprettify %}
+
+And a file named `b.dart` containing
+
+{% prettify dart tag=pre+code %}
+class C {}
+{% endprettify %}
+
+The following code produces this diagnostic because the name `C` is being
+exported from both `a.dart` and `b.dart`:
+
+{% prettify dart tag=pre+code %}
+export 'a.dart';
+export [!'b.dart'!];
+{% endprettify %}
+
+#### Common fixes
+
+If none of the names in one of the libraries needs to be exported, then
+remove the unnecessary export directives:
+
+{% prettify dart tag=pre+code %}
+export 'a.dart';
+{% endprettify %}
+
+If all of the export directives are needed, then hide the name in all
+except one of the directives:
+
+{% prettify dart tag=pre+code %}
+export 'a.dart';
+export 'b.dart' hide C;
+{% endprettify %}
+
### ambiguous_extension_member_access
_A member named '{0}' is defined in extensions '{1}' and '{2}' and neither is
@@ -570,6 +667,103 @@
String g(num y) => f(y as String);
{% endprettify %}
+### assert_in_redirecting_constructor
+
+_A redirecting constructor can't have an 'assert' initializer._
+
+#### Description
+
+The analyzer produces this diagnostic when a redirecting constructor (a
+constructor that redirects to another constructor in the same class) has an
+assert in the initializer list.
+
+#### Example
+
+The following code produces this diagnostic because the unnamed constructor
+is a redirecting constructor and also has an assert in the initializer
+list:
+
+{% prettify dart tag=pre+code %}
+class C {
+ C(int x) : [!assert(x > 0)!], this.name();
+ C.name() {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the assert isn't needed, then remove it:
+
+{% prettify dart tag=pre+code %}
+class C {
+ C(int x) : this.name();
+ C.name() {}
+}
+{% endprettify %}
+
+If the assert is needed, then convert the constructor into a factory
+constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+ factory C(int x) {
+ assert(x > 0);
+ return C.name();
+ }
+ C.name() {}
+}
+{% endprettify %}
+
+### assignment_to_const
+
+_Constant variables can't be assigned a value._
+
+#### Description
+
+The analyzer produces this diagnostic when it finds an assignment to a
+top-level variable, a static field, or a local variable that has the
+`const` modifier. The value of a compile-time constant can't be changed at
+runtime.
+
+#### Example
+
+The following code produces this diagnostic because `c` is being assigned a
+value even though it has the `const` modifier:
+
+{% prettify dart tag=pre+code %}
+const c = 0;
+
+void f() {
+ [!c!] = 1;
+ print(c);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the variable must be assignable, then remove the `const` modifier:
+
+{% prettify dart tag=pre+code %}
+var c = 0;
+
+void f() {
+ c = 1;
+ print(c);
+}
+{% endprettify %}
+
+If the constant shouldn't be changed, then either remove the assignment or
+use a local variable in place of references to the constant:
+
+{% prettify dart tag=pre+code %}
+const c = 0;
+
+void f() {
+ var v = 1;
+ print(v);
+}
+{% endprettify %}
+
### assignment_to_final
_'{0}' can't be used as a setter because it's final._
@@ -1433,6 +1627,54 @@
C f(int i) => C(i);
{% endprettify %}
+### const_with_type_parameters
+
+_A constant creation can't use a type parameter as a type argument._
+
+#### Description
+
+The analyzer produces this diagnostic when a type parameter is used as a
+type argument in a `const` invocation of a constructor. This isn't allowed
+because the value of the type parameter (the actual type that will be used
+at runtime) can't be known at compile time.
+
+#### Example
+
+The following code produces this diagnostic because the type parameter `T`
+is being used as a type argument when creating a constant:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+ const C();
+}
+
+C<T> newC<T>() => const C<[!T!]>();
+{% endprettify %}
+
+#### Common fixes
+
+If the type that will be used for the type parameter can be known at
+compile time, then remove the use of the type parameter:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+ const C();
+}
+
+C<int> newC() => const C<int>();
+{% endprettify %}
+
+If the type that will be used for the type parameter can't be known until
+runtime, then remove the keyword `const`:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+ const C();
+}
+
+C<T> newC<T>() => C<T>();
+{% endprettify %}
+
### creation_with_non_type
_The name '{0}' isn't a class._
@@ -1975,6 +2217,54 @@
int y = 1;
{% endprettify %}
+### duplicate_ignore
+
+_The diagnostic '{0}' doesn't need to be ignored here because it's already being
+ignored._
+
+#### Description
+
+The analyzer produces this diagnostic when a diagnostic name appears in an
+`ignore` comment, but the diagnostic is already being ignored, either
+because it's already included in the same `ignore` comment or because it
+appears in an `ignore-in-file` comment.
+
+#### Example
+
+The following code produces this diagnostic because the diagnostic named
+`unused_local_variable` is already being ignored for the whole file so it
+doesn't need to be ignored on a specific line:
+
+{% prettify dart tag=pre+code %}
+// ignore_for_file: unused_local_variable
+void f() {
+ // ignore: [!unused_local_variable!]
+ var x = 0;
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the diagnostic named
+`unused_local_variable` is being ignored twice on the same line:
+
+{% prettify dart tag=pre+code %}
+void f() {
+ // ignore: unused_local_variable, [!unused_local_variable!]
+ var x = 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the ignore comment, or remove the unnecessary diagnostic name if the
+ignore comment is ignoring more than one diagnostic:
+
+{% prettify dart tag=pre+code %}
+// ignore_for_file: unused_local_variable
+void f() {
+ var x = 0;
+}
+{% endprettify %}
+
### duplicate_import
_Duplicate import._
@@ -2056,6 +2346,43 @@
}
{% endprettify %}
+### duplicate_part
+
+_The library already contains a part with the URI '{0}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a single file is referenced in
+multiple part directives.
+
+#### Example
+
+Given a file named `part.dart` containing
+
+{% prettify dart tag=pre+code %}
+part of lib;
+{% endprettify %}
+
+The following code produces this diagnostic because the file `part.dart` is
+included multiple times:
+
+{% prettify dart tag=pre+code %}
+library lib;
+
+part 'part.dart';
+part [!'part.dart'!];
+{% endprettify %}
+
+#### Common fixes
+
+Remove all except the first of the duplicated part directives:
+
+{% prettify dart tag=pre+code %}
+library lib;
+
+part 'part.dart';
+{% endprettify %}
+
### equal_elements_in_const_set
_Two elements in a constant set literal can't be equal._
@@ -2216,6 +2543,84 @@
of which entry to remove might affect the order in which the keys and
values are returned by an iterator.
+### expected_one_list_type_arguments
+
+_List literals require one type argument or none, but {0} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a list literal has more than one
+type argument.
+
+#### Example
+
+The following code produces this diagnostic because the list literal has
+two type arguments when it can have at most one:
+
+{% prettify dart tag=pre+code %}
+var l = [!<int, int>!][];
+{% endprettify %}
+
+#### Common fixes
+
+Remove all except one of the type arguments:
+
+{% prettify dart tag=pre+code %}
+var l = <int>[];
+{% endprettify %}
+
+### expected_one_set_type_arguments
+
+_Set literals require one type argument or none, but {0} were found._
+
+#### Description
+
+The analyzer produces this diagnostic when a set literal has more than one
+type argument.
+
+#### Example
+
+The following code produces this diagnostic because the set literal has
+three type arguments when it can have at most one:
+
+{% prettify dart tag=pre+code %}
+var s = [!<int, String, int>!]{0, 'a', 1};
+{% endprettify %}
+
+#### Common fixes
+
+Remove all except one of the type arguments:
+
+{% prettify dart tag=pre+code %}
+var s = <int>{0, 1};
+{% endprettify %}
+
+### expected_two_map_type_arguments
+
+_Map literals require two type arguments or none, but {0} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a map literal has either one or
+more than two type arguments.
+
+#### Example
+
+The following code produces this diagnostic because the map literal has
+three type arguments when it can have either two or zero:
+
+{% prettify dart tag=pre+code %}
+var m = [!<int, String, int>!]{};
+{% endprettify %}
+
+#### Common fixes
+
+Remove all except two of the type arguments:
+
+{% prettify dart tag=pre+code %}
+var m = <int, String>{};
+{% endprettify %}
+
### export_legacy_symbol
_The symbol '{0}' is defined in a legacy library, and can't be re-exported from
@@ -2266,6 +2671,37 @@
combinator to the export directive in your library that hides all of the
names declared in the opted-out library.
+### export_of_non_library
+
+_The exported library '{0}' can't have a part-of directive._
+
+#### Description
+
+The analyzer produces this diagnostic when an export directive references a
+part rather than a library.
+
+#### Example
+
+Given a file named `part.dart` containing
+
+{% prettify dart tag=pre+code %}
+part of lib;
+{% endprettify %}
+
+The following code produces this diagnostic because the file `part.dart` is
+a part, and only libraries can be exported:
+
+{% prettify dart tag=pre+code %}
+library lib;
+
+export [!'part.dart'!];
+{% endprettify %}
+
+#### Common fixes
+
+Either remove the export directive, or change the URI to be the URI of the
+library containing the part.
+
### expression_in_map
_Expressions can't be used in a map literal._
@@ -3092,6 +3528,42 @@
}
{% endprettify %}
+### illegal_async_generator_return_type
+
+_Functions marked 'async*' must have a return type that is a supertype of
+'Stream<T>' for some type 'T'._
+
+#### Description
+
+The analyzer produces this diagnostic when the body of a function has the
+`async*` modifier even though the return type of the function isn't either
+`Stream` or a supertype of `Stream`.
+
+#### Example
+
+The following code produces this diagnostic because the body of the
+function `f` has the 'async*' modifier even though the return type `int`
+isn't a supertype of `Stream`:
+
+{% prettify dart tag=pre+code %}
+[!int!] f() async* {}
+{% endprettify %}
+
+#### Common fixes
+
+If the function should be asynchronous, then change the return type to be
+either `Stream` or a supertype of `Stream`:
+
+{% prettify dart tag=pre+code %}
+Stream<int> f() async* {}
+{% endprettify %}
+
+If the function should be synchronous, then remove the `async*` modifier:
+
+{% prettify dart tag=pre+code %}
+int f() => 0;
+{% endprettify %}
+
### illegal_async_return_type
_Functions marked 'async' must have a return type assignable to 'Future'._
@@ -3128,9 +3600,44 @@
If the function should be synchronous, then remove the `async` modifier:
{% prettify dart tag=pre+code %}
-int f() {
- return 0;
-}
+int f() => 0;
+{% endprettify %}
+
+### illegal_sync_generator_return_type
+
+_Functions marked 'sync*' must have a return type that is a supertype of
+'Iterable<T>' for some type 'T'._
+
+#### Description
+
+The analyzer produces this diagnostic when the body of a function has the
+`sync*` modifier even though the return type of the function isn't either
+`Iterable` or a supertype of `Iterable`.
+
+#### Example
+
+The following code produces this diagnostic because the body of the
+function `f` has the 'sync*' modifier even though the return type `int`
+isn't a supertype of `Iterable`:
+
+{% prettify dart tag=pre+code %}
+[!int!] f() sync* {}
+{% endprettify %}
+
+#### Common fixes
+
+If the function should return an iterable, then change the return type to
+be either `Iterable` or a supertype of `Iterable`:
+
+{% prettify dart tag=pre+code %}
+Iterable<int> f() sync* {}
+{% endprettify %}
+
+If the function should return a single value, then remove the `sync*`
+modifier:
+
+{% prettify dart tag=pre+code %}
+int f() => 0;
{% endprettify %}
### implements_non_class
@@ -3195,6 +3702,46 @@
class B implements A {}
{% endprettify %}
+### implements_super_class
+
+_'{0}' can't be used in both the 'extends' and 'implements' clauses._
+
+#### Description
+
+The analyzer produces this diagnostic when one class is listed in both the
+`extends` and `implements` clauses of another class.
+
+#### Example
+
+The following code produces this diagnostic because the class `A` is used
+in both the `extends` and `implements` clauses for the class `B`:
+
+{% prettify dart tag=pre+code %}
+class A {}
+
+class B extends A implements [!A!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If you want to inherit the implementation from the class, then remove the
+class from the `implements` clause:
+
+{% prettify dart tag=pre+code %}
+class A {}
+
+class B extends A {}
+{% endprettify %}
+
+If you don't want to inherit the implementation from the class, then remove
+the `extends` clause:
+
+{% prettify dart tag=pre+code %}
+class A {}
+
+class B implements A {}
+{% endprettify %}
+
### implicit_this_reference_in_initializer
_The instance member '{0}' can't be accessed in an initializer._
@@ -3594,6 +4141,34 @@
If there's a concrete subclass of the abstract class that can be used, then
create an instance of the concrete subclass.
+### integer_literal_out_of_range
+
+_The integer literal {0} can't be represented in 64 bits._
+
+#### Description
+
+The analyzer produces this diagnostic when an integer literal has a value
+that is too large (positive) or too small (negative) to be represented in a
+64-bit word.
+
+#### Example
+
+The following code produces this diagnostic because the value can't be
+represented in 64 bits:
+
+{% prettify dart tag=pre+code %}
+var x = [!9223372036854775810!];
+{% endprettify %}
+
+#### Common fixes
+
+If you need to represent the current value, then wrap it in an instance of
+the class `BigInt`:
+
+{% prettify dart tag=pre+code %}
+var x = BigInt.parse('9223372036854775810');
+{% endprettify %}
+
### invalid_annotation
_Annotation must be either a const variable reference or const constructor
@@ -4035,6 +4610,103 @@
class C {}
{% endprettify %}
+### invalid_super_invocation
+
+_The superclass call must be last in an initializer list: '{0}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the initializer list of a
+constructor contains an invocation of a constructor in the superclass, but
+the invocation isn't the last item in the initializer list.
+
+#### Example
+
+The following code produces this diagnostic because the invocation of the
+superclass' constructor isn't the last item in the initializer list:
+
+{% prettify dart tag=pre+code %}
+class A {
+ A(int x);
+}
+
+class B extends A {
+ B(int x) : [!super!](x), assert(x >= 0);
+}
+{% endprettify %}
+
+#### Common fixes
+
+Move the invocation of the superclass' constructor to the end of the
+initializer list:
+
+{% prettify dart tag=pre+code %}
+class A {
+ A(int x);
+}
+
+class B extends A {
+ B(int x) : assert(x >= 0), super(x);
+}
+{% endprettify %}
+
+### invalid_type_argument_in_const_literal
+
+_Constant list literals can't include a type parameter as a type argument, such
+as '{0}'._
+
+_Constant map literals can't include a type parameter as a type argument, such
+as '{0}'._
+
+_Constant set literals can't include a type parameter as a type argument, such
+as '{0}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a type parameter is used as a
+type argument in a list, map, or set literal that is prefixed by `const`.
+This isn't allowed because the value of the type parameter (the actual type
+that will be used at runtime) can't be known at compile time.
+
+#### Example
+
+The following code produces this diagnostic because the type parameter `T`
+is being used as a type argument when creating a constant list:
+
+{% prettify dart tag=pre+code %}
+List<T> newList<T>() => const <[!T!]>[];
+{% endprettify %}
+
+The following code produces this diagnostic because the type parameter `T`
+is being used as a type argument when creating a constant map:
+
+{% prettify dart tag=pre+code %}
+Map<String, T> newSet<T>() => const <String, [!T!]>{};
+{% endprettify %}
+
+The following code produces this diagnostic because the type parameter `T`
+is being used as a type argument when creating a constant set:
+
+{% prettify dart tag=pre+code %}
+Set<T> newSet<T>() => const <[!T!]>{};
+{% endprettify %}
+
+#### Common fixes
+
+If the type that will be used for the type parameter can be known at
+compile time, then remove the type parameter:
+
+{% prettify dart tag=pre+code %}
+List<int> newList() => const <int>[];
+{% endprettify %}
+
+If the type that will be used for the type parameter can't be known until
+runtime, then remove the keyword `const`:
+
+{% prettify dart tag=pre+code %}
+List<T> newList<T>() => <T>[];
+{% endprettify %}
+
### invalid_uri
_Invalid URI syntax: '{0}'._
@@ -4282,6 +4954,69 @@
var y = f();
{% endprettify %}
+### label_in_outer_scope
+
+_Can't reference label '{0}' declared in an outer method._
+
+#### Description
+
+The analyzer produces this diagnostic when a `break` or `continue`
+statement references a label that is declared in a method or function
+containing the function in which the `break` or `continue` statement
+appears. The `break` and `continue` statements can't be used to transfer
+control outside the function that contains them.
+
+#### Example
+
+The following code produces this diagnostic because the label `loop` is
+declared outside the local function `g`:
+
+{% prettify dart tag=pre+code %}
+void f() {
+ loop:
+ while (true) {
+ void g() {
+ break [!loop!];
+ }
+
+ g();
+ }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Try rewriting the code so that it isn't necessary to transfer control
+outside the local function, possibly by inlining the local function:
+
+{% prettify dart tag=pre+code %}
+void f() {
+ loop:
+ while (true) {
+ break loop;
+ }
+}
+{% endprettify %}
+
+If that isn't possible, then try rewriting the local function so that a
+value returned by the function can be used to determine whether control is
+transferred:
+
+{% prettify dart tag=pre+code %}
+void f() {
+ loop:
+ while (true) {
+ bool g() {
+ return true;
+ }
+
+ if (g()) {
+ break loop;
+ }
+ }
+}
+{% endprettify %}
+
### late_final_field_with_const_constructor
_Can't have a late final field in a class with a const constructor._
@@ -4420,6 +5155,32 @@
List<num> x = [1, 2.5, 3];
{% endprettify %}
+### main_is_not_function
+
+_The declaration named 'main' must be a function._
+
+#### Description
+
+The analyzer produces this diagnostic when a library contains a declaration
+of the name `main` that isn't the declaration of a top-level function.
+
+#### Example
+
+The following code produces this diagnostic because the name `main` is
+being used to declare a top-level variable:
+
+{% prettify dart tag=pre+code %}
+var [!main!] = 3;
+{% endprettify %}
+
+#### Common fixes
+
+Use a different name for the declaration:
+
+{% prettify dart tag=pre+code %}
+var mainIndex = 3;
+{% endprettify %}
+
### map_entry_not_in_map
_Map entries can only be used in a map literal._
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index f6d45aa..2252d76 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -692,11 +692,13 @@
Object bindAddress,
{List<String> included = const <String>[],
int preferredPort,
- String summaryPath}) {
+ String summaryPath,
+ @required String sdkPath}) {
return NonNullableFix(listener, resourceProvider, getLineInfo, bindAddress,
included: included,
preferredPort: preferredPort,
- summaryPath: summaryPath);
+ summaryPath: summaryPath,
+ sdkPath: sdkPath);
}
/// Runs the full migration process.
@@ -732,7 +734,8 @@
_fixCodeProcessor.getLineInfo, computeBindAddress(),
included: [options.directory],
preferredPort: options.previewPort,
- summaryPath: options.summary);
+ summaryPath: options.summary,
+ sdkPath: options.sdkPath);
nonNullableFix.rerunFunction = _rerunFunction;
_fixCodeProcessor.registerCodeTask(nonNullableFix);
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index d10f7f4..35f98a8 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -1236,17 +1236,27 @@
targetType = _thisOrSuper(node);
}
DecoratedType expressionType;
- if (callee == null) {
+ DecoratedType calleeType;
+ if (targetType != null &&
+ targetType.type is FunctionType &&
+ node.methodName.name == 'call') {
+ // If `X` has a function type, then in the expression `X.call()`, the
+ // function being called is `X` itself, so the callee type is simply the
+ // type of `X`.
+ calleeType = targetType;
+ } else if (callee != null) {
+ calleeType = getOrComputeElementType(callee, targetType: targetType);
+ if (callee is PropertyAccessorElement) {
+ calleeType = calleeType.returnType;
+ }
+ }
+ if (calleeType == null) {
// Dynamic dispatch. The return type is `dynamic`.
// TODO(paulberry): would it be better to assume a return type of `Never`
// so that we don't unnecessarily propagate nullabilities everywhere?
_dispatch(node.argumentList);
expressionType = _makeNullableDynamicType(node);
} else {
- var calleeType = getOrComputeElementType(callee, targetType: targetType);
- if (callee is PropertyAccessorElement) {
- calleeType = calleeType.returnType;
- }
expressionType = _handleInvocationArguments(
node,
node.argumentList.arguments,
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index 792eeba..6148a95 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -4,6 +4,7 @@
import 'dart:convert' show jsonDecode, JsonEncoder;
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -26,20 +27,10 @@
/// and determines whether the associated variable or parameter can be null
/// then adds or removes a '?' trailing the named type as appropriate.
class NonNullableFix {
- // TODO(srawlins): Refactor to use
- // `Feature.non_nullable.releaseVersion` when this becomes non-null (perhaps
- // after "Beta").
- static final Version _intendedMinimumSdkVersion = Version.parse('2.12.0-0');
-
- // In the package_config.json file, the patch number is omitted.
- static final String _intendedLanguageVersion =
- '${_intendedMinimumSdkVersion.major}.${_intendedMinimumSdkVersion.minor}';
-
- static final String _intendedSdkVersionConstraint =
- '>=$_intendedMinimumSdkVersion <3.0.0';
-
static final List<HttpPreviewServer> _allServers = [];
+ final Version _intendedMinimumSdkVersion;
+
/// The internet address the server should bind to. Should be suitable for
/// passing to HttpServer.bind, i.e. either a [String] or an
/// [InternetAddress].
@@ -87,14 +78,26 @@
NonNullableFix(
this.listener, this.resourceProvider, this._getLineInfo, this.bindAddress,
- {List<String> included = const [], this.preferredPort, this.summaryPath})
+ {List<String> included = const [],
+ this.preferredPort,
+ this.summaryPath,
+ @required String sdkPath})
: includedRoot =
- _getIncludedRoot(included, listener.server.resourceProvider) {
+ _getIncludedRoot(included, listener.server.resourceProvider),
+ _intendedMinimumSdkVersion =
+ _computeIntendedMinimumSdkVersion(resourceProvider, sdkPath) {
reset();
}
bool get isPreviewServerRunning => _server != null;
+ /// In the package_config.json file, the patch number is omitted.
+ String get _intendedLanguageVersion =>
+ '${_intendedMinimumSdkVersion.major}.${_intendedMinimumSdkVersion.minor}';
+
+ String get _intendedSdkVersionConstraint =>
+ '>=$_intendedMinimumSdkVersion <3.0.0';
+
InstrumentationListener createInstrumentationListener(
{MigrationSummary migrationSummary}) =>
InstrumentationListener(migrationSummary: migrationSummary);
@@ -371,6 +374,52 @@
_allServers.clear();
}
+ static Version _computeIntendedMinimumSdkVersion(
+ ResourceProvider resourceProvider, String sdkPath) {
+ var versionFile = resourceProvider
+ .getFile(resourceProvider.pathContext.join(sdkPath, 'version'));
+ if (!versionFile.exists) {
+ throw StateError(
+ 'Could not find SDK version file at ${versionFile.path}');
+ }
+ var sdkVersionString = versionFile.readAsStringSync().trim();
+ var sdkVersion = Version.parse(sdkVersionString);
+ // Ideally, we would like to set the user's minimum SDK constraint to the
+ // version in which null safety was released to stable. But we only want to
+ // do so if we are sure that stable release exists. An easy way to check
+ // that is to see if the current SDK version is greater than or equal to the
+ // stable release of null safety.
+ var nullSafetyStableReleaseVersion = Feature.non_nullable.releaseVersion;
+ if (sdkVersion >= nullSafetyStableReleaseVersion) {
+ // It is, so we can use it as the minimum SDK constraint.
+ return nullSafetyStableReleaseVersion;
+ } else {
+ // It isn't. This either means that null safety hasn't been released to
+ // stable yet (in which case it's definitely not safe to use
+ // `nullSafetyStableReleaseVersion` as a minimum SDK constraint), or it
+ // has been released but the user hasn't upgraded to it (in which case we
+ // don't want to use it as a minimum SDK constraint anyway, because we
+ // don't want to force the user to upgrade their SDK in order to be able
+ // to use their own package). Our next best option is to use the user's
+ // current SDK version as a minimum SDK constraint, assuming it's a proper
+ // beta release version.
+ if (sdkVersionString.contains('beta')) {
+ // It is, so we can use it.
+ return sdkVersion;
+ } else {
+ // It isn't. The user is probably either on a bleeding edge version of
+ // the SDK (e.g. `2.12.0-edge.<SHA>`), a dev version
+ // (e.g. `2.12.0-X.Y.dev`), or an internally built version
+ // (e.g. `2.12.0-<large number>`). All of these version numbers are
+ // unsafe for the user to use as their minimum SDK constraint, because
+ // if they published their package, it wouldn't be usable with the
+ // latest beta release. So just fall back on using a version of
+ // `<stable release>-0`.
+ return Version.parse('$nullSafetyStableReleaseVersion-0');
+ }
+ }
+ }
+
/// Get the "root" of all [included] paths. See [includedRoot] for its
/// definition.
static String _getIncludedRoot(
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index b0ba46d..a444f76 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -5231,6 +5231,24 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_null_aware_call_followed_by_if_null() async {
+ var content = '''
+typedef MapGetter = Map<String, String> Function();
+void f(Map<String, String> m) {}
+void g(MapGetter/*?*/ mapGetter) {
+ f(mapGetter?.call() ?? {});
+}
+''';
+ var expected = '''
+typedef MapGetter = Map<String, String> Function();
+void f(Map<String, String> m) {}
+void g(MapGetter? mapGetter) {
+ f(mapGetter?.call() ?? {});
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_null_aware_getter_invocation() async {
var content = '''
bool f(int i) => i?.isEven;
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 0497d63..712cd2a 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -4692,6 +4692,29 @@
expect(hasNullCheckHint(findNode.methodInvocation('c.m2')), isTrue);
}
+ Future<void> test_methodInvocation_call_functionTyped() async {
+ await analyze('''
+void f(void Function(int x) callback, int y) => callback.call(y);
+''');
+ assertEdge(decoratedTypeAnnotation('int y').node,
+ decoratedTypeAnnotation('int x').node,
+ hard: true);
+ }
+
+ Future<void> test_methodInvocation_call_interfaceTyped() async {
+ // Make sure that we don't try to treat all methods called `call` as though
+ // the underlying type is a function type.
+ await analyze('''
+abstract class C {
+ void call(int x);
+}
+void f(C c, int y) => c.call(y);
+''');
+ assertEdge(decoratedTypeAnnotation('int y').node,
+ decoratedTypeAnnotation('int x').node,
+ hard: true);
+ }
+
Future<void> test_methodInvocation_dynamic() async {
await analyze('''
class C {
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
index 31d3cec..72acffb 100644
--- a/pkg/nnbd_migration/test/migration_cli_test.dart
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -67,11 +67,13 @@
Object bindAddress,
{List<String> included = const <String>[],
int preferredPort,
- String summaryPath})
+ String summaryPath,
+ @required String sdkPath})
: super(listener, resourceProvider, getLineInfo, bindAddress,
included: included,
preferredPort: preferredPort,
- summaryPath: summaryPath);
+ summaryPath: summaryPath,
+ sdkPath: sdkPath);
@override
InstrumentationListener createInstrumentationListener(
@@ -150,19 +152,22 @@
Object bindAddress,
{List<String> included = const <String>[],
int preferredPort,
- String summaryPath}) {
+ String summaryPath,
+ @required String sdkPath}) {
if (cli._test.injectArtificialException) {
return _ExceptionGeneratingNonNullableFix(
listener, resourceProvider, getLineInfo, bindAddress,
included: included,
preferredPort: preferredPort,
- summaryPath: summaryPath);
+ summaryPath: summaryPath,
+ sdkPath: sdkPath);
} else {
return super.createNonNullableFix(
listener, resourceProvider, getLineInfo, bindAddress,
included: included,
preferredPort: preferredPort,
- summaryPath: summaryPath);
+ summaryPath: summaryPath,
+ sdkPath: sdkPath);
}
}
@@ -432,7 +437,7 @@
'''
name: test
environment:
- sdk: '${migrated ? '>=2.12.0-0 <3.0.0' : '>=2.6.0 <3.0.0'}'
+ sdk: '${migrated ? '>=2.12.0 <3.0.0' : '>=2.6.0 <3.0.0'}'
''',
'.dart_tool/package_config.json':
packageConfigText ?? _getPackageConfigText(migrated: migrated),
@@ -1794,7 +1799,7 @@
name: test
environment:
foo: 1
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
'''));
}
@@ -1851,7 +1856,7 @@
projectDir, simpleProject(migrated: true, pubspecText: '''
name: test
environment:
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
'''));
}
@@ -1868,7 +1873,7 @@
// This is strange-looking, but valid.
'''
environment:
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
name: test
'''));
@@ -1882,6 +1887,58 @@
expect(() async => await cliRunner.run(), throwsUnsupportedError);
}
+ test_pubspec_with_sdk_version_beta() async {
+ var projectDir = createProjectDir(simpleProject());
+ var cliRunner = _createCli(sdkVersion: '2.12.0-1.2.beta')
+ .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+ await cliRunner.run();
+ assertProjectContents(
+ projectDir, simpleProject(migrated: true, pubspecText: '''
+name: test
+environment:
+ sdk: '>=2.12.0-1.2.beta <3.0.0'
+'''));
+ }
+
+ test_pubspec_with_sdk_version_dev() async {
+ var projectDir = createProjectDir(simpleProject());
+ var cliRunner = _createCli(sdkVersion: '2.12.0-1.2.dev')
+ .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+ await cliRunner.run();
+ assertProjectContents(
+ projectDir, simpleProject(migrated: true, pubspecText: '''
+name: test
+environment:
+ sdk: '>=2.12.0-0 <3.0.0'
+'''));
+ }
+
+ test_pubspec_with_sdk_version_edge() async {
+ var projectDir = createProjectDir(simpleProject());
+ var cliRunner = _createCli(sdkVersion: '2.12.0-edge.1234567')
+ .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+ await cliRunner.run();
+ assertProjectContents(
+ projectDir, simpleProject(migrated: true, pubspecText: '''
+name: test
+environment:
+ sdk: '>=2.12.0-0 <3.0.0'
+'''));
+ }
+
+ test_pubspec_with_sdk_version_internal() async {
+ var projectDir = createProjectDir(simpleProject());
+ var cliRunner = _createCli(sdkVersion: '2.12.0-1234567')
+ .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+ await cliRunner.run();
+ assertProjectContents(
+ projectDir, simpleProject(migrated: true, pubspecText: '''
+name: test
+environment:
+ sdk: '>=2.12.0-0 <3.0.0'
+'''));
+ }
+
test_uses_physical_resource_provider_by_default() {
var cli = MigrationCli(binaryName: 'nnbd_migration');
expect(cli.resourceProvider, same(PhysicalResourceProvider.INSTANCE));
@@ -1896,9 +1953,12 @@
headers: {'Content-Type': 'application/json; charset=UTF-8'});
}
- _MigrationCli _createCli({List<String> nullSafePackages = const []}) {
+ _MigrationCli _createCli(
+ {List<String> nullSafePackages = const [], String sdkVersion}) {
mock_sdk.MockSdk(
- resourceProvider: resourceProvider, nullSafePackages: nullSafePackages);
+ resourceProvider: resourceProvider,
+ nullSafePackages: nullSafePackages,
+ sdkVersion: sdkVersion);
return _MigrationCli(this);
}
diff --git a/tests/lib/isolate/nnbd_spawnuri_autodetect_1_test.dart b/tests/lib/isolate/nnbd_spawnuri_autodetect_1_test.dart
index 013d558..987c06f 100644
--- a/tests/lib/isolate/nnbd_spawnuri_autodetect_1_test.dart
+++ b/tests/lib/isolate/nnbd_spawnuri_autodetect_1_test.dart
@@ -15,13 +15,15 @@
generateIsolateSource(sourcePath, "");
try {
+ String sourceUri = Uri.file(sourcePath).toString();
+
// Strong Isolate Spawning another Strong Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/strong_strong.dart", "", sourcePath, 're: strong');
+ "$tmpDirPath/strong_strong.dart", "", sourceUri, 're: strong');
// Weak Isolate Spawning a Strong Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/weak_strong.dart", "2.6", sourcePath, 're: strong');
+ "$tmpDirPath/weak_strong.dart", "2.6", sourceUri, 're: strong');
} finally {
tmpDir.deleteSync(recursive: true);
}
diff --git a/tests/lib/isolate/nnbd_spawnuri_autodetect_2_test.dart b/tests/lib/isolate/nnbd_spawnuri_autodetect_2_test.dart
index e2f9d1c..34ca1a8 100644
--- a/tests/lib/isolate/nnbd_spawnuri_autodetect_2_test.dart
+++ b/tests/lib/isolate/nnbd_spawnuri_autodetect_2_test.dart
@@ -15,13 +15,15 @@
generateIsolateSource(sourcePath, "2.6");
try {
+ String sourceUri = Uri.file(sourcePath).toString();
+
// Strong Isolate Spawning another weak Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/strong_weak.dart", "", sourcePath, 're: weak');
+ "$tmpDirPath/strong_weak.dart", "", sourceUri, 're: weak');
// Weak Isolate Spawning another Weak Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/weak_weak.dart", "2.6", sourcePath, 're: weak');
+ "$tmpDirPath/weak_weak.dart", "2.6", sourceUri, 're: weak');
} finally {
tmpDir.deleteSync(recursive: true);
}
diff --git a/tests/lib/isolate/nnbd_spawnuri_autodetect_3_test.dart b/tests/lib/isolate/nnbd_spawnuri_autodetect_3_test.dart
index b7650db..b50f70e 100644
--- a/tests/lib/isolate/nnbd_spawnuri_autodetect_3_test.dart
+++ b/tests/lib/isolate/nnbd_spawnuri_autodetect_3_test.dart
@@ -17,13 +17,15 @@
generateKernel(sourcePath, outPath);
try {
+ String outUri = Uri.file(outPath).toString();
+
// Strong Isolate Spawning another Strong Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/strong_strong.dart", "", outPath, 're: strong');
+ "$tmpDirPath/strong_strong.dart", "", outUri, 're: strong');
// Weak Isolate Spawning a Strong Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/weak_strong.dart", "2.6", outPath, 're: strong');
+ "$tmpDirPath/weak_strong.dart", "2.6", outUri, 're: strong');
} finally {
tmpDir.deleteSync(recursive: true);
}
diff --git a/tests/lib/isolate/nnbd_spawnuri_autodetect_4_test.dart b/tests/lib/isolate/nnbd_spawnuri_autodetect_4_test.dart
index 875d4d0..ce457dc 100644
--- a/tests/lib/isolate/nnbd_spawnuri_autodetect_4_test.dart
+++ b/tests/lib/isolate/nnbd_spawnuri_autodetect_4_test.dart
@@ -17,12 +17,14 @@
generateKernel(sourcePath, outPath);
try {
+ String outUri = Uri.file(outPath).toString();
+
// Strong Isolate Spawning another weak Isolate using spawnUri.
- testNullSafetyMode("$tmpDirPath/strong_weak.dart", "", outPath, 're: weak');
+ testNullSafetyMode("$tmpDirPath/strong_weak.dart", "", outUri, 're: weak');
// Weak Isolate Spawning another Weak Isolate using spawnUri.
testNullSafetyMode(
- "$tmpDirPath/weak_weak.dart", "2.6", outPath, 're: weak');
+ "$tmpDirPath/weak_weak.dart", "2.6", outUri, 're: weak');
} finally {
tmpDir.deleteSync(recursive: true);
}
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
index 77a53e5..b28a2fa 100644
--- a/tests/lib/lib_vm.status
+++ b/tests/lib/lib_vm.status
@@ -75,16 +75,6 @@
mirrors/library_uri_io_test: RuntimeError
mirrors/library_uri_package_test: RuntimeError
-[ $runtime == vm && $system == windows ]
-isolate/detect_nullsafety_1_test: Skip # Issue 43583
-isolate/detect_nullsafety_2_test: Skip # Issue 43583
-isolate/nnbd_spawn_autodetect_1_test: Skip # Issue 43583
-isolate/nnbd_spawn_autodetect_2_test: Skip # Issue 43583
-isolate/nnbd_spawnuri_autodetect_1_test: Skip # Issue 43583
-isolate/nnbd_spawnuri_autodetect_2_test: Skip # Issue 43583
-isolate/nnbd_spawnuri_autodetect_3_test: Skip # Issue 43583
-isolate/nnbd_spawnuri_autodetect_4_test: Skip # Issue 43583
-
[ $runtime == vm && ($arch == simarm || $arch == simarmv6) ]
convert/utf85_test: Skip # Pass, Slow Issue 12644.
diff --git a/tools/VERSION b/tools/VERSION
index c53ff28..b32f56d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 21
+PRERELEASE 22
PRERELEASE_PATCH 0
\ No newline at end of file