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

Side by Side Diff: tool/input_sdk/private/debugger.dart

Issue 2164763005: Library custom formatters (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Revert test files Created 4 years, 5 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
« no previous file with comments | « tool/input_sdk/private/ddc_runtime/types.dart ('k') | tool/sdk_expected_errors.txt » ('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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 dart._debugger; 5 library dart._debugger;
6 6
7 import 'dart:_foreign_helper' show JS; 7 import 'dart:_foreign_helper' show JS;
8 import 'dart:_runtime' as dart; 8 import 'dart:_runtime' as dart;
9 import 'dart:core'; 9 import 'dart:core';
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1 139 /// maxPowerOfSubsetSize of 2, so the list will be broken up into 1
140 /// 10000-length subset and 1 1-length subset. 140 /// 10000-length subset and 1 1-length subset.
141 int get maxPowerOfSubsetSize => 141 int get maxPowerOfSubsetSize =>
142 (log(length - .5) / log(_maxSpanLength)).truncate(); 142 (log(length - .5) / log(_maxSpanLength)).truncate();
143 int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize); 143 int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize);
144 144
145 Map<int, dynamic> asMap() => 145 Map<int, dynamic> asMap() =>
146 iterable.skip(start).take(length).toList().asMap(); 146 iterable.skip(start).take(length).toList().asMap();
147 147
148 List<NameValuePair> children() { 148 List<NameValuePair> children() {
149 var ret = <NameValuePair>[]; 149 var children = <NameValuePair>[];
150 if (length <= _maxSpanLength) { 150 if (length <= _maxSpanLength) {
151 asMap().forEach((i, element) { 151 asMap().forEach((i, element) {
152 ret.add( 152 children.add(
153 new NameValuePair(name: (i + start).toString(), value: element)); 153 new NameValuePair(name: (i + start).toString(), value: element));
154 }); 154 });
155 } else { 155 } else {
156 for (var i = start; i < end; i += subsetSize) { 156 for (var i = start; i < end; i += subsetSize) {
157 var subSpan = new IterableSpan(i, min(end, subsetSize + i), iterable); 157 var subSpan = new IterableSpan(i, min(end, subsetSize + i), iterable);
158 if (subSpan.length == 1) { 158 if (subSpan.length == 1) {
159 ret.add(new NameValuePair( 159 children.add(new NameValuePair(
160 name: i.toString(), value: iterable.elementAt(i))); 160 name: i.toString(), value: iterable.elementAt(i)));
161 } else { 161 } else {
162 ret.add(new NameValuePair( 162 children.add(new NameValuePair(
163 name: '[${i}...${subSpan.end - 1}]', 163 name: '[${i}...${subSpan.end - 1}]',
164 value: subSpan, 164 value: subSpan,
165 hideName: true)); 165 hideName: true));
166 } 166 }
167 } 167 }
168 } 168 }
169 return ret; 169 return children;
170 } 170 }
171 } 171 }
172 172
173 class ClassMetadata { 173 class Library {
174 ClassMetadata(this.object); 174 Library(this.name, this.object);
175
176 final String name;
177 final Object object;
178 }
179
180 class NamedConstructor {
181 NamedConstructor(this.object);
175 182
176 final Object object; 183 final Object object;
177 } 184 }
178 185
186 class ClassMetadata {
187 ClassMetadata(this.object, {this.name});
188
189 final Object object;
190 final String name;
191
192 String get typeName =>
193 name ??
194 getTypeName(object is Type ? object : dart.getReifiedType(object));
195 }
196
179 class HeritageClause { 197 class HeritageClause {
180 HeritageClause(this.name, this.types); 198 HeritageClause(this.name, this.types);
181 199
182 final String name; 200 final String name;
183 final List types; 201 final List types;
184 } 202 }
185 203
204 Object safeGetProperty(Object protoChain, String name) {
205 try {
206 return JSNative.getProperty(protoChain, name);
207 } catch (e) {
208 return '<Exception thrown> $e';
209 }
210 }
211
186 /// Class to simplify building the JsonML objects expected by the 212 /// Class to simplify building the JsonML objects expected by the
187 /// Devtools Formatter API. 213 /// Devtools Formatter API.
188 class JsonMLElement { 214 class JsonMLElement {
189 dynamic _attributes; 215 dynamic _attributes;
190 List _jsonML; 216 List _jsonML;
191 217
192 JsonMLElement(tagName) { 218 JsonMLElement(tagName) {
193 _attributes = JS('', '{}'); 219 _attributes = JS('', '{}');
194 _jsonML = [tagName, _attributes]; 220 _jsonML = [tagName, _attributes];
195 } 221 }
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 bool accept(object); 352 bool accept(object);
327 String preview(object); 353 String preview(object);
328 bool hasChildren(object); 354 bool hasChildren(object);
329 List<NameValuePair> children(object); 355 List<NameValuePair> children(object);
330 } 356 }
331 357
332 class DartFormatter { 358 class DartFormatter {
333 List<Formatter> _formatters; 359 List<Formatter> _formatters;
334 360
335 DartFormatter() { 361 DartFormatter() {
336 // The order of formatters matters as formatters later in the list take 362 // The order of formatters matters as formatters earlier in the list take
337 // precidence. 363 // precedence.
338 _formatters = [ 364 _formatters = [
365 new NamedConstructorFormatter(),
339 new FunctionFormatter(), 366 new FunctionFormatter(),
340 new MapFormatter(), 367 new MapFormatter(),
341 new IterableFormatter(), 368 new IterableFormatter(),
342 new MapEntryFormatter(), 369 new MapEntryFormatter(),
343 new IterableSpanFormatter(), 370 new IterableSpanFormatter(),
344 new ClassMetadataFormatter(), 371 new ClassMetadataFormatter(),
345 new HeritageClauseFormatter(), 372 new HeritageClauseFormatter(),
373 new LibraryModuleFormatter(),
374 new LibraryFormatter(),
346 new ObjectFormatter(), 375 new ObjectFormatter(),
347 ]; 376 ];
348 } 377 }
349 378
350 String preview(object) { 379 String preview(object) {
351 try { 380 try {
352 if (object == null || 381 if (object == null ||
353 object is num || 382 object is num ||
354 object is String || 383 object is String ||
355 isNativeJavaScriptObject(object)) { 384 isNativeJavaScriptObject(object)) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 436
408 String preview(object) => getObjectTypeName(object); 437 String preview(object) => getObjectTypeName(object);
409 438
410 bool hasChildren(object) => true; 439 bool hasChildren(object) => true;
411 440
412 List<NameValuePair> children(object) { 441 List<NameValuePair> children(object) {
413 var properties = new LinkedHashSet<NameValuePair>(); 442 var properties = new LinkedHashSet<NameValuePair>();
414 // Set of property names used to avoid duplicates. 443 // Set of property names used to avoid duplicates.
415 addMetadataChildren(object, properties); 444 addMetadataChildren(object, properties);
416 445
417 /// Helper to add members walking up the prototype chain being careful 446 var current = object;
418 /// to avoid properties that are Dart methods. 447
419 var protoChain = <Object>[]; 448 var protoChain = <Object>[];
420 var current = object;
421 while (current != null && 449 while (current != null &&
422 !isNativeJavaScriptObject(current) && 450 !isNativeJavaScriptObject(current) &&
423 JS("bool", "# !== Object.prototype", current)) { 451 JS("bool", "# !== Object.prototype", current)) {
424 protoChain.add(current); 452 protoChain.add(current);
425 current = JSNative.getProperty(current, '__proto__'); 453 current = safeGetProperty(current, '__proto__');
426 } 454 }
427 455
428 // We walk the prototype chain for symbol properties because they take 456 // We walk the prototype chain for symbol properties because they take
429 // priority and are accessed instead of Dart properties according to Dart 457 // priority and are accessed instead of Dart properties according to Dart
430 // calling conventions. 458 // calling conventions.
431 // TODO(jacobr): where possible use the data stored by dart.setSignature 459 // TODO(jacobr): where possible use the data stored by dart.setSignature
432 // instead of walking the JavaScript object directly. 460 // instead of walking the JavaScript object directly.
433 for (current in protoChain) { 461 for (current in protoChain) {
434 for (var symbol in getOwnPropertySymbols(current)) { 462 for (var symbol in getOwnPropertySymbols(current)) {
435 var dartName = symbolName(symbol); 463 var dartName = symbolName(symbol);
436 if (hasMethod(object, dartName)) { 464 if (hasMethod(object, dartName)) {
437 continue; 465 continue;
438 } 466 }
439 // TODO(jacobr): find a cleaner solution than checking for dartx 467 // TODO(jacobr): find a cleaner solution than checking for dartx
440 String dartXPrefix = 'dartx.'; 468 String dartXPrefix = 'dartx.';
441 if (dartName.startsWith(dartXPrefix)) { 469 if (dartName.startsWith(dartXPrefix)) {
442 dartName = dartName.substring(dartXPrefix.length); 470 dartName = dartName.substring(dartXPrefix.length);
443 } else if (!dartName.startsWith('_')) { 471 } else if (!dartName.startsWith('_')) {
444 // Dart method extension names should either be from dartx or should 472 // Dart method extension names should either be from dartx or should
445 // start with an _ 473 // start with an _
446 continue; 474 continue;
447 } 475 }
448 var value; 476 var value = safeGetProperty(object, symbol);
449 try {
450 value = JSNative.getProperty(object, symbol);
451 } catch (e) {
452 value = '<Exception thrown> $e';
453 }
454 properties.add(new NameValuePair(name: dartName, value: value)); 477 properties.add(new NameValuePair(name: dartName, value: value));
455 } 478 }
456 } 479 }
457 480
458 for (current in protoChain) { 481 for (current in protoChain) {
459 // TODO(jacobr): optionally distinguish properties and fields so that 482 // TODO(jacobr): optionally distinguish properties and fields so that
460 // it is safe to expand untrusted objects without side effects. 483 // it is safe to expand untrusted objects without side effects.
461 var className = dart.getReifiedType(current).name; 484 var className = dart.getReifiedType(current).name;
462 for (var name in getOwnPropertyNames(current)) { 485 for (var name in getOwnPropertyNames(current)) {
463 if (_customNames.contains(name) || name == className) continue; 486 if (_customNames.contains(name) || name == className) continue;
464 if (hasMethod(object, name)) { 487 if (hasMethod(object, name)) {
465 continue; 488 continue;
466 } 489 }
467 var value; 490 var value = safeGetProperty(object, name);
468 try {
469 value = JSNative.getProperty(object, name);
470 } catch (e) {
471 value = '<Exception thrown> $e';
472 }
473 properties.add(new NameValuePair(name: name, value: value)); 491 properties.add(new NameValuePair(name: name, value: value));
474 } 492 }
475 } 493 }
476 494
477 return properties.toList(); 495 return properties.toList();
478 } 496 }
479 497
480 addMetadataChildren(object, Set<NameValuePair> ret) { 498 addMetadataChildren(object, Set<NameValuePair> ret) {
481 ret.add( 499 var child = new ClassMetadata(object);
482 new NameValuePair(name: '[[class]]', value: new ClassMetadata(object))); 500 ret.add(new NameValuePair(name: child.typeName, value: child));
483 } 501 }
484 } 502 }
485 503
504 /// Formatter for module Dart Library objects.
505 class LibraryModuleFormatter extends ObjectFormatter {
506 String libraryName;
507
508 accept(object) {
509 libraryName = dart.getDartLibraryName(object);
510 return libraryName != null;
511 }
512
513 bool hasChildren(object) => true;
514
515 String preview(object) {
516 var libraryNames = libraryName.split('/');
517 // Library names are received with a repeat directory name, so strip the
518 // last directory entry here to make the path cleaner. For example, the
519 // library "third_party/dart/utf/utf" shoud display as
520 // "third_party/dart/utf/".
521 if (libraryNames.length > 1) {
522 libraryNames[libraryNames.length - 1] = '';
523 }
524 return 'Library Module: ${libraryNames.join('/')}';
525 }
526
527 List<NameValuePair> children(object) {
528 var children = new LinkedHashSet<NameValuePair>();
529 for (var name in getOwnPropertyNames(object)) {
530 var value = safeGetProperty(object, name);
531 // Replace __ with / to make file paths more readable. Then
532 // 'src__result__error' becomes 'src/result/error'.
533 name = '${name.replaceAll("__", "/")}.dart';
534 children.add(new NameValuePair(
535 name: name, value: new Library(name, value), hideName: true));
536 }
537 return children.toList();
538 }
539 }
540
541 /// Formatter for Dart Library objects.
542 class LibraryFormatter extends ObjectFormatter {
543 String genericName;
544 String genericArguments;
545
546 accept(object) => object is Library;
547
548 bool hasChildren(object) => true;
549
550 String preview(object) => object.name;
551
552 List<NameValuePair> children(object) {
553 var children = new LinkedHashSet<NameValuePair>();
554 var entry = object.object;
555 for (var name in getOwnPropertyNames(entry)) {
556 var value = safeGetProperty(entry, name);
557 if (value != null) {
558 var genericTypeConstructor = dart.getGenericTypeCtor(value);
559 if (genericTypeConstructor != null) {
560 genericName = name;
561 // Using JS toString() eliminates the leading metadata that is generat ed
562 // with the toString function provided in operations.dart.
563 // Splitting by => and taking the first element gives the list of
564 // arguments in the constructor.
565 genericArguments =
566 JS('String', '#.toString()', genericTypeConstructor)
567 .split(' =>')
568 .first
569 .replaceAll(new RegExp(r'[(|)]'), '');
570 } else if (value is Type) {
571 var typeName = getTypeName(value);
572 // Generic class names are generated with a $ at the end, so the
573 // corresponding non-generic class can be identified by adding $.
574 if ('$name\$' == genericName) {
575 typeName = '$typeName<$genericArguments>';
576 }
577 children.add(new NameValuePair(
578 name: typeName, value: new ClassMetadata(value, name: typeName)));
579 } else {
580 children.add(
581 new NameValuePair(name: name, value: new ClassMetadata(value)));
582 }
583 }
584 }
585 return children.toList();
586 }
587 }
588
486 /// Formatter for Dart Function objects. 589 /// Formatter for Dart Function objects.
487 /// Dart functions happen to be regular JavaScript Function objects but 590 /// Dart functions happen to be regular JavaScript Function objects but
488 /// we can distinguish them based on whether they have been tagged with 591 /// we can distinguish them based on whether they have been tagged with
489 /// runtime type information. 592 /// runtime type information.
490 class FunctionFormatter extends Formatter { 593 class FunctionFormatter extends Formatter {
491 accept(object) { 594 accept(object) {
492 if (_typeof(object) != 'function') return false; 595 if (_typeof(object) != 'function') return false;
493 return dart.getReifiedType(object) != null; 596 return dart.getReifiedType(object) != null;
494 } 597 }
495 598
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 } 652 }
550 } 653 }
551 654
552 bool hasChildren(object) => true; 655 bool hasChildren(object) => true;
553 656
554 List<NameValuePair> children(object) { 657 List<NameValuePair> children(object) {
555 // TODO(jacobr): be lazier about enumerating contents of Iterables that 658 // TODO(jacobr): be lazier about enumerating contents of Iterables that
556 // are not the built in Set or List types. 659 // are not the built in Set or List types.
557 // TODO(jacobr): handle large Iterables better. 660 // TODO(jacobr): handle large Iterables better.
558 // TODO(jacobr): consider only using numeric indices 661 // TODO(jacobr): consider only using numeric indices
559 var ret = new LinkedHashSet<NameValuePair>(); 662 var children = new LinkedHashSet<NameValuePair>();
560 ret.addAll((new IterableSpan(0, object.length, object)).children()); 663 children.addAll(new IterableSpan(0, object.length, object).children());
561 // TODO(jacobr): provide a link to show regular class properties here. 664 // TODO(jacobr): provide a link to show regular class properties here.
562 // required for subclasses of iterable, etc. 665 // required for subclasses of iterable, etc.
563 addMetadataChildren(object, ret); 666 addMetadataChildren(object, children);
564 return ret.toList(); 667 return children.toList();
565 } 668 }
566 } 669 }
567 670
568 // This class does double duting displaying metadata for 671 // This class does double duting displaying metadata for
569 class ClassMetadataFormatter implements Formatter { 672 class ClassMetadataFormatter implements Formatter {
570 accept(object) => object is ClassMetadata; 673 accept(object) => object is ClassMetadata;
571 674
572 _getType(object) { 675 Object _getType(object) {
573 if (object is Type) return object; 676 if (object is Type) return object;
574 return dart.getReifiedType(object); 677 return dart.getReifiedType(object);
575 } 678 }
576 679
577 String preview(object) { 680 String preview(object) {
578 ClassMetadata entry = object; 681 ClassMetadata entry = object;
579 return getTypeName(_getType(entry.object)); 682 var type =
683 entry.object is Type ? entry.object : dart.getReifiedType(entry.object);
684 var implements = dart.getImplements(type);
685 if (implements != null) {
686 var typeNames = implements().map(getTypeName);
687 return '${entry.typeName} implements ${typeNames.join(", ")}';
688 } else {
689 return entry.typeName;
690 }
580 } 691 }
581 692
582 bool hasChildren(object) => true; 693 bool hasChildren(object) => true;
583 694
584 List<NameValuePair> children(object) { 695 List<NameValuePair> children(object) {
585 ClassMetadata entry = object; 696 ClassMetadata entry = object;
697 var classObject = entry.object;
586 // TODO(jacobr): add other entries describing the class such as 698 // TODO(jacobr): add other entries describing the class such as
587 // links to the superclass, mixins, implemented interfaces, and methods. 699 // links to the superclass, mixins, implemented interfaces, and methods.
588 var type = _getType(entry.object); 700 var type = _getType(classObject);
589 var ret = <NameValuePair>[]; 701 var children = <NameValuePair>[];
590 var implements = dart.getImplements(type); 702
591 if (implements != null) {
592 ret.add(new NameValuePair(
593 name: '[[Implements]]',
594 value: new HeritageClause('implements', implements())));
595 }
596 var mixins = dart.getMixins(type); 703 var mixins = dart.getMixins(type);
597 if (mixins != null && mixins.isNotEmpty) { 704 if (mixins != null && mixins.isNotEmpty) {
598 ret.add(new NameValuePair( 705 children.add(new NameValuePair(
599 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins))); 706 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
600 } 707 }
601 ret.add(new NameValuePair(
602 name: '[[JavaScript View]]',
603 value: entry.object,
604 config: JsonMLConfig.skipDart));
605 708
709 var hiddenProperties = ['length', 'name', 'prototype'];
710 // Addition of NameValuePairs for static variables and named constructors.
711 for (var name in getOwnPropertyNames(classObject)) {
712 // TODO(bmilligan): Perform more principled checks to filter out spurious
713 // members.
714 if (hiddenProperties.contains(name)) continue;
715 var value = safeGetProperty(classObject, name);
716 if (value != null && dart.getIsNamedConstructor(value) != null) {
717 value = new NamedConstructor(value);
718 name = '${entry.typeName}.$name';
719 }
720 children.add(new NameValuePair(name: name, value: value));
721 }
722
723 // TODO(bmilligan): Replace the hard coding of $identityHash.
724 var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash'];
725 // Addition of class methods.
726 var prototype = JS('var', '#["prototype"]', classObject);
727 if (prototype != null) {
728 for (var name in getOwnPropertyNames(prototype)) {
729 if (hiddenPrototypeProperties.contains(name)) continue;
730 // Simulate dart.bind by using dart.tag and tear off the function
731 // so it will be recognized by the FunctionFormatter.
732 var function = safeGetProperty(prototype, name);
733 var constructor = safeGetProperty(prototype, 'constructor');
734 var sigObj = dart.getMethodSig(constructor);
735 if (sigObj != null) {
736 var value = safeGetProperty(sigObj, name);
737 if (getTypeName(dart.getReifiedType(value)) != 'Null') {
738 dart.tag(function, value);
739 children.add(new NameValuePair(name: name, value: function));
740 }
741 }
742 }
743 }
606 // TODO(jacobr): provide a link to the base class or perhaps the entire 744 // TODO(jacobr): provide a link to the base class or perhaps the entire
607 // base class hierarchy as a flat list. 745 // base class hierarchy as a flat list.
746 // TODO(jacobr): add constructors, methods, extended class, and static
747 return children;
748 }
749 }
608 750
609 if (entry.object is! Type) { 751 class NamedConstructorFormatter implements Formatter {
610 ret.add(new NameValuePair( 752 accept(object) => object is NamedConstructor;
611 name: '[[JavaScript Constructor]]', 753
612 value: JSNative.getProperty(entry.object, 'constructor'), 754 // TODO(bmilligan): Display the signature of the named constructor as the
613 config: JsonMLConfig.skipDart)); 755 // preview.
614 // TODO(jacobr): add constructors, methods, extended class, and static 756 String preview(object) => 'Named Constructor';
615 } 757
616 return ret; 758 bool hasChildren(object) => true;
617 } 759
760 List<NameValuePair> children(object) => <NameValuePair>[
761 new NameValuePair(
762 name: 'JavaScript Function',
763 value: object,
764 config: JsonMLConfig.skipDart)
765 ];
618 } 766 }
619 767
620 /// Formatter for synthetic MapEntry objects used to display contents of a Map 768 /// Formatter for synthetic MapEntry objects used to display contents of a Map
621 /// cleanly. 769 /// cleanly.
622 class MapEntryFormatter implements Formatter { 770 class MapEntryFormatter implements Formatter {
623 accept(object) => object is MapEntry; 771 accept(object) => object is MapEntry;
624 772
625 String preview(object) { 773 String preview(object) {
626 MapEntry entry = object; 774 MapEntry entry = object;
627 return '${safePreview(entry.key)} => ${safePreview(entry.value)}'; 775 return '${safePreview(entry.key)} => ${safePreview(entry.value)}';
628 } 776 }
629 777
630 bool hasChildren(object) => true; 778 bool hasChildren(object) => true;
631 779
632 List<NameValuePair> children(object) => <NameValuePair>[ 780 List<NameValuePair> children(object) => <NameValuePair>[
633 new NameValuePair( 781 new NameValuePair(
634 name: 'key', value: object.key, config: JsonMLConfig.keyToString), 782 name: 'key', value: object.key, config: JsonMLConfig.keyToString),
635 new NameValuePair(name: 'value', value: object.value) 783 new NameValuePair(name: 'value', value: object.value)
636 ]; 784 ];
637 } 785 }
638 786
639 /// Formatter for Dart Iterable objects including List and Set. 787 /// Formatter for Dart Iterable objects including List and Set.
640 class HeritageClauseFormatter implements Formatter { 788 class HeritageClauseFormatter implements Formatter {
641 bool accept(object) => object is HeritageClause; 789 bool accept(object) => object is HeritageClause;
642 790
643 String preview(object) { 791 String preview(object) {
644 HeritageClause clause = object; 792 HeritageClause clause = object;
645 var typeNames = clause.types.map((type) => getTypeName(type)); 793 var typeNames = clause.types.map(getTypeName);
646 return '${clause.name} ${typeNames.join(", ")}'; 794 return '${clause.name} ${typeNames.join(", ")}';
647 } 795 }
648 796
649 bool hasChildren(object) => true; 797 bool hasChildren(object) => true;
650 798
651 List<NameValuePair> children(object) { 799 List<NameValuePair> children(object) {
652 HeritageClause clause = object; 800 HeritageClause clause = object;
653 var ret = <NameValuePair>[]; 801 var children = <NameValuePair>[];
654 for (var type in clause.types) { 802 for (var type in clause.types) {
655 ret.add(new NameValuePair(value: new ClassMetadata(type))); 803 children.add(new NameValuePair(value: new ClassMetadata(type)));
656 } 804 }
657 return ret; 805 return children;
658 } 806 }
659 } 807 }
660 808
661 /// Formatter for synthetic IterableSpan objects used to display contents of 809 /// Formatter for synthetic IterableSpan objects used to display contents of
662 /// an Iterable cleanly. 810 /// an Iterable cleanly.
663 class IterableSpanFormatter implements Formatter { 811 class IterableSpanFormatter implements Formatter {
664 accept(object) => object is IterableSpan; 812 accept(object) => object is IterableSpan;
665 813
666 String preview(object) { 814 String preview(object) {
667 return '[${object.start}...${object.end-1}]'; 815 return '[${object.start}...${object.end-1}]';
668 } 816 }
669 817
670 bool hasChildren(object) => true; 818 bool hasChildren(object) => true;
671 819
672 List<NameValuePair> children(object) => object.children(); 820 List<NameValuePair> children(object) => object.children();
673 } 821 }
674 822
675 /// This entry point is automatically invoked by the code generated by 823 /// This entry point is automatically invoked by the code generated by
676 /// Dart Dev Compiler 824 /// Dart Dev Compiler
677 registerDevtoolsFormatter() { 825 registerDevtoolsFormatter() {
678 var formatters = [_devtoolsFormatter]; 826 var formatters = [_devtoolsFormatter];
679 JS('', 'dart.global.devtoolsFormatters = #', formatters); 827 JS('', 'dart.global.devtoolsFormatters = #', formatters);
680 } 828 }
OLDNEW
« no previous file with comments | « tool/input_sdk/private/ddc_runtime/types.dart ('k') | tool/sdk_expected_errors.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698