Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: lib/compiler/implementation/elements/elements.dart

Issue 10830303: Refactor Library/CompilationUnit and how we define local Scope. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix reference in dart2js_mirror.dart Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698