@@ -33,6 +33,7 @@ class CreateExtensionGetter extends _CreateExtensionMember {
33
33
34
34
@override
35
35
Future <void > compute (ChangeBuilder builder) async {
36
+ var addStaticKeyword = inStaticContext;
36
37
var nameNode = node;
37
38
if (nameNode is ! SimpleIdentifier ) {
38
39
return ;
@@ -44,29 +45,34 @@ class CreateExtensionGetter extends _CreateExtensionMember {
44
45
_getterName = nameNode.name;
45
46
46
47
// prepare target
47
- DartType ? targetType;
48
- ExtensionElement ? extensionElement;
48
+ Expression ? target;
49
49
switch (nameNode.parent) {
50
50
case PrefixedIdentifier prefixedIdentifier:
51
51
if (prefixedIdentifier.identifier == nameNode) {
52
- targetType = prefixedIdentifier.prefix.staticType ;
52
+ target = prefixedIdentifier.prefix;
53
53
}
54
54
case PropertyAccess propertyAccess:
55
55
if (propertyAccess.propertyName == nameNode) {
56
- targetType = propertyAccess.realTarget.staticType;
57
- if (propertyAccess.realTarget case ExtensionOverride (
58
- : var element,
59
- ) when targetType == null ) {
60
- extensionElement = element;
61
- targetType = extensionElement.thisType;
62
- }
63
- }
64
- case ExpressionFunctionBody expressionFunctionBody:
65
- if (expressionFunctionBody.expression == nameNode) {
66
- targetType = node.enclosingInstanceElement? .thisType;
56
+ target = propertyAccess.realTarget;
67
57
}
68
- default :
69
- targetType = nameNode.enclosingInstanceElement? .thisType;
58
+ }
59
+
60
+ DartType ? targetType;
61
+ ExtensionElement ? extensionElement;
62
+ if (target is ExtensionOverride ) {
63
+ targetType = target.extendedType;
64
+ extensionElement = target.element;
65
+ } else if (target == null ) {
66
+ extensionElement = node.enclosingInstanceElement? .ifTypeOrNull ();
67
+ targetType = extensionElement? .thisType;
68
+ } else {
69
+ // We need the type for the extension.
70
+ targetType = target.staticType;
71
+ }
72
+ if (targetType == null && target is SimpleIdentifier ) {
73
+ extensionElement = target.element? .ifTypeOrNull ();
74
+ targetType = extensionElement? .thisType;
75
+ addStaticKeyword = true ;
70
76
}
71
77
72
78
// TODO(FMorschel): We should take into account if the target type contains
@@ -86,7 +92,7 @@ class CreateExtensionGetter extends _CreateExtensionMember {
86
92
}
87
93
88
94
void writeGetter (DartEditBuilder builder) {
89
- if (inStaticContext ) {
95
+ if (addStaticKeyword ) {
90
96
builder.write ('static ' );
91
97
}
92
98
if (fieldType != null ) {
@@ -151,7 +157,7 @@ class CreateExtensionMethod extends _CreateExtensionMember {
151
157
152
158
@override
153
159
Future <void > compute (ChangeBuilder builder) async {
154
- var static = false ;
160
+ var addStaticKeyword = inStaticContext ;
155
161
var nameNode = node;
156
162
if (nameNode is ! SimpleIdentifier ) {
157
163
return ;
@@ -191,7 +197,7 @@ class CreateExtensionMethod extends _CreateExtensionMember {
191
197
if (targetType == null && target is SimpleIdentifier ) {
192
198
extensionElement = target.element? .ifTypeOrNull ();
193
199
targetType = extensionElement? .thisType;
194
- static = true ;
200
+ addStaticKeyword = true ;
195
201
}
196
202
if (targetType == null ||
197
203
targetType is DynamicType ||
@@ -224,7 +230,7 @@ class CreateExtensionMethod extends _CreateExtensionMember {
224
230
var functionType = ! isInvocation ? returnType as FunctionType : null ;
225
231
226
232
void writeMethod (DartEditBuilder builder) {
227
- if (static ) {
233
+ if (addStaticKeyword ) {
228
234
builder.write ('static ' );
229
235
}
230
236
@@ -356,7 +362,18 @@ class CreateExtensionOperator extends _CreateExtensionMember {
356
362
}
357
363
358
364
// We need the type for the extension.
359
- var targetType = target.staticType;
365
+ DartType ? targetType;
366
+ ExtensionElement ? extensionElement;
367
+ if (target is ExtensionOverride ) {
368
+ targetType = target.extendedType;
369
+ extensionElement = target.element;
370
+ } else {
371
+ targetType = target.staticType;
372
+ }
373
+ if (targetType == null && target is SimpleIdentifier ) {
374
+ extensionElement = target.element? .ifTypeOrNull ();
375
+ targetType = extensionElement? .thisType;
376
+ }
360
377
if (targetType == null ||
361
378
targetType is DynamicType ||
362
379
targetType is InvalidType ) {
@@ -406,14 +423,27 @@ class CreateExtensionOperator extends _CreateExtensionMember {
406
423
builder.write (') {}' );
407
424
}
408
425
409
- var updatedExisting = await _updateExistingExtension (builder, targetType, (
410
- extension ,
411
- builder,
412
- ) {
413
- builder.insertMethod (extension , (builder) {
414
- writeMethod (builder);
426
+ bool updatedExisting;
427
+ if (extensionElement != null ) {
428
+ updatedExisting = await _updateExistingExtension2 (
429
+ builder,
430
+ extensionElement,
431
+ (extension , builder) {
432
+ builder.insertMethod (extension , (builder) {
433
+ writeMethod (builder);
434
+ });
435
+ },
436
+ );
437
+ } else {
438
+ updatedExisting = await _updateExistingExtension (builder, targetType, (
439
+ extension ,
440
+ builder,
441
+ ) {
442
+ builder.insertMethod (extension , (builder) {
443
+ writeMethod (builder);
444
+ });
415
445
});
416
- });
446
+ }
417
447
if (updatedExisting) {
418
448
return ;
419
449
}
@@ -441,6 +471,7 @@ class CreateExtensionSetter extends _CreateExtensionMember {
441
471
442
472
@override
443
473
Future <void > compute (ChangeBuilder builder) async {
474
+ var addStaticKeyword = inStaticContext;
444
475
var nameNode = node;
445
476
if (nameNode is ! SimpleIdentifier ) {
446
477
return ;
@@ -463,14 +494,28 @@ class CreateExtensionSetter extends _CreateExtensionMember {
463
494
target = propertyAccess.realTarget;
464
495
}
465
496
}
466
- if (target == null ) {
467
- return ;
497
+
498
+ DartType ? targetType;
499
+ ExtensionElement ? extensionElement;
500
+ if (target is ExtensionOverride ) {
501
+ targetType = target.extendedType;
502
+ extensionElement = target.element;
503
+ } else if (target == null ) {
504
+ extensionElement = node.enclosingInstanceElement? .ifTypeOrNull ();
505
+ targetType = extensionElement? .thisType;
506
+ } else {
507
+ // We need the type for the extension.
508
+ targetType = target.staticType;
509
+ }
510
+ if (targetType == null && target is SimpleIdentifier ) {
511
+ extensionElement = target.element? .ifTypeOrNull ();
512
+ targetType = extensionElement? .thisType;
513
+ addStaticKeyword = true ;
468
514
}
469
515
470
516
// TODO(FMorschel): We should take into account if the target type contains
471
517
// a setter for the same name and stop the fix from being applied.
472
518
// We need the type for the extension.
473
- var targetType = target.staticType;
474
519
if (targetType == null ||
475
520
targetType is DynamicType ||
476
521
targetType is InvalidType ) {
@@ -489,19 +534,33 @@ class CreateExtensionSetter extends _CreateExtensionMember {
489
534
_setterName,
490
535
nameGroupName: 'NAME' ,
491
536
parameterType: fieldType,
537
+ isStatic: addStaticKeyword,
492
538
parameterTypeGroupName: 'TYPE' ,
493
539
typeParametersInScope: methodBeingCopied? .typeParameters,
494
540
);
495
541
}
496
542
497
- var updatedExisting = await _updateExistingExtension (builder, targetType, (
498
- extension ,
499
- builder,
500
- ) {
501
- builder.insertGetter (extension , (builder) {
502
- writeSetter (builder);
543
+ bool updatedExisting;
544
+ if (extensionElement != null ) {
545
+ updatedExisting = await _updateExistingExtension2 (
546
+ builder,
547
+ extensionElement,
548
+ (extension , builder) {
549
+ builder.insertGetter (extension , (builder) {
550
+ writeSetter (builder);
551
+ });
552
+ },
553
+ );
554
+ } else {
555
+ updatedExisting = await _updateExistingExtension (builder, targetType, (
556
+ extension ,
557
+ builder,
558
+ ) {
559
+ builder.insertGetter (extension , (builder) {
560
+ writeSetter (builder);
561
+ });
503
562
});
504
- });
563
+ }
505
564
if (updatedExisting) {
506
565
return ;
507
566
}
@@ -600,23 +659,34 @@ abstract class _CreateExtensionMember extends ResolvedCorrectionProducer {
600
659
if (library.isInSdk) {
601
660
return null ;
602
661
}
603
- var path = library.library.firstFragment.source.fullName;
662
+ var existingExtension = await getDeclarationNodeFromElement (
663
+ extension ,
664
+ includeExtensions: true ,
665
+ );
666
+ if (existingExtension is ! ExtensionDeclaration ) {
667
+ return null ;
668
+ }
669
+ var path =
670
+ existingExtension.declaredFragment? .libraryFragment.source.fullName;
671
+ if (path == null ) {
672
+ // Should never happen.
673
+ assert (
674
+ false ,
675
+ 'How is path to an existing extension null? $existingExtension ' ,
676
+ );
677
+ return null ;
678
+ }
604
679
var unit = await unitResult.session.getResolvedUnit (path);
605
680
if (unit is ! ResolvedUnitResult ) {
606
681
return null ;
607
682
}
608
- var existingExtension = unit.unit.declarations
609
- .whereType <ExtensionDeclaration >()
610
- .firstWhere (
611
- (declaration) => declaration.declaredFragment! .element == extension ,
612
- );
613
683
var instantiated = [extension ].applicableTo (
614
684
targetLibrary: libraryElement2,
615
685
targetType: extension .thisType as TypeImpl ,
616
686
strictCasts: true ,
617
687
);
618
688
if (instantiated.isNotEmpty) {
619
- return (path, existingExtension);
689
+ return (unit. path, existingExtension);
620
690
}
621
691
return null ;
622
692
}
0 commit comments