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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 | 196 |
| 195 // TODO(kasperl): This is a very bad hash code for the element and | 197 // TODO(kasperl): This is a very bad hash code for the element and |
| 196 // there's no reason why two elements with the same name should have | 198 // there's no reason why two elements with the same name should have |
| 197 // the same hash code. Replace this with a simple id in the element? | 199 // the same hash code. Replace this with a simple id in the element? |
| 198 int hashCode() => name === null ? 0 : name.hashCode(); | 200 int hashCode() => name === null ? 0 : name.hashCode(); |
| 199 | 201 |
| 200 Script getScript() { | 202 Script getScript() { |
| 201 return getCompilationUnit().script; | 203 return getCompilationUnit().script; |
| 202 } | 204 } |
| 203 | 205 |
| 204 CompilationUnitElement getCompilationUnit() { | 206 CompilationUnitElement getCompilationUnit() { |
|
ahe
2012/08/14 12:45:26
I'm confused about getCompilationUnit and asCompil
| |
| 205 Element element = this; | 207 if (isCompilationUnit()) return this; |
| 206 while (element !== null && !element.isCompilationUnit()) { | 208 return enclosingElement.getCompilationUnit(); |
| 207 element = element.enclosingElement; | |
| 208 } | |
| 209 return element.asCompilationUnit(); | |
| 210 } | 209 } |
| 211 | 210 |
| 212 LibraryElement getLibrary() { | 211 LibraryElement getLibrary() { |
| 213 Element element = this; | 212 Element element = this; |
| 214 while (element.kind !== ElementKind.LIBRARY) { | 213 while (element.kind !== ElementKind.LIBRARY) { |
| 215 element = element.enclosingElement; | 214 element = element.enclosingElement; |
| 216 } | 215 } |
| 217 return element; | 216 return element; |
| 218 } | 217 } |
| 219 | 218 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 bool isNative() => _isNative; | 270 bool isNative() => _isNative; |
| 272 | 271 |
| 273 FunctionElement asFunctionElement() => null; | 272 FunctionElement asFunctionElement() => null; |
| 274 | 273 |
| 275 Element cloneTo(Element enclosing, DiagnosticListener listener) { | 274 Element cloneTo(Element enclosing, DiagnosticListener listener) { |
| 276 listener.cancel("Unimplemented cloneTo", element: this); | 275 listener.cancel("Unimplemented cloneTo", element: this); |
| 277 } | 276 } |
| 278 } | 277 } |
| 279 | 278 |
| 280 class ContainerElement extends Element { | 279 class ContainerElement extends Element { |
| 281 ContainerElement(name, kind, enclosingElement) : | 280 Link<Element> localMembers = const EmptyLink<Element>(); |
| 282 super(name, kind, enclosingElement); | |
| 283 | 281 |
| 284 abstract void addMember(Element element, DiagnosticListener listener); | 282 ContainerElement(name, kind, enclosingElement) |
| 283 : super(name, kind, enclosingElement); | |
| 284 | |
| 285 void addMember(Element element, DiagnosticListener listener) { | |
| 286 localMembers = localMembers.prepend(element); | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 class ScopeContainerElement extends ContainerElement { | |
|
ahe
2012/08/14 12:45:26
Nit: Rename to ScopedContainerElement?
| |
| 291 final Map<SourceString, Element> localScope; | |
| 292 | |
| 293 ScopeContainerElement(name, kind, enclosingElement) | |
| 294 : super(name, kind, enclosingElement), | |
| 295 localScope = new Map<SourceString, Element>(); | |
| 296 | |
| 297 void addMember(Element element, DiagnosticListener listener) { | |
| 298 super.addMember(element, listener); | |
| 299 addToScope(element, listener); | |
| 300 } | |
| 301 | |
| 302 void addToScope(Element element, DiagnosticListener listener) { | |
| 303 if (element.isAccessor()) { | |
| 304 addGetterOrSetter(element, localScope[element.name], listener); | |
| 305 } else { | |
| 306 Element existing = localScope.putIfAbsent(element.name, () => element); | |
| 307 if (existing !== element) { | |
| 308 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | |
| 309 listener.cancel('duplicate definition', token: element.position()); | |
| 310 listener.cancel('existing definition', token: existing.position()); | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 Element localLookup(SourceString elementName) { | |
| 316 return localScope[elementName]; | |
| 317 } | |
| 285 | 318 |
| 286 void addGetterOrSetter(Element element, | 319 void addGetterOrSetter(Element element, |
| 287 Element existing, | 320 Element existing, |
| 288 DiagnosticListener listener) { | 321 DiagnosticListener listener) { |
| 289 void reportError(Element other) { | 322 void reportError(Element other) { |
| 290 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | 323 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. |
| 291 listener.cancel('duplicate definition of ${element.name.slowToString()}', | 324 listener.cancel('duplicate definition of ${element.name.slowToString()}', |
| 292 element: element); | 325 element: element); |
| 293 listener.cancel('existing definition', element: other); | 326 listener.cancel('existing definition', element: other); |
| 294 } | 327 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 317 } else { | 350 } else { |
| 318 field.setter = element; | 351 field.setter = element; |
| 319 } | 352 } |
| 320 addMember(field, listener); | 353 addMember(field, listener); |
| 321 } | 354 } |
| 322 } | 355 } |
| 323 } | 356 } |
| 324 | 357 |
| 325 class CompilationUnitElement extends ContainerElement { | 358 class CompilationUnitElement extends ContainerElement { |
| 326 final Script script; | 359 final Script script; |
| 327 Link<Element> topLevelElements = const EmptyLink<Element>(); | |
| 328 | 360 |
| 329 CompilationUnitElement(Script script, Element enclosing) | 361 CompilationUnitElement(Script script, Element enclosing) |
| 330 : this.script = script, | 362 : this.script = script, |
| 331 super(new SourceString(script.name), | 363 super(new SourceString(script.name), |
| 332 ElementKind.COMPILATION_UNIT, | 364 ElementKind.COMPILATION_UNIT, |
| 333 enclosing); | 365 enclosing); |
| 334 | 366 |
| 335 CompilationUnitElement.library(Script script) | |
| 336 : this.script = script, | |
| 337 super(new SourceString(script.name), ElementKind.LIBRARY, null); | |
| 338 | |
| 339 CompilationUnitElement asCompilationUnit() => this; | |
| 340 | |
| 341 void addMember(Element element, DiagnosticListener listener) { | 367 void addMember(Element element, DiagnosticListener listener) { |
| 342 LibraryElement library = enclosingElement; | 368 // Keep a list of top level members. |
| 343 library.addMember(element, listener); | 369 super.addMember(element, listener); |
| 344 topLevelElements = topLevelElements.prepend(element); | 370 // Provide the member to the library to build scope. |
| 345 } | 371 getLibrary().addMember(element, listener); |
| 346 | |
| 347 void define(Element element, DiagnosticListener listener) { | |
| 348 LibraryElement library = enclosingElement; | |
| 349 library.define(element, listener); | |
| 350 } | |
| 351 | |
| 352 void addTag(ScriptTag tag, DiagnosticListener listener) { | |
| 353 listener.cancel("script tags not allowed here", node: tag); | |
| 354 } | 372 } |
| 355 } | 373 } |
| 356 | 374 |
| 357 class CompilationUnitOverrideElement extends Element { | 375 class CompilationUnitOverrideElement extends Element { |
| 358 final CompilationUnitElement compilationUnit; | 376 final CompilationUnitElement compilationUnit; |
| 359 | 377 |
| 360 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, | 378 CompilationUnitOverrideElement(CompilationUnitElement compilationUnit, |
| 361 Element enclosing) | 379 Element enclosing) |
| 362 : this.compilationUnit = compilationUnit, | 380 : this.compilationUnit = compilationUnit, |
| 363 super(compilationUnit.name, | 381 super(compilationUnit.name, |
| 364 ElementKind.COMPILATION_UNIT_OVERRIDE, | 382 ElementKind.COMPILATION_UNIT_OVERRIDE, |
| 365 enclosing); | 383 enclosing); |
| 366 | 384 |
| 367 CompilationUnitElement asCompilationUnit() => compilationUnit; | 385 CompilationUnitElement asCompilationUnit() => compilationUnit; |
| 368 } | 386 } |
| 369 | 387 |
| 370 class LibraryElement extends CompilationUnitElement { | 388 class LibraryElement extends ScopeContainerElement { |
| 371 // TODO(ahe): Library element should not be a subclass of | 389 CompilationUnitElement entryCompilationUnit; |
| 372 // CompilationUnitElement. | 390 Link<CompilationUnitElement> compilationUnits = |
| 391 const EmptyLink<CompilationUnitElement>(); | |
| 373 | 392 |
| 374 Link<CompilationUnitElement> compilationUnits = | |
| 375 const EmptyLink<CompilationUnitElement>(); | |
| 376 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); | 393 Link<ScriptTag> tags = const EmptyLink<ScriptTag>(); |
| 377 ScriptTag libraryTag; | 394 ScriptTag libraryTag; |
| 378 Map<SourceString, Element> elements; | |
| 379 bool canUseNative = false; | 395 bool canUseNative = false; |
| 380 LibraryElement patch = null; | 396 LibraryElement patch = null; |
| 381 | 397 |
| 382 LibraryElement(Script script) | 398 LibraryElement(Script script) |
| 383 : elements = new Map<SourceString, Element>(), | 399 : super(new SourceString(script.name), ElementKind.LIBRARY, null) { |
| 384 super.library(script); | 400 entryCompilationUnit = new CompilationUnitElement(script, this); |
| 401 } | |
| 402 | |
| 403 Uri get uri() => entryCompilationUnit.script.uri; | |
|
ahe
2012/08/14 12:45:26
Looking at some of the other changes in this CL, t
| |
| 385 | 404 |
| 386 bool get isPatched() => patch !== null; | 405 bool get isPatched() => patch !== null; |
| 387 | 406 |
| 388 void addCompilationUnit(CompilationUnitElement element) { | 407 void addCompilationUnit(CompilationUnitElement element) { |
| 389 compilationUnits = compilationUnits.prepend(element); | 408 compilationUnits = compilationUnits.prepend(element); |
| 390 } | 409 } |
| 391 | 410 |
| 392 void addTag(ScriptTag tag, DiagnosticListener listener) { | 411 void addTag(ScriptTag tag, DiagnosticListener listener) { |
| 393 tags = tags.prepend(tag); | 412 tags = tags.prepend(tag); |
| 394 } | 413 } |
| 395 | 414 |
| 396 void addMember(Element element, DiagnosticListener listener) { | |
| 397 topLevelElements = topLevelElements.prepend(element); | |
| 398 define(element, listener); | |
| 399 } | |
| 400 | |
| 401 void define(Element element, DiagnosticListener listener) { | |
| 402 if (element.kind == ElementKind.GETTER | |
| 403 || element.kind == ElementKind.SETTER) { | |
| 404 addGetterOrSetter(element, elements[element.name], listener); | |
| 405 } else { | |
| 406 Element existing = elements.putIfAbsent(element.name, () => element); | |
| 407 if (existing !== element) { | |
| 408 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | |
| 409 listener.cancel('duplicate definition', token: element.position()); | |
| 410 listener.cancel('existing definition', token: existing.position()); | |
| 411 } | |
| 412 } | |
| 413 } | |
| 414 | |
| 415 /** Look up a top-level element in this library. The element could | 415 /** Look up a top-level element in this library. The element could |
| 416 * potentially have been imported from another library. Returns | 416 * potentially have been imported from another library. Returns |
| 417 * null if no such element exist. */ | 417 * null if no such element exist. */ |
| 418 Element find(SourceString elementName) { | 418 Element find(SourceString elementName) { |
| 419 return elements[elementName]; | 419 return localScope[elementName]; |
| 420 } | 420 } |
| 421 | 421 |
| 422 /** Look up a top-level element in this library, but only look for | 422 /** Look up a top-level element in this library, but only look for |
| 423 * non-imported elements. Returns null if no such element exist. */ | 423 * non-imported elements. Returns null if no such element exist. */ |
| 424 Element findLocal(SourceString elementName) { | 424 Element findLocal(SourceString elementName) { |
| 425 Element result = elements[elementName]; | 425 Element result = localScope[elementName]; |
| 426 if (result === null || result.getLibrary() != this) return null; | 426 if (result === null || result.getLibrary() != this) return null; |
| 427 return result; | 427 return result; |
| 428 } | 428 } |
| 429 | 429 |
| 430 void forEachExport(f(Element element)) { | 430 void forEachExport(f(Element element)) { |
| 431 elements.forEach((SourceString _, Element e) { | 431 localScope.forEach((_, Element e) { |
| 432 if (this === e.getLibrary() | 432 if (this === e.getLibrary() |
| 433 && e.kind !== ElementKind.PREFIX | 433 && e.kind !== ElementKind.PREFIX |
| 434 && e.kind !== ElementKind.FOREIGN) { | 434 && e.kind !== ElementKind.FOREIGN |
| 435 if (!e.name.isPrivate()) f(e); | 435 && !e.name.isPrivate()) { |
| 436 f(e); | |
| 436 } | 437 } |
| 437 }); | 438 }); |
| 438 } | 439 } |
| 439 | 440 |
| 440 bool hasLibraryName() => libraryTag !== null; | 441 bool hasLibraryName() => libraryTag !== null; |
| 441 | 442 |
| 442 /** | 443 /** |
| 443 * Returns the library name (as defined by the #library tag) or for script | 444 * Returns the library name (as defined by the #library tag) or for script |
| 444 * (which have no #library tag) the script file name. The latter case is used | 445 * (which have no #library tag) the script file name. The latter case is used |
| 445 * to private 'library name' for scripts to use for instance in dartdoc. | 446 * to private 'library name' for scripts to use for instance in dartdoc. |
| 446 */ | 447 */ |
| 447 String getLibraryOrScriptName() { | 448 String getLibraryOrScriptName() { |
| 448 if (libraryTag !== null) { | 449 if (libraryTag !== null) { |
| 449 return libraryTag.argument.dartString.slowToString(); | 450 return libraryTag.argument.dartString.slowToString(); |
| 450 } else { | 451 } else { |
| 451 // Use the file name as script name. | 452 // Use the file name as script name. |
| 452 var path = script.uri.path; | 453 String path = uri.path; |
| 453 return path.substring(path.lastIndexOf('/') + 1); | 454 return path.substring(path.lastIndexOf('/') + 1); |
| 454 } | 455 } |
| 455 } | 456 } |
| 456 | 457 |
| 458 CompilationUnitElement getCompilationUnit() => entryCompilationUnit; | |
| 459 | |
| 457 Scope buildEnclosingScope() => new TopScope(this); | 460 Scope buildEnclosingScope() => new TopScope(this); |
| 458 } | 461 } |
| 459 | 462 |
| 460 class PrefixElement extends Element { | 463 class PrefixElement extends Element { |
| 461 Map<SourceString, Element> imported; | 464 Map<SourceString, Element> imported; |
| 462 Token firstPosition; | 465 Token firstPosition; |
| 463 | 466 |
| 464 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) | 467 PrefixElement(SourceString prefix, Element enclosing, this.firstPosition) |
| 465 : imported = new Map<SourceString, Element>(), | 468 : imported = new Map<SourceString, Element>(), |
| 466 super(prefix, ElementKind.PREFIX, enclosing); | 469 super(prefix, ElementKind.PREFIX, enclosing); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 686 } | 689 } |
| 687 | 690 |
| 688 position() { | 691 position() { |
| 689 // The getter and setter may be defined in two different | 692 // The getter and setter may be defined in two different |
| 690 // compilation units. However, we know that one of them is | 693 // compilation units. However, we know that one of them is |
| 691 // non-null and defined in the same compilation unit as the | 694 // non-null and defined in the same compilation unit as the |
| 692 // abstract element. | 695 // abstract element. |
| 693 // | 696 // |
| 694 // We need to make sure that the position returned is relative to | 697 // We need to make sure that the position returned is relative to |
| 695 // the compilation unit of the abstract element. | 698 // the compilation unit of the abstract element. |
| 696 if (getter !== null && getter.enclosingElement === enclosingElement) { | 699 if (getter !== null |
| 700 && getter.getCompilationUnit() === getCompilationUnit()) { | |
| 697 return getter.position(); | 701 return getter.position(); |
| 698 } else { | 702 } else { |
| 699 return setter.position(); | 703 return setter.position(); |
| 700 } | 704 } |
| 701 } | 705 } |
| 702 | 706 |
| 703 Modifiers get modifiers() { | 707 Modifiers get modifiers() { |
| 704 // The resolver ensures that the flags match (ignoring abstract). | 708 // The resolver ensures that the flags match (ignoring abstract). |
| 705 if (getter !== null) { | 709 if (getter !== null) { |
| 706 return new Modifiers.withFlags( | 710 return new Modifiers.withFlags( |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 973 TypeVariableElement variableElement = | 977 TypeVariableElement variableElement = |
| 974 new TypeVariableElement(variableName, element, node); | 978 new TypeVariableElement(variableName, element, node); |
| 975 TypeVariableType variableType = new TypeVariableType(variableElement); | 979 TypeVariableType variableType = new TypeVariableType(variableElement); |
| 976 variableElement.type = variableType; | 980 variableElement.type = variableType; |
| 977 arguments.addLast(variableType); | 981 arguments.addLast(variableType); |
| 978 } | 982 } |
| 979 return arguments.toLink(); | 983 return arguments.toLink(); |
| 980 } | 984 } |
| 981 } | 985 } |
| 982 | 986 |
| 983 class ClassElement extends ContainerElement | 987 class ClassElement extends ScopeContainerElement |
| 984 implements TypeDeclarationElement { | 988 implements TypeDeclarationElement { |
| 985 static final int STATE_NOT_STARTED = 0; | 989 static final int STATE_NOT_STARTED = 0; |
| 986 static final int STATE_STARTED = 1; | 990 static final int STATE_STARTED = 1; |
| 987 static final int STATE_DONE = 2; | 991 static final int STATE_DONE = 2; |
| 988 | 992 |
| 989 final int id; | 993 final int id; |
| 990 InterfaceType type; | 994 InterfaceType type; |
| 991 Type supertype; | 995 Type supertype; |
| 992 Type defaultClass; | 996 Type defaultClass; |
| 993 Link<Element> members = const EmptyLink<Element>(); | |
| 994 Map<SourceString, Element> localMembers; | |
| 995 Map<SourceString, Element> constructors; | |
| 996 Link<Type> interfaces; | 997 Link<Type> interfaces; |
| 997 SourceString nativeName; | 998 SourceString nativeName; |
| 998 | 999 |
| 999 int _supertypeLoadState = STATE_NOT_STARTED; | 1000 int _supertypeLoadState = STATE_NOT_STARTED; |
| 1000 int get supertypeLoadState() => _supertypeLoadState; | 1001 int get supertypeLoadState() => _supertypeLoadState; |
| 1001 void set supertypeLoadState(int state) { | 1002 void set supertypeLoadState(int state) { |
| 1002 assert(state == _supertypeLoadState + 1); | 1003 assert(state == _supertypeLoadState + 1); |
| 1003 assert(state <= STATE_DONE); | 1004 assert(state <= STATE_DONE); |
| 1004 _supertypeLoadState = state; | 1005 _supertypeLoadState = state; |
| 1005 } | 1006 } |
| 1006 | 1007 |
| 1007 int _resolutionState = STATE_NOT_STARTED; | 1008 int _resolutionState = STATE_NOT_STARTED; |
| 1008 int get resolutionState() => _resolutionState; | 1009 int get resolutionState() => _resolutionState; |
| 1009 void set resolutionState(int state) { | 1010 void set resolutionState(int state) { |
| 1010 assert(state == _resolutionState + 1); | 1011 assert(state == _resolutionState + 1); |
| 1011 assert(state <= STATE_DONE); | 1012 assert(state <= STATE_DONE); |
| 1012 _resolutionState = state; | 1013 _resolutionState = state; |
| 1013 } | 1014 } |
| 1014 | 1015 |
| 1015 // backendMembers are members that have been added by the backend to simplify | 1016 // backendMembers are members that have been added by the backend to simplify |
| 1016 // compilation. They don't have any user-side counter-part. | 1017 // compilation. They don't have any user-side counter-part. |
| 1017 Link<Element> backendMembers = const EmptyLink<Element>(); | 1018 Link<Element> backendMembers = const EmptyLink<Element>(); |
| 1018 | 1019 |
| 1019 Link<Type> allSupertypes; | 1020 Link<Type> allSupertypes; |
| 1020 | 1021 |
| 1021 ClassElement(SourceString name, Element enclosing, this.id) | 1022 ClassElement(SourceString name, Element enclosing, this.id) |
| 1022 : localMembers = new Map<SourceString, Element>(), | 1023 : super(name, ElementKind.CLASS, enclosing); |
| 1023 constructors = new Map<SourceString, Element>(), | |
| 1024 super(name, ElementKind.CLASS, enclosing); | |
| 1025 | |
| 1026 void addMember(Element element, DiagnosticListener listener) { | |
| 1027 members = members.prepend(element); | |
| 1028 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | |
| 1029 element.modifiers.isFactory()) { | |
| 1030 constructors[element.name] = element; | |
| 1031 } else if (element.kind == ElementKind.GETTER | |
| 1032 || element.kind == ElementKind.SETTER) { | |
| 1033 addGetterOrSetter(element, localMembers[element.name], listener); | |
| 1034 } else { | |
| 1035 Element existing = localMembers.putIfAbsent(element.name, () => element); | |
| 1036 if (existing !== element) { | |
| 1037 // TODO(ahe): Do something similar to Resolver.reportErrorWithContext. | |
| 1038 listener.cancel('duplicate definition', token: element.position()); | |
| 1039 listener.cancel('existing definition', token: existing.position()); | |
| 1040 } | |
| 1041 } | |
| 1042 } | |
| 1043 | 1024 |
| 1044 InterfaceType computeType(compiler) { | 1025 InterfaceType computeType(compiler) { |
| 1045 if (type == null) { | 1026 if (type == null) { |
| 1046 ClassNode node = parseNode(compiler); | 1027 ClassNode node = parseNode(compiler); |
| 1047 Link<Type> parameters = | 1028 Link<Type> parameters = |
| 1048 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 1029 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| 1049 type = new InterfaceType(this, parameters); | 1030 type = new InterfaceType(this, parameters); |
| 1050 } | 1031 } |
| 1051 return type; | 1032 return type; |
| 1052 } | 1033 } |
| 1053 | 1034 |
| 1054 Link<Type> get typeVariables() => type.arguments; | 1035 Link<Type> get typeVariables() => type.arguments; |
| 1055 | 1036 |
| 1056 ClassElement ensureResolved(Compiler compiler) { | 1037 ClassElement ensureResolved(Compiler compiler) { |
| 1057 if (resolutionState == STATE_NOT_STARTED) { | 1038 if (resolutionState == STATE_NOT_STARTED) { |
| 1058 compiler.resolver.resolveClass(this); | 1039 compiler.resolver.resolveClass(this); |
| 1059 } | 1040 } |
| 1060 return this; | 1041 return this; |
| 1061 } | 1042 } |
| 1062 | 1043 |
| 1044 /** | |
| 1045 * Lookup local members in the class. This will ignore constructors. | |
| 1046 */ | |
| 1063 Element lookupLocalMember(SourceString memberName) { | 1047 Element lookupLocalMember(SourceString memberName) { |
| 1064 return localMembers[memberName]; | 1048 var result = localLookup(memberName); |
| 1049 if (result !== null && result.isConstructor()) return null; | |
| 1050 return result; | |
| 1065 } | 1051 } |
| 1066 | 1052 |
| 1053 /** | |
| 1054 * Lookup super members for the class. This will ignore constructors. | |
|
ahe
2012/08/14 12:45:26
Indent.
| |
| 1055 */ | |
| 1067 Element lookupSuperMember(SourceString memberName) { | 1056 Element lookupSuperMember(SourceString memberName) { |
| 1068 bool isPrivate = memberName.isPrivate(); | 1057 bool isPrivate = memberName.isPrivate(); |
| 1069 for (ClassElement s = superclass; s != null; s = s.superclass) { | 1058 for (ClassElement s = superclass; s != null; s = s.superclass) { |
| 1070 // Private members from a different library are not visible. | 1059 // Private members from a different library are not visible. |
| 1071 if (isPrivate && getLibrary() !== s.getLibrary()) continue; | 1060 if (isPrivate && getLibrary() !== s.getLibrary()) continue; |
| 1072 Element e = s.lookupLocalMember(memberName); | 1061 Element e = s.lookupLocalMember(memberName); |
| 1073 if (e === null) continue; | 1062 if (e === null) continue; |
| 1074 // Static members are not inherited. | 1063 // Static members are not inherited. |
| 1075 if (e.modifiers.isStatic()) continue; | 1064 if (e.modifiers.isStatic()) continue; |
| 1076 return e; | 1065 return e; |
| 1077 } | 1066 } |
| 1078 return null; | 1067 return null; |
| 1079 } | 1068 } |
| 1080 | 1069 |
| 1081 /** | 1070 /** |
| 1082 * Find the first member in the class chain with the given | 1071 * Find the first member in the class chain with the given |
| 1083 * [memberName]. This method is NOT to be used for resolving | 1072 * [memberName]. This method is NOT to be used for resolving |
| 1084 * unqualified sends because it does not implement the scoping | 1073 * unqualified sends because it does not implement the scoping |
| 1085 * rules, where library scope comes before superclass scope. | 1074 * rules, where library scope comes before superclass scope. |
| 1086 */ | 1075 */ |
| 1087 Element lookupMember(SourceString memberName) { | 1076 Element lookupMember(SourceString memberName) { |
| 1088 Element localMember = localMembers[memberName]; | 1077 Element localMember = lookupLocalMember(memberName); |
| 1089 return localMember === null ? lookupSuperMember(memberName) : localMember; | 1078 return localMember === null ? lookupSuperMember(memberName) : localMember; |
| 1090 } | 1079 } |
| 1091 | 1080 |
| 1092 /** | 1081 /** |
| 1093 * Returns true if the [fieldMember] is shadowed by another field. The given | 1082 * Returns true if the [fieldMember] is shadowed by another field. The given |
| 1094 * [fieldMember] must be a member of this class. | 1083 * [fieldMember] must be a member of this class. |
| 1095 * | 1084 * |
| 1096 * This method also works if the [fieldMember] is private. | 1085 * This method also works if the [fieldMember] is private. |
| 1097 */ | 1086 */ |
| 1098 bool isShadowedByField(Element fieldMember) { | 1087 bool isShadowedByField(Element fieldMember) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1123 Element noMatch(Element)]) { | 1112 Element noMatch(Element)]) { |
| 1124 // TODO(karlklose): have a map from class names to a map of constructors | 1113 // TODO(karlklose): have a map from class names to a map of constructors |
| 1125 // instead of creating the name here? | 1114 // instead of creating the name here? |
| 1126 SourceString normalizedName; | 1115 SourceString normalizedName; |
| 1127 if (constructorName !== const SourceString('')) { | 1116 if (constructorName !== const SourceString('')) { |
| 1128 normalizedName = Elements.constructConstructorName(className, | 1117 normalizedName = Elements.constructConstructorName(className, |
| 1129 constructorName); | 1118 constructorName); |
| 1130 } else { | 1119 } else { |
| 1131 normalizedName = className; | 1120 normalizedName = className; |
| 1132 } | 1121 } |
| 1133 Element result = constructors[normalizedName]; | 1122 Element result = localLookup(normalizedName); |
| 1134 if (result === null && noMatch !== null) { | 1123 if (result === null || !result.isConstructor()) { |
| 1135 result = noMatch(lookupLocalMember(constructorName)); | 1124 result = noMatch !== null ? noMatch(result) : null; |
| 1136 } | 1125 } |
| 1137 return result; | 1126 return result; |
| 1138 } | 1127 } |
| 1128 | |
| 1129 bool get hasConstructor() { | |
|
ahe
2012/08/14 12:45:26
This is an O(n) operation but looks like a simple
| |
| 1130 // Search in scope to be sure we search patched constructors. | |
| 1131 for (var element in localScope.getValues()) { | |
|
ahe
2012/08/14 12:45:26
This should be iterating through a Link-list and u
| |
| 1132 if (element.isConstructor()) return true; | |
| 1133 } | |
| 1134 return false; | |
| 1135 } | |
| 1136 | |
| 1137 Link<Element> get constructors() { | |
|
ahe
2012/08/14 12:45:26
Same issue as above: doesn't feel like a getter as
| |
| 1138 // TODO(ajohnsen): See if we can avoid this method at some point. | |
| 1139 Link<Element> result = const EmptyLink<Element>(); | |
| 1140 for (Element member in localMembers) { | |
|
ahe
2012/08/14 12:45:26
C-style for-loop, please.
| |
| 1141 if (member.isConstructor()) result = result.prepend(member); | |
| 1142 } | |
| 1143 return result; | |
| 1144 } | |
| 1139 | 1145 |
| 1140 /** | 1146 /** |
| 1141 * Returns the super class, if any. | 1147 * Returns the super class, if any. |
| 1142 * | 1148 * |
| 1143 * The returned element may not be resolved yet. | 1149 * The returned element may not be resolved yet. |
| 1144 */ | 1150 */ |
| 1145 ClassElement get superclass() { | 1151 ClassElement get superclass() { |
| 1146 assert(supertypeLoadState == STATE_DONE); | 1152 assert(supertypeLoadState == STATE_DONE); |
| 1147 return supertype === null ? null : supertype.element; | 1153 return supertype === null ? null : supertype.element; |
| 1148 } | 1154 } |
| 1149 | 1155 |
| 1150 /** | 1156 /** |
| 1151 * Runs through all members of this class. | 1157 * Runs through all members of this class. |
| 1152 * | 1158 * |
| 1153 * The enclosing class is passed to the callback. This is useful when | 1159 * The enclosing class is passed to the callback. This is useful when |
| 1154 * [includeSuperMembers] is [:true:]. | 1160 * [includeSuperMembers] is [:true:]. |
| 1155 */ | 1161 */ |
| 1156 void forEachMember([void f(ClassElement enclosingClass, Element member), | 1162 void forEachMember([void f(ClassElement enclosingClass, Element member), |
| 1157 includeBackendMembers = false, | 1163 includeBackendMembers = false, |
| 1158 includeSuperMembers = false]) { | 1164 includeSuperMembers = false]) { |
| 1159 Set<ClassElement> seen = new Set<ClassElement>(); | 1165 Set<ClassElement> seen = new Set<ClassElement>(); |
| 1160 ClassElement classElement = this; | 1166 ClassElement classElement = this; |
| 1161 do { | 1167 do { |
| 1162 if (seen.contains(classElement)) return; | 1168 if (seen.contains(classElement)) return; |
| 1163 seen.add(classElement); | 1169 seen.add(classElement); |
| 1164 for (Element element in classElement.members) { | 1170 for (Element element in classElement.localMembers) { |
| 1165 f(classElement, element); | 1171 f(classElement, element); |
| 1166 } | 1172 } |
| 1167 if (includeBackendMembers) { | 1173 if (includeBackendMembers) { |
| 1168 for (Element element in classElement.backendMembers) { | 1174 for (Element element in classElement.backendMembers) { |
| 1169 f(classElement, element); | 1175 f(classElement, element); |
| 1170 } | 1176 } |
| 1171 } | 1177 } |
| 1172 classElement = includeSuperMembers ? classElement.superclass : null; | 1178 classElement = includeSuperMembers ? classElement.superclass : null; |
| 1173 } while(classElement !== null); | 1179 } while(classElement !== null); |
| 1174 } | 1180 } |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1419 Node parseNode(compiler) => cachedNode; | 1425 Node parseNode(compiler) => cachedNode; |
| 1420 | 1426 |
| 1421 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1427 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1422 | 1428 |
| 1423 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) { | 1429 TypeVariableElement cloneTo(Element enclosing, DiagnosticListener listener) { |
| 1424 TypeVariableElement result = | 1430 TypeVariableElement result = |
| 1425 new TypeVariableElement(name, enclosing, node, type, bound); | 1431 new TypeVariableElement(name, enclosing, node, type, bound); |
| 1426 return result; | 1432 return result; |
| 1427 } | 1433 } |
| 1428 } | 1434 } |
| OLD | NEW |