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, |
| 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, starting from this type. If the search fails, |
| 6251 * 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>(), (InterfaceType t) => t.getGetter(name)); |
| 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 (InterfaceType 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>(), (InterfaceType 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( |
| 7248 InterfaceType targetType, |
| 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.add(targetClass)) { |
| 7259 return null; |
| 7260 } |
| 7261 if (includeTargetType) { |
| 7262 ExecutableElement member = getMember(targetType); |
| 7263 if (member != null && member.isAccessibleIn(library)) { |
| 7264 return member; |
| 7265 } |
| 7266 } |
| 7267 for (InterfaceType interfaceType in targetType.interfaces) { |
| 7268 ExecutableElement member = _lookUpMemberInInterfaces( |
| 7269 interfaceType, true, library, visitedInterfaces, getMember); |
| 7270 if (member != null) { |
| 7271 return member; |
| 7272 } |
| 7273 } |
| 7274 for (InterfaceType mixinType in targetType.mixins.reversed) { |
| 7275 PropertyAccessorElement member = _lookUpMemberInInterfaces( |
| 7276 mixinType, true, library, visitedInterfaces, getMember); |
| 7277 if (member != null) { |
| 7278 return member; |
| 7279 } |
| 7280 } |
| 7281 InterfaceType superclass = targetType.superclass; |
| 7282 if (superclass == null) { |
| 7283 return null; |
| 7284 } |
| 7285 return _lookUpMemberInInterfaces( |
| 7286 superclass, true, library, visitedInterfaces, getMember); |
| 7287 } |
7118 } | 7288 } |
7119 | 7289 |
7120 /** | 7290 /** |
7121 * A label associated with a statement. | 7291 * A label associated with a statement. |
7122 */ | 7292 */ |
7123 abstract class LabelElement implements Element { | 7293 abstract class LabelElement implements Element { |
7124 /** | 7294 /** |
7125 * An empty list of label elements. | 7295 * An empty list of label elements. |
7126 */ | 7296 */ |
7127 static const List<LabelElement> EMPTY_LIST = const <LabelElement>[]; | 7297 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) { | 7680 for (ImportElement importElement in imports) { |
7511 (importElement as ImportElementImpl).enclosingElement = this; | 7681 (importElement as ImportElementImpl).enclosingElement = this; |
7512 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; | 7682 PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; |
7513 if (prefix != null) { | 7683 if (prefix != null) { |
7514 prefix.enclosingElement = this; | 7684 prefix.enclosingElement = this; |
7515 } | 7685 } |
7516 } | 7686 } |
7517 this._imports = imports; | 7687 this._imports = imports; |
7518 } | 7688 } |
7519 | 7689 |
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() { | |
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 | 7690 @override |
7572 bool get isBrowserApplication => | 7691 bool get isBrowserApplication => |
7573 entryPoint != null && isOrImportsBrowserLibrary; | 7692 entryPoint != null && isOrImportsBrowserLibrary; |
7574 | 7693 |
7575 @override | 7694 @override |
7576 bool get isDartCore => name == "dart.core"; | 7695 bool get isDartCore => name == "dart.core"; |
7577 | 7696 |
7578 @override | 7697 @override |
7579 bool get isInSdk => | 7698 bool get isInSdk => |
7580 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); | 7699 StringUtilities.startsWith5(name, 0, 0x64, 0x61, 0x72, 0x74, 0x2E); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7798 } | 7917 } |
7799 for (CompilationUnitElement part in _parts) { | 7918 for (CompilationUnitElement part in _parts) { |
7800 type = part.getType(className); | 7919 type = part.getType(className); |
7801 if (type != null) { | 7920 if (type != null) { |
7802 return type; | 7921 return type; |
7803 } | 7922 } |
7804 } | 7923 } |
7805 return null; | 7924 return null; |
7806 } | 7925 } |
7807 | 7926 |
| 7927 /** Given an update to this library which may have added or deleted edges |
| 7928 * in the import/export graph originating from this node only, remove any |
| 7929 * cached library cycles in the element model which may have been invalidated. |
| 7930 */ |
| 7931 void invalidateLibraryCycles() { |
| 7932 if (_libraryCycle == null) { |
| 7933 // We have already invalidated this node, or we have never computed |
| 7934 // library cycle information for it. In the former case, we're done. In |
| 7935 // the latter case, this node cannot be reachable from any node for which |
| 7936 // we have computed library cycle information. Therefore, any edges added |
| 7937 // or deleted in the update causing this invalidation can only be edges to |
| 7938 // nodes which either have no library cycle information (and hence do not |
| 7939 // need invalidation), or which do not reach this node by any path. |
| 7940 // In either case, no further invalidation is needed. |
| 7941 return; |
| 7942 } |
| 7943 // If we have pre-computed library cycle information, then we must |
| 7944 // invalidate the information both on this element, and on certain |
| 7945 // other elements. Edges originating at this node may have been |
| 7946 // added or deleted. A deleted edge that points outside of this cycle |
| 7947 // cannot change the cycle information for anything outside of this cycle, |
| 7948 // and so it is sufficient to delete the cached library information on this |
| 7949 // cycle. An added edge which points to another node within the cycle |
| 7950 // only invalidates the cycle. An added edge which points to a node earlier |
| 7951 // in the topological sort of cycles induces no invalidation (since there |
| 7952 // are by definition no back edges from earlier cycles in the topological |
| 7953 // order, and hence no possible cycle can have been introduced. The only |
| 7954 // remaining case is that we have added an edge to a node which is later |
| 7955 // in the topological sort of cycles. This can induce cycles, since it |
| 7956 // represents a new back edge. It would be sufficient to invalidate the |
| 7957 // cycle information for all nodes that are between the target and the |
| 7958 // node in the topological order. For simplicity, we simply invalidate |
| 7959 // all nodes which are reachable from the the source node. |
| 7960 // Note that in the invalidation phase, we do not cut off when we encounter |
| 7961 // a node with no library cycle information, since we do not know whether |
| 7962 // we are in the case where invalidation has already been performed, or we |
| 7963 // are in the case where library cycles have simply never been computed from |
| 7964 // a newly reachable node. |
| 7965 Set<LibraryElementImpl> active = new HashSet(); |
| 7966 void invalidate(LibraryElementImpl library) { |
| 7967 if (!active.add(library)) return; |
| 7968 if (library._libraryCycle != null) { |
| 7969 library._libraryCycle.forEach(invalidate); |
| 7970 library._libraryCycle = null; |
| 7971 } |
| 7972 library.exportedLibraries.forEach(invalidate); |
| 7973 library.importedLibraries.forEach(invalidate); |
| 7974 } |
| 7975 invalidate(this); |
| 7976 } |
| 7977 |
7808 @override | 7978 @override |
7809 bool isUpToDate(int timeStamp) { | 7979 bool isUpToDate(int timeStamp) { |
7810 Set<LibraryElement> visitedLibraries = new Set(); | 7980 Set<LibraryElement> visitedLibraries = new Set(); |
7811 return _safeIsUpToDate(this, timeStamp, visitedLibraries); | 7981 return _safeIsUpToDate(this, timeStamp, visitedLibraries); |
7812 } | 7982 } |
7813 | 7983 |
7814 @override | 7984 @override |
7815 void visitChildren(ElementVisitor visitor) { | 7985 void visitChildren(ElementVisitor visitor) { |
7816 super.visitChildren(visitor); | 7986 super.visitChildren(visitor); |
7817 safelyVisitChild(_definingCompilationUnit, visitor); | 7987 safelyVisitChild(_definingCompilationUnit, visitor); |
(...skipping 3149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10967 | 11137 |
10968 @override | 11138 @override |
10969 void visitElement(Element element) { | 11139 void visitElement(Element element) { |
10970 int offset = element.nameOffset; | 11140 int offset = element.nameOffset; |
10971 if (offset != -1) { | 11141 if (offset != -1) { |
10972 map[offset] = element; | 11142 map[offset] = element; |
10973 } | 11143 } |
10974 super.visitElement(element); | 11144 super.visitElement(element); |
10975 } | 11145 } |
10976 } | 11146 } |
OLD | NEW |