From 06caa3fa11e9fe71e8037d3131ed9ac814b0deda Mon Sep 17 00:00:00 2001 From: FMorschel Date: Mon, 2 Dec 2024 18:54:59 +0000 Subject: [PATCH] [DAS] Adds new import with show option R= srawlins@google.com Fixes https://github.com/dart-lang/sdk/issues/32234 Fixes https://github.com/dart-lang/sdk/issues/55842 Change-Id: I3acb03cc6d9a5f8bc1ebaf590a45ac5ee10388f8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/396564 Auto-Submit: Felipe Morschel Commit-Queue: Phil Quitslund Reviewed-by: Samuel Rawlins Reviewed-by: Phil Quitslund --- .../correction/dart/import_library.dart | 90 ++- .../lib/src/services/correction/fix.dart | 42 +- pkg/analysis_server/test/edit/fixes_test.dart | 7 +- .../test/integration/edit/get_fixes_test.dart | 2 +- .../fix/import_library_project_test.dart | 698 +++++++++++++++++- .../fix/import_library_sdk_test.dart | 48 ++ .../change_builder/change_builder_dart.dart | 31 +- 7 files changed, 881 insertions(+), 37 deletions(-) diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart index 63fe73c806cd..ede462542391 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart @@ -26,11 +26,6 @@ import 'package:analyzer_plugin/utilities/range_factory.dart'; class ImportLibrary extends MultiCorrectionProducer { final _ImportKind _importKind; - /// Initialize a newly created instance that will add an import of - /// `dart:async`. - ImportLibrary.dartAsync({required super.context}) - : _importKind = _ImportKind.dartAsync; - /// Initialize a newly created instance that will add an import for an /// extension. ImportLibrary.forExtension({required super.context}) @@ -65,10 +60,6 @@ class ImportLibrary extends MultiCorrectionProducer { @override Future> get producers async { return switch (_importKind) { - _ImportKind.dartAsync => _importLibrary( - DartFixKind.IMPORT_ASYNC, - Uri.parse('dart:async'), - ), _ImportKind.forExtension => await _producersForExtension(), _ImportKind.forExtensionMember => await _producersForExtensionMember(), _ImportKind.forExtensionType => await _producersForExtensionType(), @@ -154,29 +145,66 @@ class ImportLibrary extends MultiCorrectionProducer { /// Otherwise, both are returned in the order: absolute, relative. List _importLibrary( FixKind fixKind, - Uri library, { + FixKind fixKindShow, + Uri library, + String name, { String? prefix, bool includeRelativeFix = false, }) { if (!includeRelativeFix) { return [ _ImportAbsoluteLibrary(fixKind, library, prefix, context: context), + _ImportAbsoluteLibrary( + fixKindShow, + library, + prefix, + show: name, + context: context, + ), ]; } var codeStyleOptions = getCodeStyleOptions(unitResult.file); if (codeStyleOptions.usePackageUris) { return [ _ImportAbsoluteLibrary(fixKind, library, prefix, context: context), + _ImportAbsoluteLibrary( + fixKindShow, + library, + prefix, + show: name, + context: context, + ), ]; } if (codeStyleOptions.useRelativeUris) { return [ _ImportRelativeLibrary(fixKind, library, prefix, context: context), + _ImportRelativeLibrary( + fixKindShow, + library, + prefix, + show: name, + context: context, + ), ]; } return [ _ImportAbsoluteLibrary(fixKind, library, prefix, context: context), + _ImportAbsoluteLibrary( + fixKindShow, + library, + prefix, + show: name, + context: context, + ), _ImportRelativeLibrary(fixKind, library, prefix, context: context), + _ImportRelativeLibrary( + fixKindShow, + library, + prefix, + show: name, + context: context, + ), ]; } @@ -282,29 +310,46 @@ class ImportLibrary extends MultiCorrectionProducer { } // Compute the fix kind. FixKind fixKind; + FixKind fixKindShow; if (libraryElement.isInSdk) { fixKind = prefix.isEmptyOrNull ? DartFixKind.IMPORT_LIBRARY_SDK : DartFixKind.IMPORT_LIBRARY_SDK_PREFIXED; + fixKindShow = + prefix.isEmptyOrNull + ? DartFixKind.IMPORT_LIBRARY_SDK_SHOW + : DartFixKind.IMPORT_LIBRARY_SDK_PREFIXED_SHOW; } else if (_isLibSrcPath(librarySource.fullName)) { // Bad: non-API. fixKind = prefix.isEmptyOrNull ? DartFixKind.IMPORT_LIBRARY_PROJECT3 : DartFixKind.IMPORT_LIBRARY_PROJECT3_PREFIXED; + fixKindShow = + prefix.isEmptyOrNull + ? DartFixKind.IMPORT_LIBRARY_PROJECT3_SHOW + : DartFixKind.IMPORT_LIBRARY_PROJECT3_PREFIXED_SHOW; } else if (declaration.library != libraryElement) { // Ugly: exports. fixKind = prefix.isEmptyOrNull ? DartFixKind.IMPORT_LIBRARY_PROJECT2 : DartFixKind.IMPORT_LIBRARY_PROJECT2_PREFIXED; + fixKindShow = + prefix.isEmptyOrNull + ? DartFixKind.IMPORT_LIBRARY_PROJECT2_SHOW + : DartFixKind.IMPORT_LIBRARY_PROJECT2_PREFIXED_SHOW; } else { // Good: direct declaration. fixKind = prefix.isEmptyOrNull ? DartFixKind.IMPORT_LIBRARY_PROJECT1 : DartFixKind.IMPORT_LIBRARY_PROJECT1_PREFIXED; + fixKindShow = + prefix.isEmptyOrNull + ? DartFixKind.IMPORT_LIBRARY_PROJECT1_SHOW + : DartFixKind.IMPORT_LIBRARY_PROJECT1_PREFIXED_SHOW; } // If both files are in the same package's 'lib' folder, also include a // relative import. @@ -316,7 +361,9 @@ class ImportLibrary extends MultiCorrectionProducer { producers.addAll( _importLibrary( fixKind, + fixKindShow, librarySource.uri, + name, prefix: prefix, includeRelativeFix: includeRelativeUri, ), @@ -543,6 +590,7 @@ class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer { final FixKind _fixKind; final String? _prefix; final Uri _library; + final String? _show; String _uriText = ''; @@ -550,8 +598,9 @@ class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer { this._fixKind, this._library, this._prefix, { + String? show, required super.context, - }); + }) : _show = show; @override CorrectionApplicability get applicability => @@ -572,14 +621,18 @@ class _ImportAbsoluteLibrary extends ResolvedCorrectionProducer { Future compute(ChangeBuilder builder) async { await builder.addDartFileEdit(file, (builder) { if (builder is DartFileEditBuilderImpl) { - _uriText = builder.importLibraryWithAbsoluteUri(_library, _prefix); + _uriText = builder.importLibraryWithAbsoluteUri( + _library, + prefix: _prefix, + shownName: _show, + useShow: _show != null, + ); } }); } } enum _ImportKind { - dartAsync, forExtension, forExtensionMember, forExtensionType, @@ -783,6 +836,7 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer { final FixKind _fixKind; final String? _prefix; final Uri _library; + final String? _show; String _uriText = ''; @@ -790,8 +844,9 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer { this._fixKind, this._library, this._prefix, { + String? show, required super.context, - }); + }) : _show = show; @override CorrectionApplicability get applicability => @@ -812,7 +867,12 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer { Future compute(ChangeBuilder builder) async { await builder.addDartFileEdit(file, (builder) { if (builder is DartFileEditBuilderImpl) { - _uriText = builder.importLibraryWithRelativeUri(_library, _prefix); + _uriText = builder.importLibraryWithRelativeUri( + _library, + prefix: _prefix, + shownName: _show, + useShow: _show != null, + ); } }); } diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart index 845b93b4a408..7d090430041b 100644 --- a/pkg/analysis_server/lib/src/services/correction/fix.dart +++ b/pkg/analysis_server/lib/src/services/correction/fix.dart @@ -844,6 +844,16 @@ abstract final class DartFixKind { DartFixKindPriority.standard + 3, "Import library '{0}' with prefix '{1}'", ); + static const IMPORT_LIBRARY_PROJECT1_PREFIXED_SHOW = FixKind( + 'dart.fix.import.libraryProject1PrefixedShow', + DartFixKindPriority.standard + 3, + "Import library '{0}' with prefix '{1}' and 'show'", + ); + static const IMPORT_LIBRARY_PROJECT1_SHOW = FixKind( + 'dart.fix.import.libraryProject1Show', + DartFixKindPriority.standard + 3, + "Import library '{0}' with 'show'", + ); static const IMPORT_LIBRARY_PROJECT2 = FixKind( 'dart.fix.import.libraryProject2', DartFixKindPriority.standard + 2, @@ -854,6 +864,16 @@ abstract final class DartFixKind { DartFixKindPriority.standard + 2, "Import library '{0}' with prefix '{1}'", ); + static const IMPORT_LIBRARY_PROJECT2_PREFIXED_SHOW = FixKind( + 'dart.fix.import.libraryProject2PrefixedShow', + DartFixKindPriority.standard + 2, + "Import library '{0}' with prefix '{1}' and 'show'", + ); + static const IMPORT_LIBRARY_PROJECT2_SHOW = FixKind( + 'dart.fix.import.libraryProject2Show', + DartFixKindPriority.standard + 2, + "Import library '{0}' with 'show'", + ); static const IMPORT_LIBRARY_PROJECT3 = FixKind( 'dart.fix.import.libraryProject3', DartFixKindPriority.standard + 1, @@ -864,16 +884,36 @@ abstract final class DartFixKind { DartFixKindPriority.standard + 1, "Import library '{0}' with prefix '{1}'", ); + static const IMPORT_LIBRARY_PROJECT3_PREFIXED_SHOW = FixKind( + 'dart.fix.import.libraryProject3PrefixedShow', + DartFixKindPriority.standard + 1, + "Import library '{0}' with prefix '{1}' and 'show'", + ); + static const IMPORT_LIBRARY_PROJECT3_SHOW = FixKind( + 'dart.fix.import.libraryProject3Show', + DartFixKindPriority.standard + 1, + "Import library '{0}' with 'show'", + ); static const IMPORT_LIBRARY_SDK = FixKind( 'dart.fix.import.librarySdk', DartFixKindPriority.standard + 4, "Import library '{0}'", ); static const IMPORT_LIBRARY_SDK_PREFIXED = FixKind( - 'dart.fix.import.librarySdk', + 'dart.fix.import.librarySdkPrefixed', DartFixKindPriority.standard + 4, "Import library '{0}' with prefix '{1}'", ); + static const IMPORT_LIBRARY_SDK_PREFIXED_SHOW = FixKind( + 'dart.fix.import.librarySdkPrefixedShow', + DartFixKindPriority.standard + 4, + "Import library '{0}' with prefix '{1}' and 'show'", + ); + static const IMPORT_LIBRARY_SDK_SHOW = FixKind( + 'dart.fix.import.librarySdkShow', + DartFixKindPriority.standard + 4, + "Import library '{0}' with 'show'", + ); static const INLINE_INVOCATION = FixKind( 'dart.fix.inlineInvocation', DartFixKindPriority.standard - 20, diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart index 12db6b7fbfc4..e30f5dcfd620 100644 --- a/pkg/analysis_server/test/edit/fixes_test.dart +++ b/pkg/analysis_server/test/edit/fixes_test.dart @@ -89,10 +89,11 @@ void f() { var errorFixes = await _getFixesAt(testFile, 'Completer'); expect(errorFixes, hasLength(1)); var fixes = errorFixes[0].fixes; - expect(fixes, hasLength(3)); + expect(fixes, hasLength(4)); expect(fixes[0].message, matches('Import library')); - expect(fixes[1].message, matches('Create class')); - expect(fixes[2].message, matches('Create mixin')); + expect(fixes[1].message, matches("Import library .+ with 'show'")); + expect(fixes[2].message, matches('Create class')); + expect(fixes[3].message, matches('Create mixin')); } Future test_fromPlugins() async { diff --git a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart index a3265de4e7fd..d4fc54452153 100644 --- a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart +++ b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart @@ -36,7 +36,7 @@ FutureOr f; // expect a suggestion to add the dart:async import expect(fix.fixes, isNotEmpty); - var change = fix.fixes.singleWhere( + var change = fix.fixes.firstWhere( (SourceChange change) => change.message.startsWith('Import '), ); expect(change.edits, hasLength(1)); diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart index 665e7505d71e..558ec02c215a 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart @@ -13,11 +13,17 @@ import 'fix_processor.dart'; void main() { defineReflectiveSuite(() { defineReflectiveTests(ImportLibraryProject1PrefixedTest); + defineReflectiveTests(ImportLibraryProject1PrefixedWithShowTest); defineReflectiveTests(ImportLibraryProject1Test); + defineReflectiveTests(ImportLibraryProject1WithShowTest); defineReflectiveTests(ImportLibraryProject2PrefixedTest); + defineReflectiveTests(ImportLibraryProject2PrefixedWithShowTest); defineReflectiveTests(ImportLibraryProject2Test); + defineReflectiveTests(ImportLibraryProject2WithShowTest); defineReflectiveTests(ImportLibraryProject3PrefixedTest); + defineReflectiveTests(ImportLibraryProject3PrefixedWithShowTest); defineReflectiveTests(ImportLibraryProject3Test); + defineReflectiveTests(ImportLibraryProject3WithShowTest); }); } @@ -154,6 +160,139 @@ void f() { } } +@reflectiveTest +class ImportLibraryProject1PrefixedWithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1_PREFIXED_SHOW; + + Future test_prefixed_class() async { + newFile('$testPackageLibPath/lib.dart', ''' +class A {} +'''); + await resolveTestCode(''' +void f() { + prefix.A? a; + print('\$a'); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as prefix show A; + +void f() { + prefix.A? a; + print('\$a'); +} +'''); + } + + Future test_prefixed_constant() async { + newFile('$testPackageLibPath/lib.dart', ''' +const value = 0; +'''); + await resolveTestCode(''' +void f() { + lib.value; +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as lib show value; + +void f() { + lib.value; +} +'''); + } + + Future test_prefixed_extension_constructor() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension A on int {} +'''); + await resolveTestCode(''' +void f(int i) { + prefix.A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as prefix show A; + +void f(int i) { + prefix.A(i); +} +'''); + } + + Future test_prefixed_extensionType() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension type A(int _) {} +'''); + await resolveTestCode(''' +void f(a.A a) { +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as a show A; + +void f(a.A a) { +} +'''); + } + + Future test_prefixed_extensionType_constructor() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension type A(int _) {} +'''); + await resolveTestCode(''' +void f(int i) { + prefix.A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as prefix show A; + +void f(int i) { + prefix.A(i); +} +'''); + } + + Future test_prefixed_function() async { + newFile('$testPackageLibPath/lib.dart', ''' +void foo() {} +'''); + await resolveTestCode(''' +void f() { + prefix.foo(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as prefix show foo; + +void f() { + prefix.foo(); +} +'''); + } + + Future test_withEnum_value() async { + newFile('$testPackageLibPath/lib.dart', ''' +library lib; +enum E { one, two } +'''); + await resolveTestCode(''' +void f() { + lib.E.one; +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' as lib show E; + +void f() { + lib.E.one; +} +'''); + } +} + @reflectiveTest class ImportLibraryProject1Test extends FixProcessorTest { @override @@ -1623,6 +1762,139 @@ void f() { } } +@reflectiveTest +class ImportLibraryProject1WithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1_SHOW; + + Future test_prefixed_class() async { + newFile('$testPackageLibPath/lib.dart', ''' +class A {} +'''); + await resolveTestCode(''' +void f() { + A? a; + print('\$a'); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show A; + +void f() { + A? a; + print('\$a'); +} +'''); + } + + Future test_prefixed_constant() async { + newFile('$testPackageLibPath/lib.dart', ''' +const value = 0; +'''); + await resolveTestCode(''' +void f() { + value; +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show value; + +void f() { + value; +} +'''); + } + + Future test_prefixed_extension_constructor() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension A on int {} +'''); + await resolveTestCode(''' +void f(int i) { + A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show A; + +void f(int i) { + A(i); +} +'''); + } + + Future test_prefixed_extensionType() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension type A(int _) {} +'''); + await resolveTestCode(''' +void f(A a) { +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show A; + +void f(A a) { +} +'''); + } + + Future test_prefixed_extensionType_constructor() async { + newFile('$testPackageLibPath/lib.dart', ''' +extension type A(int _) {} +'''); + await resolveTestCode(''' +void f(int i) { + A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show A; + +void f(int i) { + A(i); +} +'''); + } + + Future test_prefixed_function() async { + newFile('$testPackageLibPath/lib.dart', ''' +void foo() {} +'''); + await resolveTestCode(''' +void f() { + foo(); +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show foo; + +void f() { + foo(); +} +'''); + } + + Future test_withEnum_value() async { + newFile('$testPackageLibPath/lib.dart', ''' +library lib; +enum E { one, two } +'''); + await resolveTestCode(''' +void f() { + E.one; +} +'''); + await assertHasFix(''' +import 'package:test/lib.dart' show E; + +void f() { + E.one; +} +'''); + } +} + @reflectiveTest class ImportLibraryProject2PrefixedTest extends FixProcessorTest { @override @@ -1756,24 +2028,156 @@ void f() { } @reflectiveTest -class ImportLibraryProject2Test extends FixProcessorTest { +class ImportLibraryProject2PrefixedWithShowTest extends FixProcessorTest { @override - FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2; + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2_PREFIXED_SHOW; - Future test_lib() async { - newFile('$packagesRootPath/my_pkg/lib/a.dart', ''' -export 'b.dart'; + Future test_prefixed_class() async { + newFile('$testPackageLibPath/lib1.dart', ''' +class A {} '''); - newFile('$packagesRootPath/my_pkg/lib/b.dart', ''' -class Test {} + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; '''); + await resolveTestCode(''' +void f() { + prefix.A? a; + print('\$a'); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as prefix show A; + +void f() { + prefix.A? a; + print('\$a'); +} +'''); + } + + Future test_prefixed_constant() async { + newFile('$testPackageLibPath/lib1.dart', ''' +const value = 0; +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f() { + lib.value; +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as lib show value; + +void f() { + lib.value; +} +'''); + } + + Future test_prefixed_extension_constructor() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension A on int {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(int i) { + prefix.A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as prefix show A; + +void f(int i) { + prefix.A(i); +} +'''); + } + + Future test_prefixed_extensionType() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension type A(int _) {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(a.A a) { +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as a show A; + +void f(a.A a) { +} +'''); + } + + Future test_prefixed_extensionType_constructor() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension type A(int _) {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(int i) { + prefix.A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as prefix show A; + +void f(int i) { + prefix.A(i); +} +'''); + } + + Future test_prefixed_function() async { + newFile('$testPackageLibPath/lib1.dart', ''' +void foo() {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f() { + prefix.foo(); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' as prefix show foo; + +void f() { + prefix.foo(); +} +'''); + } +} + +@reflectiveTest +class ImportLibraryProject2Test extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2; + + Future test_lib() async { + newFile('$packagesRootPath/my_pkg/lib/a.dart', ''' +export 'b.dart'; +'''); + newFile('$packagesRootPath/my_pkg/lib/b.dart', ''' +class Test {} +'''); + + writeTestPackageConfig( + config: + PackageConfigFileBuilder() + ..add(name: 'my_pkg', rootPath: '$packagesRootPath/my_pkg'), + ); - writeTestPackageConfig( - config: - PackageConfigFileBuilder() - ..add(name: 'my_pkg', rootPath: '$packagesRootPath/my_pkg'), - ); - newPubspecYamlFile('/home/test', r''' dependencies: my_pkg: any @@ -1863,6 +2267,138 @@ f() { } } +@reflectiveTest +class ImportLibraryProject2WithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2_SHOW; + + Future test_prefixed_class() async { + newFile('$testPackageLibPath/lib1.dart', ''' +class A {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f() { + A? a; + print('\$a'); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show A; + +void f() { + A? a; + print('\$a'); +} +'''); + } + + Future test_prefixed_constant() async { + newFile('$testPackageLibPath/lib1.dart', ''' +const value = 0; +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f() { + value; +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show value; + +void f() { + value; +} +'''); + } + + Future test_prefixed_extension_constructor() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension A on int {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(int i) { + A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show A; + +void f(int i) { + A(i); +} +'''); + } + + Future test_prefixed_extensionType() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension type A(int _) {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(A a) { +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show A; + +void f(A a) { +} +'''); + } + + Future test_prefixed_extensionType_constructor() async { + newFile('$testPackageLibPath/lib1.dart', ''' +extension type A(int _) {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f(int i) { + A(i); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show A; + +void f(int i) { + A(i); +} +'''); + } + + Future test_prefixed_function() async { + newFile('$testPackageLibPath/lib1.dart', ''' +void foo() {} +'''); + newFile('$testPackageLibPath/lib2.dart', ''' +export 'package:test/lib1.dart'; +'''); + await resolveTestCode(''' +void f() { + foo(); +} +'''); + await assertHasFix(''' +import 'package:test/lib2.dart' show foo; + +void f() { + foo(); +} +'''); + } +} + @reflectiveTest class ImportLibraryProject3PrefixedTest extends FixProcessorTest { @override @@ -1931,6 +2467,74 @@ void f(lib.Test t) {} } } +@reflectiveTest +class ImportLibraryProject3PrefixedWithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT3_PREFIXED_SHOW; + + Future test_inLibSrc_thisContextRoot_extension() async { + newFile('$testPackageLibPath/src/lib.dart', ''' +extension E on int { + static String m() => ''; +} +'''); + await resolveTestCode(''' +f() { + print(lib.E.m()); +} +'''); + await assertHasFix(''' +import 'package:test/src/lib.dart' as lib show E; + +f() { + print(lib.E.m()); +} +'''); + } + + Future test_withClass_pub_this_inLib_includesThisSrc() async { + updateTestPubspecFile(r''' +name: test +'''); + + newFile('$testPackageLibPath/src/a.dart', r''' +class Test {} +'''); + + await resolveTestCode(''' +void f(lib.Test t) {} +'''); + + await assertHasFix(''' +import 'package:test/src/a.dart' as lib show Test; + +void f(lib.Test t) {} +'''); + } + + Future test_withClass_pub_this_inTest_includesThisSrc() async { + updateTestPubspecFile(r''' +name: test +'''); + + newFile('$testPackageLibPath/src/a.dart', r''' +class Test {} +'''); + + var b = newFile('$testPackageTestPath/b.dart', r''' +void f(lib.Test t) {} +'''); + + await getResolvedUnit(b); + + await assertHasFix(''' +import 'package:test/src/a.dart' as lib show Test; + +void f(lib.Test t) {} +''', target: b.path); + } +} + @reflectiveTest class ImportLibraryProject3Test extends FixProcessorTest { @override @@ -1998,3 +2602,71 @@ void f(Test t) {} ''', target: b.path); } } + +@reflectiveTest +class ImportLibraryProject3WithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT3_SHOW; + + Future test_inLibSrc_thisContextRoot_extension() async { + newFile('$testPackageLibPath/src/lib.dart', ''' +extension E on int { + static String m() => ''; +} +'''); + await resolveTestCode(''' +f() { + print(E.m()); +} +'''); + await assertHasFix(''' +import 'package:test/src/lib.dart' show E; + +f() { + print(E.m()); +} +'''); + } + + Future test_withClass_pub_this_inLib_includesThisSrc() async { + updateTestPubspecFile(r''' +name: test +'''); + + newFile('$testPackageLibPath/src/a.dart', r''' +class Test {} +'''); + + await resolveTestCode(''' +void f(Test t) {} +'''); + + await assertHasFix(''' +import 'package:test/src/a.dart' show Test; + +void f(Test t) {} +'''); + } + + Future test_withClass_pub_this_inTest_includesThisSrc() async { + updateTestPubspecFile(r''' +name: test +'''); + + newFile('$testPackageLibPath/src/a.dart', r''' +class Test {} +'''); + + var b = newFile('$testPackageTestPath/b.dart', r''' +void f(Test t) {} +'''); + + await getResolvedUnit(b); + + await assertHasFix(''' +import 'package:test/src/a.dart' show Test; + +void f(Test t) {} +''', target: b.path); + } +} diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart index 28d7ec5b70c2..7b8981da8ec2 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart @@ -12,7 +12,9 @@ import 'fix_processor.dart'; void main() { defineReflectiveSuite(() { defineReflectiveTests(ImportLibrarySdkPrefixedTest); + defineReflectiveTests(ImportLibrarySdkPrefixedWithShowTest); defineReflectiveTests(ImportLibrarySdkTest); + defineReflectiveTests(ImportLibrarySdkWithShowTest); }); } @@ -39,6 +41,29 @@ void f() { } } +@reflectiveTest +class ImportLibrarySdkPrefixedWithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_SDK_PREFIXED_SHOW; + + Future test_prefixed_class_async() async { + await resolveTestCode(''' +void f() { + prefix.Completer? c; + print('\$c'); +} +'''); + await assertHasFix(''' +import 'dart:async' as prefix show Completer; + +void f() { + prefix.Completer? c; + print('\$c'); +} +'''); + } +} + @reflectiveTest class ImportLibrarySdkTest extends FixProcessorTest { @override @@ -349,3 +374,26 @@ void f() { '''); } } + +@reflectiveTest +class ImportLibrarySdkWithShowTest extends FixProcessorTest { + @override + FixKind get kind => DartFixKind.IMPORT_LIBRARY_SDK_SHOW; + + Future test_prefixed_class_async() async { + await resolveTestCode(''' +void f() { + Completer? c; + print('\$c'); +} +'''); + await assertHasFix(''' +import 'dart:async' show Completer; + +void f() { + Completer? c; + print('\$c'); +} +'''); + } +} diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart index b5180013c058..d616db0961d0 100644 --- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart +++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart @@ -2226,12 +2226,35 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl return ImportLibraryElementResultImpl(null); } - String importLibraryWithAbsoluteUri(Uri uri, [String? prefix]) { - return _importLibrary(uri, prefix: prefix, forceAbsolute: true).uriText; + String importLibraryWithAbsoluteUri( + Uri uri, { + String? prefix, + String? shownName, + bool useShow = false, + }) { + return _importLibrary( + uri, + prefix: prefix, + shownName: shownName, + useShow: useShow, + forceAbsolute: true, + ).uriText; } - String importLibraryWithRelativeUri(Uri uri, [String? prefix]) { - return _importLibrary(uri, prefix: prefix, forceRelative: true).uriText; + String importLibraryWithRelativeUri( + Uri uri, { + String? prefix, + String? shownName, + bool useShow = false, + }) { + return _importLibrary( + uri, + prefix: prefix, + shownName: shownName, + useShow: useShow, + forceAbsolute: true, + forceRelative: true, + ).uriText; } @override