@@ -53,6 +53,31 @@ Map<String, Map<String, List<Map<String, dynamic>>>> get _crossdartJson {
5353int byName (Nameable a, Nameable b) =>
5454 compareAsciiLowerCaseNatural (a.name, b.name);
5555
56+ /// Items mapped less than zero will sort before custom annotations.
57+ /// Items mapped above zero are sorted after custom annotations.
58+ /// Items mapped to zero will sort alphabetically among custom annotations.
59+ /// Custom annotations are assumed to be any annotation or feature not in this
60+ /// map.
61+ const Map <String , int > featureOrder = const {
62+ 'read-only' : 1 ,
63+ 'write-only' : 1 ,
64+ 'read / write' : 1 ,
65+ 'final' : 2 ,
66+ 'inherited' : 3 ,
67+ };
68+
69+ int byFeatureOrdering (String a, String b) {
70+ int scoreA = 0 ;
71+ int scoreB = 0 ;
72+
73+ if (featureOrder.containsKey (a)) scoreA = featureOrder[a];
74+ if (featureOrder.containsKey (b)) scoreB = featureOrder[b];
75+
76+ if (scoreA < scoreB) return - 1 ;
77+ if (scoreA > scoreB) return 1 ;
78+ return compareAsciiLowerCaseNatural (a, b);
79+ }
80+
5681void _addToImplementors (Class c) {
5782 _implementors.putIfAbsent (c, () => []);
5883
@@ -867,7 +892,12 @@ class Field extends ModelElement
867892 bool get isConst => _field.isConst;
868893
869894 @override
870- bool get isFinal => _field.isFinal;
895+ bool get isFinal {
896+ /// isFinal returns true for the field even if it has an explicit getter
897+ /// (which means we should not document it as "final").
898+ if (hasExplicitGetter) return false ;
899+ return _field.isFinal;
900+ }
871901
872902 bool get isInherited => _isInherited;
873903
@@ -883,6 +913,17 @@ class Field extends ModelElement
883913
884914 bool get writeOnly => hasSetter && ! hasGetter;
885915
916+ @override
917+ Set <String > get features {
918+ Set <String > all_features = super .features;
919+ /// final/const implies read-only, so don't display both strings.
920+ if (readOnly && ! isFinal && ! isConst) all_features.add ('read-only' );
921+ if (writeOnly) all_features.add ('write-only' );
922+ if (readWrite) all_features.add ('read / write' );
923+ if (isInherited) all_features.add ('inherited' );
924+ return all_features;
925+ }
926+
886927 @override
887928 String get _computeDocumentationComment {
888929 String docs = getterSetterDocumentationComment;
@@ -1326,6 +1367,13 @@ class Method extends ModelElement
13261367
13271368 bool get isOperator => false ;
13281369
1370+ @override
1371+ Set <String > get features {
1372+ Set <String > all_features = super .features;
1373+ if (isInherited) all_features.add ('inherited' );
1374+ return all_features;
1375+ }
1376+
13291377 @override
13301378 bool get isStatic => _method.isStatic;
13311379
@@ -1448,6 +1496,26 @@ abstract class ModelElement implements Comparable, Nameable, Documentable {
14481496 }
14491497 }
14501498
1499+ /// const and static are not needed here because const/static elements get
1500+ /// their own sections in the doc.
1501+ Set <String > get features {
1502+ Set <String > all_features = new Set <String >();
1503+ all_features.addAll (annotations);
1504+ /// override as an annotation should be replaced with direct information
1505+ /// from the analyzer if we decide to display it at this level.
1506+ all_features.remove ('override' );
1507+ /// Drop the plain "deprecated" annotation, that's indicated via
1508+ /// strikethroughs. Custom @Deprecated() will still appear.
1509+ all_features.remove ('deprecated' );
1510+ if (isFinal) all_features.add ('final' );
1511+ return all_features;
1512+ }
1513+
1514+ String get featuresAsString {
1515+ List <String > all_features = features.toList ()..sort (byFeatureOrdering);
1516+ return all_features.join (', ' );
1517+ }
1518+
14511519 bool get canHaveParameters =>
14521520 element is ExecutableElement || element is FunctionTypeAliasElement ;
14531521
@@ -2477,7 +2545,12 @@ class TopLevelVariable extends ModelElement
24772545 bool get isConst => _variable.isConst;
24782546
24792547 @override
2480- bool get isFinal => _variable.isFinal;
2548+ bool get isFinal {
2549+ /// isFinal returns true for the variable even if it has an explicit getter
2550+ /// (which means we should not document it as "final").
2551+ if (hasExplicitGetter) return false ;
2552+ return _variable.isFinal;
2553+ }
24812554
24822555 @override
24832556 String get kind => 'top-level property' ;
@@ -2488,6 +2561,17 @@ class TopLevelVariable extends ModelElement
24882561 bool get readWrite => hasGetter && hasSetter;
24892562
24902563 bool get writeOnly => hasSetter && ! hasGetter;
2564+
2565+ @override
2566+ Set <String > get features {
2567+ Set <String > all_features = super .features;
2568+ /// final/const implies read-only, so don't display both strings.
2569+ if (readOnly && ! isFinal && ! isConst) all_features.add ('read-only' );
2570+ if (writeOnly) all_features.add ('write-only' );
2571+ if (readWrite) all_features.add ('read / write' );
2572+ return all_features;
2573+ }
2574+
24912575 @override
24922576 String get _computeDocumentationComment {
24932577 String docs = getterSetterDocumentationComment;
0 commit comments