diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart index 1c23a6ed318..63bcc9edc5f 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart @@ -150,6 +150,9 @@ class CreateMethod extends ResolvedCorrectionProducer { } else if (targetClassElement is ExtensionTypeElement2) { var fragment = targetClassElement.firstFragment; targetNode = await getExtensionTypeDeclaration(fragment); + } else if (targetClassElement is EnumElement2) { + var fragment = targetClassElement.firstFragment; + targetNode = await getEnumDeclaration(fragment); } if (targetNode == null) { return; @@ -158,6 +161,7 @@ class CreateMethod extends ResolvedCorrectionProducer { if (target is Identifier) { staticModifier = target.element?.kind == ElementKind.CLASS || + target.element?.kind == ElementKind.ENUM || target.element?.kind == ElementKind.EXTENSION_TYPE || target.element?.kind == ElementKind.MIXIN; } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method_or_function.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method_or_function.dart index cf5120e5486..dfee37285aa 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/create_method_or_function.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method_or_function.dart @@ -36,6 +36,7 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { @override Future compute(ChangeBuilder builder) async { + var isStatic = false; var nameNode = node; if (nameNode is SimpleIdentifier) { // prepare argument expression (to get parameter) @@ -47,6 +48,13 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { if (targetType is InterfaceType) { targetElement = targetType.element3; argument = target.parent as Expression; + } else if (target case SimpleIdentifier( + :InterfaceElement2? element, + :Expression parent, + )) { + isStatic = true; + targetElement = element; + argument = parent; } else { return; } @@ -107,7 +115,12 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { } // add proposal if (targetElement != null) { - await _createMethod(builder, targetElement, parameterType); + await _createMethod( + builder, + targetElement, + parameterType, + isStatic: isStatic, + ); } else { await _createFunction(builder, parameterType); } @@ -195,8 +208,9 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { Future _createMethod( ChangeBuilder builder, InterfaceElement2 targetClassElement, - FunctionType functionType, - ) async { + FunctionType functionType, { + required bool isStatic, + }) async { var name = (node as SimpleIdentifier).name; // prepare environment var targetSource = targetClassElement.firstFragment.libraryFragment.source; @@ -211,6 +225,14 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { var fragment = targetClassElement.firstFragment; var node = targetNode = await getClassDeclaration(fragment); classMembers = node?.members; + } else if (targetClassElement is ExtensionTypeElement2) { + var fragment = targetClassElement.firstFragment; + var node = targetNode = await getExtensionTypeDeclaration(fragment); + classMembers = node?.members; + } else if (targetClassElement is EnumElement2) { + var fragment = targetClassElement.firstFragment; + var node = targetNode = await getEnumDeclaration(fragment); + classMembers = node?.members; } if (targetNode == null || classMembers == null) { return; @@ -231,7 +253,7 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer { name, targetSource.fullName, insertOffset, - inStaticContext, + isStatic || inStaticContext, prefix, sourcePrefix, sourceSuffix, diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart index 56a88680009..b15f51125e8 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart @@ -965,6 +965,7 @@ final _builtInNonLintGenerators = >{ CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT: [ AddEnumConstant.new, ChangeTo.getterOrSetter, + CreateMethodOrFunction.new, ], CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED: [ CreateConstructor.new, diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart index d9cfe6cd95e..3d4a7fd6b5a 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/create_method_test.dart @@ -728,6 +728,164 @@ class A { '''); } + Future test_enum_invocation() async { + await resolveTestCode(''' +enum E { + e1, + e2; +} + +void test(E e) { + e.bar(); +} +'''); + await assertHasFix(''' +enum E { + e1, + e2; + + void bar() {} +} + +void test(E e) { + e.bar(); +} +'''); + } + + Future test_enum_invocation_static() async { + await resolveTestCode(''' +enum E { + e1, + e2; +} + +void test() { + E.bar(); +} +'''); + await assertHasFix(''' +enum E { + e1, + e2; + + static void bar() {} +} + +void test() { + E.bar(); +} +'''); + } + + Future test_enum_tearoff() async { + await resolveTestCode(''' +enum E { + e1, + e2; +} + +void g(int Function() f) {} + +void test(E e) { + g(e.bar); +} +'''); + await assertHasFix(''' +enum E { + e1, + e2; + int bar() { + } +} + +void g(int Function() f) {} + +void test(E e) { + g(e.bar); +} +'''); + } + + Future test_enum_tearoff_static() async { + await resolveTestCode(''' +enum E { + e1, + e2; +} + +void g(int Function() f) {} + +void test() { + g(E.bar); +} +'''); + await assertHasFix(''' +enum E { + e1, + e2; + static int bar() { + } +} + +void g(int Function() f) {} + +void test() { + g(E.bar); +} +'''); + } + + Future test_extensionType_tearoff() async { + await resolveTestCode(''' +extension type E(int i) { +} + +void g(int Function() f) {} + +void test(E e) { + g(e.bar); +} +'''); + await assertHasFix(''' +extension type E(int i) { + int bar() { + } +} + +void g(int Function() f) {} + +void test(E e) { + g(e.bar); +} +'''); + } + + Future test_extensionType_tearoff_static() async { + await resolveTestCode(''' +extension type E(int i) { +} + +void g(int Function() f) {} + +void test() { + g(E.bar); +} +'''); + await assertHasFix(''' +extension type E(int i) { + static int bar() { + } +} + +void g(int Function() f) {} + +void test() { + g(E.bar); +} +'''); + } + Future test_functionType_argument() async { await resolveTestCode(''' class A { @@ -1465,14 +1623,4 @@ void f() { } '''); } - - Future test_targetIsEnum() async { - await resolveTestCode(''' -enum MyEnum {A, B} -void f() { - MyEnum.foo(); -} -'''); - await assertNoFix(); - } } diff --git a/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart b/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart index 890b16b6273..9463fb86475 100644 --- a/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart +++ b/pkg/analysis_server_plugin/lib/edit/dart/correction_producer.dart @@ -429,6 +429,17 @@ abstract class ResolvedCorrectionProducer return null; } + /// Returns the class declaration for the given [fragment], or `null` if there + /// is no such class. + Future getEnumDeclaration(EnumFragment fragment) async { + var result = await sessionHelper.getFragmentDeclaration(fragment); + var node = result?.node; + if (node is EnumDeclaration) { + return node; + } + return null; + } + /// Returns the extension declaration for the given [fragment], or `null` if /// there is no such extension. Future getExtensionDeclaration(