66library dartdoc.models;
77
88import 'dart:async' ;
9- import 'dart:collection' show UnmodifiableListView;
9+ import 'dart:collection' show HashSet, UnmodifiableListView;
1010import 'dart:convert' ;
1111import 'dart:io' ;
1212
@@ -22,7 +22,6 @@ import 'package:analyzer/dart/ast/ast.dart'
2222 InstanceCreationExpression;
2323import 'package:analyzer/dart/element/element.dart' ;
2424import 'package:analyzer/dart/element/type.dart' ;
25- import 'package:analyzer/dart/element/type_system.dart' ;
2625import 'package:analyzer/dart/element/visitor.dart' ;
2726import 'package:analyzer/file_system/file_system.dart' as file_system;
2827import 'package:analyzer/file_system/physical_file_system.dart' ;
@@ -36,7 +35,6 @@ import 'package:analyzer/src/dart/element/element.dart';
3635import 'package:analyzer/src/dart/element/inheritance_manager3.dart' ;
3736import 'package:analyzer/src/dart/element/member.dart'
3837 show ExecutableMember, Member, ParameterMember;
39- import 'package:analyzer/src/dart/element/type.dart' show InterfaceTypeImpl;
4038import 'package:analyzer/src/dart/sdk/sdk.dart' ;
4139import 'package:analyzer/src/generated/engine.dart' ;
4240import 'package:analyzer/src/generated/java_io.dart' ;
@@ -805,7 +803,8 @@ class Class extends Container
805803 _potentiallyApplicableExtensions = utils
806804 .filterNonDocumented (packageGraph.extensions)
807805 .where ((e) => e.couldApplyTo (this ))
808- .toList (growable: false );
806+ .toList (growable: false )
807+ ..sort (byName);
809808 }
810809 return _potentiallyApplicableExtensions;
811810 }
@@ -1344,26 +1343,44 @@ class Extension extends Container
13441343 ElementType .from (_extension.extendedType, library, packageGraph);
13451344 }
13461345
1347- /// Returns [true] if there is an instantiation of [c] to which this extension
1348- /// could be applied.
1349- bool couldApplyTo (Class c) =>
1350- _couldApplyTo (extendedType.type, c.element, packageGraph.typeSystem);
1351-
1352- static bool _couldApplyTo (
1353- DartType extendedType, ClassElement element, Dart2TypeSystem typeSystem) {
1354- InterfaceTypeImpl classInstantiated =
1355- typeSystem.instantiateToBounds (element.thisType);
1356- classInstantiated = element.instantiate (
1357- typeArguments: classInstantiated.typeArguments.map ((a) {
1358- if (a.isDynamic) {
1359- return typeSystem.typeProvider.neverType;
1360- }
1361- return a;
1362- }).toList (),
1363- nullabilitySuffix: classInstantiated.nullabilitySuffix);
1364-
1365- return (classInstantiated.element == extendedType.element) ||
1366- typeSystem.isSubtypeOf (classInstantiated, extendedType);
1346+ bool couldApplyTo (Class c) => _couldApplyTo (c.modelType);
1347+
1348+ /// Return true if this extension could apply to [t] .
1349+ bool _couldApplyTo (DefinedElementType t) {
1350+ return t.instantiatedType == extendedType.instantiatedType ||
1351+ (t.instantiatedType.element == extendedType.instantiatedType.element &&
1352+ isSubtypeOf (t)) ||
1353+ isBoundSupertypeTo (t);
1354+ }
1355+
1356+ /// The instantiated to bounds [extendedType] of this extension is a subtype of
1357+ /// [t] .
1358+ bool isSubtypeOf (DefinedElementType t) => packageGraph.typeSystem
1359+ .isSubtypeOf (extendedType.instantiatedType, t.instantiatedType);
1360+
1361+ bool isBoundSupertypeTo (DefinedElementType t) =>
1362+ _isBoundSupertypeTo (t.type, HashSet ());
1363+
1364+ /// Returns true if at least one supertype (including via mixins and
1365+ /// interfaces) is equivalent to or a subtype of [extendedType] when
1366+ /// instantiated to bounds.
1367+ bool _isBoundSupertypeTo (
1368+ InterfaceType superType, HashSet <InterfaceType > visited) {
1369+ ClassElement superClass = superType? .element;
1370+ if (visited.contains (superType)) return false ;
1371+ visited.add (superType);
1372+ if (superClass == extendedType.type.element &&
1373+ (superType == extendedType.instantiatedType ||
1374+ packageGraph.typeSystem
1375+ .isSubtypeOf (superType, extendedType.instantiatedType))) {
1376+ return true ;
1377+ }
1378+ List <InterfaceType > supertypes = [];
1379+ ClassElementImpl .collectAllSupertypes (supertypes, superType, null );
1380+ for (InterfaceType toVisit in supertypes) {
1381+ if (_isBoundSupertypeTo (toVisit, visited)) return true ;
1382+ }
1383+ return false ;
13671384 }
13681385
13691386 @override
@@ -1418,7 +1435,7 @@ class Extension extends Container
14181435 }
14191436
14201437 @override
1421- DefinedElementType get modelType => super .modelType;
1438+ ParameterizedElementType get modelType => super .modelType;
14221439
14231440 List <ModelElement > _allModelElements;
14241441
@@ -5062,13 +5079,11 @@ class PackageGraph {
50625079 package._libraries.sort ((a, b) => compareNatural (a.name, b.name));
50635080 package._libraries.forEach ((library) {
50645081 library.allClasses.forEach (_addToImplementors);
5065- // TODO(jcollins-g): Use a better data structure.
50665082 _extensions.addAll (library.extensions);
50675083 });
50685084 });
50695085 _implementors.values.forEach ((l) => l.sort ());
50705086 allImplementorsAdded = true ;
5071- _extensions.sort (byName);
50725087 allExtensionsAdded = true ;
50735088
50745089 // We should have found all special classes by now.
@@ -5179,8 +5194,7 @@ class PackageGraph {
51795194 final Map <String , List <Class >> _implementors = Map ();
51805195
51815196 /// A list of extensions that exist in the package graph.
5182- // TODO(jcollins-g): Consider implementing a smarter structure for this.
5183- final List <Extension > _extensions = List ();
5197+ final List <Extension > _extensions = [];
51845198
51855199 /// PackageMeta for the default package.
51865200 final PackageMeta packageMeta;
@@ -5212,7 +5226,7 @@ class PackageGraph {
52125226 /// TODO(brianwilkerson) Replace the driver with the session.
52135227 final AnalysisDriver driver;
52145228 final AnalysisSession session;
5215- final TypeSystem typeSystem;
5229+ final Dart2TypeSystem typeSystem;
52165230 final DartSdk sdk;
52175231
52185232 Map <Source , SdkLibrary > _sdkLibrarySources;
0 commit comments