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