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

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

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

Powered by Google App Engine
This is Rietveld 408576698