@@ -72,6 +72,11 @@ const Map<String, int> featureOrder = const {
72
72
'covariant' : 2 ,
73
73
'final' : 2 ,
74
74
'inherited' : 3 ,
75
+ 'inherited-getter' : 3 ,
76
+ 'inherited-setter' : 3 ,
77
+ 'override' : 3 ,
78
+ 'override-getter' : 3 ,
79
+ 'override-setter' : 3 ,
75
80
};
76
81
77
82
int byFeatureOrdering (String a, String b) {
@@ -181,6 +186,17 @@ abstract class Inheritable implements ModelElement {
181
186
return _canonicalEnclosingClass;
182
187
}
183
188
189
+ @override
190
+ Set <String > get features {
191
+ Set <String > _features = _baseFeatures ();
192
+ if (isOverride) _features.add ('override' );
193
+ if (isInherited) _features.add ('inherited' );
194
+ if (isCovariant) _features.add ('covariant' );
195
+ return _features;
196
+ }
197
+
198
+ bool get isCovariant;
199
+
184
200
List <Class > get inheritance {
185
201
List <Class > inheritance = [];
186
202
inheritance.addAll ((enclosingElement as Class ).inheritanceChain);
@@ -197,6 +213,58 @@ abstract class Inheritable implements ModelElement {
197
213
assert (inheritance.where ((e) => e == object).length == 1 );
198
214
return inheritance;
199
215
}
216
+
217
+ Inheritable get overriddenElement;
218
+
219
+ bool _isOverride;
220
+ bool get isOverride {
221
+ if (_isOverride == null ) {
222
+ // The canonical version of the enclosing element -- not canonicalEnclosingElement,
223
+ // as that is the element enclosing the canonical version of this element,
224
+ // two different things. Defaults to the enclosing element.
225
+ //
226
+ // We use canonical elements here where possible to deal with reexports
227
+ // as seen in Flutter.
228
+ Class enclosingCanonical = enclosingElement;
229
+ if (enclosingElement is ModelElement ) {
230
+ enclosingCanonical =
231
+ (enclosingElement as ModelElement ).canonicalModelElement;
232
+ }
233
+ // The class in which this element was defined, canonical if available.
234
+ Class definingCanonical =
235
+ definingEnclosingElement.canonicalModelElement ??
236
+ definingEnclosingElement;
237
+ // The canonical version of the element we're overriding, if available.
238
+ ModelElement overriddenCanonical =
239
+ overriddenElement? .canonicalModelElement ?? overriddenElement;
240
+
241
+ // We have to have an overridden element for it to be possible for this
242
+ // element to be an override.
243
+ _isOverride = overriddenElement != null &&
244
+ // The defining class and the enclosing class for this element
245
+ // must be the same (element is defined here).
246
+ enclosingCanonical == definingCanonical &&
247
+ // If the overridden element isn't public, we shouldn't be an
248
+ // override in most cases. Approximation until #1623 is fixed.
249
+ overriddenCanonical.isPublic;
250
+ assert (! (_isOverride && isInherited));
251
+ }
252
+ return _isOverride;
253
+ }
254
+
255
+ int _overriddenDepth;
256
+ @override
257
+ int get overriddenDepth {
258
+ if (_overriddenDepth == null ) {
259
+ _overriddenDepth = 0 ;
260
+ Inheritable e = this ;
261
+ while (e.overriddenElement != null ) {
262
+ _overriddenDepth += 1 ;
263
+ e = e.overriddenElement;
264
+ }
265
+ }
266
+ return _overriddenDepth;
267
+ }
200
268
}
201
269
202
270
/// A getter or setter that is a member of a Class.
@@ -242,11 +310,46 @@ class InheritableAccessor extends Accessor with Inheritable {
242
310
return _enclosingElement;
243
311
}
244
312
313
+ bool _overriddenElementIsSet = false ;
314
+ ModelElement _overriddenElement;
245
315
@override
246
- Set <String > get features {
247
- Set <String > allFeatures = super .features;
248
- if (isInherited) allFeatures.add ('inherited' );
249
- return allFeatures;
316
+ InheritableAccessor get overriddenElement {
317
+ assert (packageGraph.allLibrariesAdded);
318
+ if (! _overriddenElementIsSet) {
319
+ _overriddenElementIsSet = true ;
320
+ Element parent = element.enclosingElement;
321
+ if (parent is ClassElement ) {
322
+ for (InterfaceType t in parent.allSupertypes) {
323
+ Element accessor = this .isGetter
324
+ ? t.getGetter (element.name)
325
+ : t.getSetter (element.name);
326
+ if (accessor != null ) {
327
+ if (accessor is Member ) {
328
+ accessor = PackageGraph .getBasestElement (accessor);
329
+ }
330
+ Class parentClass =
331
+ new ModelElement .fromElement (t.element, packageGraph);
332
+ List <Field > possibleFields = [];
333
+ possibleFields.addAll (parentClass.allInstanceProperties);
334
+ possibleFields.addAll (parentClass.staticProperties);
335
+ String fieldName = accessor.name.replaceFirst ('=' , '' );
336
+ Field foundField = possibleFields.firstWhere (
337
+ (f) => f.element.name == fieldName,
338
+ orElse: () => null );
339
+ if (foundField != null ) {
340
+ if (this .isGetter) {
341
+ _overriddenElement = foundField.getter;
342
+ } else {
343
+ _overriddenElement = foundField.setter;
344
+ }
345
+ assert (! (_overriddenElement as Accessor ).isInherited);
346
+ break ;
347
+ }
348
+ }
349
+ }
350
+ }
351
+ }
352
+ return _overriddenElement;
250
353
}
251
354
}
252
355
@@ -378,48 +481,6 @@ class Accessor extends ModelElement implements EnclosedElement {
378
481
bool get isGetter => _accessor.isGetter;
379
482
bool get isSetter => _accessor.isSetter;
380
483
381
- bool _overriddenElementIsSet = false ;
382
- ModelElement _overriddenElement;
383
- @override
384
- Accessor get overriddenElement {
385
- assert (packageGraph.allLibrariesAdded);
386
- if (! _overriddenElementIsSet) {
387
- _overriddenElementIsSet = true ;
388
- Element parent = element.enclosingElement;
389
- if (parent is ClassElement ) {
390
- for (InterfaceType t in parent.allSupertypes) {
391
- Element accessor = this .isGetter
392
- ? t.getGetter (element.name)
393
- : t.getSetter (element.name);
394
- if (accessor != null ) {
395
- if (accessor is Member ) {
396
- accessor = PackageGraph .getBasestElement (accessor);
397
- }
398
- Class parentClass =
399
- new ModelElement .fromElement (t.element, packageGraph);
400
- List <Field > possibleFields = [];
401
- possibleFields.addAll (parentClass.allInstanceProperties);
402
- possibleFields.addAll (parentClass.staticProperties);
403
- String fieldName = accessor.name.replaceFirst ('=' , '' );
404
- Field foundField = possibleFields.firstWhere (
405
- (f) => f.element.name == fieldName,
406
- orElse: () => null );
407
- if (foundField != null ) {
408
- if (this .isGetter) {
409
- _overriddenElement = foundField.getter;
410
- } else {
411
- _overriddenElement = foundField.setter;
412
- }
413
- assert (! (_overriddenElement as Accessor ).isInherited);
414
- break ;
415
- }
416
- }
417
- }
418
- }
419
- }
420
- return _overriddenElement;
421
- }
422
-
423
484
@override
424
485
String get kind => 'accessor' ;
425
486
@@ -1559,6 +1620,9 @@ class EnumField extends Field {
1559
1620
1560
1621
@override
1561
1622
String get oneLineDoc => documentationAsHtml;
1623
+
1624
+ @override
1625
+ Inheritable get overriddenElement => null ;
1562
1626
}
1563
1627
1564
1628
class Field extends ModelElement
@@ -1668,16 +1732,28 @@ class Field extends ModelElement
1668
1732
1669
1733
@override
1670
1734
Set <String > get features {
1671
- Set <String > allFeatures = super .features..addAll (comboFeatures);
1735
+ Set <String > allFeatures = _baseFeatures ()..addAll (comboFeatures);
1736
+ // Combo features can indicate 'inherited' and 'override' if
1737
+ // either the getter or setter has one of those properties, but that's not
1738
+ // really specific enough for [Field]s that have public getter/setters.
1672
1739
if (hasPublicGetter && hasPublicSetter) {
1673
1740
if (getter.isInherited && setter.isInherited) {
1674
1741
allFeatures.add ('inherited' );
1675
1742
} else {
1743
+ allFeatures.remove ('inherited' );
1676
1744
if (getter.isInherited) allFeatures.add ('inherited-getter' );
1677
1745
if (setter.isInherited) allFeatures.add ('inherited-setter' );
1678
1746
}
1747
+ if (getter.isOverride && setter.isOverride) {
1748
+ allFeatures.add ('override' );
1749
+ } else {
1750
+ allFeatures.remove ('override' );
1751
+ if (getter.isOverride) allFeatures.add ('override-getter' );
1752
+ if (setter.isOverride) allFeatures.add ('override-setter' );
1753
+ }
1679
1754
} else {
1680
1755
if (isInherited) allFeatures.add ('inherited' );
1756
+ if (isOverride) allFeatures.add ('override' );
1681
1757
}
1682
1758
return allFeatures;
1683
1759
}
@@ -1725,6 +1801,9 @@ class Field extends ModelElement
1725
1801
_modelType = getter.modelType;
1726
1802
}
1727
1803
}
1804
+
1805
+ @override
1806
+ Inheritable get overriddenElement => null ;
1728
1807
}
1729
1808
1730
1809
/// Mixin for top-level variables and fields (aka properties)
@@ -1733,16 +1812,18 @@ abstract class GetterSetterCombo implements ModelElement {
1733
1812
1734
1813
Set <String > get comboFeatures {
1735
1814
Set <String > allFeatures = new Set ();
1736
- if (hasExplicitGetter) allFeatures.addAll (getter.features);
1737
- if (hasExplicitSetter) allFeatures.addAll (setter.features);
1815
+ if (hasExplicitGetter && hasPublicGetter)
1816
+ allFeatures.addAll (getter.features);
1817
+ if (hasExplicitSetter && hasPublicSetter)
1818
+ allFeatures.addAll (setter.features);
1738
1819
if (readOnly && ! isFinal && ! isConst) allFeatures.add ('read-only' );
1739
1820
if (writeOnly) allFeatures.add ('write-only' );
1740
1821
if (readWrite) allFeatures.add ('read / write' );
1741
1822
if (isCovariant) allFeatures.add ('covariant' );
1742
1823
return allFeatures;
1743
1824
}
1744
1825
1745
- bool get isCovariant => false ;
1826
+ bool get isCovariant => (hasSetter && setter.isCovariant) ;
1746
1827
1747
1828
@override
1748
1829
ModelElement enclosingElement;
@@ -2621,6 +2702,10 @@ class Method extends ModelElement
2621
2702
String get typeName => 'method' ;
2622
2703
2623
2704
MethodElement get _method => (element as MethodElement );
2705
+
2706
+ /// Methods can not be covariant; always returns false.
2707
+ @override
2708
+ bool get isCovariant => false ;
2624
2709
}
2625
2710
2626
2711
/// This class represents the score for a particular element; how likely
@@ -2713,8 +2798,8 @@ abstract class Privacy {
2713
2798
/// ModelElement will reference itself as part of the "wrong" [Library]
2714
2799
/// from the public interface perspective.
2715
2800
abstract class ModelElement extends Canonicalization
2716
- with Privacy , Warnable , Nameable , SourceCodeMixin
2717
- implements Comparable , Documentable , Indexable {
2801
+ with Privacy , Warnable , Nameable , SourceCodeMixin , Indexable
2802
+ implements Comparable , Documentable {
2718
2803
final Element _element;
2719
2804
// TODO(jcollins-g): This really wants a "member that has a type" class.
2720
2805
final Member _originalMember;
@@ -3049,12 +3134,12 @@ abstract class ModelElement extends Canonicalization
3049
3134
.where ((s) => s.isNotEmpty));
3050
3135
}
3051
3136
3052
- Set <String > get features {
3137
+ Set <String > _baseFeatures () {
3053
3138
Set <String > allFeatures = new Set <String >();
3054
3139
allFeatures.addAll (annotations);
3055
3140
3056
- // override as an annotation should be replaced with direct information
3057
- // from the analyzer if we decide to display it at this level .
3141
+ // Replace the @override annotation with a feature that explicitly
3142
+ // indicates whether an override has occurred .
3058
3143
allFeatures.remove ('@override' );
3059
3144
3060
3145
// Drop the plain "deprecated" annotation, that's indicated via
@@ -3066,6 +3151,8 @@ abstract class ModelElement extends Canonicalization
3066
3151
return allFeatures;
3067
3152
}
3068
3153
3154
+ Set <String > get features => _baseFeatures ();
3155
+
3069
3156
String get featuresAsString {
3070
3157
List <String > allFeatures = features.toList ()..sort (byFeatureOrdering);
3071
3158
return allFeatures.join (', ' );
@@ -3111,8 +3198,9 @@ abstract class ModelElement extends Canonicalization
3111
3198
3112
3199
if (computeDocumentationComment == null &&
3113
3200
canOverride () &&
3114
- overriddenElement != null ) {
3115
- docFrom = overriddenElement.documentationFrom;
3201
+ this is Inheritable &&
3202
+ (this as Inheritable ).overriddenElement != null ) {
3203
+ docFrom = (this as Inheritable ).overriddenElement.documentationFrom;
3116
3204
} else if (this is Inheritable && (this as Inheritable ).isInherited) {
3117
3205
Inheritable thisInheritable = (this as Inheritable );
3118
3206
Class definingEnclosingClass =
@@ -3483,22 +3571,6 @@ abstract class ModelElement extends Canonicalization
3483
3571
3484
3572
Member get originalMember => _originalMember;
3485
3573
3486
- ModelElement get overriddenElement => null ;
3487
-
3488
- int _overriddenDepth;
3489
- @override
3490
- int get overriddenDepth {
3491
- if (_overriddenDepth == null ) {
3492
- _overriddenDepth = 0 ;
3493
- ModelElement e = this ;
3494
- while (e.overriddenElement != null ) {
3495
- _overriddenDepth += 1 ;
3496
- e = e.overriddenElement;
3497
- }
3498
- }
3499
- return _overriddenDepth;
3500
- }
3501
-
3502
3574
final PackageGraph _packageGraph;
3503
3575
@override
3504
3576
PackageGraph get packageGraph => _packageGraph;
0 commit comments