Skip to content

Commit 8561a56

Browse files
authored
Add 'override' to features list (#1798)
* Add override feature * dartfmt * Review comments
1 parent 6c95c02 commit 8561a56

File tree

840 files changed

+1039
-175
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

840 files changed

+1039
-175
lines changed

lib/src/markdown_processor.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
374374
List<Class> tryClasses = [preferredClass];
375375
Class realClass = tryClasses.first;
376376
if (element is Inheritable) {
377-
ModelElement overriddenElement = element.overriddenElement;
377+
Inheritable overriddenElement = element.overriddenElement;
378378
while (overriddenElement != null) {
379379
tryClasses.add(
380380
(element.overriddenElement as EnclosedElement).enclosingElement);

lib/src/model.dart

Lines changed: 145 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7782
int 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

15641628
class 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.
27152800
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 {
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;

lib/templates/method.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ <h1>{{{self.nameWithGenerics}}} {{self.kind}}</h1>
1111
{{#method}}
1212
<section class="multi-line-signature">
1313
{{>callable_multiline}}
14+
{{>features}}
1415
</section>
1516
{{>documentation}}
1617

0 commit comments

Comments
 (0)