@@ -14,6 +14,7 @@ import 'package:analyzer/dart/element/element.dart';
1414import 'package:analyzer/dart/element/type.dart' ;
1515import 'package:analyzer/dart/element/type_system.dart' ;
1616import 'package:analyzer/source/source_range.dart' ;
17+ import 'package:analyzer/src/dart/ast/extensions.dart' ;
1718import 'package:analyzer/src/dart/element/inheritance_manager3.dart' ;
1819import 'package:analyzer/src/dart/resolver/applicable_extensions.dart' ;
1920import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart' ;
@@ -145,28 +146,36 @@ class ImportLibrary extends MultiCorrectionProducer {
145146 List <ResolvedCorrectionProducer > _importLibrary (
146147 FixKind fixKind,
147148 Uri library, {
149+ String ? prefix,
148150 bool includeRelativeFix = false ,
149151 }) {
150152 if (! includeRelativeFix) {
151- return [_ImportAbsoluteLibrary (fixKind, library, context: context)];
153+ return [
154+ _ImportAbsoluteLibrary (fixKind, library, prefix, context: context)
155+ ];
152156 }
153157 var codeStyleOptions = getCodeStyleOptions (unitResult.file);
154158 if (codeStyleOptions.usePackageUris) {
155- return [_ImportAbsoluteLibrary (fixKind, library, context: context)];
159+ return [
160+ _ImportAbsoluteLibrary (fixKind, library, prefix, context: context)
161+ ];
156162 }
157163 if (codeStyleOptions.useRelativeUris) {
158- return [_ImportRelativeLibrary (fixKind, library, context: context)];
164+ return [
165+ _ImportRelativeLibrary (fixKind, library, prefix, context: context)
166+ ];
159167 }
160168 return [
161- _ImportAbsoluteLibrary (fixKind, library, context: context),
162- _ImportRelativeLibrary (fixKind, library, context: context),
169+ _ImportAbsoluteLibrary (fixKind, library, prefix, context: context),
170+ _ImportRelativeLibrary (fixKind, library, prefix, context: context),
163171 ];
164172 }
165173
166174 Future <List <ResolvedCorrectionProducer >> _importLibraryForElement (
167175 String name,
168- List <ElementKind > kinds,
169- ) async {
176+ List <ElementKind > kinds, {
177+ String ? prefix,
178+ }) async {
170179 // Ignore the element if the name is private.
171180 if (name.startsWith ('_' )) {
172181 return const [];
@@ -251,24 +260,36 @@ class ImportLibrary extends MultiCorrectionProducer {
251260 // Compute the fix kind.
252261 FixKind fixKind;
253262 if (libraryElement.isInSdk) {
254- fixKind = DartFixKind .IMPORT_LIBRARY_SDK ;
263+ fixKind = prefix.isEmptyOrNull
264+ ? DartFixKind .IMPORT_LIBRARY_SDK
265+ : DartFixKind .IMPORT_LIBRARY_SDK_PREFIXED ;
255266 } else if (_isLibSrcPath (librarySource.fullName)) {
256267 // Bad: non-API.
257- fixKind = DartFixKind .IMPORT_LIBRARY_PROJECT3 ;
268+ fixKind = prefix.isEmptyOrNull
269+ ? DartFixKind .IMPORT_LIBRARY_PROJECT3
270+ : DartFixKind .IMPORT_LIBRARY_PROJECT3_PREFIXED ;
258271 } else if (declaration.library != libraryElement) {
259272 // Ugly: exports.
260- fixKind = DartFixKind .IMPORT_LIBRARY_PROJECT2 ;
273+ fixKind = prefix.isEmptyOrNull
274+ ? DartFixKind .IMPORT_LIBRARY_PROJECT2
275+ : DartFixKind .IMPORT_LIBRARY_PROJECT2_PREFIXED ;
261276 } else {
262277 // Good: direct declaration.
263- fixKind = DartFixKind .IMPORT_LIBRARY_PROJECT1 ;
278+ fixKind = prefix.isEmptyOrNull
279+ ? DartFixKind .IMPORT_LIBRARY_PROJECT1
280+ : DartFixKind .IMPORT_LIBRARY_PROJECT1_PREFIXED ;
264281 }
265282 // If both files are in the same package's 'lib' folder, also include a
266283 // relative import.
267284 var includeRelativeUri = canBeRelativeImport (
268285 librarySource.uri, this .libraryElement.librarySource.uri);
269286 // Add the fix(es).
270- producers.addAll (_importLibrary (fixKind, librarySource.uri,
271- includeRelativeFix: includeRelativeUri));
287+ producers.addAll (_importLibrary (
288+ fixKind,
289+ librarySource.uri,
290+ prefix: prefix,
291+ includeRelativeFix: includeRelativeUri,
292+ ));
272293 }
273294 return producers;
274295 }
@@ -284,11 +305,9 @@ class ImportLibrary extends MultiCorrectionProducer {
284305 }
285306
286307 Future <List <ResolvedCorrectionProducer >> _producersForExtension () async {
287- if (node case SimpleIdentifier (: var name)) {
288- return await _importLibraryForElement (
289- name,
290- const [ElementKind .EXTENSION ],
291- );
308+ if (node case SimpleIdentifier (: var name, : var parent)) {
309+ return await _producersForMethodInvocation (
310+ name, parent, const [ElementKind .EXTENSION ]);
292311 }
293312
294313 return const [];
@@ -350,24 +369,70 @@ class ImportLibrary extends MultiCorrectionProducer {
350369
351370 Future <List <ResolvedCorrectionProducer >> _producersForFunction () async {
352371 if (node case SimpleIdentifier (: var name, : var parent)) {
353- if (parent is MethodInvocation ) {
354- if (parent.realTarget != null || parent.methodName != node) {
355- return const [];
372+ return await _producersForMethodInvocation (name, parent,
373+ const [ElementKind .FUNCTION , ElementKind .TOP_LEVEL_VARIABLE ]);
374+ }
375+
376+ return const [];
377+ }
378+
379+ /// Returns a list of import corrections considering the [name] and [parent] .
380+ ///
381+ /// If the [parent] is a [MethodInvocation] it can be a method invocation or
382+ /// a prefixed identifier. So we calculate both import options for this case.
383+ ///
384+ /// If we have unresolved code like `foo.bar()` then we have two options:
385+ /// - Import of some library, prefixed with `foo` , that contains a top-level
386+ /// function called bar;
387+ /// - Import of some library that contains a top-level propriety or class
388+ /// called `foo` that has a method called `bar` (has to be static for a
389+ /// _class_ with that name).
390+ Future <List <ResolvedCorrectionProducer >> _producersForMethodInvocation (
391+ String name, AstNode ? parent, List <ElementKind > kinds) async {
392+ String ? prefix;
393+ var producers = < ResolvedCorrectionProducer > [];
394+ if (parent case MethodInvocation (: var target? , : var function)) {
395+ // Getting the import library for elements with [name].
396+ producers.addAll (await _importLibraryForElement (name, kinds));
397+
398+ // Set the prefix and (maybe swap) name and get the other import library
399+ // option - with prefix!.
400+ if (target == node) {
401+ prefix = name;
402+ if (function case SimpleIdentifier (name: var realName)) {
403+ name = realName;
356404 }
405+ } else if (target case SimpleIdentifier (: var name)) {
406+ prefix = name;
407+ }
408+ } else if (parent
409+ case PrefixedIdentifier (prefix: var parentPrefix, : var identifier)) {
410+ producers.addAll (await _importLibraryForElement (name, kinds));
411+
412+ // Set the prefix and (maybe swap) name and get the other import library
413+ // option - with prefix!.
414+ if (identifier != node) {
415+ prefix = name;
416+ name = identifier.name;
417+ } else {
418+ prefix = parentPrefix.name;
357419 }
358-
359- return await _importLibraryForElement (name, const [
360- ElementKind .FUNCTION ,
361- ElementKind .TOP_LEVEL_VARIABLE ,
362- ]);
363420 }
364421
365- return const [];
422+ producers
423+ .addAll (await _importLibraryForElement (name, kinds, prefix: prefix));
424+ return producers;
366425 }
367426
368427 Future <List <ResolvedCorrectionProducer >>
369428 _producersForTopLevelVariable () async {
429+ String ? prefix;
370430 var targetNode = node;
431+ if (targetNode.parent case PrefixedIdentifier prefixed
432+ when prefixed.prefix == node) {
433+ targetNode = prefixed.identifier;
434+ prefix = prefixed.prefix.name;
435+ }
371436 if (targetNode case Annotation (: var name)) {
372437 if (name.staticElement == null ) {
373438 if (targetNode.arguments != null ) {
@@ -377,15 +442,28 @@ class ImportLibrary extends MultiCorrectionProducer {
377442 }
378443 }
379444 if (targetNode case SimpleIdentifier (: var name)) {
380- return await _importLibraryForElement (name, const [
381- ElementKind .TOP_LEVEL_VARIABLE ,
382- ]);
445+ return await _importLibraryForElement (
446+ name,
447+ const [ElementKind .TOP_LEVEL_VARIABLE ],
448+ prefix: prefix,
449+ );
383450 }
384451
385452 return const [];
386453 }
387454
388455 Future <List <ResolvedCorrectionProducer >> _producersForType () async {
456+ const kinds = [
457+ ElementKind .CLASS ,
458+ ElementKind .ENUM ,
459+ ElementKind .EXTENSION_TYPE ,
460+ ElementKind .FUNCTION_TYPE_ALIAS ,
461+ ElementKind .MIXIN ,
462+ ElementKind .TYPE_ALIAS ,
463+ ];
464+ if (node case SimpleIdentifier (: var name, : var parent)) {
465+ return await _producersForMethodInvocation (name, parent, kinds);
466+ }
389467 var targetNode = node;
390468 if (targetNode case Annotation (: var name)) {
391469 if (name.staticElement == null ) {
@@ -395,22 +473,27 @@ class ImportLibrary extends MultiCorrectionProducer {
395473 targetNode = name;
396474 }
397475 }
476+ String ? prefix;
477+ if (node case NamedType (: var importPrefix, : var parent)
478+ // Makes sure that
479+ // [ImportLibraryProject1Test.test_withClass_instanceCreation_const_namedConstructor]
480+ // and
481+ // [ImportLibraryProject1Test.test_withClass_instanceCreation_new_namedConstructor]
482+ // are not broken.
483+ when parent is ! ConstructorName ) {
484+ prefix = importPrefix? .name.lexeme;
485+ }
398486 var typeName = targetNode.nameOfType;
399487 if (typeName != null ) {
400- return await _importLibraryForElement (typeName, const [
401- ElementKind .CLASS ,
402- ElementKind .ENUM ,
403- ElementKind .EXTENSION_TYPE ,
404- ElementKind .FUNCTION_TYPE_ALIAS ,
405- ElementKind .MIXIN ,
406- ElementKind .TYPE_ALIAS ,
407- ]);
488+ return await _importLibraryForElement (typeName, kinds, prefix: prefix);
408489 }
409490 if (targetNode.mightBeImplicitConstructor) {
410491 var typeName = (targetNode as SimpleIdentifier ).name;
411- return await _importLibraryForElement (typeName, const [
412- ElementKind .CLASS ,
413- ]);
492+ return await _importLibraryForElement (
493+ typeName,
494+ const [ElementKind .CLASS ],
495+ prefix: prefix,
496+ );
414497 }
415498
416499 return const [];
@@ -420,12 +503,12 @@ class ImportLibrary extends MultiCorrectionProducer {
420503/// A correction processor that can add an import using an absolute URI.
421504class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer {
422505 final FixKind _fixKind;
423-
506+ final String ? _prefix;
424507 final Uri _library;
425508
426509 String _uriText = '' ;
427510
428- _ImportAbsoluteLibrary (this ._fixKind, this ._library,
511+ _ImportAbsoluteLibrary (this ._fixKind, this ._library, this ._prefix,
429512 {required super .context});
430513
431514 @override
@@ -434,7 +517,8 @@ class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer {
434517 CorrectionApplicability .singleLocation;
435518
436519 @override
437- List <String > get fixArguments => [_uriText];
520+ List <String > get fixArguments =>
521+ [_uriText, if (_prefix != null && _prefix.isNotEmpty) _prefix];
438522
439523 @override
440524 FixKind get fixKind => _fixKind;
@@ -443,7 +527,7 @@ class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer {
443527 Future <void > compute (ChangeBuilder builder) async {
444528 await builder.addDartFileEdit (file, (builder) {
445529 if (builder is DartFileEditBuilderImpl ) {
446- _uriText = builder.importLibraryWithAbsoluteUri (_library);
530+ _uriText = builder.importLibraryWithAbsoluteUri (_library, _prefix );
447531 }
448532 });
449533 }
@@ -614,14 +698,15 @@ class _ImportLibraryPrefix extends ResolvedCorrectionProducer {
614698/// A correction processor that can add an import using a relative URI.
615699class _ImportRelativeLibrary extends ResolvedCorrectionProducer {
616700 final FixKind _fixKind;
617-
701+ final String ? _prefix;
618702 final Uri _library;
619703
620704 String _uriText = '' ;
621705
622706 _ImportRelativeLibrary (
623707 this ._fixKind,
624- this ._library, {
708+ this ._library,
709+ this ._prefix, {
625710 required super .context,
626711 });
627712
@@ -631,7 +716,8 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer {
631716 CorrectionApplicability .singleLocation;
632717
633718 @override
634- List <String > get fixArguments => [_uriText];
719+ List <String > get fixArguments =>
720+ [_uriText, if (_prefix != null && _prefix.isNotEmpty) _prefix];
635721
636722 @override
637723 FixKind get fixKind => _fixKind;
@@ -640,7 +726,7 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer {
640726 Future <void > compute (ChangeBuilder builder) async {
641727 await builder.addDartFileEdit (file, (builder) {
642728 if (builder is DartFileEditBuilderImpl ) {
643- _uriText = builder.importLibraryWithRelativeUri (_library);
729+ _uriText = builder.importLibraryWithRelativeUri (_library, _prefix );
644730 }
645731 });
646732 }
0 commit comments