Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library engine.element; | 5 library engine.element; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import 'dart:math' show min; | 8 import 'dart:math' show min; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/utilities_general.dart'; | 10 import 'package:analyzer/src/generated/utilities_general.dart'; |
| (...skipping 4873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4884 * [element]. | 4884 * [element]. |
| 4885 */ | 4885 */ |
| 4886 FunctionTypeImpl(ExecutableElement element, [this.prunedTypedefs]) | 4886 FunctionTypeImpl(ExecutableElement element, [this.prunedTypedefs]) |
| 4887 : super(element, null); | 4887 : super(element, null); |
| 4888 | 4888 |
| 4889 /** | 4889 /** |
| 4890 * Initialize a newly created function type to be declared by the given | 4890 * Initialize a newly created function type to be declared by the given |
| 4891 * [element]. | 4891 * [element]. |
| 4892 */ | 4892 */ |
| 4893 @deprecated // Use new FunctionTypeImpl(element) | 4893 @deprecated // Use new FunctionTypeImpl(element) |
| 4894 FunctionTypeImpl.con1(ExecutableElement element) | 4894 FunctionTypeImpl.con1(ExecutableElement element) : this(element); |
| 4895 : prunedTypedefs = null, | |
| 4896 super(element, null); | |
| 4897 | 4895 |
| 4898 /** | 4896 /** |
| 4899 * Initialize a newly created function type to be declared by the given | 4897 * Initialize a newly created function type to be declared by the given |
| 4900 * [element]. | 4898 * [element]. |
| 4901 */ | 4899 */ |
| 4902 @deprecated // Use new FunctionTypeImpl.forTypedef(element) | 4900 @deprecated // Use new FunctionTypeImpl.forTypedef(element) |
| 4903 FunctionTypeImpl.con2(FunctionTypeAliasElement element) | 4901 FunctionTypeImpl.con2(FunctionTypeAliasElement element) |
| 4904 : prunedTypedefs = null, | 4902 : this.forTypedef(element); |
| 4905 super(element, element == null ? null : element.name); | |
| 4906 | 4903 |
| 4907 /** | 4904 /** |
| 4908 * Initialize a newly created function type to be declared by the given | 4905 * Initialize a newly created function type to be declared by the given |
| 4909 * [element]. | 4906 * [element]. |
| 4910 */ | 4907 */ |
| 4911 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element, | 4908 FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element, |
| 4912 [this.prunedTypedefs]) | 4909 [this.prunedTypedefs]) |
| 4913 : super(element, element == null ? null : element.name); | 4910 : super(element, element == null ? null : element.name); |
| 4914 | 4911 |
| 4915 /** | 4912 /** |
| (...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6228 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a | 6225 * setter) is the result of the lookup. Otherwise, if <i>C</i> has a |
| 6229 * superclass <i>S</i>, then the result of the lookup is the result of | 6226 * superclass <i>S</i>, then the result of the lookup is the result of |
| 6230 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect | 6227 * looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect |
| 6231 * to <i>L</i>. Otherwise, we say that the lookup has failed. | 6228 * to <i>L</i>. Otherwise, we say that the lookup has failed. |
| 6232 * </blockquote> | 6229 * </blockquote> |
| 6233 */ | 6230 */ |
| 6234 PropertyAccessorElement lookUpGetterInSuperclass( | 6231 PropertyAccessorElement lookUpGetterInSuperclass( |
| 6235 String name, LibraryElement library); | 6232 String name, LibraryElement library); |
| 6236 | 6233 |
| 6237 /** | 6234 /** |
| 6235 * Look up the member with the given [name] in this type and all extended | |
| 6236 * and mixed in classes, and by default including [thisType]. If the search | |
| 6237 * fails, this will then search interfaces. | |
| 6238 * | |
| 6239 * Return the element representing the member that was found, or `null` if | |
| 6240 * there is no getter with the given name. | |
| 6241 * | |
| 6242 * The [library] determines if a private member name is visible, and does not | |
| 6243 * need to be supplied for public names. | |
| 6244 */ | |
| 6245 PropertyAccessorElement lookUpInheritedGetter(String name, | |
|
Jennifer Messerly
2015/10/29 16:36:40
the intent of these methods is to expose the same
| |
| 6246 {LibraryElement library, bool thisType: true}); | |
| 6247 | |
| 6248 /** | |
| 6249 * Look up the member with the given [name] in this type and all extended | |
| 6250 * and mixed in classes, and by default including [thisType]. If the search | |
|
Paul Berry
2015/10/29 16:29:59
Change this comment to reflect the fact that for `
Jennifer Messerly
2015/10/29 17:24:33
Done.
Paul Berry
2015/10/29 17:57:47
Looks like maybe you overfixed this? You've remov
Jennifer Messerly
2015/10/29 18:12:42
oops. Yes :)
| |
| 6251 * fails, this will then search interfaces. | |
| 6252 * | |
| 6253 * Return the element representing the member that was found, or `null` if | |
| 6254 * there is no getter with the given name. | |
| 6255 * | |
| 6256 * The [library] determines if a private member name is visible, and does not | |
| 6257 * need to be supplied for public names. | |
| 6258 */ | |
| 6259 ExecutableElement lookUpInheritedGetterOrMethod(String name, | |
| 6260 {LibraryElement library}); | |
| 6261 | |
| 6262 /** | |
| 6263 * Look up the member with the given [name] in this type and all extended | |
| 6264 * and mixed in classes, and by default including [thisType]. If the search | |
| 6265 * fails, this will then search interfaces. | |
| 6266 * | |
| 6267 * Return the element representing the member that was found, or `null` if | |
| 6268 * there is no getter with the given name. | |
| 6269 * | |
| 6270 * The [library] determines if a private member name is visible, and does not | |
| 6271 * need to be supplied for public names. | |
| 6272 */ | |
| 6273 MethodElement lookUpInheritedMethod(String name, | |
| 6274 {LibraryElement library, bool thisType: true}); | |
| 6275 | |
| 6276 /** | |
| 6277 * Look up the member with the given [name] in this type and all extended | |
| 6278 * and mixed in classes, and by default including [thisType]. If the search | |
| 6279 * fails, this will then search interfaces. | |
| 6280 * | |
| 6281 * Return the element representing the member that was found, or `null` if | |
| 6282 * there is no getter with the given name. | |
| 6283 * | |
| 6284 * The [library] determines if a private member name is visible, and does not | |
| 6285 * need to be supplied for public names. | |
| 6286 */ | |
| 6287 PropertyAccessorElement lookUpInheritedSetter(String name, | |
| 6288 {LibraryElement library, bool thisType: true}); | |
| 6289 | |
| 6290 /** | |
| 6238 * Return the element representing the method that results from looking up the | 6291 * Return the element representing the method that results from looking up the |
| 6239 * method with the given [name] in this class with respect to the given | 6292 * method with the given [name] in this class with respect to the given |
| 6240 * [library], or `null` if the look up fails. The behavior of this method is | 6293 * [library], or `null` if the look up fails. The behavior of this method is |
| 6241 * defined by the Dart Language Specification in section 12.15.1: | 6294 * defined by the Dart Language Specification in section 12.15.1: |
| 6242 * <blockquote> | 6295 * <blockquote> |
| 6243 * The result of looking up method <i>m</i> in class <i>C</i> with respect to | 6296 * The result of looking up method <i>m</i> in class <i>C</i> with respect to |
| 6244 * library <i>L</i> is: | 6297 * library <i>L</i> is: |
| 6245 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible | 6298 * * If <i>C</i> declares an instance method named <i>m</i> that is accessible |
| 6246 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if | 6299 * to <i>L</i>, then that method is the result of the lookup. Otherwise, if |
| 6247 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the | 6300 * <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6835 return element; | 6888 return element; |
| 6836 } | 6889 } |
| 6837 } | 6890 } |
| 6838 supertype = supertype.superclass; | 6891 supertype = supertype.superclass; |
| 6839 supertypeElement = supertype == null ? null : supertype.element; | 6892 supertypeElement = supertype == null ? null : supertype.element; |
| 6840 } | 6893 } |
| 6841 return null; | 6894 return null; |
| 6842 } | 6895 } |
| 6843 | 6896 |
| 6844 @override | 6897 @override |
| 6898 PropertyAccessorElement lookUpInheritedGetter(String name, | |
| 6899 {LibraryElement library, bool thisType: true}) { | |
| 6900 PropertyAccessorElement result; | |
| 6901 if (thisType) { | |
| 6902 result = lookUpGetter(name, library); | |
| 6903 } else { | |
| 6904 result = lookUpGetterInSuperclass(name, library); | |
| 6905 } | |
| 6906 if (result != null) { | |
| 6907 return result; | |
| 6908 } | |
| 6909 return _lookUpMemberInInterfaces(this, false, library, | |
| 6910 new HashSet<ClassElement>(), (t) => t.getGetter(name)); | |
|
Brian Wilkerson
2015/10/29 15:32:01
We fully type everything in the analyzer, so I'd p
Jennifer Messerly
2015/10/29 17:24:33
Oops, good catch. Done!
I wonder if we can turn
Brian Wilkerson
2015/10/29 17:57:54
I use type annotations in order to express my inte
| |
| 6911 } | |
| 6912 | |
| 6913 @override | |
| 6914 ExecutableElement lookUpInheritedGetterOrMethod(String name, | |
| 6915 {LibraryElement library}) { | |
| 6916 ExecutableElement result = | |
| 6917 lookUpGetter(name, library) ?? lookUpMethod(name, library); | |
| 6918 | |
| 6919 if (result != null) { | |
| 6920 return result; | |
| 6921 } | |
| 6922 return _lookUpMemberInInterfaces( | |
| 6923 this, | |
| 6924 false, | |
| 6925 library, | |
| 6926 new HashSet<ClassElement>(), | |
| 6927 (t) => t.getGetter(name) ?? t.getMethod(name)); | |
| 6928 } | |
| 6929 | |
| 6930 @override | |
| 6931 MethodElement lookUpInheritedMethod(String name, | |
| 6932 {LibraryElement library, bool thisType: true}) { | |
| 6933 MethodElement result; | |
| 6934 if (thisType) { | |
| 6935 result = lookUpMethod(name, library); | |
| 6936 } else { | |
| 6937 result = lookUpMethodInSuperclass(name, library); | |
| 6938 } | |
| 6939 if (result != null) { | |
| 6940 return result; | |
| 6941 } | |
| 6942 return _lookUpMemberInInterfaces(this, false, library, | |
| 6943 new HashSet<ClassElement>(), (t) => t.getMethod(name)); | |
| 6944 } | |
| 6945 | |
| 6946 @override | |
| 6947 PropertyAccessorElement lookUpInheritedSetter(String name, | |
| 6948 {LibraryElement library, bool thisType: true}) { | |
| 6949 PropertyAccessorElement result; | |
| 6950 if (thisType) { | |
| 6951 result = lookUpSetter(name, library); | |
| 6952 } else { | |
| 6953 result = lookUpSetterInSuperclass(name, library); | |
| 6954 } | |
| 6955 if (result != null) { | |
| 6956 return result; | |
| 6957 } | |
| 6958 return _lookUpMemberInInterfaces(this, false, library, | |
| 6959 new HashSet<ClassElement>(), (t) => t.getSetter(name)); | |
| 6960 } | |
| 6961 | |
| 6962 @override | |
| 6845 MethodElement lookUpMethod(String methodName, LibraryElement library) { | 6963 MethodElement lookUpMethod(String methodName, LibraryElement library) { |
| 6846 MethodElement element = getMethod(methodName); | 6964 MethodElement element = getMethod(methodName); |
| 6847 if (element != null && element.isAccessibleIn(library)) { | 6965 if (element != null && element.isAccessibleIn(library)) { |
| 6848 return element; | 6966 return element; |
| 6849 } | 6967 } |
| 6850 return lookUpMethodInSuperclass(methodName, library); | 6968 return lookUpMethodInSuperclass(methodName, library); |
| 6851 } | 6969 } |
| 6852 | 6970 |
| 6853 @override | 6971 @override |
| 6854 MethodElement lookUpMethodInSuperclass( | 6972 MethodElement lookUpMethodInSuperclass( |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7108 /** | 7226 /** |
| 7109 * Return the intersection of the [first] and [second] sets of types, where | 7227 * Return the intersection of the [first] and [second] sets of types, where |
| 7110 * intersection is based on the equality of the types themselves. | 7228 * intersection is based on the equality of the types themselves. |
| 7111 */ | 7229 */ |
| 7112 static List<InterfaceType> _intersection( | 7230 static List<InterfaceType> _intersection( |
| 7113 Set<InterfaceType> first, Set<InterfaceType> second) { | 7231 Set<InterfaceType> first, Set<InterfaceType> second) { |
| 7114 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); | 7232 Set<InterfaceType> result = new HashSet<InterfaceType>.from(first); |
| 7115 result.retainAll(second); | 7233 result.retainAll(second); |
| 7116 return new List.from(result); | 7234 return new List.from(result); |
| 7117 } | 7235 } |
| 7236 | |
| 7237 /** | |
| 7238 * Look up the getter with the given [name] in the interfaces | |
| 7239 * implemented by the given [targetType], either directly or indirectly. | |
| 7240 * Return the element representing the getter that was found, or `null` if | |
| 7241 * there is no getter with the given name. The flag [includeTargetType] should | |
| 7242 * be `true` if the search should include the target type. The | |
| 7243 * [visitedInterfaces] is a set containing all of the interfaces that have | |
| 7244 * been examined, used to prevent infinite recursion and to optimize the | |
| 7245 * search. | |
| 7246 */ | |
| 7247 static ExecutableElement _lookUpMemberInInterfaces( | |
|
Jennifer Messerly
2015/10/29 16:36:40
this method replaced 4 variants that existed previ
| |
| 7248 InterfaceType targetType, | |
|
Brian Wilkerson
2015/10/29 15:32:01
nit: This was probably copy/pasted, but this metho
Jennifer Messerly
2015/10/29 17:24:33
yeah ... actually tried that first, the problem is
Brian Wilkerson
2015/10/29 17:57:54
I agree. Leave it as it is and we can address it l
| |
| 7249 bool includeTargetType, | |
| 7250 LibraryElement library, | |
| 7251 HashSet<ClassElement> visitedInterfaces, | |
| 7252 ExecutableElement getMember(InterfaceType type)) { | |
| 7253 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | |
| 7254 // specification (titled "Inheritance and Overriding" under "Interfaces") | |
| 7255 // describes a much more complex scheme for finding the inherited member. | |
| 7256 // We need to follow that scheme. The code below should cover the 80% case. | |
| 7257 ClassElement targetClass = targetType.element; | |
| 7258 if (visitedInterfaces.contains(targetClass)) { | |
|
Brian Wilkerson
2015/10/29 15:32:01
nit: This was probably copy/pasted, but it would b
Jennifer Messerly
2015/10/29 17:24:33
good catch! Done.
| |
| 7259 return null; | |
| 7260 } | |
| 7261 visitedInterfaces.add(targetClass); | |
| 7262 if (includeTargetType) { | |
| 7263 ExecutableElement member = getMember(targetType); | |
| 7264 if (member != null && member.isAccessibleIn(library)) { | |
| 7265 return member; | |
| 7266 } | |
| 7267 } | |
| 7268 for (InterfaceType interfaceType in targetType.interfaces) { | |
| 7269 ExecutableElement member = _lookUpMemberInInterfaces( | |
| 7270 interfaceType, true, library, visitedInterfaces, getMember); | |
| 7271 if (member != null) { | |
| 7272 return member; | |
| 7273 } | |
| 7274 } | |
| 7275 for (InterfaceType mixinType in targetType.mixins.reversed) { | |
| 7276 PropertyAccessorElement member = _lookUpMemberInInterfaces( | |
| 7277 mixinType, true, library, visitedInterfaces, getMember); | |
| 7278 if (member != null) { | |
| 7279 return member; | |
| 7280 } | |
| 7281 } | |
| 7282 InterfaceType superclass = targetType.superclass; | |
| 7283 if (superclass == null) { | |
| 7284 return null; | |
| 7285 } | |
| 7286 return _lookUpMemberInInterfaces( | |
| 7287 superclass, true, library, visitedInterfaces, getMember); | |
| 7288 } | |
| 7118 } | 7289 } |
| 7119 | 7290 |
| 7120 /** | 7291 /** |
| 7121 * A label associated with a statement. | 7292 * A label associated with a statement. |
| 7122 */ | 7293 */ |
| 7123 abstract class LabelElement implements Element { | 7294 abstract class LabelElement implements Element { |
| 7124 /** | 7295 /** |
| 7125 * An empty list of label elements. | 7296 * An empty list of label elements. |
| 7126 */ | 7297 */ |
| 7127 static const List<LabelElement> EMPTY_LIST = const <LabelElement>[]; | 7298 static const List<LabelElement> EMPTY_LIST = const <LabelElement>[]; |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7510 for (ImportElement importElement in imports) { | 7681 for (ImportElement importElement in imports) { |
| 7511 (importElement as ImportElementImpl).enclosingElement = this; | 7682 (importElement as ImportElementImpl).enclosingElement = this; |
| 7512 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; | 7683 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; |
| 7513 if (prefix != null) { | 7684 if (prefix != null) { |
| 7514 prefix.enclosingElement = this; | 7685 prefix.enclosingElement = this; |
| 7515 } | 7686 } |
| 7516 } | 7687 } |
| 7517 this._imports = imports; | 7688 this._imports = imports; |
| 7518 } | 7689 } |
| 7519 | 7690 |
| 7520 /** Given an update to this library which may have added or deleted edges | |
| 7521 * in the import/export graph originating from this node only, remove any | |
| 7522 * cached library cycles in the element model which may have been invalidated. | |
| 7523 */ | |
| 7524 void invalidateLibraryCycles() { | |
|
Jennifer Messerly
2015/10/29 16:36:40
I didn't change this method ... it was moved by so
Brian Wilkerson
2015/10/29 17:57:54
No need. I've learned to recognize and ignore chur
| |
| 7525 if (_libraryCycle == null) { | |
| 7526 // We have already invalidated this node, or we have never computed | |
| 7527 // library cycle information for it. In the former case, we're done. In | |
| 7528 // the latter case, this node cannot be reachable from any node for which | |
| 7529 // we have computed library cycle information. Therefore, any edges added | |
| 7530 // or deleted in the update causing this invalidation can only be edges to | |
| 7531 // nodes which either have no library cycle information (and hence do not | |
| 7532 // need invalidation), or which do not reach this node by any path. | |
| 7533 // In either case, no further invalidation is needed. | |
| 7534 return; | |
| 7535 } | |
| 7536 // If we have pre-computed library cycle information, then we must | |
| 7537 // invalidate the information both on this element, and on certain | |
| 7538 // other elements. Edges originating at this node may have been | |
| 7539 // added or deleted. A deleted edge that points outside of this cycle | |
| 7540 // cannot change the cycle information for anything outside of this cycle, | |
| 7541 // and so it is sufficient to delete the cached library information on this | |
| 7542 // cycle. An added edge which points to another node within the cycle | |
| 7543 // only invalidates the cycle. An added edge which points to a node earlier | |
| 7544 // in the topological sort of cycles induces no invalidation (since there | |
| 7545 // are by definition no back edges from earlier cycles in the topological | |
| 7546 // order, and hence no possible cycle can have been introduced. The only | |
| 7547 // remaining case is that we have added an edge to a node which is later | |
| 7548 // in the topological sort of cycles. This can induce cycles, since it | |
| 7549 // represents a new back edge. It would be sufficient to invalidate the | |
| 7550 // cycle information for all nodes that are between the target and the | |
| 7551 // node in the topological order. For simplicity, we simply invalidate | |
| 7552 // all nodes which are reachable from the the source node. | |
| 7553 // Note that in the invalidation phase, we do not cut off when we encounter | |
| 7554 // a node with no library cycle information, since we do not know whether | |
| 7555 // we are in the case where invalidation has already been performed, or we | |
| 7556 // are in the case where library cycles have simply never been computed from | |
| 7557 // a newly reachable node. | |
| 7558 Set<LibraryElementImpl> active = new HashSet(); | |
| 7559 void invalidate(LibraryElementImpl library) { | |
| 7560 if (!active.add(library)) return; | |
| 7561 if (library._libraryCycle != null) { | |
| 7562 library._libraryCycle.forEach(invalidate); | |
| 7563 library._libraryCycle = null; | |
| 7564 } | |
| 7565 library.exportedLibraries.forEach(invalidate); | |
| 7566 library.importedLibraries.forEach(invalidate); | |
| 7567 } | |
| 7568 invalidate(this); | |
| 7569 } | |
| 7570 | |
| 7571 @override | 7691 @override |
| 7572 bool get isBrowserApplication => | 7692 bool get isBrowserApplication => |
| 7573 entryPoint != null && isOrImportsBrowserLibrary; | 7693 entryPoint != null && isOrImportsBrowserLibrary; |
| 7574 | 7694 |
| 7575 @override | 7695 @override |
| 7576 bool get isDartCore => name == "dart.core"; | 7696 bool get isDartCore => name == "dart.core"; |
| 7577 | 7697 |
| 7578 @override | 7698 @override |
| 7579 bool get isInSdk => | 7699 bool get isInSdk => |
| 7580 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); | 7700 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7798 } | 7918 } |
| 7799 for (CompilationUnitElement part in _parts) { | 7919 for (CompilationUnitElement part in _parts) { |
| 7800 type = part.getType(className); | 7920 type = part.getType(className); |
| 7801 if (type != null) { | 7921 if (type != null) { |
| 7802 return type; | 7922 return type; |
| 7803 } | 7923 } |
| 7804 } | 7924 } |
| 7805 return null; | 7925 return null; |
| 7806 } | 7926 } |
| 7807 | 7927 |
| 7928 /** Given an update to this library which may have added or deleted edges | |
| 7929 * in the import/export graph originating from this node only, remove any | |
| 7930 * cached library cycles in the element model which may have been invalidated. | |
| 7931 */ | |
| 7932 void invalidateLibraryCycles() { | |
| 7933 if (_libraryCycle == null) { | |
| 7934 // We have already invalidated this node, or we have never computed | |
| 7935 // library cycle information for it. In the former case, we're done. In | |
| 7936 // the latter case, this node cannot be reachable from any node for which | |
| 7937 // we have computed library cycle information. Therefore, any edges added | |
| 7938 // or deleted in the update causing this invalidation can only be edges to | |
| 7939 // nodes which either have no library cycle information (and hence do not | |
| 7940 // need invalidation), or which do not reach this node by any path. | |
| 7941 // In either case, no further invalidation is needed. | |
| 7942 return; | |
| 7943 } | |
| 7944 // If we have pre-computed library cycle information, then we must | |
| 7945 // invalidate the information both on this element, and on certain | |
| 7946 // other elements. Edges originating at this node may have been | |
| 7947 // added or deleted. A deleted edge that points outside of this cycle | |
| 7948 // cannot change the cycle information for anything outside of this cycle, | |
| 7949 // and so it is sufficient to delete the cached library information on this | |
| 7950 // cycle. An added edge which points to another node within the cycle | |
| 7951 // only invalidates the cycle. An added edge which points to a node earlier | |
| 7952 // in the topological sort of cycles induces no invalidation (since there | |
| 7953 // are by definition no back edges from earlier cycles in the topological | |
| 7954 // order, and hence no possible cycle can have been introduced. The only | |
| 7955 // remaining case is that we have added an edge to a node which is later | |
| 7956 // in the topological sort of cycles. This can induce cycles, since it | |
| 7957 // represents a new back edge. It would be sufficient to invalidate the | |
| 7958 // cycle information for all nodes that are between the target and the | |
| 7959 // node in the topological order. For simplicity, we simply invalidate | |
| 7960 // all nodes which are reachable from the the source node. | |
| 7961 // Note that in the invalidation phase, we do not cut off when we encounter | |
| 7962 // a node with no library cycle information, since we do not know whether | |
| 7963 // we are in the case where invalidation has already been performed, or we | |
| 7964 // are in the case where library cycles have simply never been computed from | |
| 7965 // a newly reachable node. | |
| 7966 Set<LibraryElementImpl> active = new HashSet(); | |
| 7967 void invalidate(LibraryElementImpl library) { | |
| 7968 if (!active.add(library)) return; | |
| 7969 if (library._libraryCycle != null) { | |
| 7970 library._libraryCycle.forEach(invalidate); | |
| 7971 library._libraryCycle = null; | |
| 7972 } | |
| 7973 library.exportedLibraries.forEach(invalidate); | |
| 7974 library.importedLibraries.forEach(invalidate); | |
| 7975 } | |
| 7976 invalidate(this); | |
| 7977 } | |
| 7978 | |
| 7808 @override | 7979 @override |
| 7809 bool isUpToDate(int timeStamp) { | 7980 bool isUpToDate(int timeStamp) { |
| 7810 Set<LibraryElement> visitedLibraries = new Set(); | 7981 Set<LibraryElement> visitedLibraries = new Set(); |
| 7811 return _safeIsUpToDate(this, timeStamp, visitedLibraries); | 7982 return _safeIsUpToDate(this, timeStamp, visitedLibraries); |
| 7812 } | 7983 } |
| 7813 | 7984 |
| 7814 @override | 7985 @override |
| 7815 void visitChildren(ElementVisitor visitor) { | 7986 void visitChildren(ElementVisitor visitor) { |
| 7816 super.visitChildren(visitor); | 7987 super.visitChildren(visitor); |
| 7817 safelyVisitChild(_definingCompilationUnit, visitor); | 7988 safelyVisitChild(_definingCompilationUnit, visitor); |
| (...skipping 3149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10967 | 11138 |
| 10968 @override | 11139 @override |
| 10969 void visitElement(Element element) { | 11140 void visitElement(Element element) { |
| 10970 int offset = element.nameOffset; | 11141 int offset = element.nameOffset; |
| 10971 if (offset != -1) { | 11142 if (offset != -1) { |
| 10972 map[offset] = element; | 11143 map[offset] = element; |
| 10973 } | 11144 } |
| 10974 super.visitElement(element); | 11145 super.visitElement(element); |
| 10975 } | 11146 } |
| 10976 } | 11147 } |
| OLD | NEW |