@@ -72,6 +72,11 @@ const Map<String, int> featureOrder = const {
7272 'covariant' : 2 ,
7373 'final' : 2 ,
7474 'inherited' : 3 ,
75+ 'inherited-getter' : 3 ,
76+ 'inherited-setter' : 3 ,
77+ 'override' : 3 ,
78+ 'override-getter' : 3 ,
79+ 'override-setter' : 3 ,
7580};
7681
7782int byFeatureOrdering (String a, String b) {
@@ -181,6 +186,17 @@ abstract class Inheritable implements ModelElement {
181186 return _canonicalEnclosingClass;
182187 }
183188
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+
184200 List <Class > get inheritance {
185201 List <Class > inheritance = [];
186202 inheritance.addAll ((enclosingElement as Class ).inheritanceChain);
@@ -197,6 +213,58 @@ abstract class Inheritable implements ModelElement {
197213 assert (inheritance.where ((e) => e == object).length == 1 );
198214 return inheritance;
199215 }
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+ }
200268}
201269
202270/// A getter or setter that is a member of a Class.
@@ -242,11 +310,46 @@ class InheritableAccessor extends Accessor with Inheritable {
242310 return _enclosingElement;
243311 }
244312
313+ bool _overriddenElementIsSet = false ;
314+ ModelElement _overriddenElement;
245315 @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;
250353 }
251354}
252355
@@ -378,48 +481,6 @@ class Accessor extends ModelElement implements EnclosedElement {
378481 bool get isGetter => _accessor.isGetter;
379482 bool get isSetter => _accessor.isSetter;
380483
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-
423484 @override
424485 String get kind => 'accessor' ;
425486
@@ -1559,6 +1620,9 @@ class EnumField extends Field {
15591620
15601621 @override
15611622 String get oneLineDoc => documentationAsHtml;
1623+
1624+ @override
1625+ Inheritable get overriddenElement => null ;
15621626}
15631627
15641628class Field extends ModelElement
@@ -1668,16 +1732,28 @@ class Field extends ModelElement
16681732
16691733 @override
16701734 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.
16721739 if (hasPublicGetter && hasPublicSetter) {
16731740 if (getter.isInherited && setter.isInherited) {
16741741 allFeatures.add ('inherited' );
16751742 } else {
1743+ allFeatures.remove ('inherited' );
16761744 if (getter.isInherited) allFeatures.add ('inherited-getter' );
16771745 if (setter.isInherited) allFeatures.add ('inherited-setter' );
16781746 }
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+ }
16791754 } else {
16801755 if (isInherited) allFeatures.add ('inherited' );
1756+ if (isOverride) allFeatures.add ('override' );
16811757 }
16821758 return allFeatures;
16831759 }
@@ -1725,6 +1801,9 @@ class Field extends ModelElement
17251801 _modelType = getter.modelType;
17261802 }
17271803 }
1804+
1805+ @override
1806+ Inheritable get overriddenElement => null ;
17281807}
17291808
17301809/// Mixin for top-level variables and fields (aka properties)
@@ -1733,16 +1812,18 @@ abstract class GetterSetterCombo implements ModelElement {
17331812
17341813 Set <String > get comboFeatures {
17351814 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);
17381819 if (readOnly && ! isFinal && ! isConst) allFeatures.add ('read-only' );
17391820 if (writeOnly) allFeatures.add ('write-only' );
17401821 if (readWrite) allFeatures.add ('read / write' );
17411822 if (isCovariant) allFeatures.add ('covariant' );
17421823 return allFeatures;
17431824 }
17441825
1745- bool get isCovariant => false ;
1826+ bool get isCovariant => (hasSetter && setter.isCovariant) ;
17461827
17471828 @override
17481829 ModelElement enclosingElement;
@@ -2621,6 +2702,10 @@ class Method extends ModelElement
26212702 String get typeName => 'method' ;
26222703
26232704 MethodElement get _method => (element as MethodElement );
2705+
2706+ /// Methods can not be covariant; always returns false.
2707+ @override
2708+ bool get isCovariant => false ;
26242709}
26252710
26262711/// This class represents the score for a particular element; how likely
@@ -2713,8 +2798,8 @@ abstract class Privacy {
27132798/// ModelElement will reference itself as part of the "wrong" [Library]
27142799/// from the public interface perspective.
27152800abstract 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 {
27182803 final Element _element;
27192804 // TODO(jcollins-g): This really wants a "member that has a type" class.
27202805 final Member _originalMember;
@@ -3049,12 +3134,12 @@ abstract class ModelElement extends Canonicalization
30493134 .where ((s) => s.isNotEmpty));
30503135 }
30513136
3052- Set <String > get features {
3137+ Set <String > _baseFeatures () {
30533138 Set <String > allFeatures = new Set <String >();
30543139 allFeatures.addAll (annotations);
30553140
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 .
30583143 allFeatures.remove ('@override' );
30593144
30603145 // Drop the plain "deprecated" annotation, that's indicated via
@@ -3066,6 +3151,8 @@ abstract class ModelElement extends Canonicalization
30663151 return allFeatures;
30673152 }
30683153
3154+ Set <String > get features => _baseFeatures ();
3155+
30693156 String get featuresAsString {
30703157 List <String > allFeatures = features.toList ()..sort (byFeatureOrdering);
30713158 return allFeatures.join (', ' );
@@ -3111,8 +3198,9 @@ abstract class ModelElement extends Canonicalization
31113198
31123199 if (computeDocumentationComment == null &&
31133200 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;
31163204 } else if (this is Inheritable && (this as Inheritable ).isInherited) {
31173205 Inheritable thisInheritable = (this as Inheritable );
31183206 Class definingEnclosingClass =
@@ -3483,22 +3571,6 @@ abstract class ModelElement extends Canonicalization
34833571
34843572 Member get originalMember => _originalMember;
34853573
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-
35023574 final PackageGraph _packageGraph;
35033575 @override
35043576 PackageGraph get packageGraph => _packageGraph;
0 commit comments