Index: pkg/analyzer/lib/src/generated/element.dart |
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart |
index 2c3e830ab95f03df9bbbc4cce2f35acc0d26fc1f..307e6fe4db3efa6578511d14c5a15143ba09c7fc 100644 |
--- a/pkg/analyzer/lib/src/generated/element.dart |
+++ b/pkg/analyzer/lib/src/generated/element.dart |
@@ -4891,9 +4891,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
* [element]. |
*/ |
@deprecated // Use new FunctionTypeImpl(element) |
- FunctionTypeImpl.con1(ExecutableElement element) |
- : prunedTypedefs = null, |
- super(element, null); |
+ FunctionTypeImpl.con1(ExecutableElement element) : this(element); |
/** |
* Initialize a newly created function type to be declared by the given |
@@ -4901,8 +4899,7 @@ class FunctionTypeImpl extends TypeImpl implements FunctionType { |
*/ |
@deprecated // Use new FunctionTypeImpl.forTypedef(element) |
FunctionTypeImpl.con2(FunctionTypeAliasElement element) |
- : prunedTypedefs = null, |
- super(element, element == null ? null : element.name); |
+ : this.forTypedef(element); |
/** |
* Initialize a newly created function type to be declared by the given |
@@ -6235,6 +6232,62 @@ abstract class InterfaceType implements ParameterizedType { |
String name, LibraryElement library); |
/** |
+ * Look up the member with the given [name] in this type and all extended |
+ * and mixed in classes, and by default including [thisType]. If the search |
+ * fails, this will then search interfaces. |
+ * |
+ * Return the element representing the member that was found, or `null` if |
+ * there is no getter with the given name. |
+ * |
+ * The [library] determines if a private member name is visible, and does not |
+ * need to be supplied for public names. |
+ */ |
+ PropertyAccessorElement lookUpInheritedGetter(String name, |
+ {LibraryElement library, bool thisType: true}); |
+ |
+ /** |
+ * Look up the member with the given [name] in this type and all extended |
+ * and mixed in classes, starting from this type. If the search fails, |
+ * search interfaces. |
+ * |
+ * Return the element representing the member that was found, or `null` if |
+ * there is no getter with the given name. |
+ * |
+ * The [library] determines if a private member name is visible, and does not |
+ * need to be supplied for public names. |
+ */ |
+ ExecutableElement lookUpInheritedGetterOrMethod(String name, |
+ {LibraryElement library}); |
+ |
+ /** |
+ * Look up the member with the given [name] in this type and all extended |
+ * and mixed in classes, and by default including [thisType]. If the search |
+ * fails, this will then search interfaces. |
+ * |
+ * Return the element representing the member that was found, or `null` if |
+ * there is no getter with the given name. |
+ * |
+ * The [library] determines if a private member name is visible, and does not |
+ * need to be supplied for public names. |
+ */ |
+ MethodElement lookUpInheritedMethod(String name, |
+ {LibraryElement library, bool thisType: true}); |
+ |
+ /** |
+ * Look up the member with the given [name] in this type and all extended |
+ * and mixed in classes, and by default including [thisType]. If the search |
+ * fails, this will then search interfaces. |
+ * |
+ * Return the element representing the member that was found, or `null` if |
+ * there is no getter with the given name. |
+ * |
+ * The [library] determines if a private member name is visible, and does not |
+ * need to be supplied for public names. |
+ */ |
+ PropertyAccessorElement lookUpInheritedSetter(String name, |
+ {LibraryElement library, bool thisType: true}); |
+ |
+ /** |
* Return the element representing the method that results from looking up the |
* method with the given [name] in this class with respect to the given |
* [library], or `null` if the look up fails. The behavior of this method is |
@@ -6842,6 +6895,71 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
} |
@override |
+ PropertyAccessorElement lookUpInheritedGetter(String name, |
+ {LibraryElement library, bool thisType: true}) { |
+ PropertyAccessorElement result; |
+ if (thisType) { |
+ result = lookUpGetter(name, library); |
+ } else { |
+ result = lookUpGetterInSuperclass(name, library); |
+ } |
+ if (result != null) { |
+ return result; |
+ } |
+ return _lookUpMemberInInterfaces(this, false, library, |
+ new HashSet<ClassElement>(), (InterfaceType t) => t.getGetter(name)); |
+ } |
+ |
+ @override |
+ ExecutableElement lookUpInheritedGetterOrMethod(String name, |
+ {LibraryElement library}) { |
+ ExecutableElement result = |
+ lookUpGetter(name, library) ?? lookUpMethod(name, library); |
+ |
+ if (result != null) { |
+ return result; |
+ } |
+ return _lookUpMemberInInterfaces( |
+ this, |
+ false, |
+ library, |
+ new HashSet<ClassElement>(), |
+ (InterfaceType t) => t.getGetter(name) ?? t.getMethod(name)); |
+ } |
+ |
+ @override |
+ MethodElement lookUpInheritedMethod(String name, |
+ {LibraryElement library, bool thisType: true}) { |
+ MethodElement result; |
+ if (thisType) { |
+ result = lookUpMethod(name, library); |
+ } else { |
+ result = lookUpMethodInSuperclass(name, library); |
+ } |
+ if (result != null) { |
+ return result; |
+ } |
+ return _lookUpMemberInInterfaces(this, false, library, |
+ new HashSet<ClassElement>(), (InterfaceType t) => t.getMethod(name)); |
+ } |
+ |
+ @override |
+ PropertyAccessorElement lookUpInheritedSetter(String name, |
+ {LibraryElement library, bool thisType: true}) { |
+ PropertyAccessorElement result; |
+ if (thisType) { |
+ result = lookUpSetter(name, library); |
+ } else { |
+ result = lookUpSetterInSuperclass(name, library); |
+ } |
+ if (result != null) { |
+ return result; |
+ } |
+ return _lookUpMemberInInterfaces(this, false, library, |
+ new HashSet<ClassElement>(), (t) => t.getSetter(name)); |
+ } |
+ |
+ @override |
MethodElement lookUpMethod(String methodName, LibraryElement library) { |
MethodElement element = getMethod(methodName); |
if (element != null && element.isAccessibleIn(library)) { |
@@ -7115,6 +7233,58 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType { |
result.retainAll(second); |
return new List.from(result); |
} |
+ |
+ /** |
+ * Look up the getter with the given [name] in the interfaces |
+ * implemented by the given [targetType], either directly or indirectly. |
+ * Return the element representing the getter that was found, or `null` if |
+ * there is no getter with the given name. The flag [includeTargetType] should |
+ * be `true` if the search should include the target type. The |
+ * [visitedInterfaces] is a set containing all of the interfaces that have |
+ * been examined, used to prevent infinite recursion and to optimize the |
+ * search. |
+ */ |
+ static ExecutableElement _lookUpMemberInInterfaces( |
+ InterfaceType targetType, |
+ bool includeTargetType, |
+ LibraryElement library, |
+ HashSet<ClassElement> visitedInterfaces, |
+ ExecutableElement getMember(InterfaceType type)) { |
+ // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
+ // specification (titled "Inheritance and Overriding" under "Interfaces") |
+ // describes a much more complex scheme for finding the inherited member. |
+ // We need to follow that scheme. The code below should cover the 80% case. |
+ ClassElement targetClass = targetType.element; |
+ if (!visitedInterfaces.add(targetClass)) { |
+ return null; |
+ } |
+ if (includeTargetType) { |
+ ExecutableElement member = getMember(targetType); |
+ if (member != null && member.isAccessibleIn(library)) { |
+ return member; |
+ } |
+ } |
+ for (InterfaceType interfaceType in targetType.interfaces) { |
+ ExecutableElement member = _lookUpMemberInInterfaces( |
+ interfaceType, true, library, visitedInterfaces, getMember); |
+ if (member != null) { |
+ return member; |
+ } |
+ } |
+ for (InterfaceType mixinType in targetType.mixins.reversed) { |
+ PropertyAccessorElement member = _lookUpMemberInInterfaces( |
+ mixinType, true, library, visitedInterfaces, getMember); |
+ if (member != null) { |
+ return member; |
+ } |
+ } |
+ InterfaceType superclass = targetType.superclass; |
+ if (superclass == null) { |
+ return null; |
+ } |
+ return _lookUpMemberInInterfaces( |
+ superclass, true, library, visitedInterfaces, getMember); |
+ } |
} |
/** |
@@ -7517,57 +7687,6 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
this._imports = imports; |
} |
- /** Given an update to this library which may have added or deleted edges |
- * in the import/export graph originating from this node only, remove any |
- * cached library cycles in the element model which may have been invalidated. |
- */ |
- void invalidateLibraryCycles() { |
- if (_libraryCycle == null) { |
- // We have already invalidated this node, or we have never computed |
- // library cycle information for it. In the former case, we're done. In |
- // the latter case, this node cannot be reachable from any node for which |
- // we have computed library cycle information. Therefore, any edges added |
- // or deleted in the update causing this invalidation can only be edges to |
- // nodes which either have no library cycle information (and hence do not |
- // need invalidation), or which do not reach this node by any path. |
- // In either case, no further invalidation is needed. |
- return; |
- } |
- // If we have pre-computed library cycle information, then we must |
- // invalidate the information both on this element, and on certain |
- // other elements. Edges originating at this node may have been |
- // added or deleted. A deleted edge that points outside of this cycle |
- // cannot change the cycle information for anything outside of this cycle, |
- // and so it is sufficient to delete the cached library information on this |
- // cycle. An added edge which points to another node within the cycle |
- // only invalidates the cycle. An added edge which points to a node earlier |
- // in the topological sort of cycles induces no invalidation (since there |
- // are by definition no back edges from earlier cycles in the topological |
- // order, and hence no possible cycle can have been introduced. The only |
- // remaining case is that we have added an edge to a node which is later |
- // in the topological sort of cycles. This can induce cycles, since it |
- // represents a new back edge. It would be sufficient to invalidate the |
- // cycle information for all nodes that are between the target and the |
- // node in the topological order. For simplicity, we simply invalidate |
- // all nodes which are reachable from the the source node. |
- // Note that in the invalidation phase, we do not cut off when we encounter |
- // a node with no library cycle information, since we do not know whether |
- // we are in the case where invalidation has already been performed, or we |
- // are in the case where library cycles have simply never been computed from |
- // a newly reachable node. |
- Set<LibraryElementImpl> active = new HashSet(); |
- void invalidate(LibraryElementImpl library) { |
- if (!active.add(library)) return; |
- if (library._libraryCycle != null) { |
- library._libraryCycle.forEach(invalidate); |
- library._libraryCycle = null; |
- } |
- library.exportedLibraries.forEach(invalidate); |
- library.importedLibraries.forEach(invalidate); |
- } |
- invalidate(this); |
- } |
- |
@override |
bool get isBrowserApplication => |
entryPoint != null && isOrImportsBrowserLibrary; |
@@ -7805,6 +7924,57 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
return null; |
} |
+ /** Given an update to this library which may have added or deleted edges |
+ * in the import/export graph originating from this node only, remove any |
+ * cached library cycles in the element model which may have been invalidated. |
+ */ |
+ void invalidateLibraryCycles() { |
+ if (_libraryCycle == null) { |
+ // We have already invalidated this node, or we have never computed |
+ // library cycle information for it. In the former case, we're done. In |
+ // the latter case, this node cannot be reachable from any node for which |
+ // we have computed library cycle information. Therefore, any edges added |
+ // or deleted in the update causing this invalidation can only be edges to |
+ // nodes which either have no library cycle information (and hence do not |
+ // need invalidation), or which do not reach this node by any path. |
+ // In either case, no further invalidation is needed. |
+ return; |
+ } |
+ // If we have pre-computed library cycle information, then we must |
+ // invalidate the information both on this element, and on certain |
+ // other elements. Edges originating at this node may have been |
+ // added or deleted. A deleted edge that points outside of this cycle |
+ // cannot change the cycle information for anything outside of this cycle, |
+ // and so it is sufficient to delete the cached library information on this |
+ // cycle. An added edge which points to another node within the cycle |
+ // only invalidates the cycle. An added edge which points to a node earlier |
+ // in the topological sort of cycles induces no invalidation (since there |
+ // are by definition no back edges from earlier cycles in the topological |
+ // order, and hence no possible cycle can have been introduced. The only |
+ // remaining case is that we have added an edge to a node which is later |
+ // in the topological sort of cycles. This can induce cycles, since it |
+ // represents a new back edge. It would be sufficient to invalidate the |
+ // cycle information for all nodes that are between the target and the |
+ // node in the topological order. For simplicity, we simply invalidate |
+ // all nodes which are reachable from the the source node. |
+ // Note that in the invalidation phase, we do not cut off when we encounter |
+ // a node with no library cycle information, since we do not know whether |
+ // we are in the case where invalidation has already been performed, or we |
+ // are in the case where library cycles have simply never been computed from |
+ // a newly reachable node. |
+ Set<LibraryElementImpl> active = new HashSet(); |
+ void invalidate(LibraryElementImpl library) { |
+ if (!active.add(library)) return; |
+ if (library._libraryCycle != null) { |
+ library._libraryCycle.forEach(invalidate); |
+ library._libraryCycle = null; |
+ } |
+ library.exportedLibraries.forEach(invalidate); |
+ library.importedLibraries.forEach(invalidate); |
+ } |
+ invalidate(this); |
+ } |
+ |
@override |
bool isUpToDate(int timeStamp) { |
Set<LibraryElement> visitedLibraries = new Set(); |