Chromium Code Reviews| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 | 117 |
| 116 void addMetadata(Node node) { | 118 void addMetadata(Node node) { |
| 117 metadata = metadata.prepend(node); | 119 metadata = metadata.prepend(node); |
| 118 } | 120 } |
| 119 | 121 |
| 120 bool isFunction() => kind === ElementKind.FUNCTION; | 122 bool isFunction() => kind === ElementKind.FUNCTION; |
| 121 bool isClosure() => false; | 123 bool isClosure() => false; |
| 122 bool isMember() => | 124 bool isMember() => |
| 123 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; | 125 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; |
| 124 bool isInstanceMember() => false; | 126 bool isInstanceMember() => false; |
| 127 bool isConstructor() => isFactoryConstructor() || isGenerativeConstructor(); | |
| 125 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); | 128 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); |
| 126 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 129 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 127 bool isGenerativeConstructorBody() => | 130 bool isGenerativeConstructorBody() => |
| 128 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY; | 131 kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY; |
| 129 bool isCompilationUnit() { | 132 bool isCompilationUnit() { |
| 130 return kind === ElementKind.COMPILATION_UNIT || | 133 return kind === ElementKind.COMPILATION_UNIT || |
| 131 kind === ElementKind.LIBRARY; | 134 kind === ElementKind.LIBRARY; |
| 132 } | 135 } |
| 133 bool isClass() => kind === ElementKind.CLASS; | 136 bool isClass() => kind === ElementKind.CLASS; |
| 134 bool isPrefix() => kind === ElementKind.PREFIX; | 137 bool isPrefix() => kind === ElementKind.PREFIX; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 243 } |
| 241 | 244 |
| 242 bool _isNative = false; | 245 bool _isNative = false; |
| 243 void setNative() { _isNative = true; } | 246 void setNative() { _isNative = true; } |
| 244 bool isNative() => _isNative; | 247 bool isNative() => _isNative; |
| 245 | 248 |
| 246 FunctionElement asFunctionElement() => null; | 249 FunctionElement asFunctionElement() => null; |
| 247 } | 250 } |
| 248 | 251 |
| 249 class ContainerElement extends Element { | 252 class ContainerElement extends Element { |
| 250 ContainerElement(name, kind, enclosingElement) : | 253 Link<Element> localMembers = const EmptyLink<Element>(); |
| 251 super(name, kind, enclosingElement); | |
| 252 | 254 |
| 253 abstract void addMember(Element element, DiagnosticListener listener); | 255 ContainerElement(name, kind, enclosingElement) |
| 256 : super(name, kind, enclosingElement); | |
| 257 | |
| 258 void addMember(Element element, DiagnosticListener listener) { | |
| 259 localMembers = localMembers.prepend(element); | |
| 260 } | |
| 261 } | |
| 262 | |
| 263 class ScopeContainerElement extends ContainerElement { | |
| 264 final Map<SourceString, Element> localScope; | |
| 265 | |
| 266 ScopeContainerElement(name, kind, enclosingElement) | |
| 267 : super(name, kind, enclosingElement), | |
| 268 localScope = new Map<SourceString, Element>(); | |
| 269 | |
| 270 void addMember(Element element, DiagnosticListener listener) { | |
| 271 super.addMember(element, listener); | |
| 272 addToScope(element, listener); | |
| 273 } | |
| 274 | |
| 275 void addToScope(Element element, DiagnosticListener listener) { | |
| 276 if (element.isAccessor()) { | |
| 277 addGetterOrSetter(element, localScope[element.name], listener); | |
| 278 } else { | |
| 279 Element existing = localScope.putIfAbsent(element.name, () => element); | |
| 280 if (existing !== element) { | |
| 281 listener.cancel('duplicate definition', token: element.position()); | |
| 282 listener.cancel('existing definition', token: existing.position()); | |
| 283 } | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 Element localLookup(SourceString elementName) { | |
| 288 return localScope[elementName]; | |
| 289 } | |
| 254 | 290 |
| 255 void addGetterOrSetter(Element element, | 291 void addGetterOrSetter(Element element, |
| 256 Element existing, | 292 Element existing, |
| 257 DiagnosticListener listener) { | 293 DiagnosticListener listener) { |
| 258 void reportError(Element other) { | 294 void reportError(Element other) { |
| 259 listener.cancel('duplicate definition of ${element.name.slowToString()}', | 295 listener.cancel('duplicate definition of ${element.name.slowToString()}', |
| 260 element: element); | 296 element: element); |
| 261 listener.cancel('existing definition', element: other); | 297 listener.cancel('existing definition', element: other); |
| 262 } | 298 } |
| 263 | 299 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 283 if (element.kind == ElementKind.GETTER) { | 319 if (element.kind == ElementKind.GETTER) { |
| 284 field.getter = element; | 320 field.getter = element; |
| 285 } else { | 321 } else { |
| 286 field.setter = element; | 322 field.setter = element; |
| 287 } | 323 } |
| 288 addMember(field, listener); | 324 addMember(field, listener); |
| 289 } | 325 } |
| 290 } | 326 } |
| 291 } | 327 } |
| 292 | 328 |
| 329 | |
| 330 | |
| 293 class CompilationUnitElement extends ContainerElement { | 331 class CompilationUnitElement extends ContainerElement { |
| 294 final Script script; | 332 final Script script; |
| 295 Link<Element> topLevelElements = const EmptyLink<Element>(); | |
| 296 | 333 |
| 297 CompilationUnitElement(Script script, Element enclosing) | 334 CompilationUnitElement(Script script, Element enclosing) |
| 298 : this.script = script, | 335 : this.script = script, |
| 299 super(new SourceString(script.name), | 336 super(new SourceString(script.name), |
| 300 ElementKind.COMPILATION_UNIT, | 337 ElementKind.COMPILATION_UNIT, |
| 301 enclosing); | 338 enclosing); |
| 302 | 339 |
| 303 CompilationUnitElement.library(Script script) | |
| 304 : this.script = script, | |
| 305 super(new SourceString(script.name), ElementKind.LIBRARY, null); | |
| 306 | |
| 307 void addMember(Element element, DiagnosticListener listener) { | 340 void addMember(Element element, DiagnosticListener listener) { |
| 308 LibraryElement library = enclosingElement; | 341 // Keep a list of top level members. |
| 309 library.addMember(element, listener); | 342 super.addMember(element, listener); |
| 310 topLevelElements = topLevelElements.prepend(element); | 343 // Provide the member to the library to build scope. |
| 311 } | 344 getLibrary().addMember(element, listener); |
| 312 | |
| 313 void define(Element element, DiagnosticListener listener) { | |
| 314 LibraryElement library = enclosingElement; | |
| 315 library.define(element, listener); | |
| 316 } | |
| 317 | |
| 318 void addTag(ScriptTag tag, DiagnosticListener listener) { | |
| 319 listener.cancel("script tags not allowed here", node: tag); | |
| 320 } | 345 } |
| 321 } | 346 } |
| 322 | 347 |
| 323 class LibraryElement extends CompilationUnitElement { | 348 class LibraryElement extends ScopeContainerElement { |
| 324 // TODO(ahe): Library element should not be a subclass of | 349 CompilationUnitElement entryCompilationUnit; |
| 325 // CompilationUnitElement. | 350 Link<CompilationUnitElement> compilationUnits = |
| 351 const EmptyLink<CompilationUnitElement>(); | |
| 326 | 352 |
| 327 Link<CompilationUnitElement> compilationUnits = | |
| 328 const EmptyLink<CompilationUnitElement>(); | |
| 329 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); | 353 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); |
| 330 ScriptTag libraryTag; | 354 ScriptTag libraryTag; |
| 331 Map<SourceString, Element> elements; | |
| 332 bool canUseNative = false; | 355 bool canUseNative = false; |
| 333 LibraryElement patch = null; | 356 LibraryElement patch = null; |
| 334 | 357 |
| 335 LibraryElement(Script script) | 358 LibraryElement(Script script) |
| 336 : elements = new Map<SourceString, Element>(), | 359 : super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 337 super.library(script); | 360 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 361 } | |
| 362 | |
| 363 Uri get uri() => entryCompilationUnit.script.uri; | |
| 338 | 364 |
| 339 bool get isPatched() => patch !== null; | 365 bool get isPatched() => patch !== null; |
| 340 | 366 |
| 341 void addCompilationUnit(CompilationUnitElement element) { | 367 void addCompilationUnit(CompilationUnitElement element) { |
| 342 compilationUnits = compilationUnits.prepend(element); | 368 compilationUnits = compilationUnits.prepend(element); |
| 343 } | 369 } |
| 344 | 370 |
| 345 void addTag(ScriptTag tag, DiagnosticListener listener) { | 371 void addTag(ScriptTag tag, DiagnosticListener listener) { |
| 346 tags = tags.prepend(tag); | 372 tags = tags.prepend(tag); |
| 347 } | 373 } |
| 348 | 374 |
| 349 void addMember(Element element, DiagnosticListener listener) { | |
| 350 topLevelElements = topLevelElements.prepend(element); | |
| 351 define(element, listener); | |
| 352 } | |
| 353 | |
| 354 void define(Element element, DiagnosticListener listener) { | |
| 355 if (element.kind == ElementKind.GETTER | |
| 356 || element.kind == ElementKind.SETTER) { | |
| 357 addGetterOrSetter(element, elements[element.name], listener); | |
| 358 } else { | |
| 359 Element existing = elements.putIfAbsent(element.name, () => element); | |
| 360 if (existing !== element) { | |
| 361 listener.cancel('duplicate definition', token: element.position()); | |
| 362 listener.cancel('existing definition', token: existing.position()); | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 /** 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 |
| 368 * potentially have been imported from another library. Returns | 376 * potentially have been imported from another library. Returns |
| 369 * null if no such element exist. */ | 377 * null if no such element exist. */ |
| 370 Element find(SourceString elementName) { | 378 Element find(SourceString elementName) { |
| 371 return elements[elementName]; | 379 return localScope[elementName]; |
| 372 } | 380 } |
| 373 | 381 |
| 374 /** 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 |
| 375 * non-imported elements. Returns null if no such element exist. */ | 383 * non-imported elements. Returns null if no such element exist. */ |
| 376 Element findLocal(SourceString elementName) { | 384 Element findLocal(SourceString elementName) { |
| 377 Element result = elements[elementName]; | 385 Element result = localScope[elementName]; |
| 378 if (result === null || result.getLibrary() != this) return null; | 386 if (result === null || result.getLibrary() != this) return null; |
| 379 return result; | 387 return result; |
| 380 } | 388 } |
| 381 | 389 |
| 382 void forEachExport(f(Element element)) { | 390 void forEachExport(f(Element element)) { |
| 383 elements.forEach((SourceString _, Element e) { | 391 localMembers.forEach((Element e) { |
| 384 if (this === e.getLibrary() | 392 if (e.kind !== ElementKind.PREFIX |
| 385 && e.kind !== ElementKind.PREFIX | 393 && e.kind !== ElementKind.FOREIGN |
| 386 && e.kind !== ElementKind.FOREIGN) { | 394 && !e.name.isPrivate()) { |
| 387 if (!e.name.isPrivate()) f(e); | 395 f(e); |
| 388 } | 396 } |
| 389 }); | 397 }); |
| 390 } | 398 } |
| 391 | 399 |
| 392 bool hasLibraryName() => libraryTag !== null; | 400 bool hasLibraryName() => libraryTag !== null; |
| 393 | 401 |
| 394 /** | 402 /** |
| 395 * 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 |
| 396 * (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 |
| 397 * 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. |
| 398 */ | 406 */ |
| 399 String getLibraryOrScriptName() { | 407 String getLibraryOrScriptName() { |
| 400 if (libraryTag !== null) { | 408 if (libraryTag !== null) { |
| 401 return libraryTag.argument.dartString.slowToString(); | 409 return libraryTag.argument.dartString.slowToString(); |
| 402 } else { | 410 } else { |
| 403 // Use the file name as script name. | 411 // Use the file name as script name. |
| 404 var path = script.uri.path; | 412 String path = uri.path; |
| 405 return path.substring(path.lastIndexOf('/') + 1); | 413 return path.substring(path.lastIndexOf('/') + 1); |
| 406 } | 414 } |
| 407 } | 415 } |
| 408 | 416 |
| 417 CompilationUnitElement getCompilationUnit() => entryCompilationUnit; | |
| 418 | |
| 409 Scope buildEnclosingScope() => new TopScope(this); | 419 Scope buildEnclosingScope() => new TopScope(this); |
| 410 } | 420 } |
| 411 | 421 |
| 412 class PrefixElement extends Element { | 422 class PrefixElement extends Element { |
| 413 Map<SourceString, Element> imported; | 423 Map<SourceString, Element> imported; |
| 414 Token firstPosition; | 424 Token firstPosition; |
| 415 final CompilationUnitElement patchSource; | 425 final CompilationUnitElement patchCompilationUnit; |
| 416 | 426 |
| 417 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, | 427 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition, |
| 418 [this.patchSource]) | 428 [this.patchCompilationUnit]) |
| 419 : imported = new Map<SourceString, Element>(), | 429 : imported = new Map<SourceString, Element>(), |
| 420 super(prefix, ElementKind.PREFIX, enclosing); | 430 super(prefix, ElementKind.PREFIX, enclosing); |
| 421 | 431 |
| 422 CompilationUnitElement getCompilationUnit() { | 432 CompilationUnitElement getCompilationUnit() { |
| 423 if (patchSource !== null) return patchSource; | 433 if (patchCompilationUnit !== null) return patchCompilationUnit; |
| 424 return super.getCompilationUnit(); | 434 return super.getCompilationUnit(); |
| 425 } | 435 } |
| 426 | 436 |
| 427 lookupLocalMember(SourceString memberName) => imported[memberName]; | 437 lookupLocalMember(SourceString memberName) => imported[memberName]; |
| 428 | 438 |
| 429 Type computeType(Compiler compiler) => compiler.types.dynamicType; | 439 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
| 430 | 440 |
| 431 Token position() => firstPosition; | 441 Token position() => firstPosition; |
| 432 } | 442 } |
| 433 | 443 |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 TypeVariableElement variableElement = | 874 TypeVariableElement variableElement = |
| 865 new TypeVariableElement(variableName, element, node); | 875 new TypeVariableElement(variableName, element, node); |
| 866 TypeVariableType variableType = new TypeVariableType(variableElement); | 876 TypeVariableType variableType = new TypeVariableType(variableElement); |
| 867 variableElement.type = variableType; | 877 variableElement.type = variableType; |
| 868 arguments.addLast(variableType); | 878 arguments.addLast(variableType); |
| 869 } | 879 } |
| 870 return arguments.toLink(); | 880 return arguments.toLink(); |
| 871 } | 881 } |
| 872 } | 882 } |
| 873 | 883 |
| 874 class ClassElement extends ContainerElement | 884 class ClassElement extends ScopeContainerElement |
| 875 implements TypeDeclarationElement { | 885 implements TypeDeclarationElement { |
| 876 final int id; | 886 final int id; |
| 877 InterfaceType type; | 887 InterfaceType type; |
| 878 Type supertype; | 888 Type supertype; |
| 879 Type defaultClass; | 889 Type defaultClass; |
| 880 Link<Element> members = const EmptyLink<Element>(); | |
| 881 Map<SourceString, Element> localMembers; | |
| 882 Map<SourceString, Element> constructors; | |
| 883 Link<Type> interfaces = const EmptyLink<Type>(); | 890 Link<Type> interfaces = const EmptyLink<Type>(); |
| 884 bool isResolved = false; | 891 bool isResolved = false; |
| 885 bool isBeingResolved = false; | 892 bool isBeingResolved = false; |
| 886 // backendMembers are members that have been added by the backend to simplify | 893 // backendMembers are members that have been added by the backend to simplify |
| 887 // compilation. They don't have any user-side counter-part. | 894 // compilation. They don't have any user-side counter-part. |
| 888 Link<Element> backendMembers = const EmptyLink<Element>(); | 895 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 889 | 896 |
| 890 Link<Type> allSupertypes; | 897 Link<Type> allSupertypes; |
| 891 ClassElement patch = null; | 898 ClassElement patch = null; |
| 892 | 899 |
| 893 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 900 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) |
| 894 : localMembers = new Map<SourceString, Element>(), | 901 : super(name, ElementKind.CLASS, enclosing); |
| 895 constructors = new Map<SourceString, Element>(), | |
| 896 super(name, ElementKind.CLASS, enclosing); | |
| 897 | |
| 898 void addMember(Element element, DiagnosticListener listener) { | |
| 899 members = members.prepend(element); | |
| 900 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | |
| 901 element.modifiers.isFactory()) { | |
| 902 constructors[element.name] = element; | |
| 903 } else if (element.kind == ElementKind.GETTER | |
| 904 || element.kind == ElementKind.SETTER) { | |
| 905 addGetterOrSetter(element, localMembers[element.name], listener); | |
| 906 } else { | |
| 907 localMembers[element.name] = element; | |
| 908 } | |
| 909 } | |
| 910 | 902 |
| 911 InterfaceType computeType(compiler) { | 903 InterfaceType computeType(compiler) { |
| 912 if (type == null) { | 904 if (type == null) { |
| 913 ClassNode node = parseNode(compiler); | 905 ClassNode node = parseNode(compiler); |
| 914 Link<Type> parameters = | 906 Link<Type> parameters = |
| 915 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 907 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| 916 type = new InterfaceType(this, parameters); | 908 type = new InterfaceType(this, parameters); |
| 917 } | 909 } |
| 918 return type; | 910 return type; |
| 919 } | 911 } |
| 920 | 912 |
| 921 Link<Type> get typeVariables() => type.arguments; | 913 Link<Type> get typeVariables() => type.arguments; |
| 922 | 914 |
| 923 ClassElement ensureResolved(Compiler compiler) { | 915 ClassElement ensureResolved(Compiler compiler) { |
| 924 compiler.resolveClass(this); | 916 compiler.resolveClass(this); |
| 925 return this; | 917 return this; |
| 926 } | 918 } |
| 927 | 919 |
| 920 /** | |
| 921 * Lookup local members in the class. This will ignore constructors. | |
| 922 */ | |
| 928 Element lookupLocalMember(SourceString memberName) { | 923 Element lookupLocalMember(SourceString memberName) { |
| 929 return localMembers[memberName]; | 924 var result = localLookup(memberName); |
| 925 if (result !== null && result.isConstructor()) return null; | |
| 926 return result; | |
| 930 } | 927 } |
| 931 | 928 |
| 929 /** | |
| 930 * Lookup super members for the class. This will ignore constructors. | |
| 931 */ | |
| 932 Element lookupSuperMember(SourceString memberName) { | 932 Element lookupSuperMember(SourceString memberName) { |
| 933 bool isPrivate = memberName.isPrivate(); | 933 bool isPrivate = memberName.isPrivate(); |
| 934 for (ClassElement s = superclass; s != null; s = s.superclass) { | 934 for (ClassElement s = superclass; s != null; s = s.superclass) { |
| 935 // Private members from a different library are not visible. | 935 // Private members from a different library are not visible. |
| 936 if (isPrivate && getLibrary() !== s.getLibrary()) continue; | 936 if (isPrivate && getLibrary() !== s.getLibrary()) continue; |
| 937 Element e = s.lookupLocalMember(memberName); | 937 Element e = s.lookupLocalMember(memberName); |
| 938 if (e === null) continue; | 938 if (e === null) continue; |
| 939 // Static members are not inherited. | 939 // Static members are not inherited. |
| 940 if (e.modifiers.isStatic()) continue; | 940 if (e.modifiers.isStatic()) continue; |
| 941 return e; | 941 return e; |
| 942 } | 942 } |
| 943 return null; | 943 return null; |
| 944 } | 944 } |
| 945 | 945 |
| 946 /** | 946 /** |
| 947 * Find the first member in the class chain with the given | 947 * Find the first member in the class chain with the given |
| 948 * [memberName]. This method is NOT to be used for resolving | 948 * [memberName]. This method is NOT to be used for resolving |
| 949 * unqualified sends because it does not implement the scoping | 949 * unqualified sends because it does not implement the scoping |
| 950 * rules, where library scope comes before superclass scope. | 950 * rules, where library scope comes before superclass scope. |
| 951 */ | 951 */ |
| 952 Element lookupMember(SourceString memberName) { | 952 Element lookupMember(SourceString memberName) { |
| 953 Element localMember = localMembers[memberName]; | 953 Element localMember = lookupLocalMember(memberName); |
| 954 return localMember === null ? lookupSuperMember(memberName) : localMember; | 954 return localMember === null ? lookupSuperMember(memberName) : localMember; |
| 955 } | 955 } |
| 956 | 956 |
| 957 /** | 957 /** |
| 958 * Returns true if the [fieldMember] is shadowed by another field. The given | 958 * Returns true if the [fieldMember] is shadowed by another field. The given |
| 959 * [fieldMember] must be a member of this class. | 959 * [fieldMember] must be a member of this class. |
| 960 * | 960 * |
| 961 * This method also works if the [fieldMember] is private. | 961 * This method also works if the [fieldMember] is private. |
| 962 */ | 962 */ |
| 963 bool isShadowedByField(Element fieldMember) { | 963 bool isShadowedByField(Element fieldMember) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 988 Element noMatch(Element)]) { | 988 Element noMatch(Element)]) { |
| 989 // TODO(karlklose): have a map from class names to a map of constructors | 989 // TODO(karlklose): have a map from class names to a map of constructors |
| 990 // instead of creating the name here? | 990 // instead of creating the name here? |
| 991 SourceString normalizedName; | 991 SourceString normalizedName; |
| 992 if (constructorName !== const SourceString('')) { | 992 if (constructorName !== const SourceString('')) { |
| 993 normalizedName = Elements.constructConstructorName(className, | 993 normalizedName = Elements.constructConstructorName(className, |
| 994 constructorName); | 994 constructorName); |
| 995 } else { | 995 } else { |
| 996 normalizedName = className; | 996 normalizedName = className; |
| 997 } | 997 } |
| 998 Element result = constructors[normalizedName]; | 998 Element result = localLookup(normalizedName); |
| 999 if (result === null && noMatch !== null) { | 999 if (result === null || !result.isConstructor()) { |
| 1000 result = noMatch(lookupLocalMember(constructorName)); | 1000 result = noMatch !== null ? noMatch(result) : null; |
| 1001 } | 1001 } |
| 1002 return result; | 1002 return result; |
| 1003 } | 1003 } |
| 1004 | 1004 |
| 1005 bool get hasConstructor() { | |
| 1006 // Search in scope to be sure we search patched constructors. | |
| 1007 for (var element in localScope.getValues()) { | |
| 1008 if (element.isConstructor()) return true; | |
| 1009 } | |
| 1010 return false; | |
| 1011 } | |
| 1012 | |
| 1013 Collection<Element> get constructors() { | |
| 1014 // TODO(ajohnsen): See if we can avoid this method at some point. | |
| 1015 var result = <Element>[]; | |
| 1016 // Search in scope to be sure we search patched constructors. | |
| 1017 return localScope.getValues().filter((element) => element.isConstructor()); | |
|
ahe
2012/08/08 17:39:05
This scares me. Can't you run through the members?
Lasse Reichstein Nielsen
2012/08/10 11:32:17
I personally don't like the filter function.
In th
Anders Johnsen
2012/08/13 06:22:41
I have no preference here, changing.
| |
| 1018 } | |
| 1019 | |
| 1005 /** | 1020 /** |
| 1006 * Returns the super class, if any. | 1021 * Returns the super class, if any. |
| 1007 * | 1022 * |
| 1008 * The returned element may not be resolved yet. | 1023 * The returned element may not be resolved yet. |
| 1009 */ | 1024 */ |
| 1010 ClassElement get superclass() { | 1025 ClassElement get superclass() { |
| 1011 assert(isResolved); | 1026 assert(isResolved); |
| 1012 return supertype === null ? null : supertype.element; | 1027 return supertype === null ? null : supertype.element; |
| 1013 } | 1028 } |
| 1014 | 1029 |
| 1015 /** | 1030 /** |
| 1016 * Runs through all members of this class. | 1031 * Runs through all members of this class. |
| 1017 * | 1032 * |
| 1018 * The enclosing class is passed to the callback. This is useful when | 1033 * The enclosing class is passed to the callback. This is useful when |
| 1019 * [includeSuperMembers] is [:true:]. | 1034 * [includeSuperMembers] is [:true:]. |
| 1020 */ | 1035 */ |
| 1021 void forEachMember([void f(ClassElement enclosingClass, Element member), | 1036 void forEachMember([void f(ClassElement enclosingClass, Element member), |
| 1022 includeBackendMembers = false, | 1037 includeBackendMembers = false, |
| 1023 includeSuperMembers = false]) { | 1038 includeSuperMembers = false]) { |
| 1024 Set<ClassElement> seen = new Set<ClassElement>(); | 1039 Set<ClassElement> seen = new Set<ClassElement>(); |
| 1025 ClassElement classElement = this; | 1040 ClassElement classElement = this; |
| 1026 do { | 1041 do { |
| 1027 if (seen.contains(classElement)) return; | 1042 if (seen.contains(classElement)) return; |
| 1028 seen.add(classElement); | 1043 seen.add(classElement); |
| 1029 for (Element element in classElement.members) { | 1044 for (Element element in classElement.localMembers) { |
| 1030 f(classElement, element); | 1045 f(classElement, element); |
| 1031 } | 1046 } |
| 1032 if (includeBackendMembers) { | 1047 if (includeBackendMembers) { |
| 1033 for (Element element in classElement.backendMembers) { | 1048 for (Element element in classElement.backendMembers) { |
| 1034 f(classElement, element); | 1049 f(classElement, element); |
| 1035 } | 1050 } |
| 1036 } | 1051 } |
| 1037 classElement = includeSuperMembers ? classElement.superclass : null; | 1052 classElement = includeSuperMembers ? classElement.superclass : null; |
| 1038 } while(classElement !== null); | 1053 } while(classElement !== null); |
| 1039 } | 1054 } |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1277 TypeVariableElement(name, Element enclosing, this.cachedNode, | 1292 TypeVariableElement(name, Element enclosing, this.cachedNode, |
| 1278 [this.type, this.bound]) | 1293 [this.type, this.bound]) |
| 1279 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1294 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
| 1280 | 1295 |
| 1281 TypeVariableType computeType(compiler) => type; | 1296 TypeVariableType computeType(compiler) => type; |
| 1282 | 1297 |
| 1283 Node parseNode(compiler) => cachedNode; | 1298 Node parseNode(compiler) => cachedNode; |
| 1284 | 1299 |
| 1285 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1300 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1286 } | 1301 } |
| OLD | NEW |