Skip to content

Commit d8e378e

Browse files
scheglovCommit Queue
authored andcommitted
Elements. Migrate FlutterConvertToStatefulWidget.
Change-Id: Iaacb9e2ccc908c64528ae7e6ee48c7094076b7d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389264 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]> Reviewed-by: Phil Quitslund <[email protected]>
1 parent 3b30477 commit d8e378e

File tree

4 files changed

+126
-27
lines changed

4 files changed

+126
-27
lines changed

pkg/analysis_server/analyzer_use_new_elements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ lib/src/services/correction/dart/exchange_operands.dart
317317
lib/src/services/correction/dart/extend_class_for_mixin.dart
318318
lib/src/services/correction/dart/extract_local_variable.dart
319319
lib/src/services/correction/dart/flutter_convert_to_children.dart
320+
lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
320321
lib/src/services/correction/dart/flutter_move_down.dart
321322
lib/src/services/correction/dart/flutter_move_up.dart
322323
lib/src/services/correction/dart/flutter_remove_widget.dart

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

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import 'package:analysis_server/src/utilities/extensions/flutter.dart';
88
import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
99
import 'package:analyzer/dart/ast/ast.dart';
1010
import 'package:analyzer/dart/ast/visitor.dart';
11-
import 'package:analyzer/dart/element/element.dart';
11+
import 'package:analyzer/dart/element/element2.dart';
1212
import 'package:analyzer/source/source_range.dart';
1313
import 'package:analyzer/src/dart/ast/extensions.dart';
1414
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
@@ -43,7 +43,7 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
4343
}
4444

4545
// Must be a StatelessWidget subclass.
46-
var widgetClassElement = widgetClass.declaredElement!;
46+
var widgetClassElement = widgetClass.declaredFragment!.element;
4747
var superType = widgetClassElement.supertype;
4848
if (superType == null || !superType.isExactlyStatelessWidgetType) {
4949
return;
@@ -70,29 +70,30 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
7070

7171
// Prepare nodes to move.
7272
var nodesToMove = <ClassMember>{};
73-
var elementsToMove = <Element>{};
73+
var elementsToMove = <Element2>{};
7474
for (var member in widgetClass.members) {
7575
if (member is FieldDeclaration && !member.isStatic) {
7676
for (var fieldNode in member.fields.variables) {
77-
var fieldElement = fieldNode.declaredElement as FieldElement;
77+
var fieldFragment = fieldNode.declaredFragment as FieldFragment;
78+
var fieldElement = fieldFragment.element;
7879
if (!fieldsAssignedInConstructors.contains(fieldElement)) {
7980
nodesToMove.add(member);
8081
elementsToMove.add(fieldElement);
8182

82-
var getter = fieldElement.getter;
83+
var getter = fieldElement.getter2;
8384
if (getter != null) {
8485
elementsToMove.add(getter);
8586
}
8687

87-
var setter = fieldElement.setter;
88+
var setter = fieldElement.setter2;
8889
if (setter != null) {
8990
elementsToMove.add(setter);
9091
}
9192
}
9293
}
9394
} else if (member is MethodDeclaration && !member.isStatic) {
9495
nodesToMove.add(member);
95-
elementsToMove.add(member.declaredElement!);
96+
elementsToMove.add(member.declaredFragment!.element);
9697
}
9798
}
9899

@@ -112,15 +113,15 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
112113
}
113114

114115
var statefulWidgetClass =
115-
await sessionHelper.getFlutterClass('StatefulWidget');
116-
var stateClass = await sessionHelper.getFlutterClass('State');
116+
await sessionHelper.getFlutterClass2('StatefulWidget');
117+
var stateClass = await sessionHelper.getFlutterClass2('State');
117118
if (statefulWidgetClass == null || stateClass == null) {
118119
return;
119120
}
120121

121122
await builder.addDartFileEdit(file, (builder) {
122123
builder.addReplacement(range.node(superclass), (builder) {
123-
builder.writeReference(statefulWidgetClass);
124+
builder.writeReference2(statefulWidgetClass);
124125
});
125126

126127
var replaceOffset = 0;
@@ -148,7 +149,7 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
148149
}
149150
builder.writeln(' @override');
150151
builder.write(' ');
151-
builder.writeReference(stateClass);
152+
builder.writeReference2(stateClass);
152153
builder.write('<${widgetClass.name.lexeme}$typeParams>');
153154
builder.writeln(' createState() => $stateName$typeParams();');
154155
if (hasEmptyLineAfterCreateState) {
@@ -205,7 +206,7 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
205206
builder.writeln();
206207

207208
builder.write('class $stateName$typeParams extends ');
208-
builder.writeReference(stateClass);
209+
builder.writeReference2(stateClass);
209210

210211
// Write just param names (and not bounds, metadata and docs).
211212
builder.write('<${widgetClass.name.lexeme}');
@@ -262,13 +263,13 @@ class FlutterConvertToStatefulWidget extends ResolvedCorrectionProducer {
262263
}
263264

264265
class _FieldFinder extends RecursiveAstVisitor<void> {
265-
Set<FieldElement> fieldsAssignedInConstructors = {};
266+
Set<FieldElement2> fieldsAssignedInConstructors = {};
266267

267268
@override
268269
void visitFieldFormalParameter(FieldFormalParameter node) {
269-
var element = node.declaredElement;
270-
if (element is FieldFormalParameterElement) {
271-
var field = element.field;
270+
var element = node.declaredFragment?.element;
271+
if (element is FieldFormalParameterElement2) {
272+
var field = element.field2;
272273
if (field != null) {
273274
fieldsAssignedInConstructors.add(field);
274275
}
@@ -280,16 +281,16 @@ class _FieldFinder extends RecursiveAstVisitor<void> {
280281
@override
281282
void visitSimpleIdentifier(SimpleIdentifier node) {
282283
if (node.parent is ConstructorFieldInitializer) {
283-
var element = node.staticElement;
284-
if (element is FieldElement) {
284+
var element = node.element;
285+
if (element is FieldElement2) {
285286
fieldsAssignedInConstructors.add(element);
286287
}
287288
}
288289
if (node.inSetterContext()) {
289-
var element = node.writeOrReadElement;
290-
if (element is PropertyAccessorElement) {
291-
var field = element.variable2;
292-
if (field is FieldElement) {
290+
var element = node.writeOrReadElement2;
291+
if (element is SetterElement) {
292+
var field = element.variable3;
293+
if (field is FieldElement2) {
293294
fieldsAssignedInConstructors.add(field);
294295
}
295296
}
@@ -298,9 +299,9 @@ class _FieldFinder extends RecursiveAstVisitor<void> {
298299
}
299300

300301
class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
301-
final ClassElement widgetClassElement;
302+
final ClassElement2 widgetClassElement;
302303

303-
final Set<Element> elementsToMove;
304+
final Set<Element2> elementsToMove;
304305

305306
final SourceRange linesRange;
306307

@@ -314,9 +315,9 @@ class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
314315
if (node.inDeclarationContext()) {
315316
return;
316317
}
317-
var element = node.staticElement;
318-
if (element is ExecutableElement &&
319-
element.enclosingElement3 == widgetClassElement &&
318+
var element = node.element;
319+
if (element is ExecutableElement2 &&
320+
element.enclosingElement2 == widgetClassElement &&
320321
!elementsToMove.contains(element)) {
321322
var offset = node.offset - linesRange.offset;
322323
var qualifier =

pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,14 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
947947
write(element.displayName);
948948
}
949949

950+
@override
951+
void writeReference2(Element2 element) {
952+
if (element.enclosingElement2 is LibraryElement2) {
953+
_writeLibraryReference2(element);
954+
}
955+
write(element.displayName);
956+
}
957+
950958
@override
951959
void writeSetterDeclaration(String name,
952960
{void Function()? bodyWriter,
@@ -1502,6 +1510,42 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
15021510
}
15031511
}
15041512

1513+
/// Writes the import prefix to reference the [element], if needed.
1514+
///
1515+
/// The prefix is not needed if the [element] is defined in the target
1516+
/// library, or there is already an import without prefix that exports the
1517+
/// [element]. If there are no existing import that exports the [element], a
1518+
/// library that exports the [element] is scheduled for import, possibly with
1519+
/// a prefix.
1520+
void _writeLibraryReference2(Element2 element) {
1521+
// If the element is defined in the library, then no prefix needed.
1522+
if (dartFileEditBuilder._isDefinedLocally2(element)) {
1523+
return;
1524+
}
1525+
1526+
// TODO(scheglov): We should use "methodBeingCopied" to verify that
1527+
// we really are just copying this type parameter.
1528+
if (element is TypeParameterElement2) {
1529+
return;
1530+
}
1531+
1532+
var import = dartFileEditBuilder._getImportElement2(element);
1533+
if (import == null) {
1534+
var library = element.library2?.firstFragment.source.uri;
1535+
if (library != null) {
1536+
import = dartFileEditBuilder._importLibrary(library);
1537+
}
1538+
}
1539+
if (import == null) {
1540+
return;
1541+
}
1542+
import.ensureShown(element.name!);
1543+
var prefix = import.prefix;
1544+
if (prefix.isNotEmpty) {
1545+
write('$prefix.');
1546+
}
1547+
}
1548+
15051549
void _writeSuperMemberInvocation(ExecutableElement element, String memberName,
15061550
List<ParameterElement> parameters) {
15071551
var isOperator = element.isOperator;
@@ -1921,6 +1965,10 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
19211965
/// them visible in the generated code.
19221966
final Map<Element, _LibraryImport> _elementLibrariesToImport = {};
19231967

1968+
/// A mapping of [Element2]s to pending imports that will be added to make
1969+
/// them visible in the generated code.
1970+
final Map<Element2, _LibraryImport> _elementLibrariesToImport2 = {};
1971+
19241972
/// Initializes a newly created builder to build a source file edit within the
19251973
/// change being built by the given [changeBuilder].
19261974
///
@@ -2001,6 +2049,9 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
20012049
for (var entry in _elementLibrariesToImport.entries) {
20022050
copy._elementLibrariesToImport[entry.key] = entry.value;
20032051
}
2052+
for (var entry in _elementLibrariesToImport2.entries) {
2053+
copy._elementLibrariesToImport2[entry.key] = entry.value;
2054+
}
20042055
return copy;
20052056
}
20062057

@@ -2696,6 +2747,40 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
26962747
return (libraryChangeBuilder ?? this)._elementLibrariesToImport[element];
26972748
}
26982749

2750+
/// Returns information about the library used to import the given [element]
2751+
/// into the target library, or `null` if the element was not imported, such
2752+
/// as when the element is declared in the same library.
2753+
///
2754+
/// The result may be an existing import, or one that is pending.
2755+
_LibraryImport? _getImportElement2(Element2 element) {
2756+
for (var import
2757+
in resolvedUnit.libraryElement2.firstFragment.libraryImports2) {
2758+
var definedNames = import.namespace.definedNames2;
2759+
if (definedNames.containsValue(element)) {
2760+
var importedLibrary = import.importedLibrary2;
2761+
if (importedLibrary != null) {
2762+
return _LibraryImport(
2763+
uriText: importedLibrary.firstFragment.source.uri.toString(),
2764+
isExplicitlyImported: true,
2765+
shownNames: [
2766+
for (var combinator in import.combinators)
2767+
if (combinator is ShowElementCombinator)
2768+
combinator.shownNames.toList(),
2769+
],
2770+
hiddenNames: [
2771+
for (var combinator in import.combinators)
2772+
if (combinator is HideElementCombinator)
2773+
combinator.hiddenNames.toList(),
2774+
],
2775+
prefix: import.prefix2?.name ?? '',
2776+
);
2777+
}
2778+
}
2779+
}
2780+
2781+
return (libraryChangeBuilder ?? this)._elementLibrariesToImport2[element];
2782+
}
2783+
26992784
List<LibraryImportElement> _getImportsForUri(Uri uri) {
27002785
return [
27012786
for (var import
@@ -2829,6 +2914,11 @@ class DartFileEditBuilderImpl extends FileEditBuilderImpl
28292914
return element.library == resolvedUnit.libraryElement;
28302915
}
28312916

2917+
/// Returns whether the [element] is defined in the target library.
2918+
bool _isDefinedLocally2(Element2 element) {
2919+
return element.library2 == resolvedUnit.libraryElement2;
2920+
}
2921+
28322922
/// Removes any pending imports (for [Element]s) that are no longer necessary
28332923
/// because the newly-added [newImport] for [newLibrary] also provides those
28342924
/// [Element]s.

pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,13 @@ abstract class DartEditBuilder implements EditBuilder {
333333
/// the current library, imports will be updated.
334334
void writeReference(Element element);
335335

336+
/// Writes the code that references the [element].
337+
///
338+
/// If the [element] is a top-level element that has not been imported into
339+
/// the current library, imports will be updated.
340+
@experimental
341+
void writeReference2(Element2 element);
342+
336343
/// Writes the code for a declaration of a setter with the given [name].
337344
///
338345
/// If a [bodyWriter] is provided, it will be invoked to write the body of the

0 commit comments

Comments
 (0)