Version 2.18.0-7.0.dev
Merge commit '531cb9784a14f748c849a359843a8c5f8db079f2' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index ff7217a..457e79d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -82,7 +82,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 214;
+ static const int DATA_VERSION = 215;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart b/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
index 76d4b1d..d3633fb 100644
--- a/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
+++ b/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
@@ -7,19 +7,22 @@
class _SuperVisitor extends RecursiveAstVisitor<void> {
final String name;
+ final _Usage _usage;
/// Set to `true` if a super invocation with the [name] is found.
bool hasSuperInvocation = false;
- _SuperVisitor(this.name);
+ _SuperVisitor(this.name, this._usage);
@override
void visitAssignmentExpression(AssignmentExpression node) {
- var left = node.leftHandSide;
- if (left is PropertyAccess) {
- if (left.target is SuperExpression && left.propertyName.name == name) {
- hasSuperInvocation = true;
- return;
+ if (_usage == _Usage.writing) {
+ var left = node.leftHandSide;
+ if (left is PropertyAccess) {
+ if (left.target is SuperExpression && left.propertyName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
}
}
super.visitAssignmentExpression(node);
@@ -27,35 +30,51 @@
@override
void visitBinaryExpression(BinaryExpression node) {
- if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
- hasSuperInvocation = true;
- return;
+ if (_usage == _Usage.reading) {
+ if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
+ hasSuperInvocation = true;
+ return;
+ }
}
super.visitBinaryExpression(node);
}
@override
void visitMethodInvocation(MethodInvocation node) {
- if (node.target is SuperExpression && node.methodName.name == name) {
- hasSuperInvocation = true;
- return;
+ if (_usage == _Usage.reading) {
+ if (node.target is SuperExpression && node.methodName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
}
super.visitMethodInvocation(node);
}
@override
void visitPropertyAccess(PropertyAccess node) {
- if (node.target is SuperExpression && node.propertyName.name == name) {
- hasSuperInvocation = true;
- return;
+ if (_usage == _Usage.reading) {
+ var parent = node.parent;
+ if (parent is AssignmentExpression && parent.leftHandSide == node) {
+ // Not reading, skip.
+ } else {
+ if (node.target is SuperExpression && node.propertyName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
+ }
}
super.visitPropertyAccess(node);
}
}
+enum _Usage { writing, reading }
+
extension MethodDeclarationExtension on MethodDeclaration {
bool get invokesSuperSelf {
- var visitor = _SuperVisitor(name.name);
+ var visitor = _SuperVisitor(
+ name.name,
+ isSetter ? _Usage.writing : _Usage.reading,
+ );
body.accept(visitor);
return visitor.hasSuperInvocation;
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index c99be86..f646b7e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2829,6 +2829,14 @@
setModifier(Modifier.IMPLICIT_TYPE, hasImplicitReturnType);
}
+ bool get invokesSuperSelf {
+ return hasModifier(Modifier.INVOKES_SUPER_SELF);
+ }
+
+ set invokesSuperSelf(bool value) {
+ setModifier(Modifier.INVOKES_SUPER_SELF, value);
+ }
+
@override
bool get isAbstract {
return hasModifier(Modifier.ABSTRACT);
@@ -4322,29 +4330,32 @@
/// type being referred to is the return type.
static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 16);
+ /// Indicates that the method invokes the super method with the same name.
+ static const Modifier INVOKES_SUPER_SELF = Modifier('INVOKES_SUPER_SELF', 17);
+
/// Indicates that modifier 'lazy' was applied to the element.
- static const Modifier LATE = Modifier('LATE', 17);
+ static const Modifier LATE = Modifier('LATE', 18);
/// Indicates that a class is a macro builder.
- static const Modifier MACRO = Modifier('MACRO', 18);
+ static const Modifier MACRO = Modifier('MACRO', 19);
/// Indicates that a class is a mixin application.
- static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 19);
+ static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 20);
/// Indicates that the pseudo-modifier 'set' was applied to the element.
- static const Modifier SETTER = Modifier('SETTER', 20);
+ static const Modifier SETTER = Modifier('SETTER', 21);
/// See [TypeParameterizedElement.isSimplyBounded].
- static const Modifier SIMPLY_BOUNDED = Modifier('SIMPLY_BOUNDED', 21);
+ static const Modifier SIMPLY_BOUNDED = Modifier('SIMPLY_BOUNDED', 22);
/// Indicates that the modifier 'static' was applied to the element.
- static const Modifier STATIC = Modifier('STATIC', 22);
+ static const Modifier STATIC = Modifier('STATIC', 23);
/// Indicates that the element does not appear in the source code but was
/// implicitly created. For example, if a class does not define any
/// constructors, an implicit zero-argument constructor will be created and it
/// will be marked as being synthetic.
- static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 23);
+ static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 24);
static const List<Modifier> values = [
ABSTRACT,
diff --git a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
index 810758d..20856f3 100644
--- a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
+++ b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
@@ -7,7 +7,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
class MustCallSuperVerifier {
@@ -133,7 +133,8 @@
void _verifySuperIsCalled(MethodDeclaration node, String methodName,
String? overriddenEnclosingName) {
- if (!node.invokesSuperSelf) {
+ var declaredElement = node.declaredElement as ExecutableElementImpl;
+ if (!declaredElement.invokesSuperSelf) {
// Overridable elements are always enclosed in named elements, so it is
// safe to assume [overriddenEnclosingName] is non-`null`.
_errorReporter.reportErrorForNode(
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index c27ae0c..7b8fc96 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -844,6 +845,7 @@
executableElement = element;
}
executableElement.hasImplicitReturnType = node.returnType == null;
+ executableElement.invokesSuperSelf = node.invokesSuperSelf;
executableElement.isAsynchronous = node.body.isAsynchronous;
executableElement.isExternal =
node.externalKeyword != null || node.body is NativeFunctionBody;
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index 945b4ab..b489c33 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -182,16 +182,18 @@
class MethodElementFlags {
static const int _hasImplicitReturnType = 1 << 0;
- static const int _isAbstract = 1 << 1;
- static const int _isAsynchronous = 1 << 2;
- static const int _isExternal = 1 << 3;
- static const int _isGenerator = 1 << 4;
- static const int _isStatic = 1 << 5;
- static const int _isSynthetic = 1 << 6;
+ static const int _invokesSuperSelf = 1 << 1;
+ static const int _isAbstract = 1 << 2;
+ static const int _isAsynchronous = 1 << 3;
+ static const int _isExternal = 1 << 4;
+ static const int _isGenerator = 1 << 5;
+ static const int _isStatic = 1 << 6;
+ static const int _isSynthetic = 1 << 7;
static void read(SummaryDataReader reader, MethodElementImpl element) {
var byte = reader.readByte();
element.hasImplicitReturnType = (byte & _hasImplicitReturnType) != 0;
+ element.invokesSuperSelf = (byte & _invokesSuperSelf) != 0;
element.isAbstract = (byte & _isAbstract) != 0;
element.isAsynchronous = (byte & _isAsynchronous) != 0;
element.isExternal = (byte & _isExternal) != 0;
@@ -203,6 +205,7 @@
static void write(BufferedSink sink, MethodElementImpl element) {
var result = 0;
result |= element.hasImplicitReturnType ? _hasImplicitReturnType : 0;
+ result |= element.invokesSuperSelf ? _invokesSuperSelf : 0;
result |= element.isAbstract ? _isAbstract : 0;
result |= element.isAsynchronous ? _isAsynchronous : 0;
result |= element.isExternal ? _isExternal : 0;
@@ -253,20 +256,22 @@
}
class PropertyAccessorElementFlags {
- static const int _isGetter = 1 << 0;
- static const int _isSetter = 1 << 1;
- static const int _hasImplicitReturnType = 1 << 2;
- static const int _isAbstract = 1 << 3;
- static const int _isAsynchronous = 1 << 4;
- static const int _isExternal = 1 << 5;
- static const int _isGenerator = 1 << 6;
- static const int _isStatic = 1 << 7;
+ static const int _invokesSuperSelf = 1 << 0;
+ static const int _isGetter = 1 << 1;
+ static const int _isSetter = 1 << 2;
+ static const int _hasImplicitReturnType = 1 << 3;
+ static const int _isAbstract = 1 << 4;
+ static const int _isAsynchronous = 1 << 5;
+ static const int _isExternal = 1 << 6;
+ static const int _isGenerator = 1 << 7;
+ static const int _isStatic = 1 << 8;
static void read(
SummaryDataReader reader,
PropertyAccessorElementImpl element,
) {
var byte = reader.readUInt30();
+ element.invokesSuperSelf = (byte & _invokesSuperSelf) != 0;
element.isGetter = (byte & _isGetter) != 0;
element.isSetter = (byte & _isSetter) != 0;
element.hasImplicitReturnType = (byte & _hasImplicitReturnType) != 0;
@@ -279,6 +284,7 @@
static void write(BufferedSink sink, PropertyAccessorElementImpl element) {
var result = 0;
+ result |= element.invokesSuperSelf ? _invokesSuperSelf : 0;
result |= element.isGetter ? _isGetter : 0;
result |= element.isSetter ? _isSetter : 0;
result |= element.hasImplicitReturnType ? _hasImplicitReturnType : 0;
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
index 082f9c0..adcb920 100644
--- a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -481,11 +481,11 @@
test_classLike_method_body_block_invokesSuperSelf_trueToFalse_assignmentExpression() {
_assertNotSameSignature_classLike(r'''
-void foo() {
+set foo(int _) {
super.foo = 0;
}
''', r'''
-void foo() {}
+set foo(int _) {}
''');
}
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index ddc7589..1e81987 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -146,6 +146,28 @@
''');
}
+ test_fromExtendingClass_getter_invokesSuper_setter() async {
+ await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class A {
+ @mustCallSuper
+ int get foo => 0;
+
+ set foo(int _) {}
+}
+
+class B extends A {
+ int get foo {
+ super.foo = 0;
+ return 0;
+ }
+}
+''', [
+ error(HintCode.MUST_CALL_SUPER, 135, 3),
+ ]);
+ }
+
test_fromExtendingClass_operator() async {
await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@@ -208,6 +230,27 @@
''');
}
+ test_fromExtendingClass_setter_invokesSuper_getter() async {
+ await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class A {
+ int get foo => 0;
+
+ @mustCallSuper
+ set foo(int _) {}
+}
+
+class B extends A {
+ set foo(int _) {
+ super.foo;
+ }
+}
+''', [
+ error(HintCode.MUST_CALL_SUPER, 131, 3),
+ ]);
+ }
+
test_fromInterface() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 23fd861..d8bae60 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -263,6 +263,10 @@
}
_writeIf(e.isGenerator, '*');
+
+ if (e is ExecutableElementImpl && e.invokesSuperSelf) {
+ buffer.write(' invokesSuperSelf');
+ }
}
void _writeClassElement(ClassElement e) {
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index fdca05f..810c873 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -4563,6 +4563,78 @@
''');
}
+ test_class_getter_invokesSuperSelf_getter() async {
+ var library = await buildLibrary(r'''
+class A {
+ int get foo {
+ super.foo;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ fields
+ synthetic foo @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ get foo @20 invokesSuperSelf
+ returnType: int
+''');
+ }
+
+ test_class_getter_invokesSuperSelf_getter_nestedInAssignment() async {
+ var library = await buildLibrary(r'''
+class A {
+ int get foo {
+ (super.foo).foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ fields
+ synthetic foo @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ get foo @20 invokesSuperSelf
+ returnType: int
+''');
+ }
+
+ test_class_getter_invokesSuperSelf_setter() async {
+ var library = await buildLibrary(r'''
+class A {
+ int get foo {
+ super.foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ fields
+ synthetic foo @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ get foo @20
+ returnType: int
+''');
+ }
+
test_class_getter_native() async {
var library = await buildLibrary('''
class C {
@@ -4933,6 +5005,27 @@
''');
}
+ test_class_method_invokesSuperSelf() async {
+ var library = await buildLibrary(r'''
+class A {
+ void foo() {
+ super.foo();
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ constructors
+ synthetic @-1
+ methods
+ foo @17 invokesSuperSelf
+ returnType: void
+''');
+ }
+
test_class_method_namedAsSupertype() async {
var library = await buildLibrary(r'''
class A {}
@@ -6172,6 +6265,60 @@
''');
}
+ test_class_setter_invokesSuperSelf_getter() async {
+ var library = await buildLibrary(r'''
+class A {
+ set foo(int _) {
+ super.foo;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ fields
+ synthetic foo @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ set foo @16
+ parameters
+ requiredPositional _ @24
+ type: int
+ returnType: void
+''');
+ }
+
+ test_class_setter_invokesSuperSelf_setter() async {
+ var library = await buildLibrary(r'''
+class A {
+ set foo(int _) {
+ super.foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @6
+ fields
+ synthetic foo @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ set foo @16 invokesSuperSelf
+ parameters
+ requiredPositional _ @24
+ type: int
+ returnType: void
+''');
+ }
+
test_class_setter_native() async {
var library = await buildLibrary('''
class C {
@@ -30273,6 +30420,78 @@
expect(mixins[0].name, 'M');
}
+ test_mixin_getter_invokesSuperSelf_getter() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ int get foo {
+ super.foo;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ fields
+ synthetic foo @-1
+ type: int
+ accessors
+ get foo @25 invokesSuperSelf
+ returnType: int
+''');
+ }
+
+ test_mixin_getter_invokesSuperSelf_getter_nestedInAssignment() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ int get foo {
+ (super.foo).foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ fields
+ synthetic foo @-1
+ type: int
+ accessors
+ get foo @25 invokesSuperSelf
+ returnType: int
+''');
+ }
+
+ test_mixin_getter_invokesSuperSelf_setter() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ int get foo {
+ super.foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ fields
+ synthetic foo @-1
+ type: int
+ accessors
+ get foo @25
+ returnType: int
+''');
+ }
+
test_mixin_implicitObjectSuperclassConstraint() async {
var library = await buildLibrary(r'''
mixin M {}
@@ -30438,6 +30657,27 @@
''');
}
+ test_mixin_method_invokesSuperSelf() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ void foo() {
+ super.foo();
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ methods
+ foo @22 invokesSuperSelf
+ returnType: void
+''');
+ }
+
test_mixin_method_namedAsConstraint() async {
var library = await buildLibrary(r'''
class A {}
@@ -30462,6 +30702,60 @@
''');
}
+ test_mixin_setter_invokesSuperSelf_getter() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ set foo(int _) {
+ super.foo;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ fields
+ synthetic foo @-1
+ type: int
+ accessors
+ set foo @21
+ parameters
+ requiredPositional _ @29
+ type: int
+ returnType: void
+''');
+ }
+
+ test_mixin_setter_invokesSuperSelf_setter() async {
+ var library = await buildLibrary(r'''
+mixin M on A {
+ set foo(int _) {
+ super.foo = 0;
+ }
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ mixins
+ mixin M @6
+ superclassConstraints
+ Object
+ fields
+ synthetic foo @-1
+ type: int
+ accessors
+ set foo @21 invokesSuperSelf
+ parameters
+ requiredPositional _ @29
+ type: int
+ returnType: void
+''');
+ }
+
test_mixin_typeParameters_variance_contravariant() async {
var library = await buildLibrary('mixin M<in T> {}');
checkElementText(library, r'''
diff --git a/tools/VERSION b/tools/VERSION
index fd2f0a9..1e75bc9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 6
+PRERELEASE 7
PRERELEASE_PATCH 0
\ No newline at end of file