@@ -17,11 +17,57 @@ import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
1717import 'package:analyzer_plugin/utilities/range_factory.dart' ;
1818
1919class CreateMethodOrFunction extends ResolvedCorrectionProducer {
20- FixKind _fixKind = DartFixKind .CREATE_METHOD ;
20+ @override
21+ final FixKind fixKind;
2122
2223 String _functionName = '' ;
2324
24- CreateMethodOrFunction ({required super .context});
25+ /// The [Element] for the target of the node's parent, if that is a
26+ /// [PrefixedIdentifier] or [PropertyAccess] , and `null` otherwise.
27+ final Element ? _targetElement;
28+
29+ factory CreateMethodOrFunction ({required CorrectionProducerContext context}) {
30+ if (context is StubCorrectionProducerContext ) {
31+ return CreateMethodOrFunction ._(context: context);
32+ }
33+
34+ if (context.node case SimpleIdentifier node) {
35+ // Prepare the argument expression (to get the parameter).
36+ Element ? targetElement;
37+ var target = getQualifiedPropertyTarget (node);
38+ if (target == null ) {
39+ targetElement = node.enclosingInterfaceElement;
40+ } else {
41+ var targetType = target.staticType;
42+ if (targetType is InterfaceType ) {
43+ targetElement = targetType.element;
44+ } else {
45+ targetElement = switch (target) {
46+ SimpleIdentifier () => target.element,
47+ PrefixedIdentifier () => target.identifier.element,
48+ _ => null ,
49+ };
50+ }
51+ }
52+
53+ return CreateMethodOrFunction ._(
54+ context: context,
55+ targetElement: targetElement,
56+ fixKind:
57+ targetElement is InterfaceElement
58+ ? DartFixKind .CREATE_METHOD
59+ : DartFixKind .CREATE_FUNCTION ,
60+ );
61+ }
62+
63+ return CreateMethodOrFunction ._(context: context);
64+ }
65+
66+ CreateMethodOrFunction ._({
67+ required super .context,
68+ Element ? targetElement,
69+ this .fixKind = DartFixKind .CREATE_METHOD ,
70+ }) : _targetElement = targetElement;
2571
2672 @override
2773 CorrectionApplicability get applicability =>
@@ -31,103 +77,27 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer {
3177 @override
3278 List <String > get fixArguments => [_functionName];
3379
34- @override
35- FixKind get fixKind => _fixKind;
36-
3780 @override
3881 Future <void > compute (ChangeBuilder builder) async {
39- var isStatic = false ;
40- var nameNode = node;
41- if (nameNode is SimpleIdentifier ) {
42- // prepare argument expression (to get parameter)
43- InterfaceElement ? targetElement;
44- Expression argument;
82+ if (node case SimpleIdentifier node) {
4583 var target = getQualifiedPropertyTarget (node);
46- if (target != null ) {
47- var targetType = target.staticType;
48- if (targetType is InterfaceType ) {
49- targetElement = targetType.element;
50- argument = target.parent as Expression ;
51- } else if (target case SimpleIdentifier (
52- : InterfaceElement ? element,
53- : Expression parent,
54- )) {
55- isStatic = true ;
56- targetElement = element;
57- argument = parent;
58- } else if (target
59- case SimpleIdentifier identifier ||
60- PrefixedIdentifier (: var identifier)) {
61- if (identifier.element case InterfaceElement element) {
62- isStatic = true ;
63- targetElement = element;
64- argument = target.parent as Expression ;
65- } else {
66- return ;
67- }
68- } else {
69- return ;
70- }
71- } else {
72- targetElement = node.enclosingInterfaceElement;
73- argument = nameNode;
74- }
75- argument = stepUpNamedExpression (argument);
76- // should be argument of some invocation
77- // or child of an expression that is one
78- var parameterElement = argument.correspondingParameter;
79- int ? recordFieldIndex;
80- if (argument.parent case ConditionalExpression parent) {
81- if (argument == parent.condition) {
82- return ;
83- }
84- parameterElement = parent.correspondingParameter;
85- } else if (argument.parent case RecordLiteral record) {
86- parameterElement = record.correspondingParameter;
87- for (var (index, field)
88- in record.fields.whereNotType <NamedExpression >().indexed) {
89- if (field == argument) {
90- recordFieldIndex = index;
91- break ;
92- }
93- }
94- }
95- if (parameterElement == null ) {
96- return ;
97- }
98- // should be parameter of function type
99- var parameterType = parameterElement.type;
100- if (parameterType is RecordType ) {
101- // Finds the corresponding field for argument
102- if (argument is NamedExpression ) {
103- var fieldName = argument.name.label.name;
104- for (var field in parameterType.namedFields) {
105- if (field.name == fieldName) {
106- parameterType = field.type;
107- break ;
108- }
109- }
110- } else if (recordFieldIndex != null ) {
111- var field = parameterType.positionalFields[recordFieldIndex];
112- parameterType = field.type;
113- }
114- }
115- if (parameterType is InterfaceType && parameterType.isDartCoreFunction) {
116- parameterType = FunctionTypeImpl (
117- typeFormals: const [],
118- parameters: const [],
119- returnType: DynamicTypeImpl .instance,
120- nullabilitySuffix: NullabilitySuffix .none,
121- );
122- }
84+
85+ // In order to fix this by creating a function or a method,
86+ // `parameterType` should be be a function type.
87+ var parameterType = _computeParameterType (node, target);
12388 if (parameterType is ! FunctionType ) {
12489 return ;
12590 }
126- // add proposal
127- if (targetElement != null ) {
91+
92+ if (_targetElement is InterfaceElement ) {
93+ var isStatic =
94+ (target is SimpleIdentifier &&
95+ target.element is InterfaceElement ) ||
96+ (target is PrefixedIdentifier &&
97+ target.identifier.element is InterfaceElement );
12898 await _createMethod (
12999 builder,
130- targetElement ,
100+ _targetElement ,
131101 parameterType,
132102 isStatic: isStatic,
133103 );
@@ -137,6 +107,69 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer {
137107 }
138108 }
139109
110+ DartType ? _computeParameterType (SimpleIdentifier node, Expression ? target) {
111+ // `argument` should be an argument of some invocation or child of an
112+ // expression that is one.
113+ Expression argument;
114+ if (target == null ) {
115+ argument = node;
116+ } else {
117+ var targetParent = target.parent;
118+ if (targetParent is ! Expression ) {
119+ return null ;
120+ }
121+ argument = targetParent;
122+ }
123+ argument = stepUpNamedExpression (argument);
124+
125+ var parameterElement = argument.correspondingParameter;
126+ int ? recordFieldIndex;
127+ if (argument.parent case ConditionalExpression parent) {
128+ if (argument == parent.condition) {
129+ return null ;
130+ }
131+ parameterElement = parent.correspondingParameter;
132+ } else if (argument.parent case RecordLiteral record) {
133+ parameterElement = record.correspondingParameter;
134+ for (var (index, field)
135+ in record.fields.whereNotType <NamedExpression >().indexed) {
136+ if (field == argument) {
137+ recordFieldIndex = index;
138+ break ;
139+ }
140+ }
141+ }
142+ if (parameterElement == null ) {
143+ return null ;
144+ }
145+
146+ var parameterType = parameterElement.type;
147+ if (parameterType is RecordType ) {
148+ // Finds the corresponding field for argument
149+ if (argument is NamedExpression ) {
150+ var fieldName = argument.name.label.name;
151+ for (var field in parameterType.namedFields) {
152+ if (field.name == fieldName) {
153+ parameterType = field.type;
154+ break ;
155+ }
156+ }
157+ } else if (recordFieldIndex != null ) {
158+ var field = parameterType.positionalFields[recordFieldIndex];
159+ parameterType = field.type;
160+ }
161+ }
162+ if (parameterType is InterfaceType && parameterType.isDartCoreFunction) {
163+ return FunctionTypeImpl (
164+ typeFormals: const [],
165+ parameters: const [],
166+ returnType: DynamicTypeImpl .instance,
167+ nullabilitySuffix: NullabilitySuffix .none,
168+ );
169+ }
170+ return parameterType;
171+ }
172+
140173 /// Prepares proposal for creating function corresponding to the given
141174 /// [FunctionType] .
142175 Future <void > _createExecutable (
@@ -211,7 +244,6 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer {
211244 sourcePrefix,
212245 sourceSuffix,
213246 );
214- _fixKind = DartFixKind .CREATE_FUNCTION ;
215247 _functionName = name;
216248 }
217249
@@ -270,7 +302,6 @@ class CreateMethodOrFunction extends ResolvedCorrectionProducer {
270302 sourcePrefix,
271303 sourceSuffix,
272304 );
273- _fixKind = DartFixKind .CREATE_METHOD ;
274305 _functionName = name;
275306 }
276307}
0 commit comments