Skip to content

Commit 144fe2b

Browse files
FMorschelCommit Queue
authored andcommitted
[DAS] Fixes update combinators to follow lint and to work with multiple
Fixes: #60131 Change-Id: Idfb03889875e3e902cb530bf10a9f4fd51b6a560 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/409765 Auto-Submit: Felipe Morschel <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 58ab0bb commit 144fe2b

File tree

5 files changed

+182
-110
lines changed

5 files changed

+182
-110
lines changed

pkg/analysis_server/lib/src/services/correction/dart/import_library.dart

Lines changed: 72 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart
2626
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
2727
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
2828
import 'package:analyzer_plugin/utilities/range_factory.dart';
29+
import 'package:collection/collection.dart';
2930

3031
typedef _ProducersGenerators =
3132
Future<List<ResolvedCorrectionProducer>> Function(
@@ -110,12 +111,9 @@ class ImportLibrary extends MultiCorrectionProducer {
110111
String? prefix,
111112
}) async {
112113
var combinators = import.combinators;
113-
if (combinators.length != 1) {
114+
if (combinators.isEmpty) {
114115
return (null, null);
115116
}
116-
_ImportLibraryCombinator? importCombinator;
117-
_ImportLibraryCombinatorMultiple? importCombinatorMultiple;
118-
var combinator = combinators.first;
119117
var otherNames = await _otherUnresolvedNames(prefix, name);
120118
var namesInThisLibrary = <String>[
121119
name,
@@ -125,41 +123,23 @@ class ImportLibrary extends MultiCorrectionProducer {
125123
exportedName,
126124
];
127125
var importPrefix = import.prefix2?.element;
128-
if (combinator is HideElementCombinator) {
129-
importCombinator = _ImportLibraryCombinator(
130-
uri,
131-
combinator,
132-
name,
133-
removePrefix: importPrefix == null,
134-
context: context,
135-
);
136-
if (namesInThisLibrary.length > 1) {
137-
importCombinatorMultiple = _ImportLibraryCombinatorMultiple(
138-
uri,
139-
combinator,
140-
namesInThisLibrary,
141-
removePrefix: importPrefix == null,
142-
context: context,
143-
);
144-
}
145-
} else if (combinator is ShowElementCombinator) {
146-
importCombinator = _ImportLibraryCombinator(
147-
uri,
148-
combinator,
149-
name,
150-
removePrefix: importPrefix == null,
151-
context: context,
152-
);
153-
if (namesInThisLibrary.length > 1) {
154-
importCombinatorMultiple = _ImportLibraryCombinatorMultiple(
155-
uri,
156-
combinator,
157-
namesInThisLibrary,
158-
removePrefix: importPrefix == null,
159-
context: context,
160-
);
161-
}
126+
var importCombinator = _ImportLibraryCombinator(
127+
uri,
128+
combinators,
129+
name,
130+
removePrefix: importPrefix == null,
131+
context: context,
132+
);
133+
if (namesInThisLibrary.length == 1) {
134+
return (importCombinator, null);
162135
}
136+
var importCombinatorMultiple = _ImportLibraryCombinatorMultiple(
137+
uri,
138+
combinators,
139+
namesInThisLibrary,
140+
removePrefix: importPrefix == null,
141+
context: context,
142+
);
163143
return (importCombinator, importCombinatorMultiple);
164144
}
165145

@@ -435,8 +415,6 @@ class ImportLibrary extends MultiCorrectionProducer {
435415
for (var instantiatedExtension in instantiatedExtensions) {
436416
// If the import has a combinator that needs to be updated, then offer
437417
// to update it.
438-
// TODO(FMorschel): We should fix all combinators for the import, if
439-
// we don't, we may not import at all.
440418
var libraryElement = import.importedLibrary2;
441419
if (libraryElement == null) {
442420
continue;
@@ -857,11 +835,11 @@ enum _ImportKind {
857835
class _ImportLibraryCombinator extends _ImportLibraryCombinatorMultiple {
858836
_ImportLibraryCombinator(
859837
String libraryName,
860-
NamespaceCombinator combinator,
838+
List<NamespaceCombinator> combinators,
861839
String updatedName, {
862840
super.removePrefix,
863841
required super.context,
864-
}) : super(libraryName, combinator, [updatedName]);
842+
}) : super(libraryName, combinators, [updatedName]);
865843

866844
@override
867845
List<String> get fixArguments => [_updatedNames.first, _libraryName];
@@ -875,15 +853,15 @@ class _ImportLibraryCombinator extends _ImportLibraryCombinatorMultiple {
875853
class _ImportLibraryCombinatorMultiple extends ResolvedCorrectionProducer {
876854
final String _libraryName;
877855

878-
final NamespaceCombinator _combinator;
856+
final List<NamespaceCombinator> _combinators;
879857

880858
final List<String> _updatedNames;
881859

882860
final bool _removePrefix;
883861

884862
_ImportLibraryCombinatorMultiple(
885863
this._libraryName,
886-
this._combinator,
864+
this._combinators,
887865
this._updatedNames, {
888866
bool removePrefix = false,
889867
required super.context,
@@ -910,50 +888,57 @@ class _ImportLibraryCombinatorMultiple extends ResolvedCorrectionProducer {
910888

911889
@override
912890
Future<void> compute(ChangeBuilder builder) async {
913-
Set<String> finalNames = SplayTreeSet<String>();
914-
int offset;
915-
int length;
916-
Keyword keyword;
917-
if (_combinator case ShowElementCombinator(shownNames: var names)) {
918-
finalNames.addAll(names);
919-
offset = _combinator.offset;
920-
length = _combinator.end - offset;
921-
finalNames.addAll(_updatedNames);
922-
keyword = Keyword.SHOW;
923-
} else if (_combinator case HideElementCombinator(hiddenNames: var names)) {
924-
finalNames.addAll(names);
925-
offset = _combinator.offset;
926-
length = _combinator.end - offset;
927-
finalNames.removeAll(_updatedNames);
928-
keyword = Keyword.HIDE;
929-
} else {
930-
return;
931-
}
932-
var newCombinatorCode = '';
933-
if (finalNames.isNotEmpty) {
934-
newCombinatorCode = ' ${keyword.lexeme} ${finalNames.join(', ')}';
935-
}
936-
var libraryPath = unitResult.libraryElement2.firstFragment.source.fullName;
937-
await builder.addDartFileEdit(libraryPath, (builder) {
938-
builder.addSimpleReplacement(
939-
SourceRange(offset - 1, length + 1),
940-
newCombinatorCode,
941-
);
942-
if (_removePrefix) {
943-
AstNode? prefix;
944-
if (node case NamedType(:var importPrefix?)) {
945-
prefix = importPrefix;
946-
} else if (node case PrefixedIdentifier(:var prefix)) {
947-
prefix = prefix;
948-
} else {
949-
return;
950-
}
951-
if (prefix == null) {
952-
return;
953-
}
954-
builder.addDeletion(range.node(prefix));
891+
var codeStyleOptions = getCodeStyleOptions(unitResult.file);
892+
893+
for (var combinator in _combinators) {
894+
var combinatorNames = <String>{};
895+
var offset = combinator.offset;
896+
var length = combinator.end - offset;
897+
898+
Keyword keyword;
899+
switch (combinator) {
900+
case ShowElementCombinator(shownNames: var names):
901+
combinatorNames.addAll(names);
902+
combinatorNames.addAll(_updatedNames);
903+
keyword = Keyword.SHOW;
904+
case HideElementCombinator(hiddenNames: var names):
905+
combinatorNames.addAll(names);
906+
combinatorNames.removeAll(_updatedNames);
907+
keyword = Keyword.HIDE;
955908
}
956-
});
909+
910+
var names =
911+
codeStyleOptions.sortCombinators
912+
? combinatorNames.sorted()
913+
: combinatorNames;
914+
915+
var newCombinatorCode = '';
916+
if (names.isNotEmpty) {
917+
newCombinatorCode = ' ${keyword.lexeme} ${names.join(', ')}';
918+
}
919+
var libraryPath =
920+
unitResult.libraryElement2.firstFragment.source.fullName;
921+
await builder.addDartFileEdit(libraryPath, (builder) {
922+
builder.addSimpleReplacement(
923+
SourceRange(offset - 1, length + 1),
924+
newCombinatorCode,
925+
);
926+
if (_removePrefix) {
927+
AstNode? prefix;
928+
if (node case NamedType(:var importPrefix?)) {
929+
prefix = importPrefix;
930+
} else if (node case PrefixedIdentifier(:var prefix)) {
931+
prefix = prefix;
932+
} else {
933+
return;
934+
}
935+
if (prefix == null) {
936+
return;
937+
}
938+
builder.addDeletion(range.node(prefix));
939+
}
940+
});
941+
}
957942
}
958943
}
959944

pkg/analysis_server/test/src/services/correction/fix/import_library_hide_test.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:analysis_server/src/services/correction/fix.dart';
66
import 'package:analyzer/src/error/codes.dart';
77
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
8+
import 'package:linter/src/lint_names.dart';
89
import 'package:test_reflective_loader/test_reflective_loader.dart';
910

1011
import 'fix_processor.dart';
@@ -457,6 +458,55 @@ void f() {
457458
''');
458459
}
459460

461+
Future<void> test_lint_active() async {
462+
createAnalysisOptionsFile(lints: [LintNames.combinators_ordering]);
463+
newFile('$testPackageLibPath/lib.dart', '''
464+
class A {}
465+
class B {}
466+
class C {}
467+
class D {}
468+
''');
469+
await resolveTestCode(r'''
470+
// ignore: combinators_ordering
471+
import 'lib.dart' hide C, D, B;
472+
void f(A a, C c) {
473+
print('$a $c');
474+
}
475+
''');
476+
await assertHasFix(r'''
477+
// ignore: combinators_ordering
478+
import 'lib.dart' hide B, D;
479+
void f(A a, C c) {
480+
print('$a $c');
481+
}
482+
''');
483+
}
484+
485+
// Two hides, one that should be removed entirely and a show that should be
486+
// updated. Even though the show is not part of these tests, it should be
487+
// fixed too for making the import correct.
488+
Future<void> test_multiple_combinators() async {
489+
newFile('$testPackageLibPath/lib.dart', '''
490+
class A {}
491+
class B {}
492+
class C {}
493+
''');
494+
await resolveTestCode(r'''
495+
// ignore: multiple_combinators
496+
import 'lib.dart' hide B, C show A hide C;
497+
void f(A a, C c) {
498+
print('$a $c');
499+
}
500+
''');
501+
await assertHasFix(r'''
502+
// ignore: multiple_combinators
503+
import 'lib.dart' hide B show A, C;
504+
void f(A a, C c) {
505+
print('$a $c');
506+
}
507+
''');
508+
}
509+
460510
Future<void> test_multipleHide_extension_getter() async {
461511
newFile('$testPackageLibPath/lib.dart', '''
462512
class C {}

pkg/analysis_server/test/src/services/correction/fix/import_library_show_test.dart

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:analysis_server/src/services/correction/fix.dart';
66
import 'package:analyzer/src/error/codes.dart';
77
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
8+
import 'package:linter/src/lint_names.dart';
89
import 'package:test_reflective_loader/test_reflective_loader.dart';
910

1011
import 'fix_processor.dart';
@@ -47,7 +48,7 @@ void f(A a, B b, C c) {
4748
);
4849
await assertHasFix(
4950
r'''
50-
import 'lib.dart' show A, B, C;
51+
import 'lib.dart' show A, C, B;
5152
void f(A a, B b, C c) {
5253
print('$a');
5354
}
@@ -252,7 +253,7 @@ void f(A a1) {
252253
);
253254
await assertHasFix(
254255
r'''
255-
import 'lib.dart' show A, E, a;
256+
import 'lib.dart' show A, a, E;
256257
void f(A a1) {
257258
print('$a1 ${E.m()} $a');
258259
}
@@ -402,14 +403,59 @@ void f(String s, lib2.C c) {
402403
''');
403404
await assertHasFix('''
404405
import 'package:test/lib.dart' as lib show C;
405-
import 'package:test/lib.dart' show C, E;
406+
import 'package:test/lib.dart' show E, C;
406407
407408
void f(String s, C c) {
408409
s.m;
409410
}
410411
''');
411412
}
412413

414+
Future<void> test_lint_active() async {
415+
createAnalysisOptionsFile(lints: [LintNames.combinators_ordering]);
416+
newFile('$testPackageLibPath/lib.dart', '''
417+
class A {}
418+
class B {}
419+
class C {}
420+
''');
421+
await resolveTestCode(r'''
422+
import 'lib.dart' show B, C;
423+
void f(A a, C c) {
424+
print('$a $c');
425+
}
426+
''');
427+
await assertHasFix(r'''
428+
import 'lib.dart' show A, B, C;
429+
void f(A a, C c) {
430+
print('$a $c');
431+
}
432+
''');
433+
}
434+
435+
// Two shows, and a hide that should be updated. Even though the hide is not
436+
// part of these tests, it should be fixed too for making the import correct.
437+
Future<void> test_multiple_combinators() async {
438+
newFile('$testPackageLibPath/lib.dart', '''
439+
class A {}
440+
class B {}
441+
class C {}
442+
''');
443+
await resolveTestCode(r'''
444+
// ignore: multiple_combinators
445+
import 'lib.dart' show A show A, B hide B, C;
446+
void f(A a, C c) {
447+
print('$a $c');
448+
}
449+
''');
450+
await assertHasFix(r'''
451+
// ignore: multiple_combinators
452+
import 'lib.dart' show A, C show A, B, C hide B;
453+
void f(A a, C c) {
454+
print('$a $c');
455+
}
456+
''');
457+
}
458+
413459
Future<void> test_override_samePackage() async {
414460
newFile('$testPackageLibPath/lib.dart', '''
415461
class A {}

0 commit comments

Comments
 (0)