Cherry-pick 5c3bcff375bae0f2ca383aca49f71a3b63c469e2 to dev channel
diff --git a/DEPS b/DEPS
index 923c0f7..ab3a7bc 100644
--- a/DEPS
+++ b/DEPS
@@ -58,7 +58,7 @@
"csslib_tag" : "@0.13.3+1",
"dart2js_info_tag" : "@0.5.3+1",
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
- "dart_style_tag": "@1.0.2+1",
+ "dart_style_tag": "@1.0.3",
"dartdoc_tag" : "@v0.9.14-dev",
"fixnum_tag": "@0.10.5",
"func_tag": "@0.1.1",
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ea9a428..57c8d14 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3147,7 +3147,8 @@
*/
DartType _checkElementOfType(DartType type) {
Element element = type?.element;
- if (element is GenericFunctionTypeElementImpl) {
+ if (element is GenericFunctionTypeElementImpl &&
+ element.enclosingElement == null) {
element.enclosingElement = this;
}
return type;
@@ -7192,8 +7193,9 @@
if (_unlinkedVariable != null && _initializer == null) {
UnlinkedExecutable unlinkedInitializer = _unlinkedVariable.initializer;
if (unlinkedInitializer != null) {
- _initializer = new FunctionElementImpl.forSerialized(
- unlinkedInitializer, this)..isSynthetic = true;
+ _initializer =
+ new FunctionElementImpl.forSerialized(unlinkedInitializer, this)
+ ..isSynthetic = true;
} else {
return null;
}
@@ -7484,8 +7486,9 @@
if (_unlinkedParam != null && _initializer == null) {
UnlinkedExecutable unlinkedInitializer = _unlinkedParam.initializer;
if (unlinkedInitializer != null) {
- _initializer = new FunctionElementImpl.forSerialized(
- unlinkedInitializer, this)..isSynthetic = true;
+ _initializer =
+ new FunctionElementImpl.forSerialized(unlinkedInitializer, this)
+ ..isSynthetic = true;
} else {
return null;
}
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 4cfce64..9f19a7f 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -359,7 +359,7 @@
static const HintCode MUST_BE_IMMUTABLE = const HintCode(
'MUST_BE_IMMUTABLE',
"This class inherits from a class marked as @immutable, "
- "and therefore should be immutable (all fields must be final).");
+ "and therefore should be immutable (all instance fields must be final).");
/**
* Generate a hint for methods that override methods annotated `@mustCallSuper`
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index ea2830a..173a2c8 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -780,11 +780,12 @@
}
/**
- * Return `true` if the given class [element] defines a non-final field.
+ * Return `true` if the given class [element] defines a non-final instance
+ * field.
*/
- bool hasNonFinalField(ClassElement element) {
+ bool hasNonFinalInstanceField(ClassElement element) {
for (FieldElement field in element.fields) {
- if (!field.isSynthetic && !field.isFinal) {
+ if (!field.isSynthetic && !field.isFinal && !field.isStatic) {
return true;
}
}
@@ -795,19 +796,20 @@
* Return `true` if the given class [element] defines or inherits a
* non-final field.
*/
- bool hasOrInheritsNonFinalField(
+ bool hasOrInheritsNonFinalInstanceField(
ClassElement element, HashSet<ClassElement> visited) {
if (visited.add(element)) {
- if (hasNonFinalField(element)) {
+ if (hasNonFinalInstanceField(element)) {
return true;
}
for (InterfaceType mixin in element.mixins) {
- if (hasNonFinalField(mixin.element)) {
+ if (hasNonFinalInstanceField(mixin.element)) {
return true;
}
}
if (element.supertype != null) {
- return hasOrInheritsNonFinalField(element.supertype.element, visited);
+ return hasOrInheritsNonFinalInstanceField(
+ element.supertype.element, visited);
}
}
return false;
@@ -815,7 +817,8 @@
ClassElement element = node.element;
if (isOrInheritsImmutable(element, new HashSet<ClassElement>()) &&
- hasOrInheritsNonFinalField(element, new HashSet<ClassElement>())) {
+ hasOrInheritsNonFinalInstanceField(
+ element, new HashSet<ClassElement>())) {
_errorReporter.reportErrorForNode(HintCode.MUST_BE_IMMUTABLE, node.name);
}
}
@@ -8398,7 +8401,7 @@
List<DartType> typeArguments = new List<DartType>(parameterCount);
if (argumentCount == parameterCount) {
for (int i = 0; i < parameterCount; i++) {
- typeArguments[i] = _getType(arguments[i]) ?? dynamicType;
+ typeArguments[i] = _getType(arguments[i]);
}
} else {
reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
@@ -8461,6 +8464,34 @@
DartType type = annotation.type;
if (type == null) {
return undefinedType;
+ } else if (type is FunctionType) {
+ Element element = type.element;
+ if (annotation is TypeName && element is GenericTypeAliasElement) {
+ List<TypeParameterElement> parameterElements = element.typeParameters;
+ FunctionType functionType = element.function.type;
+ if (parameterElements.isNotEmpty) {
+ List<DartType> parameterTypes =
+ TypeParameterTypeImpl.getTypes(parameterElements);
+ int parameterCount = parameterTypes.length;
+ TypeArgumentList argumentList = annotation.typeArguments;
+ List<DartType> typeArguments;
+ if (argumentList != null) {
+ List<TypeAnnotation> arguments = argumentList.arguments;
+ int argumentCount = arguments.length;
+ if (argumentCount == parameterCount) {
+ typeArguments = new List<DartType>(parameterCount);
+ for (int i = 0; i < parameterCount; i++) {
+ typeArguments[i] = _getType(arguments[i]);
+ }
+ }
+ }
+ typeArguments ??=
+ new List<DartType>.filled(parameterCount, dynamicType);
+ functionType =
+ functionType.substitute2(typeArguments, parameterTypes);
+ }
+ return functionType;
+ }
}
return type;
}
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 93ea7b3..f0852ba 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -2007,6 +2007,19 @@
verify([source]);
}
+ test_mustBeImmutable_instance() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+@immutable
+class A {
+ static int x;
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, []);
+ verify([source]);
+ }
+
test_mustBeImmutable_extends() async {
Source source = addSource(r'''
import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index f9c5a45..0f5557f 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2158,6 +2158,38 @@
verify([source]);
}
+ test_genericTypeAlias_noTypeParameters() async {
+ Source source = addSource(r'''
+typedef Foo = int Function<T>(T x);
+int foo<T>(T x) => 3;
+void test1() {
+ Foo y = foo;
+ // These two should be equivalent
+ foo<String>("hello");
+ y<String>("hello");
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_genericTypeAlias_typeParameters() async {
+ Source source = addSource(r'''
+typedef Foo<S> = S Function<T>(T x);
+int foo<T>(T x) => 3;
+void test1() {
+ Foo<int> y = foo;
+ // These two should be equivalent
+ foo<String>("hello");
+ y<String>("hello");
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_implicitConstructorDependencies() async {
// No warning should be generated for the code below; this requires that
// implicit constructors are generated for C1 before C2, even though C1