[DAS] Fixes create method for enums and extension types
Fixes: https://github.com/dart-lang/sdk/issues/60562 Change-Id: I8bbc92205f5900c025e9dc31110f3e1cb2343643 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/423240 Reviewed-by: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Auto-Submit: Felipe Morschel <git@fmorschel.dev> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+26
-4
@@ -36,6 +36,7 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer {
|
||||
|
||||
@override
|
||||
Future<void> 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<void> _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,
|
||||
|
||||
@@ -965,6 +965,7 @@ final _builtInNonLintGenerators = <ErrorCode, List<ProducerGenerator>>{
|
||||
CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT: [
|
||||
AddEnumConstant.new,
|
||||
ChangeTo.getterOrSetter,
|
||||
CreateMethodOrFunction.new,
|
||||
],
|
||||
CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED: [
|
||||
CreateConstructor.new,
|
||||
|
||||
@@ -728,6 +728,164 @@ class A {
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> 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<void> 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<void> 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<void> 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<void> 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<void> 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<void> test_functionType_argument() async {
|
||||
await resolveTestCode('''
|
||||
class A {
|
||||
@@ -1465,14 +1623,4 @@ void f() {
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_targetIsEnum() async {
|
||||
await resolveTestCode('''
|
||||
enum MyEnum {A, B}
|
||||
void f() {
|
||||
MyEnum.foo();
|
||||
}
|
||||
''');
|
||||
await assertNoFix();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<EnumDeclaration?> 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<ExtensionDeclaration?> getExtensionDeclaration(
|
||||
|
||||
Reference in New Issue
Block a user