| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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('elements'); | 5 #library('elements'); |
| 6 | 6 |
| 7 #import('dart:uri'); |
| 8 |
| 7 #import('../tree/tree.dart'); | 9 #import('../tree/tree.dart'); |
| 8 #import('../scanner/scannerlib.dart'); | 10 #import('../scanner/scannerlib.dart'); |
| 9 #import('../leg.dart'); // TODO(karlklose): we only need type. | 11 #import('../leg.dart'); // TODO(karlklose): we only need type. |
| 10 #import('../util/util.dart'); | 12 #import('../util/util.dart'); |
| 11 | 13 |
| 12 class ElementCategory { | 14 class ElementCategory { |
| 13 /** | 15 /** |
| 14 * Represents things that we don't expect to find when looking in a | 16 * Represents things that we don't expect to find when looking in a |
| 15 * scope. | 17 * scope. |
| 16 */ | 18 */ |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 } | 250 } |
| 249 | 251 |
| 250 bool _isNative = false; | 252 bool _isNative = false; |
| 251 void setNative() { _isNative = true; } | 253 void setNative() { _isNative = true; } |
| 252 bool isNative() => _isNative; | 254 bool isNative() => _isNative; |
| 253 | 255 |
| 254 FunctionElement asFunctionElement() => null; | 256 FunctionElement asFunctionElement() => null; |
| 255 } | 257 } |
| 256 | 258 |
| 257 class ContainerElement extends Element { | 259 class ContainerElement extends Element { |
| 258 ContainerElement(name, kind, enclosingElement) : | 260 Link<Element> localMembers = const EmptyLink<Element>(); |
| 259 super(name, kind, enclosingElement); | |
| 260 | 261 |
| 261 abstract void addMember(Element element, DiagnosticListener listener); | 262 ContainerElement(name, kind, enclosingElement) |
| 263 : super(name, kind, enclosingElement); |
| 264 |
| 265 void addMember(Element element, DiagnosticListener listener) { |
| 266 localMembers = localMembers.prepend(element); |
| 267 } |
| 268 } |
| 269 |
| 270 class ScopeContainerElement extends ContainerElement { |
| 271 final Map<SourceString, Element> localScope; |
| 272 |
| 273 ScopeContainerElement(name, kind, enclosingElement) |
| 274 : super(name, kind, enclosingElement), |
| 275 localScope = new Map<SourceString, Element>(); |
| 276 |
| 277 void addMember(Element element, DiagnosticListener listener) { |
| 278 super.addMember(element, listener); |
| 279 addToScope(element, listener); |
| 280 } |
| 281 |
| 282 void addToScope(Element element, DiagnosticListener listener) { |
| 283 if (element.isAccessor()) { |
| 284 addGetterOrSetter(element, localScope[element.name], listener); |
| 285 } else { |
| 286 Element existing = localScope.putIfAbsent(element.name, () => element); |
| 287 if (existing !== element) { |
| 288 listener.cancel('duplicate definition', token: element.position()); |
| 289 listener.cancel('existing definition', token: existing.position()); |
| 290 } |
| 291 } |
| 292 } |
| 293 |
| 294 Element localLookup(SourceString elementName) { |
| 295 return localScope[elementName]; |
| 296 } |
| 262 | 297 |
| 263 void addGetterOrSetter(Element element, | 298 void addGetterOrSetter(Element element, |
| 264 Element existing, | 299 Element existing, |
| 265 DiagnosticListener listener) { | 300 DiagnosticListener listener) { |
| 266 void reportError(Element other) { | 301 void reportError(Element other) { |
| 267 listener.cancel('duplicate definition of ${element.name.slowToString()}', | 302 listener.cancel('duplicate definition of ${element.name.slowToString()}', |
| 268 element: element); | 303 element: element); |
| 269 listener.cancel('existing definition', element: other); | 304 listener.cancel('existing definition', element: other); |
| 270 } | 305 } |
| 271 | 306 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 291 if (element.kind == ElementKind.GETTER) { | 326 if (element.kind == ElementKind.GETTER) { |
| 292 field.getter = element; | 327 field.getter = element; |
| 293 } else { | 328 } else { |
| 294 field.setter = element; | 329 field.setter = element; |
| 295 } | 330 } |
| 296 addMember(field, listener); | 331 addMember(field, listener); |
| 297 } | 332 } |
| 298 } | 333 } |
| 299 } | 334 } |
| 300 | 335 |
| 336 |
| 337 |
| 301 class CompilationUnitElement extends ContainerElement { | 338 class CompilationUnitElement extends ContainerElement { |
| 302 final Script script; | 339 final Script script; |
| 303 Link<Element> topLevelElements = const EmptyLink<Element>(); | |
| 304 | 340 |
| 305 CompilationUnitElement(Script script, Element enclosing) | 341 CompilationUnitElement(Script script, Element enclosing) |
| 306 : this.script = script, | 342 : this.script = script, |
| 307 super(new SourceString(script.name), | 343 super(new SourceString(script.name), |
| 308 ElementKind.COMPILATION_UNIT, | 344 ElementKind.COMPILATION_UNIT, |
| 309 enclosing); | 345 enclosing); |
| 310 | 346 |
| 311 CompilationUnitElement.library(Script script) | |
| 312 : this.script = script, | |
| 313 super(new SourceString(script.name), ElementKind.LIBRARY, null); | |
| 314 | |
| 315 void addMember(Element element, DiagnosticListener listener) { | 347 void addMember(Element element, DiagnosticListener listener) { |
| 316 LibraryElement library = enclosingElement; | 348 // Keep a list of top level members. |
| 317 library.addMember(element, listener); | 349 super.addMember(element, listener); |
| 318 topLevelElements = topLevelElements.prepend(element); | 350 // Provide the member to the library to build scope. |
| 319 } | 351 getLibrary().addMember(element, listener); |
| 320 | |
| 321 void define(Element element, DiagnosticListener listener) { | |
| 322 LibraryElement library = enclosingElement; | |
| 323 library.define(element, listener); | |
| 324 } | |
| 325 | |
| 326 void addTag(ScriptTag tag, DiagnosticListener listener) { | |
| 327 listener.cancel("script tags not allowed here", node: tag); | |
| 328 } | 352 } |
| 329 } | 353 } |
| 330 | 354 |
| 331 class LibraryElement extends CompilationUnitElement { | 355 class LibraryElement extends ScopeContainerElement { |
| 332 // TODO(ahe): Library element should not be a subclass of | 356 CompilationUnitElement entryCompilationUnit; |
| 333 // CompilationUnitElement. | 357 Link<CompilationUnitElement> compilationUnits = |
| 358 const EmptyLink<CompilationUnitElement>(); |
| 334 | 359 |
| 335 Link<CompilationUnitElement> compilationUnits = | |
| 336 const EmptyLink<CompilationUnitElement>(); | |
| 337 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); | 360 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); |
| 338 ScriptTag libraryTag; | 361 ScriptTag libraryTag; |
| 339 Map<SourceString, Element> elements; | |
| 340 bool canUseNative = false; | 362 bool canUseNative = false; |
| 341 LibraryElement patch = null; | 363 LibraryElement patch = null; |
| 342 | 364 |
| 343 LibraryElement(Script script) | 365 LibraryElement(Script script) |
| 344 : elements = new Map<SourceString, Element>(), | 366 : super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 345 super.library(script); | 367 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 368 } |
| 369 |
| 370 Uri get uri() => entryCompilationUnit.script.uri; |
| 346 | 371 |
| 347 bool get isPatched() => patch !== null; | 372 bool get isPatched() => patch !== null; |
| 348 | 373 |
| 349 void addCompilationUnit(CompilationUnitElement element) { | 374 void addCompilationUnit(CompilationUnitElement element) { |
| 350 compilationUnits = compilationUnits.prepend(element); | 375 compilationUnits = compilationUnits.prepend(element); |
| 351 } | 376 } |
| 352 | 377 |
| 353 void addTag(ScriptTag tag, DiagnosticListener listener) { | 378 void addTag(ScriptTag tag, DiagnosticListener listener) { |
| 354 tags = tags.prepend(tag); | 379 tags = tags.prepend(tag); |
| 355 } | 380 } |
| 356 | 381 |
| 357 void addMember(Element element, DiagnosticListener listener) { | |
| 358 topLevelElements = topLevelElements.prepend(element); | |
| 359 define(element, listener); | |
| 360 } | |
| 361 | |
| 362 void define(Element element, DiagnosticListener listener) { | |
| 363 if (element.kind == ElementKind.GETTER | |
| 364 || element.kind == ElementKind.SETTER) { | |
| 365 addGetterOrSetter(element, elements[element.name], listener); | |
| 366 } else { | |
| 367 Element existing = elements.putIfAbsent(element.name, () => element); | |
| 368 if (existing !== element) { | |
| 369 listener.cancel('duplicate definition', token: element.position()); | |
| 370 listener.cancel('existing definition', token: existing.position()); | |
| 371 } | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 /** Look up a top-level element in this library. The element could | 382 /** Look up a top-level element in this library. The element could |
| 376 * potentially have been imported from another library. Returns | 383 * potentially have been imported from another library. Returns |
| 377 * null if no such element exist. */ | 384 * null if no such element exist. */ |
| 378 Element find(SourceString elementName) { | 385 Element find(SourceString elementName) { |
| 379 return elements[elementName]; | 386 return localScope[elementName]; |
| 380 } | 387 } |
| 381 | 388 |
| 382 /** Look up a top-level element in this library, but only look for | 389 /** Look up a top-level element in this library, but only look for |
| 383 * non-imported elements. Returns null if no such element exist. */ | 390 * non-imported elements. Returns null if no such element exist. */ |
| 384 Element findLocal(SourceString elementName) { | 391 Element findLocal(SourceString elementName) { |
| 385 Element result = elements[elementName]; | 392 Element result = localScope[elementName]; |
| 386 if (result === null || result.getLibrary() != this) return null; | 393 if (result === null || result.getLibrary() != this) return null; |
| 387 return result; | 394 return result; |
| 388 } | 395 } |
| 389 | 396 |
| 390 void forEachExport(f(Element element)) { | 397 void forEachExport(f(Element element)) { |
| 391 elements.forEach((SourceString _, Element e) { | 398 localMembers.forEach((Element e) { |
| 392 if (this === e.getLibrary() | 399 if (e.kind !== ElementKind.PREFIX |
| 393 && e.kind !== ElementKind.PREFIX | 400 && e.kind !== ElementKind.FOREIGN |
| 394 && e.kind !== ElementKind.FOREIGN) { | 401 && !e.name.isPrivate()) { |
| 395 if (!e.name.isPrivate()) f(e); | 402 f(e); |
| 396 } | 403 } |
| 397 }); | 404 }); |
| 398 } | 405 } |
| 399 | 406 |
| 400 bool hasLibraryName() => libraryTag !== null; | 407 bool hasLibraryName() => libraryTag !== null; |
| 401 | 408 |
| 402 /** | 409 /** |
| 403 * Returns the library name (as defined by the #library tag) or for script | 410 * Returns the library name (as defined by the #library tag) or for script |
| 404 * (which have no #library tag) the script file name. The latter case is used | 411 * (which have no #library tag) the script file name. The latter case is used |
| 405 * to private 'library name' for scripts to use for instance in dartdoc. | 412 * to private 'library name' for scripts to use for instance in dartdoc. |
| 406 */ | 413 */ |
| 407 String getLibraryOrScriptName() { | 414 String getLibraryOrScriptName() { |
| 408 if (libraryTag !== null) { | 415 if (libraryTag !== null) { |
| 409 return libraryTag.argument.dartString.slowToString(); | 416 return libraryTag.argument.dartString.slowToString(); |
| 410 } else { | 417 } else { |
| 411 // Use the file name as script name. | 418 // Use the file name as script name. |
| 412 var path = script.uri.path; | 419 String path = uri.path; |
| 413 return path.substring(path.lastIndexOf('/') + 1); | 420 return path.substring(path.lastIndexOf('/') + 1); |
| 414 } | 421 } |
| 415 } | 422 } |
| 416 | 423 |
| 424 CompilationUnitElement getCompilationUnit() => entryCompilationUnit; |
| 425 |
| 417 Scope buildEnclosingScope() => new TopScope(this); | 426 Scope buildEnclosingScope() => new TopScope(this); |
| 418 } | 427 } |
| 419 | 428 |
| 420 class PrefixElement extends Element { | 429 class PrefixElement extends Element { |
| 421 Map<SourceString, Element> imported; | 430 Map<SourceString, Element> imported; |
| 422 Token firstPosition; | 431 Token firstPosition; |
| 423 final CompilationUnitElement patchSource; | 432 final CompilationUnitElement patchCompilationUnit; |
| 424 | 433 |
| 425 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, | 434 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, |
| 426 [this.patchSource]) | 435 [this.patchCompilationUnit]) |
| 427 : imported = new Map<SourceString, Element>(), | 436 : imported = new Map<SourceString, Element>(), |
| 428 super(prefix, ElementKind.PREFIX, enclosing); | 437 super(prefix, ElementKind.PREFIX, enclosing); |
| 429 | 438 |
| 430 CompilationUnitElement getCompilationUnit() { | 439 CompilationUnitElement getCompilationUnit() { |
| 431 if (patchSource !== null) return patchSource; | 440 if (patchCompilationUnit !== null) return patchCompilationUnit; |
| 432 return super.getCompilationUnit(); | 441 return super.getCompilationUnit(); |
| 433 } | 442 } |
| 434 | 443 |
| 435 lookupLocalMember(SourceString memberName) => imported[memberName]; | 444 lookupLocalMember(SourceString memberName) => imported[memberName]; |
| 436 | 445 |
| 437 Type computeType(Compiler compiler) => compiler.types.dynamicType; | 446 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
| 438 | 447 |
| 439 Token position() => firstPosition; | 448 Token position() => firstPosition; |
| 440 } | 449 } |
| 441 | 450 |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 TypeVariableElement variableElement = | 881 TypeVariableElement variableElement = |
| 873 new TypeVariableElement(variableName, element, node); | 882 new TypeVariableElement(variableName, element, node); |
| 874 TypeVariableType variableType = new TypeVariableType(variableElement); | 883 TypeVariableType variableType = new TypeVariableType(variableElement); |
| 875 variableElement.type = variableType; | 884 variableElement.type = variableType; |
| 876 arguments.addLast(variableType); | 885 arguments.addLast(variableType); |
| 877 } | 886 } |
| 878 return arguments.toLink(); | 887 return arguments.toLink(); |
| 879 } | 888 } |
| 880 } | 889 } |
| 881 | 890 |
| 882 class ClassElement extends ContainerElement | 891 class ClassElement extends ScopeContainerElement |
| 883 implements TypeDeclarationElement { | 892 implements TypeDeclarationElement { |
| 884 final int id; | 893 final int id; |
| 885 InterfaceType type; | 894 InterfaceType type; |
| 886 Type supertype; | 895 Type supertype; |
| 887 Type defaultClass; | 896 Type defaultClass; |
| 888 Link<Element> members = const EmptyLink<Element>(); | |
| 889 Map<SourceString, Element> localMembers; | |
| 890 Map<SourceString, Element> constructors; | |
| 891 Link<Type> interfaces = const EmptyLink<Type>(); | 897 Link<Type> interfaces = const EmptyLink<Type>(); |
| 892 bool isResolved = false; | 898 bool isResolved = false; |
| 893 bool isBeingResolved = false; | 899 bool isBeingResolved = false; |
| 894 // backendMembers are members that have been added by the backend to simplify | 900 // backendMembers are members that have been added by the backend to simplify |
| 895 // compilation. They don't have any user-side counter-part. | 901 // compilation. They don't have any user-side counter-part. |
| 896 Link<Element> backendMembers = const EmptyLink<Element>(); | 902 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 897 | 903 |
| 898 Link<Type> allSupertypes; | 904 Link<Type> allSupertypes; |
| 899 ClassElement patch = null; | 905 ClassElement patch = null; |
| 900 | 906 |
| 901 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 907 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) |
| 902 : localMembers = new Map<SourceString, Element>(), | 908 : super(name, ElementKind.CLASS, enclosing); |
| 903 constructors = new Map<SourceString, Element>(), | |
| 904 super(name, ElementKind.CLASS, enclosing); | |
| 905 | |
| 906 void addMember(Element element, DiagnosticListener listener) { | |
| 907 members = members.prepend(element); | |
| 908 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | |
| 909 element.modifiers.isFactory()) { | |
| 910 constructors[element.name] = element; | |
| 911 } else if (element.kind == ElementKind.GETTER | |
| 912 || element.kind == ElementKind.SETTER) { | |
| 913 addGetterOrSetter(element, localMembers[element.name], listener); | |
| 914 } else { | |
| 915 localMembers[element.name] = element; | |
| 916 } | |
| 917 } | |
| 918 | 909 |
| 919 InterfaceType computeType(compiler) { | 910 InterfaceType computeType(compiler) { |
| 920 if (type == null) { | 911 if (type == null) { |
| 921 ClassNode node = parseNode(compiler); | 912 ClassNode node = parseNode(compiler); |
| 922 Link<Type> parameters = | 913 Link<Type> parameters = |
| 923 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 914 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| 924 type = new InterfaceType(this, parameters); | 915 type = new InterfaceType(this, parameters); |
| 925 } | 916 } |
| 926 return type; | 917 return type; |
| 927 } | 918 } |
| 928 | 919 |
| 929 Link<Type> get typeVariables() => type.arguments; | 920 Link<Type> get typeVariables() => type.arguments; |
| 930 | 921 |
| 931 ClassElement ensureResolved(Compiler compiler) { | 922 ClassElement ensureResolved(Compiler compiler) { |
| 932 compiler.resolveClass(this); | 923 compiler.resolveClass(this); |
| 933 return this; | 924 return this; |
| 934 } | 925 } |
| 935 | 926 |
| 927 /** |
| 928 * Lookup local members in the class. This will ignore constructors. |
| 929 */ |
| 936 Element lookupLocalMember(SourceString memberName) { | 930 Element lookupLocalMember(SourceString memberName) { |
| 937 return localMembers[memberName]; | 931 var result = localLookup(memberName); |
| 932 if (result !== null && result.isConstructor()) return null; |
| 933 return result; |
| 938 } | 934 } |
| 939 | 935 |
| 936 /** |
| 937 * Lookup super members for the class. This will ignore constructors. |
| 938 */ |
| 940 Element lookupSuperMember(SourceString memberName) { | 939 Element lookupSuperMember(SourceString memberName) { |
| 941 bool isPrivate = memberName.isPrivate(); | 940 bool isPrivate = memberName.isPrivate(); |
| 942 for (ClassElement s = superclass; s != null; s = s.superclass) { | 941 for (ClassElement s = superclass; s != null; s = s.superclass) { |
| 943 // Private members from a different library are not visible. | 942 // Private members from a different library are not visible. |
| 944 if (isPrivate && getLibrary() !== s.getLibrary()) continue; | 943 if (isPrivate && getLibrary() !== s.getLibrary()) continue; |
| 945 Element e = s.lookupLocalMember(memberName); | 944 Element e = s.lookupLocalMember(memberName); |
| 946 if (e === null) continue; | 945 if (e === null) continue; |
| 947 // Static members are not inherited. | 946 // Static members are not inherited. |
| 948 if (e.modifiers.isStatic()) continue; | 947 if (e.modifiers.isStatic()) continue; |
| 949 return e; | 948 return e; |
| 950 } | 949 } |
| 951 return null; | 950 return null; |
| 952 } | 951 } |
| 953 | 952 |
| 954 /** | 953 /** |
| 955 * Find the first member in the class chain with the given | 954 * Find the first member in the class chain with the given |
| 956 * [memberName]. This method is NOT to be used for resolving | 955 * [memberName]. This method is NOT to be used for resolving |
| 957 * unqualified sends because it does not implement the scoping | 956 * unqualified sends because it does not implement the scoping |
| 958 * rules, where library scope comes before superclass scope. | 957 * rules, where library scope comes before superclass scope. |
| 959 */ | 958 */ |
| 960 Element lookupMember(SourceString memberName) { | 959 Element lookupMember(SourceString memberName) { |
| 961 Element localMember = localMembers[memberName]; | 960 Element localMember = lookupLocalMember(memberName); |
| 962 return localMember === null ? lookupSuperMember(memberName) : localMember; | 961 return localMember === null ? lookupSuperMember(memberName) : localMember; |
| 963 } | 962 } |
| 964 | 963 |
| 965 /** | 964 /** |
| 966 * Returns true if the [fieldMember] is shadowed by another field. The given | 965 * Returns true if the [fieldMember] is shadowed by another field. The given |
| 967 * [fieldMember] must be a member of this class. | 966 * [fieldMember] must be a member of this class. |
| 968 * | 967 * |
| 969 * This method also works if the [fieldMember] is private. | 968 * This method also works if the [fieldMember] is private. |
| 970 */ | 969 */ |
| 971 bool isShadowedByField(Element fieldMember) { | 970 bool isShadowedByField(Element fieldMember) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 996 Element noMatch(Element)]) { | 995 Element noMatch(Element)]) { |
| 997 // TODO(karlklose): have a map from class names to a map of constructors | 996 // TODO(karlklose): have a map from class names to a map of constructors |
| 998 // instead of creating the name here? | 997 // instead of creating the name here? |
| 999 SourceString normalizedName; | 998 SourceString normalizedName; |
| 1000 if (constructorName !== const SourceString('')) { | 999 if (constructorName !== const SourceString('')) { |
| 1001 normalizedName = Elements.constructConstructorName(className, | 1000 normalizedName = Elements.constructConstructorName(className, |
| 1002 constructorName); | 1001 constructorName); |
| 1003 } else { | 1002 } else { |
| 1004 normalizedName = className; | 1003 normalizedName = className; |
| 1005 } | 1004 } |
| 1006 Element result = constructors[normalizedName]; | 1005 Element result = localLookup(normalizedName); |
| 1007 if (result === null && noMatch !== null) { | 1006 if (result === null || !result.isConstructor()) { |
| 1008 result = noMatch(lookupLocalMember(constructorName)); | 1007 result = noMatch !== null ? noMatch(result) : null; |
| 1009 } | 1008 } |
| 1010 return result; | 1009 return result; |
| 1011 } | 1010 } |
| 1012 | 1011 |
| 1012 bool get hasConstructor() { |
| 1013 // Search in scope to be sure we search patched constructors. |
| 1014 for (var element in localScope.getValues()) { |
| 1015 if (element.isConstructor()) return true; |
| 1016 } |
| 1017 return false; |
| 1018 } |
| 1019 |
| 1020 Collection<Element> get constructors() { |
| 1021 // TODO(ajohnsen): See if we can avoid this method at some point. |
| 1022 List<Element> result = <Element>[]; |
| 1023 // Search in scope to be sure we search patched constructors. |
| 1024 localScope.forEach((_, Element value) { |
| 1025 if (value.isConstructor()) result.add(value); |
| 1026 }); |
| 1027 return result; |
| 1028 } |
| 1029 |
| 1013 /** | 1030 /** |
| 1014 * Returns the super class, if any. | 1031 * Returns the super class, if any. |
| 1015 * | 1032 * |
| 1016 * The returned element may not be resolved yet. | 1033 * The returned element may not be resolved yet. |
| 1017 */ | 1034 */ |
| 1018 ClassElement get superclass() { | 1035 ClassElement get superclass() { |
| 1019 assert(isResolved); | 1036 assert(isResolved); |
| 1020 return supertype === null ? null : supertype.element; | 1037 return supertype === null ? null : supertype.element; |
| 1021 } | 1038 } |
| 1022 | 1039 |
| 1023 /** | 1040 /** |
| 1024 * Runs through all members of this class. | 1041 * Runs through all members of this class. |
| 1025 * | 1042 * |
| 1026 * The enclosing class is passed to the callback. This is useful when | 1043 * The enclosing class is passed to the callback. This is useful when |
| 1027 * [includeSuperMembers] is [:true:]. | 1044 * [includeSuperMembers] is [:true:]. |
| 1028 */ | 1045 */ |
| 1029 void forEachMember([void f(ClassElement enclosingClass, Element member), | 1046 void forEachMember([void f(ClassElement enclosingClass, Element member), |
| 1030 includeBackendMembers = false, | 1047 includeBackendMembers = false, |
| 1031 includeSuperMembers = false]) { | 1048 includeSuperMembers = false]) { |
| 1032 Set<ClassElement> seen = new Set<ClassElement>(); | 1049 Set<ClassElement> seen = new Set<ClassElement>(); |
| 1033 ClassElement classElement = this; | 1050 ClassElement classElement = this; |
| 1034 do { | 1051 do { |
| 1035 if (seen.contains(classElement)) return; | 1052 if (seen.contains(classElement)) return; |
| 1036 seen.add(classElement); | 1053 seen.add(classElement); |
| 1037 for (Element element in classElement.members) { | 1054 for (Element element in classElement.localMembers) { |
| 1038 f(classElement, element); | 1055 f(classElement, element); |
| 1039 } | 1056 } |
| 1040 if (includeBackendMembers) { | 1057 if (includeBackendMembers) { |
| 1041 for (Element element in classElement.backendMembers) { | 1058 for (Element element in classElement.backendMembers) { |
| 1042 f(classElement, element); | 1059 f(classElement, element); |
| 1043 } | 1060 } |
| 1044 } | 1061 } |
| 1045 classElement = includeSuperMembers ? classElement.superclass : null; | 1062 classElement = includeSuperMembers ? classElement.superclass : null; |
| 1046 } while(classElement !== null); | 1063 } while(classElement !== null); |
| 1047 } | 1064 } |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 TypeVariableElement(name, Element enclosing, this.cachedNode, | 1301 TypeVariableElement(name, Element enclosing, this.cachedNode, |
| 1285 [this.type, this.bound]) | 1302 [this.type, this.bound]) |
| 1286 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1303 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
| 1287 | 1304 |
| 1288 TypeVariableType computeType(compiler) => type; | 1305 TypeVariableType computeType(compiler) => type; |
| 1289 | 1306 |
| 1290 Node parseNode(compiler) => cachedNode; | 1307 Node parseNode(compiler) => cachedNode; |
| 1291 | 1308 |
| 1292 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1309 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1293 } | 1310 } |
| OLD | NEW |