33// BSD-style license that can be found in the LICENSE file.
44
55import 'package:analysis_server/src/services/correction/fix.dart' ;
6+ import 'package:analysis_server/src/services/correction/util.dart' ;
67import 'package:analysis_server_plugin/edit/dart/correction_producer.dart' ;
7- import 'package:analyzer/dart/analysis/results.dart' ;
88import 'package:analyzer/dart/ast/ast.dart' ;
99import 'package:analyzer/dart/element/element.dart' ;
1010import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart' ;
@@ -88,14 +88,48 @@ class CreateMethod extends ResolvedCorrectionProducer {
8888 }
8989
9090 Future <void > _createMethod (ChangeBuilder builder) async {
91- if (node is ! SimpleIdentifier || node.parent is ! MethodInvocation ) {
92- return ;
93- }
91+ if (node is ! SimpleIdentifier ) return ;
9492 _memberName = (node as SimpleIdentifier ).name;
95- var invocation = node.parent as MethodInvocation ;
93+
94+ var invocation = node.parent;
95+ switch (invocation) {
96+ case MethodInvocation ():
97+ await _createMethodFromMethodInvocation (builder, invocation);
98+ case DotShorthandInvocation ():
99+ await _createMethodFromDotShorthandInvocation (builder, invocation);
100+ }
101+ }
102+
103+ Future <void > _createMethodFromDotShorthandInvocation (
104+ ChangeBuilder builder,
105+ DotShorthandInvocation invocation,
106+ ) async {
107+ var targetClassElement = computeDotShorthandContextTypeElement (
108+ invocation,
109+ unitResult.libraryElement,
110+ );
111+ if (targetClassElement == null ) return ;
112+
113+ var targetNode = await _declarationNodeFromElement (targetClassElement);
114+ if (targetNode is ! CompilationUnitMember ) return ;
115+
116+ await _writeMethod (
117+ builder,
118+ invocation,
119+ invocation.argumentList,
120+ targetClassElement.firstFragment,
121+ targetNode,
122+ hasStaticModifier: true ,
123+ );
124+ }
125+
126+ Future <void > _createMethodFromMethodInvocation (
127+ ChangeBuilder builder,
128+ MethodInvocation invocation,
129+ ) async {
96130 // Prepare environment.
97131 Fragment ? targetFragment;
98- var staticModifier = false ;
132+ var hasStaticModifier = false ;
99133
100134 CompilationUnitMember ? targetNode;
101135 var target = invocation.realTarget;
@@ -117,7 +151,7 @@ class CreateMethod extends ResolvedCorrectionProducer {
117151 if (enclosingMemberParent is CompilationUnitMember &&
118152 enclosingMemberParent is ! ExtensionDeclaration ) {
119153 targetNode = enclosingMemberParent;
120- staticModifier = switch (enclosingMember) {
154+ hasStaticModifier = switch (enclosingMember) {
121155 ConstructorDeclaration (: var factoryKeyword) => factoryKeyword != null ,
122156 MethodDeclaration (: var isStatic) => isStatic,
123157 FieldDeclaration (
@@ -129,64 +163,72 @@ class CreateMethod extends ResolvedCorrectionProducer {
129163 }
130164 } else {
131165 var targetClassElement = getTargetInterfaceElement (target);
132- if (targetClassElement == null ) {
133- return ;
134- }
166+ if (targetClassElement == null ) return ;
135167 targetFragment = targetClassElement.firstFragment;
136- if (targetClassElement.library.isInSdk) {
137- return ;
138- }
139- // Prepare target ClassDeclaration.
140- if (targetClassElement is MixinElement ) {
141- var fragment = targetClassElement.firstFragment;
142- targetNode = await getMixinDeclaration (fragment);
143- } else if (targetClassElement is ClassElement ) {
144- var fragment = targetClassElement.firstFragment;
145- targetNode = await getClassDeclaration (fragment);
146- } else if (targetClassElement is ExtensionTypeElement ) {
147- var fragment = targetClassElement.firstFragment;
148- targetNode = await getExtensionTypeDeclaration (fragment);
149- } else if (targetClassElement is EnumElement ) {
150- var fragment = targetClassElement.firstFragment;
151- targetNode = await getEnumDeclaration (fragment);
152- }
153- if (targetNode == null ) {
154- return ;
155- }
168+
169+ targetNode = await _declarationNodeFromElement (targetClassElement);
170+ if (targetNode == null ) return ;
171+
156172 // Maybe static.
157173 if (target is Identifier ) {
158- staticModifier =
174+ hasStaticModifier =
159175 target.element? .kind == ElementKind .CLASS ||
160176 target.element? .kind == ElementKind .ENUM ||
161177 target.element? .kind == ElementKind .EXTENSION_TYPE ||
162178 target.element? .kind == ElementKind .MIXIN ;
163179 }
164- // Use different utils.
165- var targetPath = targetFragment.libraryFragment! .source.fullName;
166- var targetResolveResult = await unitResult.session.getResolvedUnit (
167- targetPath,
168- );
169- if (targetResolveResult is ! ResolvedUnitResult ) {
170- return ;
171- }
172180 }
173- var targetSource = targetFragment? .libraryFragment! .source;
174- if (targetSource == null ) {
175- return ;
181+ await _writeMethod (
182+ builder,
183+ invocation,
184+ invocation.argumentList,
185+ targetFragment,
186+ targetNode,
187+ hasStaticModifier: hasStaticModifier,
188+ );
189+ }
190+
191+ Future <CompilationUnitMember ?> _declarationNodeFromElement (
192+ InterfaceElement element,
193+ ) async {
194+ if (element.library.isInSdk) return null ;
195+ if (element is MixinElement ) {
196+ var fragment = element.firstFragment;
197+ return await getMixinDeclaration (fragment);
198+ } else if (element is ClassElement ) {
199+ var fragment = element.firstFragment;
200+ return await getClassDeclaration (fragment);
201+ } else if (element is ExtensionTypeElement ) {
202+ var fragment = element.firstFragment;
203+ return await getExtensionTypeDeclaration (fragment);
204+ } else if (element is EnumElement ) {
205+ var fragment = element.firstFragment;
206+ return await getEnumDeclaration (fragment);
176207 }
208+ return null ;
209+ }
210+
211+ /// Inserts the new method into the source code.
212+ Future <void > _writeMethod (
213+ ChangeBuilder builder,
214+ Expression invocation,
215+ ArgumentList argumentList,
216+ Fragment ? targetFragment,
217+ CompilationUnitMember ? targetNode, {
218+ required bool hasStaticModifier,
219+ }) async {
220+ var targetSource = targetFragment? .libraryFragment! .source;
221+ if (targetSource == null ) return ;
222+
177223 var targetFile = targetSource.fullName;
178- // Build method source.
179224 await builder.addDartFileEdit (targetFile, (builder) {
180- if (targetNode == null ) {
181- return ;
182- }
225+ if (targetNode == null ) return ;
183226 builder.insertMethod (targetNode, (builder) {
184227 // Maybe 'static'.
185- if (staticModifier ) {
228+ if (hasStaticModifier ) {
186229 builder.write ('static ' );
187230 }
188231 // Append return type.
189-
190232 var type = inferUndefinedExpressionType (invocation);
191233 if (builder.writeType (type, groupName: 'RETURN_TYPE' )) {
192234 builder.write (' ' );
@@ -197,7 +239,7 @@ class CreateMethod extends ResolvedCorrectionProducer {
197239 builder.write (_memberName);
198240 });
199241 builder.write ('(' );
200- builder.writeParametersMatchingArguments (invocation. argumentList);
242+ builder.writeParametersMatchingArguments (argumentList);
201243 builder.write (')' );
202244 if (type? .isDartAsyncFuture == true ) {
203245 builder.write (' async' );
0 commit comments