Version 2.17.0-139.0.dev
Merge commit '567834e49993c77911ef5da9cc4030c521be88e1' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index 0aa6a8f..6ae7fe4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -66,10 +66,7 @@
var callInsertion = _resolver.insertImplicitCallReference(initializer);
if (callInsertion != null) {
- var insertedExpression = callInsertion.expression;
- if (insertedExpression != null) {
- initializer = callInsertion.expression;
- }
+ initializer = callInsertion.expression;
}
// Initializers of top-level variables and fields are already included
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 38fc6db..7f5aba1 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -106,6 +106,12 @@
}
}
+ _checkConflictingConstructorAndStatic(
+ classElement: enumElement,
+ staticGetters: staticGetters,
+ staticSetters: staticSetters,
+ );
+
for (var accessor in enumElement.accessors) {
var baseName = accessor.displayName;
if (accessor.isStatic) {
@@ -384,37 +390,17 @@
}
}
+ _checkConflictingConstructorAndStatic(
+ classElement: element,
+ staticGetters: staticGetters,
+ staticSetters: staticSetters,
+ );
+
// Check for local static members conflicting with local instance members.
+ // TODO(scheglov) This code is duplicated for enums. But for classes it is
+ // separated also into ErrorVerifier - where we check inherited.
for (ClassMember member in members) {
- if (member is ConstructorDeclaration) {
- var nameNode = member.name;
- if (nameNode != null) {
- String name = nameNode.name;
- var staticMember = staticGetters[name] ?? staticSetters[name];
- if (staticMember != null) {
- if (staticMember is PropertyAccessorElement) {
- CompileTimeErrorCode errorCode;
- if (staticMember.isSynthetic) {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD;
- } else if (staticMember.isGetter) {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER;
- } else {
- errorCode = CompileTimeErrorCode
- .CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER;
- }
- _errorReporter.reportErrorForNode(errorCode, nameNode, [name]);
- } else {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
- nameNode,
- [name],
- );
- }
- }
- }
- } else if (member is FieldDeclaration) {
+ if (member is FieldDeclaration) {
if (member.isStatic) {
for (VariableDeclaration field in member.fields.variables) {
SimpleIdentifier identifier = field.name;
@@ -446,6 +432,37 @@
}
}
+ void _checkConflictingConstructorAndStatic({
+ required ClassElement classElement,
+ required Map<String, Element> staticGetters,
+ required Map<String, Element> staticSetters,
+ }) {
+ for (var constructor in classElement.constructors) {
+ var name = constructor.name;
+ var staticMember = staticGetters[name] ?? staticSetters[name];
+ if (staticMember is PropertyAccessorElement) {
+ CompileTimeErrorCode errorCode;
+ if (staticMember.isSynthetic) {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD;
+ } else if (staticMember.isGetter) {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER;
+ } else {
+ errorCode =
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER;
+ }
+ _errorReporter.reportErrorForElement(errorCode, constructor, [name]);
+ } else if (staticMember is MethodElement) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD,
+ constructor,
+ [name],
+ );
+ }
+ }
+ }
+
/// Check whether the given [element] defined by the [identifier] is already
/// in one of the scopes - [getterScope] or [setterScope], and produce an
/// error if it is.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d42e16a..4e32f72 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -81,14 +81,8 @@
/// Data structure describing the result of inserting an implicit call reference
/// into the AST.
class ImplicitCallInsertionResult {
- /// The expression that was inserted, or `null`, if no expression was
- /// inserted.
- ///
- /// The only reason this might be `null` is that, at the moment, we only
- /// insert implicit call reference expressions if the 'constructor-tearoffs'
- /// feature is enabled (to avoid breaking clients).
- /// TODO(paulberry): make this non-nullable when we change this behavior.
- final ImplicitCallReferenceImpl? expression;
+ /// The expression that was inserted.
+ final ImplicitCallReferenceImpl expression;
/// The type of the implicit call tear-off.
final FunctionType staticType;
@@ -862,14 +856,6 @@
typeArgumentTypes = [];
}
- if (!isConstructorTearoffsEnabled) {
- // Temporarily, only create [ImplicitCallReference] nodes under the
- // 'constructor-tearoffs' feature.
- // TODO(srawlins, paulberry): When we are ready to make a breaking change
- // release to the analyzer package, remove this exception.
- return ImplicitCallInsertionResult(null, callMethodType);
- }
-
var callReference = astFactory.implicitCallReference(
expression: expression,
staticElement: callMethod,
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
index 4bd1277..2447ef9 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
@@ -16,7 +16,16 @@
@reflectiveTest
class ConflictingConstructorAndStaticFieldTest
extends PubPackageResolutionTest {
- test_class_field() async {
+ test_class_instance_field() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ C.foo();
+ int foo = 0;
+}
+''');
+ }
+
+ test_class_static_field() async {
await assertErrorsInCode(r'''
class C {
C.foo();
@@ -28,7 +37,7 @@
]);
}
- test_class_getter() async {
+ test_class_static_getter() async {
await assertErrorsInCode(r'''
class C {
C.foo();
@@ -40,7 +49,7 @@
]);
}
- test_class_OK_notSameClass() async {
+ test_class_static_notSameClass() async {
await assertNoErrorsInCode(r'''
class A {
static int foo = 0;
@@ -51,16 +60,7 @@
''');
}
- test_class_OK_notStatic() async {
- await assertNoErrorsInCode(r'''
-class C {
- C.foo();
- int foo = 0;
-}
-''');
- }
-
- test_class_setter() async {
+ test_class_static_setter() async {
await assertErrorsInCode(r'''
class C {
C.foo();
@@ -72,33 +72,64 @@
]);
}
- test_enum_field() async {
+ test_enum_constant() async {
+ await assertErrorsInCode(r'''
+enum E {
+ foo.foo();
+ const E.foo();
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 32, 3),
+ ]);
+ }
+
+ test_enum_instance_field() async {
await assertNoErrorsInCode(r'''
enum E {
v.foo();
- const E.foo(); // _$foo
+ const E.foo();
+ final int foo = 0;
+}
+''');
+ }
+
+ test_enum_static_field() async {
+ await assertErrorsInCode(r'''
+enum E {
+ v.foo();
+ const E.foo();
static int foo = 0;
}
-''');
+''', [
+ error(
+ CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 30, 3),
+ ]);
}
- test_enum_getter() async {
- await assertNoErrorsInCode(r'''
+ test_enum_static_getter() async {
+ await assertErrorsInCode(r'''
enum E {
v.foo();
- const E.foo(); // _$foo
+ const E.foo();
static int get foo => 0;
}
-''');
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER, 30,
+ 3),
+ ]);
}
- test_enum_setter() async {
- await assertNoErrorsInCode(r'''
+ test_enum_static_setter() async {
+ await assertErrorsInCode(r'''
enum E {
v.foo();
- const E.foo(); // _$foo
+ const E.foo();
static void set foo(_) {}
}
-''');
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER, 30,
+ 3),
+ ]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
index d962c52..2ce27da 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
@@ -16,7 +16,27 @@
@reflectiveTest
class ConflictingConstructorAndStaticMethodTest
extends PubPackageResolutionTest {
- test_class() async {
+ test_class_instance() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ C.foo();
+ void foo() {}
+}
+''');
+ }
+
+ test_class_notSameClass() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ static void foo() {}
+}
+class B extends A {
+ B.foo();
+}
+''');
+ }
+
+ test_class_static() async {
await assertErrorsInCode(r'''
class C {
C.foo();
@@ -28,33 +48,26 @@
]);
}
- test_class_OK_notSameClass() async {
+ test_enum_instance() async {
await assertNoErrorsInCode(r'''
-class A {
- static void foo() {}
-}
-class B extends A {
- B.foo();
-}
-''');
- }
-
- test_class_OK_notStatic() async {
- await assertNoErrorsInCode(r'''
-class C {
- C.foo();
+enum E {
+ v.foo();
+ const E.foo();
void foo() {}
}
''');
}
- test_enum() async {
- await assertNoErrorsInCode(r'''
+ test_enum_static() async {
+ await assertErrorsInCode(r'''
enum E {
v.foo();
- const E.foo(); // _$foo
+ const E.foo();
static void foo() {}
}
-''');
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD, 30,
+ 3),
+ ]);
}
}
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index d79ce34..ed5ca6e 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -1151,6 +1151,18 @@
}
@override
+ DecoratedType? visitImplicitCallReference(ImplicitCallReference node) {
+ return _handlePropertyAccessGeneralized(
+ node: node,
+ target: node.expression,
+ propertyName: 'call',
+ isNullAware: false,
+ isCascaded: false,
+ inSetterContext: false,
+ callee: node.staticElement);
+ }
+
+ @override
DecoratedType? visitIndexExpression(IndexExpression node) {
DecoratedType? targetType;
var target = node.target;
@@ -3112,24 +3124,43 @@
DecoratedType? _handlePropertyAccess(Expression node, Expression? target,
SimpleIdentifier propertyName, bool isNullAware, bool isCascaded) {
- DecoratedType? targetType;
+ if (!isCascaded && _isPrefix(target)) {
+ return _dispatch(propertyName, skipNullCheckHint: true);
+ }
var callee = getWriteOrReadElement(propertyName);
+ return _handlePropertyAccessGeneralized(
+ node: node,
+ target: target,
+ propertyName: propertyName.name,
+ isNullAware: isNullAware,
+ isCascaded: isCascaded,
+ inSetterContext: propertyName.inSetterContext(),
+ callee: callee);
+ }
+
+ DecoratedType? _handlePropertyAccessGeneralized(
+ {required Expression node,
+ required Expression? target,
+ required String propertyName,
+ required bool isNullAware,
+ required bool isCascaded,
+ required bool inSetterContext,
+ required Element? callee}) {
+ DecoratedType? targetType;
bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
if (isCascaded) {
targetType = _currentCascadeTargetType;
- } else if (_isPrefix(target)) {
- return _dispatch(propertyName, skipNullCheckHint: true);
} else if (calleeIsStatic) {
_dispatch(target);
} else if (isNullAware) {
targetType = _dispatch(target);
} else {
- targetType = _handleTarget(target, propertyName.name, callee);
+ targetType = _handleTarget(target, propertyName, callee);
}
DecoratedType? calleeType;
if (targetType != null &&
targetType.type is FunctionType &&
- propertyName.name == 'call') {
+ propertyName == 'call') {
// If `X` has a function type, then in the expression `X.call`, the
// function being torn off is `X` itself, so the callee type is simply the
// non-nullable counterpart to the type of `X`.
@@ -3148,7 +3179,7 @@
// Dynamic dispatch.
return _makeNullableDynamicType(node);
}
- if (propertyName.inSetterContext()) {
+ if (inSetterContext) {
if (isNullAware) {
_conditionalNodes[node] = targetType!.node;
}
diff --git a/tools/VERSION b/tools/VERSION
index 029a3c9..4edaf3c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 138
+PRERELEASE 139
PRERELEASE_PATCH 0
\ No newline at end of file