From 2bc46e980767b3d6862363688c0333288bc6c63c Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 28 Nov 2023 03:32:03 +0000 Subject: [PATCH 1/2] analyzer: Remove pre-NNBD strong_mode and non_error tests Change-Id: Iee24d33b8fb9dc625712746d45e66874be27a7ce Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/337845 Reviewed-by: Konstantin Shcheglov Commit-Queue: Samuel Rawlins --- .../generated/non_error_resolver_test.dart | 608 ++++++++---------- .../test/generated/strong_mode_test.dart | 23 +- 2 files changed, 278 insertions(+), 353 deletions(-) diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart index da14118aa083..a341c59e600f 100644 --- a/pkg/analyzer/test/generated/non_error_resolver_test.dart +++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart @@ -16,158 +16,11 @@ import '../src/dart/resolution/context_collection_resolution.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(NonErrorResolverTest); - defineReflectiveTests(NonErrorResolverWithoutNullSafetyTest); }); } @reflectiveTest -class NonErrorResolverTest extends PubPackageResolutionTest - with NonErrorResolverTestCases { - test_async_callback_in_with_unknown_return_type_context() async { - await assertNoErrorsInCode(''' -abstract class C { - R run(R Function() action); -} -f(C c) { - c.run(() async {}); -} -'''); - } - - test_await_flattened() async { - await assertNoErrorsInCode(''' -Future>? ffi() => null; -f() async { - Future? b = await ffi(); - b; -} -'''); - } - - test_conflictingStaticGetterAndInstanceSetter_thisClass() async { - await assertErrorsInCode(r''' -class A { - static get x => 0; - static set x(int p) {} -} -''', [ - error(CompileTimeErrorCode.GETTER_NOT_SUBTYPE_SETTER_TYPES, 23, 1), - ]); - } - - test_const_constructor_with_named_generic_parameter() async { - await assertNoErrorsInCode(''' -class C { - const C({required T t}); -} -const c = const C(t: 1); -'''); - } - - test_generic_staticParameterElement_annotation() async { - await assertNoErrorsInCode(''' -class C { - const C.named({arg}); -} -@C.named(arg: true) -test() {} -'''); - var x = findNode.namedExpression('arg: true'); - var y = x.staticParameterElement!; - expect(y, TypeMatcher()); - expect(y.declaration, findElement.parameter('arg')); - } - - test_inconsistentMethodInheritance_accessors_typeParameters1() async { - await assertNoErrorsInCode(r''' -abstract class A { - E? get x; -} -abstract class B { - E? get x; -} -class C implements A, B { - E? get x => null; -} -'''); - } - - test_inconsistentMethodInheritance_accessors_typeParameters2() async { - await assertNoErrorsInCode(r''' -abstract class A { - E? get x {return null;} -} -class B { - E? get x {return null;} -} -class C extends A implements B {} -'''); - } - - test_inconsistentMethodInheritance_accessors_typeParameters_diamond() async { - await assertNoErrorsInCode(r''' -abstract class F extends B {} -class D extends F { - external E? get g; -} -abstract class C { - E? get g; -} -abstract class B implements C { - E? get g { return null; } -} -class A extends B implements D { -} -'''); - } - - test_mixinDeclaresConstructor() async { - await assertNoErrorsInCode(r''' -mixin class A { - m() {} -} -class B extends Object with A {} -'''); - } - - test_mixinDeclaresConstructor_factory() async { - await assertNoErrorsInCode(r''' -mixin class A { - factory A() => throw 0; -} -class B extends Object with A {} -'''); - } - - test_no_call_tearoff_on_promoted_var() async { - await assertNoErrorsInCode(''' -class B { - Object call() => ''; -} -void test(Object x) { - x as Object Function(); - x; // promoted - x = B(); // No implicit tearoff of `.call`, demotes x - x; // demoted -} -'''); - assertType(findNode.simple('x; // promoted'), 'Object Function()'); - assertType(findNode.assignment('x = B()'), 'B'); - assertType(findNode.simple('x; // demoted'), 'Object'); - } - - test_typedef_not_function() async { - newFile('$testPackageLibPath/a.dart', ''' -typedef F = int; -'''); - await assertNoErrorsInCode(''' -import 'a.dart'; -F f = 0; -'''); - } -} - -mixin NonErrorResolverTestCases on PubPackageResolutionTest { +class NonErrorResolverTest extends PubPackageResolutionTest { test_ambiguousExport() async { newFile("$testPackageLibPath/lib1.dart", r''' library lib1; @@ -538,6 +391,17 @@ main() { '''); } + test_async_callback_in_with_unknown_return_type_context() async { + await assertNoErrorsInCode(''' +abstract class C { + R run(R Function() action); +} +f(C c) { + c.run(() async {}); +} +'''); + } + test_async_dynamic_with_return() async { await assertNoErrorsInCode(''' dynamic f() async { @@ -709,6 +573,16 @@ f(list) async* { ]); } + test_await_flattened() async { + await assertNoErrorsInCode(''' +Future>? ffi() => null; +f() async { + Future? b = await ffi(); + b; +} +'''); + } + test_await_simple() async { await assertNoErrorsInCode(''' Future fi() => Future.value(0); @@ -792,6 +666,24 @@ f() { ]); } + test_castFrom() async { + // This test exercises a corner case of legacy erasure: due to the type + // substitution in the `newSet` parameter of `Set.castFrom`, we wind up with + // a synthetic `ParameterMember` that belongs to no library. We need to + // make sure this doesn't lead to a crash. + await assertErrorsInCode(''' +class C {} + +void testNewSet(Set setEls) { + var customNewSet; + Set.castFrom(setEls, + newSet: () => customNewSet = new Set()); +} +''', [ + error(WarningCode.UNUSED_LOCAL_VARIABLE, 51, 12), + ]); + } + test_class_type_alias_documentationComment() async { await assertNoErrorsInCode(''' /** @@ -845,6 +737,26 @@ set x(_) {} '''); } + test_conflictingStaticGetterAndInstanceSetter_thisClass() async { + await assertErrorsInCode(r''' +class A { + static get x => 0; + static set x(int p) {} +} +''', [ + error(CompileTimeErrorCode.GETTER_NOT_SUBTYPE_SETTER_TYPES, 23, 1), + ]); + } + + test_const_constructor_with_named_generic_parameter() async { + await assertNoErrorsInCode(''' +class C { + const C({required T t}); +} +const c = const C(t: 1); +'''); + } + test_const_dynamic() async { await assertNoErrorsInCode(''' const Type d = dynamic; @@ -1010,6 +922,18 @@ class B { '''); } + test_constEvalTypeBoolNumString_equal_null() async { + await assertNoErrorsInCode(r''' +class B { + final v; + const B.n1(num? p) : v = p == null; + const B.n2(num? p) : v = null == p; + const B.n3(Object? p) : v = p == null; + const B.n4(Object? p) : v = null == p; +} +'''); + } + test_constEvalTypeBoolNumString_notEqual() async { await assertNoErrorsInCode(r''' class B { @@ -1033,6 +957,18 @@ class B { '''); } + test_constEvalTypeBoolNumString_notEqual_null() async { + await assertNoErrorsInCode(''' +class B { + final v; + const B.n1(num? p) : v = p != null; + const B.n2(num? p) : v = null != p; + const B.n3(Object? p) : v = p != null; + const B.n4(Object? p) : v = null != p; +} +'''); + } + test_constEvAlTypeNum_String() async { await assertNoErrorsInCode(r''' const String A = 'a'; @@ -1417,6 +1353,20 @@ typedef int f(@app int app); '''); } + test_generic_staticParameterElement_annotation() async { + await assertNoErrorsInCode(''' +class C { + const C.named({arg}); +} +@C.named(arg: true) +test() {} +'''); + var x = findNode.namedExpression('arg: true'); + var y = x.staticParameterElement!; + expect(y, TypeMatcher()); + expect(y.declaration, findElement.parameter('arg')); + } + test_generic_staticParameterElement_annotation_implicitTypeArg() async { var required = isNullSafetyEnabled ? 'required' : ''; await assertNoErrorsInCode(''' @@ -1598,6 +1548,15 @@ class A { '''); } + test_genericTypeAlias_invalidGenericFunctionType() async { + await assertNoErrorsInCode(''' +typedef F = int; +main(p) { + p is F; +} +'''); + } + test_genericTypeAlias_noTypeParameters() async { await assertNoErrorsInCode(r''' typedef Foo = int Function(T x); @@ -1728,16 +1687,59 @@ main() { '''); } - test_inconsistentMethodInheritance_methods_typeParameter2() async { + test_inconsistentMethodInheritance_accessors_typeParameters1() async { await assertNoErrorsInCode(r''' -class A { - x(E e) {} +abstract class A { + E? get x; } -class B { - x(E e) {} +abstract class B { + E? get x; } -class C extends A implements B { - x(E e) {} +class C implements A, B { + E? get x => null; +} +'''); + } + + test_inconsistentMethodInheritance_accessors_typeParameters2() async { + await assertNoErrorsInCode(r''' +abstract class A { + E? get x {return null;} +} +class B { + E? get x {return null;} +} +class C extends A implements B {} +'''); + } + + test_inconsistentMethodInheritance_accessors_typeParameters_diamond() async { + await assertNoErrorsInCode(r''' +abstract class F extends B {} +class D extends F { + external E? get g; +} +abstract class C { + E? get g; +} +abstract class B implements C { + E? get g { return null; } +} +class A extends B implements D { +} +'''); + } + + test_inconsistentMethodInheritance_methods_typeParameter2() async { + await assertNoErrorsInCode(r''' +class A { + x(E e) {} +} +class B { + x(E e) {} +} +class C extends A implements B { + x(E e) {} } '''); } @@ -2405,6 +2407,24 @@ class C { '''); } + test_mixinDeclaresConstructor() async { + await assertNoErrorsInCode(r''' +mixin class A { + m() {} +} +class B extends Object with A {} +'''); + } + + test_mixinDeclaresConstructor_factory() async { + await assertNoErrorsInCode(r''' +mixin class A { + factory A() => throw 0; +} +class B extends Object with A {} +'''); + } + test_multipleSuperInitializers_no() async { await assertNoErrorsInCode(r''' class A {} @@ -2437,6 +2457,23 @@ A f() { '''); } + test_no_call_tearoff_on_promoted_var() async { + await assertNoErrorsInCode(''' +class B { + Object call() => ''; +} +void test(Object x) { + x as Object Function(); + x; // promoted + x = B(); // No implicit tearoff of `.call`, demotes x + x; // demoted +} +'''); + assertType(findNode.simple('x; // promoted'), 'Object Function()'); + assertType(findNode.assignment('x = B()'), 'B'); + assertType(findNode.simple('x; // demoted'), 'Object'); + } + test_nonBoolExpression_interfaceType() async { await assertNoErrorsInCode(r''' f() { @@ -3021,6 +3058,16 @@ class A{} '''); } + test_typedef_not_function() async { + newFile('$testPackageLibPath/a.dart', ''' +typedef F = int; +'''); + await assertNoErrorsInCode(''' +import 'a.dart'; +F f = 0; +'''); + } + test_typePromotion_booleanAnd_useInRight() async { await assertNoErrorsInCode(r''' main(Object p) { @@ -3054,6 +3101,46 @@ main(Object p) { '''); } + test_typePromotion_functionType_arg_ignoreIfNotMoreSpecific() async { + await assertNoErrorsInCode(r''' +typedef FuncB(B b); +typedef FuncA(A a); +class A {} +class B {} +void f(FuncA f) { + if (f is FuncB) { + f(new A()); + } +} +'''); + } + + test_typePromotion_functionType_return_ignoreIfNotMoreSpecific() async { + await assertNoErrorsInCode(r''' +class A {} +typedef FuncAtoDyn(A a); +typedef FuncDynToDyn(x); +void f(FuncAtoDyn f, A a) { + if (f is FuncDynToDyn) { + a = f(new A()); + } +} +'''); + } + + test_typePromotion_functionType_return_voidToDynamic() async { + await assertNoErrorsInCode(r''' +typedef FuncDynToDyn(x); +typedef void FuncDynToVoid(x); +class A {} +void f(FuncDynToVoid? f, A a) { + if (f is FuncDynToDyn) { + a = f(null); + } +} +'''); + } + test_typePromotion_if_accessedInClosure_noAssignment() async { await assertNoErrorsInCode(r''' callMe(f()) { f(); } @@ -3067,6 +3154,23 @@ main(Object p) { '''); } + test_typePromotion_if_extends_moreSpecific() async { + await assertNoErrorsInCode(r''' +class V {} +class VP extends V {} +class A {} +class B extends A { + var b; +} + +void f(A p) { + if (p is B) { + p.b; + } +} +'''); + } + test_typePromotion_if_hasAssignment_outsideAfter() async { await assertNoErrorsInCode(r''' main(Object p) { @@ -3088,6 +3192,23 @@ main(Object p, Object p2) { }'''); } + test_typePromotion_if_implements_moreSpecific() async { + await assertNoErrorsInCode(r''' +class V {} +class VP extends V {} +class A {} +class B implements A { + var b; +} + +void f(A p) { + if (p is B) { + p.b; + } +} +'''); + } + test_typePromotion_if_inClosure_assignedAfter_inSameFunction() async { await assertErrorsInCode(r''' main() { @@ -3252,183 +3373,6 @@ class B extends A { import 'dart:core' as core; core.dynamic dynamicVariable; -'''); - } -} - -@reflectiveTest -class NonErrorResolverWithoutNullSafetyTest extends PubPackageResolutionTest - with WithoutNullSafetyMixin, NonErrorResolverTestCases { - test_castFrom() async { - // This test exercises a corner case of legacy erasure: due to the type - // substitution in the `newSet` parameter of `Set.castFrom`, we wind up with - // a synthetic `ParameterMember` that belongs to no library. We need to - // make sure this doesn't lead to a crash. - await assertErrorsInCode(''' -class C {} - -void testNewSet(Set setEls) { - var customNewSet; - Set.castFrom(setEls, - newSet: () => customNewSet = new Set()); -} -''', [ - error(WarningCode.UNUSED_LOCAL_VARIABLE, 51, 12), - ]); - } - - test_conflictingStaticGetterAndInstanceSetter_thisClass() async { - await assertNoErrorsInCode(r''' -class A { - static get x => 0; - static set x(int p) {} -} -'''); - } - - test_constEvalTypeBoolNumString_equal_null() async { - await assertNoErrorsInCode(r''' -class B { - final v; - const B.n1(num p) : v = p == null; - const B.n2(num p) : v = null == p; - const B.n3(Object p) : v = p == null; - const B.n4(Object p) : v = null == p; -} -'''); - } - - test_constEvalTypeBoolNumString_notEqual_null() async { - await assertNoErrorsInCode(''' -class B { - final v; - const B.n1(num p) : v = p != null; - const B.n2(num p) : v = null != p; - const B.n3(Object p) : v = p != null; - const B.n4(Object p) : v = null != p; -} -'''); - } - - test_genericTypeAlias_invalidGenericFunctionType() async { - // There is a parse error, but no crashes. - await assertErrorsInCode(''' -typedef F = int; -main(p) { - p is F; -} -''', [ - error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 10, 1), - ]); - } - - test_mixinDeclaresConstructor() async { - await assertNoErrorsInCode(r''' -class A { - m() {} -} -class B extends Object with A {} -'''); - } - - test_mixinDeclaresConstructor_factory() async { - await assertNoErrorsInCode(r''' -class A { - factory A() => throw 0; -} -class B extends Object with A {} -'''); - } - - test_typePromotion_conditional_issue14655() async { - await assertNoErrorsInCode(r''' -class A {} -class B extends A {} -class C extends B { - mc() {} -} -print(_) {} -main(A p) { - (p is C) && (print(() => p) && (p is B)) ? p.mc() : p = null; -} -'''); - } - - test_typePromotion_functionType_arg_ignoreIfNotMoreSpecific() async { - await assertNoErrorsInCode(r''' -typedef FuncB(B b); -typedef FuncA(A a); -class A {} -class B {} -main(FuncA f) { - if (f is FuncB) { - f(new A()); - } -} -'''); - } - - test_typePromotion_functionType_return_ignoreIfNotMoreSpecific() async { - await assertErrorsInCode(r''' -class A {} -typedef FuncAtoDyn(A a); -typedef FuncDynToDyn(x); -main(FuncAtoDyn f) { - if (f is FuncDynToDyn) { - A a = f(new A()); - } -} -''', [ - error(WarningCode.UNUSED_LOCAL_VARIABLE, 115, 1), - ]); - } - - test_typePromotion_functionType_return_voidToDynamic() async { - await assertErrorsInCode(r''' -typedef FuncDynToDyn(x); -typedef void FuncDynToVoid(x); -class A {} -main(FuncDynToVoid f) { - if (f is FuncDynToDyn) { - A a = f(null); - } -} -''', [ - error(WarningCode.UNUSED_LOCAL_VARIABLE, 124, 1), - ]); - } - - test_typePromotion_if_extends_moreSpecific() async { - await assertNoErrorsInCode(r''' -class V {} -class VP extends V {} -class A {} -class B extends A { - var b; -} - -main(A p) { - if (p is B) { - p.b; - } -} -'''); - } - - test_typePromotion_if_implements_moreSpecific() async { - await assertNoErrorsInCode(r''' -class V {} -class VP extends V {} -class A {} -class B implements A { - var b; -} - -main(A p) { - if (p is B) { - p.b; - } -} '''); } diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart index 5029fa828795..8b4d753eb1fa 100644 --- a/pkg/analyzer/test/generated/strong_mode_test.dart +++ b/pkg/analyzer/test/generated/strong_mode_test.dart @@ -20,19 +20,14 @@ import 'test_support.dart'; main() { defineReflectiveSuite(() { defineReflectiveTests(StrongModeLocalInferenceTest); - defineReflectiveTests(StrongModeLocalInferenceWithoutNullSafetyTest); defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test); - defineReflectiveTests(StrongModeStaticTypeAnalyzer2WithoutNullSafetyTest); defineReflectiveTests(StrongModeTypePropagationTest); }); } /// Strong mode static analyzer local type inference tests. @reflectiveTest -class StrongModeLocalInferenceTest extends PubPackageResolutionTest - with StrongModeLocalInferenceTestCases {} - -mixin StrongModeLocalInferenceTestCases on PubPackageResolutionTest { +class StrongModeLocalInferenceTest extends PubPackageResolutionTest { TypeAssertions? _assertions; late final Asserter _isDynamic; @@ -4049,17 +4044,8 @@ $code } } -/// Strong mode static analyzer local type inference tests. -@reflectiveTest -class StrongModeLocalInferenceWithoutNullSafetyTest - extends PubPackageResolutionTest - with StrongModeLocalInferenceTestCases, WithoutNullSafetyMixin {} - @reflectiveTest -class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared - with StrongModeStaticTypeAnalyzer2TestCases {} - -mixin StrongModeStaticTypeAnalyzer2TestCases on StaticTypeAnalyzer2TestShared { +class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared { test_dynamicObjectGetter_hashCode() async { await assertErrorsInCode(r''' main() { @@ -6746,11 +6732,6 @@ main() { } } -@reflectiveTest -class StrongModeStaticTypeAnalyzer2WithoutNullSafetyTest - extends StaticTypeAnalyzer2TestShared - with StrongModeStaticTypeAnalyzer2TestCases, WithoutNullSafetyMixin {} - @reflectiveTest class StrongModeTypePropagationTest extends PubPackageResolutionTest { test_inconsistentMethodInheritance_inferFunctionTypeFromTypedef() async { From d91f3a113eba288f0f232a3df2a55e80af3c30a0 Mon Sep 17 00:00:00 2001 From: Brian Wilkerson Date: Tue, 28 Nov 2023 06:09:10 +0000 Subject: [PATCH 2/2] Add diagnostic docs for extension types I'm fairly sure there will be other diagnostics added later, so this isn't everything, but it covers the diagnostics that are currently implemented in the analyzer. Change-Id: I27100c9a76e6db4fb2b0bf8b9bc6b0b2c326707f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322442 Reviewed-by: Marya Belanger Reviewed-by: Brian Wilkerson Commit-Queue: Brian Wilkerson --- pkg/analyzer/lib/src/error/codes.g.dart | 8 +- pkg/analyzer/messages.yaml | 492 +++++++++++++++- .../test/verify_diagnostics_test.dart | 4 + pkg/analyzer/tool/diagnostics/diagnostics.md | 543 +++++++++++++++++- 4 files changed, 1039 insertions(+), 8 deletions(-) diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart index 280326c7936a..a67288425cba 100644 --- a/pkg/analyzer/lib/src/error/codes.g.dart +++ b/pkg/analyzer/lib/src/error/codes.g.dart @@ -258,7 +258,9 @@ class CompileTimeErrorCode extends AnalyzerErrorCode { 'AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE', "The 'await' expression can't be used for an expression with an extension " "type that is not a subtype of 'Future'.", - correctionMessage: "Try updating the extension type to implement 'Future'.", + correctionMessage: + "Try removing the `await`, or updating the extension type to implement " + "'Future'.", ); /// Parameters: @@ -1672,8 +1674,8 @@ class CompileTimeErrorCode extends AnalyzerErrorCode { static const CompileTimeErrorCode EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_INVOCATION = CompileTimeErrorCode( 'EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_INVOCATION', - "Extension type constructors can't include superinitializers.", - correctionMessage: "Try removing the superconstructor invocation.", + "Extension type constructors can't include super initializers.", + correctionMessage: "Try removing the super constructor invocation.", ); /// No parameters. diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml index ff769bf9117e..0e9e5f88cd5b 100644 --- a/pkg/analyzer/messages.yaml +++ b/pkg/analyzer/messages.yaml @@ -1170,7 +1170,51 @@ CompileTimeErrorCode: await expression.) AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE: problemMessage: "The 'await' expression can't be used for an expression with an extension type that is not a subtype of 'Future'." - correctionMessage: Try updating the extension type to implement 'Future'. + correctionMessage: Try removing the `await`, or updating the extension type to implement 'Future'. + documentation: |- + #### Description + + The analyzer produces this diagnostic when the type of the expression in + an `await` expression is an extension type, and the extension type isn't a + subclass of `Future`. + + #### Example + + The following code produces this diagnostic because the extension type `E` + isn't a subclass of `Future`: + + ```dart + extension type E(int i) {} + + void f(E e) async { + [!await!] e; + } + ``` + + #### Common fixes + + If the extension type is correctly defined, then remove the `await`: + + ```dart + extension type E(int i) {} + + void f(E e) { + e; + } + ``` + + If the extension type is intended to be awaitable, then add `Future` (or a + subtype of `Future`) to the `implements` clause (adding an `implements` + clause if there isn't one already), and make the representation type + match: + + ```dart + extension type E(Future i) implements Future {} + + void f(E e) async { + await e; + } + ``` BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY: sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY problemMessage: "The class '{0}' can't be implemented outside of its library because it's a base class." @@ -5139,28 +5183,222 @@ CompileTimeErrorCode: problemMessage: "Extension type constructors can't declare super formal parameters." correctionMessage: Try removing the super formal parameter declaration. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when a constructor in an extension + type has a super parameter. Super parameters aren't valid because + extension types don't have a superclass. + + #### Example + + The following code produces this diagnostic because the named constructor + `n` contains a super parameter: + + ```dart + extension type E(int i) { + E.n(this.i, [!super!].foo); + } + ``` + + #### Common fixes + + If you need the parameter, replace the super parameter with a normal + parameter: + + ```dart + extension type E(int i) { + E.n(this.i, String foo); + } + ``` + + If you don't need the parameter, remove the super parameter: + + ```dart + extension type E(int i) { + E.n(this.i); + } + ``` EXTENSION_TYPE_CONSTRUCTOR_WITH_SUPER_INVOCATION: - problemMessage: "Extension type constructors can't include superinitializers." - correctionMessage: Try removing the superconstructor invocation. + problemMessage: Extension type constructors can't include super initializers. + correctionMessage: Try removing the super constructor invocation. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when a constructor in an extension + type includes an invocation of a super constructor in the initializer + list. Because extension types don't have a superclass, there's no + constructor to invoke. + + #### Example + + The following code produces this diagnostic because the constructor `E.n` + invokes a super constructor in its initializer list: + + ```dart + extension type E(int i) { + E.n() : i = 0, [!super!].n(); + } + ``` + + #### Common fixes + + Remove the invocation of the super constructor: + + ```dart + extension type E(int i) { + E.n() : i = 0; + } + ``` EXTENSION_TYPE_DECLARES_INSTANCE_FIELD: problemMessage: "Extension types can't declare instance fields." correctionMessage: Try replacing the field with a getter. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when there's a field declaration in + the body of an extension type declaration. + + #### Example + + The following code produces this diagnostic because the extension type `E` + declares a field named `f`: + + ```dart + extension type E(int i) { + final int [!f!] = 0; + } + ``` + + #### Common fixes + + If you don't need the field, then remove it or replace it with a getter + and/or setter: + + ```dart + extension type E(int i) { + int get f => 0; + } + ``` + + If you need the field, then convert the extension type into a class: + + ```dart + class E { + final int i; + + final int f = 0; + + E(this.i); + } + ``` EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT: problemMessage: "Extension types can't declare members with the same name as a member declared by 'Object'." correctionMessage: Try specifying a different name for the member. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when the body of an extension type + declaration contains a member with the same name as one of the members + declared by `Object`. + + #### Example + + The following code produces this diagnostic because the class `Object` + already defines a member named `hashCode`: + + ```dart + extension type E(int i) { + int get [!hashCode!] => 0; + } + ``` + + #### Common fixes + + If you need a member with the implemented semantics, then rename the + member: + + ```dart + extension type E(int i) { + int get myHashCode => 0; + } + ``` + + If you don't need a member with the implemented semantics, then remove the + member: + + ```dart + extension type E(int i) {} + ``` EXTENSION_TYPE_IMPLEMENTS_DISALLOWED_TYPE: problemMessage: "Extension types can't implement '{0}'." correctionMessage: Try specifying a different type, or remove the type from the list. comment: |- Parameters: 0: the display string of the disallowed type + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type implements a + type that it isn't allowed to implement. + + #### Example + + The following code produces this diagnostic because extension types can't + implement the type `dynamic`: + + ```dart + extension type A(int i) implements [!dynamic!] {} + ``` + + #### Common fixes + + Remove the disallowed type from the implements clause: + + ```dart + extension type A(int i) {} + ``` EXTENSION_TYPE_IMPLEMENTS_ITSELF: problemMessage: "The extension type can't implement itself." correctionMessage: Try removing the superinterface that references this extension type. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type implements + itself, either directly or indirectly. + + #### Example + + The following code produces this diagnostic because the extension type `A` + directly implements itself: + + ```dart + extension type [!A!](int i) implements A {} + ``` + + The following code produces this diagnostic because the extension type `A` + indirectly implements itself (through `B`): + + ```dart + extension type [!A!](int i) implements B {} + + extension type [!B!](int i) implements A {} + ``` + + #### Common fixes + + Break the cycle by removing a type from the implements clause of at least + one of the types involved in the cycle: + + ```dart + extension type A(int i) implements B {} + + extension type B(int i) {} + ``` EXTENSION_TYPE_IMPLEMENTS_NOT_SUPERTYPE: problemMessage: "'{0}' is not a supertype of '{1}', the representation type." correctionMessage: Try specifying a different type, or remove the type from the list. @@ -5168,6 +5406,37 @@ CompileTimeErrorCode: Parameters: 0: the implemented not extension type 1: the ultimate representation type + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type implements a + type that isn't a supertype of the representation type. + + #### Example + + The following code produces this diagnostic because the extension type `A` + implements `String`, but `String` isn't a supertype of the representation + type `int`: + + ```dart + extension type A(int i) implements [!String!] {} + ``` + + #### Common fixes + + If the representation type is correct, then remove or replace the type in + the implements clause: + + ```dart + extension type A(int i) {} + ``` + + If the representation type isn't correct, then replace it with the correct + type: + + ```dart + extension type A(String s) implements String {} + ``` EXTENSION_TYPE_IMPLEMENTS_REPRESENTATION_NOT_SUPERTYPE: problemMessage: "'{0}', the representation type of '{1}', is not a supertype of '{2}', the representation type of '{3}'." correctionMessage: Try specifying a different type, or remove the type from the list. @@ -5177,6 +5446,45 @@ CompileTimeErrorCode: 1: the name of the implemented extension type 2: the representation type of the this extension type 3: the name of the this extension type + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type implements + another extension type, and the representation type of the implemented + extension type isn't a subtype of the representation type of the implementing + extension type. + + #### Example + + The following code produces this diagnostic because the extension type `B` + implements `A`, but the representation type of `A` (`num`) isn't a + subtype of the representation type of `B` (`String`): + + ```dart + extension type A(num i) {} + + extension type B(String s) implements [!A!] {} + ``` + + #### Common fixes + + Either change the representation types of the two extension types so that + the representation type of the implemented type is a supertype of the + representation type of the implementing type: + + ```dart + extension type A(num i) {} + + extension type B(int n) implements A {} + ``` + + Or remove the implemented type from the implements clause: + + ```dart + extension type A(num i) {} + + extension type B(String s) {} + ``` EXTENSION_TYPE_INHERITED_MEMBER_CONFLICT: problemMessage: "The extension type '{0}' has more than one distinct member named '{1}' from implemented types." correctionMessage: Try redeclaring the corresponding member in this extension type. @@ -5184,10 +5492,106 @@ CompileTimeErrorCode: Parameters: 0: the name of the extension type 1: the name of the conflicting member + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type implements + two or more other types, and at least two of those types declare a member + with the same name. + + #### Example + + The following code produces this diagnostic because the extension type `C` + implements both `A` and `B`, and both declare a member named `m`: + + ```dart + class A { + void m() {} + } + + extension type B(A a) { + void m() {} + } + + extension type [!C!](A a) implements A, B {} + ``` + + #### Common fixes + + If the extension type doesn't need to implement all of the listed types, + then remove all but one of the types introducing the conflicting members: + + ```dart + class A { + void m() {} + } + + extension type B(A a) { + void m() {} + } + + extension type C(A a) implements A {} + ``` + + If the extension type needs to implement all of the listed types but you + can rename the members in those types, then give the conflicting members + unique names: + + ```dart + class A { + void m() {} + } + + extension type B(A a) { + void n() {} + } + + extension type C(A a) implements A, B {} + ``` EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF: problemMessage: "The extension type representation can't depend on itself." correctionMessage: Try specifying a different type. comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when an extension type has a + representation type that depends on the extension type itself, either + directly or indirectly. + + #### Example + + The following code produces this diagnostic because the representation + type of the extension type `A` depends on `A` directly: + + ```dart + extension type [!A!](A a) {} + ``` + + The following two code examples produce this diagnostic because the + representation type of the extension type `A` depends on `A` + indirectly through the extension type `B`: + + ```dart + extension type [!A!](B b) {} + + extension type [!B!](A a) {} + ``` + + ```dart + extension type [!A!](List b) {} + + extension type [!B!](List a) {} + ``` + + #### Common fixes + + Remove the dependency by choosing a different representation type for at + least one of the types in the cycle: + + ```dart + extension type A(String s) {} + ``` EXTENSION_TYPE_REPRESENTATION_TYPE_BOTTOM: problemMessage: "The representation type can't be a bottom type." correctionMessage: Try specifying a different type. @@ -11101,6 +11505,30 @@ CompileTimeErrorCode: problemMessage: "An extension type parameter can't be used in a non-covariant position of its representation type." correctionMessage: "Try removing the type parameters from function parameter types and type parameter bounds." comment: No parameters. + documentation: |- + #### Description + + The analyzer produces this diagnostic when a type parameter of an + extension type is used in a non-covariant position in the representation + type of that extension type. + + #### Example + + The following code produces this diagnostic because the type parameter `T` + is used as a parameter type in the function type `void Function(T)`, and + parameters are not covariant: + + ```dart + extension type A<[!T!]>(void Function(T) f) {} + ``` + + #### Common fixes + + Remove the use of the type parameter: + + ```dart + extension type A(void Function(String) f) {} + ``` NON_EXHAUSTIVE_SWITCH_EXPRESSION: problemMessage: "The type '{0}' is not exhaustively matched by the switch cases since it doesn't match '{1}'." correctionMessage: "Try adding a wildcard pattern or cases that match '{2}'." @@ -20861,7 +21289,7 @@ PubspecWarningCode: #### Common fixes If you can rely on automatic platform detection, then omit the - top-level `platforms` field. + top-level `platforms` field. ```yaml %uri="pubspec.yaml" @@ -24234,6 +24662,62 @@ WarningCode: Parameters: 0: the kind of member + documentation: |- + #### Description + + The analyzer produces this diagnostic when a member of an extension type + is annotated with `@redeclare`, but none of the implemented interfaces + has a member with the same name. + + #### Example + + The following code produces this diagnostic because the member `n` + declared by the extension type `E` is annotated with `@redeclare`, but `C` + doesn't have a member named `n`: + + ```dart + import 'package:meta/meta.dart'; + + class C { + void m() {} + } + + extension type E(C c) implements C { + @redeclare + void [!n!]() {} + } + ``` + + #### Common fixes + + If the annotated member has the right name, then remove the annotation: + + ```dart + class C { + void m() {} + } + + extension type E(C c) implements C { + void n() {} + } + ``` + + If the annotated member is suppose to replace a member from the + implemented interfaces, then change the name of the annotated member to + match the member being replaced: + + ```dart + import 'package:meta/meta.dart'; + + class C { + void m() {} + } + + extension type E(C c) implements C { + @redeclare + void m() {} + } + ``` REMOVED_LINT_USE: problemMessage: "'{0}' was removed in Dart '{1}'" correctionMessage: "Remove the reference to '{0}'." diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart index 01bde789fe49..51c8da57ac4e 100644 --- a/pkg/analyzer/test/verify_diagnostics_test.dart +++ b/pkg/analyzer/test/verify_diagnostics_test.dart @@ -44,6 +44,10 @@ class DocumentationValidator { 'CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY', // Also reports CompileTimeErrorCode.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED 'CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS', + // The following codes produce two diagnostics because they illustrate a + // cycle. + 'CompileTimeErrorCode.EXTENSION_TYPE_IMPLEMENTS_ITSELF', + 'CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_DEPENDS_ON_ITSELF', // Has code in the example section that needs to be skipped (because it's // part of the explanatory text not part of the example), but there's // currently no way to do that. diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md index ab9875e3a50d..87fd16f527c2 100644 --- a/pkg/analyzer/tool/diagnostics/diagnostics.md +++ b/pkg/analyzer/tool/diagnostics/diagnostics.md @@ -1473,6 +1473,55 @@ Future f() async { } {% endprettify %} +### await_of_extension_type_not_future + +_The 'await' expression can't be used for an expression with an extension type +that is not a subtype of 'Future'._ + +#### Description + +The analyzer produces this diagnostic when the type of the expression in +an `await` expression is an extension type, and the extension type isn't a +subclass of `Future`. + +#### Example + +The following code produces this diagnostic because the extension type `E` +isn't a subclass of `Future`: + +{% prettify dart tag=pre+code %} +extension type E(int i) {} + +void f(E e) async { + [!await!] e; +} +{% endprettify %} + +#### Common fixes + +If the extension type is correctly defined, then remove the `await`: + +{% prettify dart tag=pre+code %} +extension type E(int i) {} + +void f(E e) { + e; +} +{% endprettify %} + +If the extension type is intended to be awaitable, then add `Future` (or a +subtype of `Future`) to the `implements` clause (adding an `implements` +clause if there isn't one already), and make the representation type +match: + +{% prettify dart tag=pre+code %} +extension type E(Future i) implements Future {} + +void f(E e) async { + await e; +} +{% endprettify %} + ### body_might_complete_normally _The body might complete normally, causing 'null' to be returned, but the return @@ -6139,6 +6188,409 @@ f() { If there are multiple cascaded accesses, you'll need to duplicate the extension override for each one. +### extension_type_constructor_with_super_formal_parameter + +_Extension type constructors can't declare super formal parameters._ + +#### Description + +The analyzer produces this diagnostic when a constructor in an extension +type has a super parameter. Super parameters aren't valid because +extension types don't have a superclass. + +#### Example + +The following code produces this diagnostic because the named constructor +`n` contains a super parameter: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + E.n(this.i, [!super!].foo); +} +{% endprettify %} + +#### Common fixes + +If you need the parameter, replace the super parameter with a normal +parameter: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + E.n(this.i, String foo); +} +{% endprettify %} + +If you don't need the parameter, remove the super parameter: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + E.n(this.i); +} +{% endprettify %} + +### extension_type_constructor_with_super_invocation + +_Extension type constructors can't include super initializers._ + +#### Description + +The analyzer produces this diagnostic when a constructor in an extension +type includes an invocation of a super constructor in the initializer +list. Because extension types don't have a superclass, there's no +constructor to invoke. + +#### Example + +The following code produces this diagnostic because the constructor `E.n` +invokes a super constructor in its initializer list: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + E.n() : i = 0, [!super!].n(); +} +{% endprettify %} + +#### Common fixes + +Remove the invocation of the super constructor: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + E.n() : i = 0; +} +{% endprettify %} + +### extension_type_declares_instance_field + +_Extension types can't declare instance fields._ + +#### Description + +The analyzer produces this diagnostic when there's a field declaration in +the body of an extension type declaration. + +#### Example + +The following code produces this diagnostic because the extension type `E` +declares a field named `f`: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + final int [!f!] = 0; +} +{% endprettify %} + +#### Common fixes + +If you don't need the field, then remove it or replace it with a getter +and/or setter: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + int get f => 0; +} +{% endprettify %} + +If you need the field, then convert the extension type into a class: + +{% prettify dart tag=pre+code %} +class E { + final int i; + + final int f = 0; + + E(this.i); +} +{% endprettify %} + +### extension_type_declares_member_of_object + +_Extension types can't declare members with the same name as a member declared +by 'Object'._ + +#### Description + +The analyzer produces this diagnostic when the body of an extension type +declaration contains a member with the same name as one of the members +declared by `Object`. + +#### Example + +The following code produces this diagnostic because the class `Object` +already defines a member named `hashCode`: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + int get [!hashCode!] => 0; +} +{% endprettify %} + +#### Common fixes + +If you need a member with the implemented semantics, then rename the +member: + +{% prettify dart tag=pre+code %} +extension type E(int i) { + int get myHashCode => 0; +} +{% endprettify %} + +If you don't need a member with the implemented semantics, then remove the +member: + +{% prettify dart tag=pre+code %} +extension type E(int i) {} +{% endprettify %} + +### extension_type_implements_disallowed_type + +_Extension types can't implement '{0}'._ + +#### Description + +The analyzer produces this diagnostic when an extension type implements a +type that it isn't allowed to implement. + +#### Example + +The following code produces this diagnostic because extension types can't +implement the type `dynamic`: + +{% prettify dart tag=pre+code %} +extension type A(int i) implements [!dynamic!] {} +{% endprettify %} + +#### Common fixes + +Remove the disallowed type from the implements clause: + +{% prettify dart tag=pre+code %} +extension type A(int i) {} +{% endprettify %} + +### extension_type_implements_itself + +_The extension type can't implement itself._ + +#### Description + +The analyzer produces this diagnostic when an extension type implements +itself, either directly or indirectly. + +#### Example + +The following code produces this diagnostic because the extension type `A` +directly implements itself: + +{% prettify dart tag=pre+code %} +extension type [!A!](int i) implements A {} +{% endprettify %} + +The following code produces this diagnostic because the extension type `A` +indirectly implements itself (through `B`): + +{% prettify dart tag=pre+code %} +extension type [!A!](int i) implements B {} + +extension type [!B!](int i) implements A {} +{% endprettify %} + +#### Common fixes + +Break the cycle by removing a type from the implements clause of at least +one of the types involved in the cycle: + +{% prettify dart tag=pre+code %} +extension type A(int i) implements B {} + +extension type B(int i) {} +{% endprettify %} + +### extension_type_implements_not_supertype + +_'{0}' is not a supertype of '{1}', the representation type._ + +#### Description + +The analyzer produces this diagnostic when an extension type implements a +type that isn't a supertype of the representation type. + +#### Example + +The following code produces this diagnostic because the extension type `A` +implements `String`, but `String` isn't a supertype of the representation +type `int`: + +{% prettify dart tag=pre+code %} +extension type A(int i) implements [!String!] {} +{% endprettify %} + +#### Common fixes + +If the representation type is correct, then remove or replace the type in +the implements clause: + +{% prettify dart tag=pre+code %} +extension type A(int i) {} +{% endprettify %} + +If the representation type isn't correct, then replace it with the correct +type: + +{% prettify dart tag=pre+code %} +extension type A(String s) implements String {} +{% endprettify %} + +### extension_type_implements_representation_not_supertype + +_'{0}', the representation type of '{1}', is not a supertype of '{2}', the +representation type of '{3}'._ + +#### Description + +The analyzer produces this diagnostic when an extension type implements +another extension type, and the representation type of the implemented +extension type isn't a subtype of the representation type of the implementing +extension type. + +#### Example + +The following code produces this diagnostic because the extension type `B` +implements `A`, but the representation type of `A` (`num`) isn't a +subtype of the representation type of `B` (`String`): + +{% prettify dart tag=pre+code %} +extension type A(num i) {} + +extension type B(String s) implements [!A!] {} +{% endprettify %} + +#### Common fixes + +Either change the representation types of the two extension types so that +the representation type of the implemented type is a supertype of the +representation type of the implementing type: + +{% prettify dart tag=pre+code %} +extension type A(num i) {} + +extension type B(int n) implements A {} +{% endprettify %} + +Or remove the implemented type from the implements clause: + +{% prettify dart tag=pre+code %} +extension type A(num i) {} + +extension type B(String s) {} +{% endprettify %} + +### extension_type_inherited_member_conflict + +_The extension type '{0}' has more than one distinct member named '{1}' from +implemented types._ + +#### Description + +The analyzer produces this diagnostic when an extension type implements +two or more other types, and at least two of those types declare a member +with the same name. + +#### Example + +The following code produces this diagnostic because the extension type `C` +implements both `A` and `B`, and both declare a member named `m`: + +{% prettify dart tag=pre+code %} +class A { + void m() {} +} + +extension type B(A a) { + void m() {} +} + +extension type [!C!](A a) implements A, B {} +{% endprettify %} + +#### Common fixes + +If the extension type doesn't need to implement all of the listed types, +then remove all but one of the types introducing the conflicting members: + +{% prettify dart tag=pre+code %} +class A { + void m() {} +} + +extension type B(A a) { + void m() {} +} + +extension type C(A a) implements A {} +{% endprettify %} + +If the extension type needs to implement all of the listed types but you +can rename the members in those types, then give the conflicting members +unique names: + +{% prettify dart tag=pre+code %} +class A { + void m() {} +} + +extension type B(A a) { + void n() {} +} + +extension type C(A a) implements A, B {} +{% endprettify %} + +### extension_type_representation_depends_on_itself + +_The extension type representation can't depend on itself._ + +#### Description + +The analyzer produces this diagnostic when an extension type has a +representation type that depends on the extension type itself, either +directly or indirectly. + +#### Example + +The following code produces this diagnostic because the representation +type of the extension type `A` depends on `A` directly: + +{% prettify dart tag=pre+code %} +extension type [!A!](A a) {} +{% endprettify %} + +The following two code examples produce this diagnostic because the +representation type of the extension type `A` depends on `A` +indirectly through the extension type `B`: + +{% prettify dart tag=pre+code %} +extension type [!A!](B b) {} + +extension type [!B!](A a) {} +{% endprettify %} + +{% prettify dart tag=pre+code %} +extension type [!A!](List b) {} + +extension type [!B!](List a) {} +{% endprettify %} + +#### Common fixes + +Remove the dependency by choosing a different representation type for at +least one of the types in the cycle: + +{% prettify dart tag=pre+code %} +extension type A(String s) {} +{% endprettify %} + ### external_with_initializer _External fields can't have initializers._ @@ -10186,7 +10638,7 @@ platforms: #### Common fixes If you can rely on automatic platform detection, then omit the -top-level `platforms` field. +top-level `platforms` field. {% prettify yaml tag=pre+code %} name: example @@ -14219,6 +14671,35 @@ enum E { } {% endprettify %} +### non_covariant_type_parameter_position_in_representation_type + +_An extension type parameter can't be used in a non-covariant position of its +representation type._ + +#### Description + +The analyzer produces this diagnostic when a type parameter of an +extension type is used in a non-covariant position in the representation +type of that extension type. + +#### Example + +The following code produces this diagnostic because the type parameter `T` +is used as a parameter type in the function type `void Function(T)`, and +parameters are not covariant: + +{% prettify dart tag=pre+code %} +extension type A<[!T!]>(void Function(T) f) {} +{% endprettify %} + +#### Common fixes + +Remove the use of the type parameter: + +{% prettify dart tag=pre+code %} +extension type A(void Function(String) f) {} +{% endprettify %} + ### non_exhaustive_switch_expression _The type '{0}' is not exhaustively matched by the switch cases since it doesn't @@ -16891,6 +17372,66 @@ class B implements A {} Change the type hierarchy so that there's no circularity. +### redeclare_on_non_redeclaring_member + +_The {0} doesn't redeclare a {0} declared in a superinterface._ + +#### Description + +The analyzer produces this diagnostic when a member of an extension type +is annotated with `@redeclare`, but none of the implemented interfaces +has a member with the same name. + +#### Example + +The following code produces this diagnostic because the member `n` +declared by the extension type `E` is annotated with `@redeclare`, but `C` +doesn't have a member named `n`: + +{% prettify dart tag=pre+code %} +import 'package:meta/meta.dart'; + +class C { + void m() {} +} + +extension type E(C c) implements C { + @redeclare + void [!n!]() {} +} +{% endprettify %} + +#### Common fixes + +If the annotated member has the right name, then remove the annotation: + +{% prettify dart tag=pre+code %} +class C { + void m() {} +} + +extension type E(C c) implements C { + void n() {} +} +{% endprettify %} + +If the annotated member is suppose to replace a member from the +implemented interfaces, then change the name of the annotated member to +match the member being replaced: + +{% prettify dart tag=pre+code %} +import 'package:meta/meta.dart'; + +class C { + void m() {} +} + +extension type E(C c) implements C { + @redeclare + void m() {} +} +{% endprettify %} + ### redirect_generative_to_missing_constructor _The constructor '{0}' couldn't be found in '{1}'._