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

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

Issue 2205733002: Deprecation of ClassMetadata wrapper for Class formatters so a stand-alone class is recognizable. (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Changed to expected errors Created 4 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
« no previous file with comments | « lib/runtime/dart_sdk.js ('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 10 matching lines...) Expand all
21 /// the Dart formatter. 21 /// the Dart formatter.
22 /// 22 ///
23 /// We'd like this to be an enum, but we can't because it's a dev_compiler bug. 23 /// We'd like this to be an enum, but we can't because it's a dev_compiler bug.
24 class JsonMLConfig { 24 class JsonMLConfig {
25 const JsonMLConfig(this.name); 25 const JsonMLConfig(this.name);
26 26
27 final String name; 27 final String name;
28 static const none = const JsonMLConfig("none"); 28 static const none = const JsonMLConfig("none");
29 static const skipDart = const JsonMLConfig("skipDart"); 29 static const skipDart = const JsonMLConfig("skipDart");
30 static const keyToString = const JsonMLConfig("keyToString"); 30 static const keyToString = const JsonMLConfig("keyToString");
31 static const asClass = const JsonMLConfig("asClass");
31 } 32 }
32 33
33 int _maxSpanLength = 100; 34 int _maxSpanLength = 100;
34
35 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter()); 35 var _devtoolsFormatter = new JsonMLFormatter(new DartFormatter());
36 36
37 String _typeof(object) => JS('String', 'typeof #', object); 37 String _typeof(object) => JS('String', 'typeof #', object);
38 38
39 List<String> getOwnPropertyNames(object) => JS('List<String>', 39 List<String> getOwnPropertyNames(object) => JS('List<String>',
40 'dart.list(Object.getOwnPropertyNames(#), #)', object, String); 40 'dart.list(Object.getOwnPropertyNames(#), #)', object, String);
41 41
42 List getOwnPropertySymbols(object) => 42 List getOwnPropertySymbols(object) =>
43 JS('List', 'Object.getOwnPropertySymbols(#)', object); 43 JS('List', 'Object.getOwnPropertySymbols(#)', object);
44 44
45 // TODO(jacobr): move this to dart:js and fully implement. 45 // TODO(jacobr): move this to dart:js and fully implement.
46 class JSNative { 46 class JSNative {
47 // Name may be a String or a Symbol. 47 // Name may be a String or a Symbol.
48 static getProperty(object, name) => JS('', '#[#]', object, name); 48 static getProperty(object, name) => JS('', '#[#]', object, name);
49 // Name may be a String or a Symbol. 49 // Name may be a String or a Symbol.
50 static setProperty(object, name, value) => 50 static setProperty(object, name, value) =>
51 JS('', '#[#]=#', object, name, value); 51 JS('', '#[#]=#', object, name, value);
52 } 52 }
53 53
54 void addMetadataChildren(object, Set<NameValuePair> ret) {
55 ret.add(new NameValuePair(
56 name: getTypeName(_getType(object)),
57 value: object,
58 config: JsonMLConfig.asClass));
59 }
60
54 String getObjectTypeName(object) { 61 String getObjectTypeName(object) {
55 var reifiedType = dart.getReifiedType(object); 62 var reifiedType = dart.getReifiedType(object);
56 if (reifiedType == null) { 63 if (reifiedType == null) {
57 if (_typeof(object) == 'function') { 64 if (_typeof(object) == 'function') {
58 return '[[Raw JavaScript Function]]'; 65 return '[[Raw JavaScript Function]]';
59 } 66 }
60 return '<Error getting type name>'; 67 return '<Error getting type name>';
61 } 68 }
62 return getTypeName(reifiedType); 69 return getTypeName(reifiedType);
63 } 70 }
64 71
65 String getTypeName(Type type) { 72 String getTypeName(Type type) {
66 var name = dart.typeName(type); 73 var name = dart.typeName(type);
67 // Hack to cleanup names for List<dynamic> 74 // Hack to cleanup names for List<dynamic>
68 // TODO(jacobr): it would be nice if there was a way we could distinguish 75 // TODO(jacobr): it would be nice if there was a way we could distinguish
69 // between a List<dynamic> created from Dart and an Array passed in from 76 // between a List<dynamic> created from Dart and an Array passed in from
70 // JavaScript. 77 // JavaScript.
71 if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>') 78 if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>')
72 return 'List<dynamic>'; 79 return 'List<dynamic>';
73 return name; 80 return name;
74 } 81 }
75 82
76 String safePreview(object) { 83 Object _getType(object) =>
84 object is Type ? object : dart.getReifiedType(object);
85
86 String safePreview(object, config) {
77 try { 87 try {
78 var preview = _devtoolsFormatter._simpleFormatter.preview(object); 88 var preview = _devtoolsFormatter._simpleFormatter.preview(object, config);
79 if (preview != null) return preview; 89 if (preview != null) return preview;
80 return object.toString(); 90 return object.toString();
81 } catch (e) { 91 } catch (e) {
82 return '<Exception thrown> $e'; 92 return '<Exception thrown> $e';
83 } 93 }
84 } 94 }
85 95
86 String symbolName(symbol) { 96 String symbolName(symbol) {
87 var name = symbol.toString(); 97 var name = symbol.toString();
88 assert(name.startsWith('Symbol(')); 98 assert(name.startsWith('Symbol('));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 final String name; 186 final String name;
177 final Object object; 187 final Object object;
178 } 188 }
179 189
180 class NamedConstructor { 190 class NamedConstructor {
181 NamedConstructor(this.object); 191 NamedConstructor(this.object);
182 192
183 final Object object; 193 final Object object;
184 } 194 }
185 195
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
197 class HeritageClause { 196 class HeritageClause {
198 HeritageClause(this.name, this.types); 197 HeritageClause(this.name, this.types);
199 198
200 final String name; 199 final String name;
201 final List types; 200 final List types;
202 } 201 }
203 202
204 Object safeGetProperty(Object protoChain, String name) { 203 Object safeGetProperty(Object protoChain, Object name) {
205 try { 204 try {
206 return JSNative.getProperty(protoChain, name); 205 return JSNative.getProperty(protoChain, name);
207 } catch (e) { 206 } catch (e) {
208 return '<Exception thrown> $e'; 207 return '<Exception thrown> $e';
209 } 208 }
210 } 209 }
211 210
212 safeProperties(object) => new Map.fromIterable( 211 safeProperties(object) => new Map.fromIterable(
213 getOwnPropertyNames(object) 212 getOwnPropertyNames(object)
214 .where((each) => safeGetProperty(object, each) != null), 213 .where((each) => safeGetProperty(object, each) != null),
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 292
294 void setMaxSpanLengthForTestingOnly(int spanLength) { 293 void setMaxSpanLengthForTestingOnly(int spanLength) {
295 _maxSpanLength = spanLength; 294 _maxSpanLength = spanLength;
296 } 295 }
297 296
298 header(object, config) { 297 header(object, config) {
299 customFormattersOn = true; 298 customFormattersOn = true;
300 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) { 299 if (config == JsonMLConfig.skipDart || isNativeJavaScriptObject(object)) {
301 return null; 300 return null;
302 } 301 }
303 302 var c = _simpleFormatter.preview(object, config);
304 var c = _simpleFormatter.preview(object);
305 if (c == null) return null; 303 if (c == null) return null;
306 304
307 if (config == JsonMLConfig.keyToString) { 305 if (config == JsonMLConfig.keyToString) {
308 c = object.toString(); 306 c = object.toString();
309 } 307 }
310 308
311 // Indicate this is a Dart Object by using a Dart background color. 309 // Indicate this is a Dart Object by using a Dart background color.
312 // This is stylistically a bit ugly but it eases distinguishing Dart and 310 // This is stylistically a bit ugly but it eases distinguishing Dart and
313 // JS objects. 311 // JS objects.
314 var element = new JsonMLElement('span') 312 var element = new JsonMLElement('span')
315 ..setStyle('background-color: #d9edf7;') 313 ..setStyle('background-color: #d9edf7;')
316 ..createTextChild(c); 314 ..createTextChild(c);
317 return element.toJsonML(); 315 return element.toJsonML();
318 } 316 }
319 317
320 bool hasBody(object) => _simpleFormatter.hasChildren(object); 318 bool hasBody(object, config) => _simpleFormatter.hasChildren(object, config);
321 319
322 body(object) { 320 body(object, config) {
323 var body = new JsonMLElement('ol') 321 var body = new JsonMLElement('ol')
324 ..setStyle('list-style-type: none;' 322 ..setStyle('list-style-type: none;'
325 'padding-left: 0px;' 323 'padding-left: 0px;'
326 'margin-top: 0px;' 324 'margin-top: 0px;'
327 'margin-bottom: 0px;' 325 'margin-bottom: 0px;'
328 'margin-left: 12px;'); 326 'margin-left: 12px;');
329 if (object is StackTrace) { 327 if (object is StackTrace) {
330 body.addStyle('color: rgb(196, 26, 22);'); 328 body.addStyle('color: rgb(196, 26, 22);');
331 } 329 }
332 var children = _simpleFormatter.children(object); 330 var children = _simpleFormatter.children(object, config);
333 for (NameValuePair child in children) { 331 for (NameValuePair child in children) {
334 var li = body.createChild('li'); 332 var li = body.createChild('li');
335 var nameSpan = new JsonMLElement('span') 333 var nameSpan = new JsonMLElement('span')
336 ..createTextChild( 334 ..createTextChild(
337 child.displayName.isNotEmpty ? '${child.displayName}: ' : '') 335 child.displayName.isNotEmpty ? '${child.displayName}: ' : '')
338 ..setStyle('color: rgb(136, 19, 145);'); 336 ..setStyle('color: rgb(136, 19, 145);');
339 if (_typeof(child.value) == 'object' || 337 if (_typeof(child.value) == 'object' ||
340 _typeof(child.value) == 'function') { 338 _typeof(child.value) == 'function') {
341 nameSpan.addStyle("padding-left: 13px;"); 339 nameSpan.addStyle("padding-left: 13px;");
342 340
343 li.appendChild(nameSpan); 341 li.appendChild(nameSpan);
344 var objectTag = li.createObjectTag(child.value); 342 var objectTag = li.createObjectTag(child.value);
345 objectTag.addAttribute('config', child.config); 343 objectTag.addAttribute('config', child.config);
346 if (!_simpleFormatter.hasChildren(child.value)) { 344 if (!_simpleFormatter.hasChildren(child.value, child.config)) {
347 li.setStyle("padding-left: 13px;"); 345 li.setStyle("padding-left: 13px;");
348 } 346 }
349 } else { 347 } else {
350 li.setStyle("padding-left: 13px;"); 348 li.setStyle("padding-left: 13px;");
351 li.createChild('span') 349 li.createChild('span')
352 ..appendChild(nameSpan) 350 ..appendChild(nameSpan)
353 ..createTextChild(safePreview(child.value)); 351 ..createTextChild(safePreview(child.value, child.config));
354 } 352 }
355 } 353 }
356 return body.toJsonML(); 354 return body.toJsonML();
357 } 355 }
358 } 356 }
359 357
360 abstract class Formatter { 358 abstract class Formatter {
361 bool accept(object); 359 bool accept(object, config);
362 String preview(object); 360 String preview(object);
363 bool hasChildren(object); 361 bool hasChildren(object);
364 List<NameValuePair> children(object); 362 List<NameValuePair> children(object);
365 } 363 }
366 364
367 class DartFormatter { 365 class DartFormatter {
368 List<Formatter> _formatters; 366 List<Formatter> _formatters;
369 367
370 DartFormatter() { 368 DartFormatter() {
371 // The order of formatters matters as formatters earlier in the list take 369 // The order of formatters matters as formatters earlier in the list take
372 // precedence. 370 // precedence.
373 _formatters = [ 371 _formatters = [
372 new ClassFormatter(),
374 new NamedConstructorFormatter(), 373 new NamedConstructorFormatter(),
375 new FunctionFormatter(),
376 new MapFormatter(), 374 new MapFormatter(),
377 new IterableFormatter(), 375 new IterableFormatter(),
376 new IterableSpanFormatter(),
378 new MapEntryFormatter(), 377 new MapEntryFormatter(),
379 new IterableSpanFormatter(),
380 new StackTraceFormatter(), 378 new StackTraceFormatter(),
381 new ClassMetadataFormatter(), 379 new FunctionFormatter(),
382 new HeritageClauseFormatter(), 380 new HeritageClauseFormatter(),
383 new LibraryModuleFormatter(), 381 new LibraryModuleFormatter(),
384 new LibraryFormatter(), 382 new LibraryFormatter(),
385 new ObjectFormatter(), 383 new ObjectFormatter(),
386 ]; 384 ];
387 } 385 }
388 386
389 String preview(object) { 387 String preview(object, config) {
390 try { 388 try {
391 if (object == null || 389 if (object == null ||
392 object is num || 390 object is num ||
393 object is String || 391 object is String ||
394 isNativeJavaScriptObject(object)) { 392 isNativeJavaScriptObject(object)) {
395 return object.toString(); 393 return object.toString();
396 } 394 }
397
398 for (var formatter in _formatters) { 395 for (var formatter in _formatters) {
399 if (formatter.accept(object)) return formatter.preview(object); 396 if (formatter.accept(object, config)) return formatter.preview(object);
400 } 397 }
401 } catch (e, trace) { 398 } catch (e, trace) {
402 // Log formatter internal errors as unfortunately the devtools cannot 399 // Log formatter internal errors as unfortunately the devtools cannot
403 // be used to debug formatter errors. 400 // be used to debug formatter errors.
404 html.window.console.error("Caught exception $e\n trace:\n$trace"); 401 html.window.console.error("Caught exception $e\n trace:\n$trace");
405 } 402 }
406 403
407 return null; 404 return null;
408 } 405 }
409 406
410 bool hasChildren(object) { 407 bool hasChildren(object, config) {
411 if (object == null) return false; 408 if (object == null) return false;
412 try { 409 try {
413 for (var formatter in _formatters) { 410 for (var formatter in _formatters) {
414 if (formatter.accept(object)) return formatter.hasChildren(object); 411 if (formatter.accept(object, config))
412 return formatter.hasChildren(object);
415 } 413 }
416 } catch (e, trace) { 414 } catch (e, trace) {
417 // See comment for preview. 415 // See comment for preview.
418 html.window.console 416 html.window.console
419 .error("[hasChildren] Caught exception $e\n trace:\n$trace"); 417 .error("[hasChildren] Caught exception $e\n trace:\n$trace");
420 } 418 }
421 return false; 419 return false;
422 } 420 }
423 421
424 List<NameValuePair> children(object) { 422 List<NameValuePair> children(object, config) {
425 try { 423 try {
426 if (object != null) { 424 if (object != null) {
427 for (var formatter in _formatters) { 425 for (var formatter in _formatters) {
428 if (formatter.accept(object)) return formatter.children(object); 426 if (formatter.accept(object, config))
427 return formatter.children(object);
429 } 428 }
430 } 429 }
431 } catch (e, trace) { 430 } catch (e, trace) {
432 // See comment for preview. 431 // See comment for preview.
433 html.window.console.error("Caught exception $e\n trace:\n$trace"); 432 html.window.console.error("Caught exception $e\n trace:\n$trace");
434 } 433 }
435 return <NameValuePair>[]; 434 return <NameValuePair>[];
436 } 435 }
437 } 436 }
438 437
439 /// Default formatter for Dart Objects. 438 /// Default formatter for Dart Objects.
440 class ObjectFormatter extends Formatter { 439 class ObjectFormatter extends Formatter {
441 static Set<String> _customNames = new Set() 440 static Set<String> _customNames = new Set()
442 ..add('constructor') 441 ..add('constructor')
443 ..add('prototype') 442 ..add('prototype')
444 ..add('__proto__'); 443 ..add('__proto__');
445 bool accept(object) => !isNativeJavaScriptObject(object); 444 bool accept(object, config) => !isNativeJavaScriptObject(object);
446 445
447 String preview(object) => getObjectTypeName(object); 446 String preview(object) => getObjectTypeName(object);
448 447
449 bool hasChildren(object) => true; 448 bool hasChildren(object) => true;
450 449
451 List<NameValuePair> children(object) { 450 List<NameValuePair> children(object) {
452 var properties = new LinkedHashSet<NameValuePair>(); 451 var properties = new LinkedHashSet<NameValuePair>();
453 // Set of property names used to avoid duplicates. 452 // Set of property names used to avoid duplicates.
454 addMetadataChildren(object, properties); 453 addMetadataChildren(object, properties);
455 454
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 if (hasMethod(object, name)) { 496 if (hasMethod(object, name)) {
498 continue; 497 continue;
499 } 498 }
500 var value = safeGetProperty(object, name); 499 var value = safeGetProperty(object, name);
501 properties.add(new NameValuePair(name: name, value: value)); 500 properties.add(new NameValuePair(name: name, value: value));
502 } 501 }
503 } 502 }
504 503
505 return properties.toList(); 504 return properties.toList();
506 } 505 }
507
508 addMetadataChildren(object, Set<NameValuePair> ret) {
509 var child = new ClassMetadata(object);
510 ret.add(new NameValuePair(name: child.typeName, value: child));
511 }
512 } 506 }
513 507
514 /// Formatter for module Dart Library objects. 508 /// Formatter for module Dart Library objects.
515 class LibraryModuleFormatter extends ObjectFormatter { 509 class LibraryModuleFormatter implements Formatter {
516 String libraryName; 510 String libraryName;
517 511
518 accept(object) { 512 accept(object, config) {
519 libraryName = dart.getDartLibraryName(object); 513 libraryName = dart.getDartLibraryName(object);
520 return libraryName != null; 514 return libraryName != null;
521 } 515 }
522 516
523 bool hasChildren(object) => true; 517 bool hasChildren(object) => true;
524 518
525 String preview(object) { 519 String preview(object) {
526 var libraryNames = libraryName.split('/'); 520 var libraryNames = libraryName.split('/');
527 // Library names are received with a repeat directory name, so strip the 521 // Library names are received with a repeat directory name, so strip the
528 // last directory entry here to make the path cleaner. For example, the 522 // last directory entry here to make the path cleaner. For example, the
(...skipping 12 matching lines...) Expand all
541 // Replace __ with / to make file paths more readable. Then 535 // Replace __ with / to make file paths more readable. Then
542 // 'src__result__error' becomes 'src/result/error'. 536 // 'src__result__error' becomes 'src/result/error'.
543 name = '${name.replaceAll("__", "/")}.dart'; 537 name = '${name.replaceAll("__", "/")}.dart';
544 children.add(new NameValuePair( 538 children.add(new NameValuePair(
545 name: name, value: new Library(name, value), hideName: true)); 539 name: name, value: new Library(name, value), hideName: true));
546 } 540 }
547 return children.toList(); 541 return children.toList();
548 } 542 }
549 } 543 }
550 544
551 /// Formatter for Dart Library objects. 545 class LibraryFormatter implements Formatter {
552 class LibraryFormatter extends ObjectFormatter {
553 var genericParameters = new HashMap<String, String>(); 546 var genericParameters = new HashMap<String, String>();
554 547
555 accept(object) => object is Library; 548 accept(object, config) => object is Library;
556 549
557 bool hasChildren(object) => true; 550 bool hasChildren(object) => true;
558 551
559 String preview(object) => object.name; 552 String preview(object) => object.name;
560 553
561 List<NameValuePair> children(object) { 554 List<NameValuePair> children(object) {
562 var children = new LinkedHashSet<NameValuePair>(); 555 var children = new LinkedHashSet<NameValuePair>();
563 var nonGenericProperties = new LinkedHashMap<String, Object>(); 556 var nonGenericProperties = new LinkedHashMap<String, Object>();
564 var objectProperties = safeProperties(object.object); 557 var objectProperties = safeProperties(object.object);
565 objectProperties.forEach((name, value) { 558 objectProperties.forEach((name, value) {
(...skipping 26 matching lines...) Expand all
592 .replaceAll(new RegExp(r'[(|)]'), ''); 585 .replaceAll(new RegExp(r'[(|)]'), '');
593 } 586 }
594 587
595 classChild(String name, Object child) { 588 classChild(String name, Object child) {
596 var typeName = getTypeName(child); 589 var typeName = getTypeName(child);
597 // Generic class names are generated with a $ at the end, so the 590 // Generic class names are generated with a $ at the end, so the
598 // corresponding non-generic class can be identified by adding $. 591 // corresponding non-generic class can be identified by adding $.
599 var parameterName = '$name\$'; 592 var parameterName = '$name\$';
600 if (genericParameters.keys.contains(parameterName)) { 593 if (genericParameters.keys.contains(parameterName)) {
601 typeName = '$typeName<${genericParameters[parameterName]}>'; 594 typeName = '$typeName<${genericParameters[parameterName]}>';
595 // TODO(bmilligan): Add a symbol to classes with generic types at their
596 // creation so they can be recognized independently by the debugger.
597 JSNative.setProperty(child, 'genericTypeName', typeName);
602 } 598 }
603 return new NameValuePair( 599 return new NameValuePair(name: typeName, value: child);
604 name: typeName, value: new ClassMetadata(child, name: typeName));
605 } 600 }
606 } 601 }
607 602
608 /// Formatter for Dart Function objects. 603 /// Formatter for Dart Function objects.
609 /// Dart functions happen to be regular JavaScript Function objects but 604 /// Dart functions happen to be regular JavaScript Function objects but
610 /// we can distinguish them based on whether they have been tagged with 605 /// we can distinguish them based on whether they have been tagged with
611 /// runtime type information. 606 /// runtime type information.
612 class FunctionFormatter extends Formatter { 607 class FunctionFormatter implements Formatter {
613 accept(object) { 608 accept(object, config) {
614 if (_typeof(object) != 'function') return false; 609 if (_typeof(object) != 'function') return false;
615 return dart.getReifiedType(object) != null; 610 return dart.getReifiedType(object) != null;
616 } 611 }
617 612
618 bool hasChildren(object) => true; 613 bool hasChildren(object) => true;
619 614
620 String preview(object) { 615 String preview(object) {
621 return dart.typeName(dart.getReifiedType(object)); 616 return dart.typeName(dart.getReifiedType(object));
622 } 617 }
623 618
624 List<NameValuePair> children(object) => <NameValuePair>[ 619 List<NameValuePair> children(object) => <NameValuePair>[
625 new NameValuePair(name: 'signature', value: preview(object)), 620 new NameValuePair(name: 'signature', value: preview(object)),
626 new NameValuePair( 621 new NameValuePair(
627 name: 'JavaScript Function', 622 name: 'JavaScript Function',
628 value: object, 623 value: object,
629 config: JsonMLConfig.skipDart) 624 config: JsonMLConfig.skipDart)
630 ]; 625 ];
631 } 626 }
632 627
633 /// Formatter for Dart Map objects. 628 /// Formatter for Dart Map objects.
634 class MapFormatter extends ObjectFormatter { 629 class MapFormatter implements Formatter {
635 accept(object) => object is Map; 630 accept(object, config) => object is Map;
636 631
637 bool hasChildren(object) => true; 632 bool hasChildren(object) => true;
638 633
639 String preview(object) { 634 String preview(object) {
640 Map map = object; 635 Map map = object;
641 return '${getObjectTypeName(map)} length ${map.length}'; 636 return '${getObjectTypeName(map)} length ${map.length}';
642 } 637 }
643 638
644 List<NameValuePair> children(object) { 639 List<NameValuePair> children(object) {
645 // TODO(jacobr): be lazier about enumerating contents of Maps that are not 640 // TODO(jacobr): be lazier about enumerating contents of Maps that are not
646 // the build in LinkedHashMap class. 641 // the build in LinkedHashMap class.
647 // TODO(jacobr): handle large Maps better. 642 // TODO(jacobr): handle large Maps better.
648 Map map = object; 643 Map map = object;
649 var entries = new LinkedHashSet<NameValuePair>(); 644 var entries = new LinkedHashSet<NameValuePair>();
650 map.forEach((key, value) { 645 map.forEach((key, value) {
651 var entryWrapper = new MapEntry(key: key, value: value); 646 var entryWrapper = new MapEntry(key: key, value: value);
652 entries.add(new NameValuePair( 647 entries.add(new NameValuePair(
653 name: entries.length.toString(), value: entryWrapper)); 648 name: entries.length.toString(), value: entryWrapper));
654 }); 649 });
655 addMetadataChildren(object, entries); 650 addMetadataChildren(object, entries);
656 return entries.toList(); 651 return entries.toList();
657 } 652 }
658 } 653 }
659 654
660 /// Formatter for Dart Iterable objects including List and Set. 655 /// Formatter for Dart Iterable objects including List and Set.
661 class IterableFormatter extends ObjectFormatter { 656 class IterableFormatter implements Formatter {
662 bool accept(object) => object is Iterable; 657 bool accept(object, config) => object is Iterable;
663 658
664 String preview(object) { 659 String preview(object) {
665 Iterable iterable = object; 660 Iterable iterable = object;
666 try { 661 try {
667 var length = iterable.length; 662 var length = iterable.length;
668 return '${getObjectTypeName(iterable)} length $length'; 663 return '${getObjectTypeName(iterable)} length $length';
669 } catch (_) { 664 } catch (_) {
670 return '${getObjectTypeName(iterable)}'; 665 return '${getObjectTypeName(iterable)}';
671 } 666 }
672 } 667 }
673 668
674 bool hasChildren(object) => true; 669 bool hasChildren(object) => true;
675 670
676 List<NameValuePair> children(object) { 671 List<NameValuePair> children(object) {
677 // TODO(jacobr): be lazier about enumerating contents of Iterables that 672 // TODO(jacobr): be lazier about enumerating contents of Iterables that
678 // are not the built in Set or List types. 673 // are not the built in Set or List types.
679 // TODO(jacobr): handle large Iterables better. 674 // TODO(jacobr): handle large Iterables better.
680 // TODO(jacobr): consider only using numeric indices 675 // TODO(jacobr): consider only using numeric indices
681 var children = new LinkedHashSet<NameValuePair>(); 676 var children = new LinkedHashSet<NameValuePair>();
682 children.addAll(new IterableSpan(0, object.length, object).children()); 677 children.addAll(new IterableSpan(0, object.length, object).children());
683 // TODO(jacobr): provide a link to show regular class properties here. 678 // TODO(jacobr): provide a link to show regular class properties here.
684 // required for subclasses of iterable, etc. 679 // required for subclasses of iterable, etc.
685 addMetadataChildren(object, children); 680 addMetadataChildren(object, children);
686 return children.toList(); 681 return children.toList();
687 } 682 }
688 } 683 }
689 684
690 // This class does double duting displaying metadata for
691 class ClassMetadataFormatter implements Formatter {
692 accept(object) => object is ClassMetadata;
693
694 Object _getType(object) {
695 if (object is Type) return object;
696 return dart.getReifiedType(object);
697 }
698
699 String preview(object) {
700 ClassMetadata entry = object;
701 var type =
702 entry.object is Type ? entry.object : dart.getReifiedType(entry.object);
703 var implements = dart.getImplements(type);
704 if (implements != null) {
705 var typeNames = implements().map(getTypeName);
706 return '${entry.typeName} implements ${typeNames.join(", ")}';
707 } else {
708 return entry.typeName;
709 }
710 }
711
712 bool hasChildren(object) => true;
713
714 List<NameValuePair> children(object) {
715 ClassMetadata entry = object;
716 var classObject = entry.object;
717 // TODO(jacobr): add other entries describing the class such as
718 // links to the superclass, mixins, implemented interfaces, and methods.
719 var type = _getType(classObject);
720 var children = <NameValuePair>[];
721
722 var mixins = dart.getMixins(type);
723 if (mixins != null && mixins.isNotEmpty) {
724 children.add(new NameValuePair(
725 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
726 }
727
728 var hiddenProperties = ['length', 'name', 'prototype'];
729 // Addition of NameValuePairs for static variables and named constructors.
730 for (var name in getOwnPropertyNames(classObject)) {
731 // TODO(bmilligan): Perform more principled checks to filter out spurious
732 // members.
733 if (hiddenProperties.contains(name)) continue;
734 var value = safeGetProperty(classObject, name);
735 if (value != null && dart.getIsNamedConstructor(value) != null) {
736 value = new NamedConstructor(value);
737 name = '${entry.typeName}.$name';
738 }
739 children.add(new NameValuePair(name: name, value: value));
740 }
741
742 // TODO(bmilligan): Replace the hard coding of $identityHash.
743 var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash'];
744 // Addition of class methods.
745 var prototype = JS('var', '#["prototype"]', classObject);
746 if (prototype != null) {
747 for (var name in getOwnPropertyNames(prototype)) {
748 if (hiddenPrototypeProperties.contains(name)) continue;
749 // Simulate dart.bind by using dart.tag and tear off the function
750 // so it will be recognized by the FunctionFormatter.
751 var function = safeGetProperty(prototype, name);
752 var constructor = safeGetProperty(prototype, 'constructor');
753 var sigObj = dart.getMethodSig(constructor);
754 if (sigObj != null) {
755 var value = safeGetProperty(sigObj, name);
756 if (getTypeName(dart.getReifiedType(value)) != 'Null') {
757 dart.tag(function, value);
758 children.add(new NameValuePair(name: name, value: function));
759 }
760 }
761 }
762 }
763 // TODO(jacobr): provide a link to the base class or perhaps the entire
764 // base class hierarchy as a flat list.
765 // TODO(jacobr): add constructors, methods, extended class, and static
766 return children;
767 }
768 }
769
770 class NamedConstructorFormatter implements Formatter { 685 class NamedConstructorFormatter implements Formatter {
771 accept(object) => object is NamedConstructor; 686 accept(object, config) => object is NamedConstructor;
772 687
773 // TODO(bmilligan): Display the signature of the named constructor as the 688 // TODO(bmilligan): Display the signature of the named constructor as the
774 // preview. 689 // preview.
775 String preview(object) => 'Named Constructor'; 690 String preview(object) => 'Named Constructor';
776 691
777 bool hasChildren(object) => true; 692 bool hasChildren(object) => true;
778 693
779 List<NameValuePair> children(object) => <NameValuePair>[ 694 List<NameValuePair> children(object) => <NameValuePair>[
780 new NameValuePair( 695 new NameValuePair(
781 name: 'JavaScript Function', 696 name: 'JavaScript Function',
782 value: object, 697 value: object,
783 config: JsonMLConfig.skipDart) 698 config: JsonMLConfig.skipDart)
784 ]; 699 ];
785 } 700 }
786 701
787 /// Formatter for synthetic MapEntry objects used to display contents of a Map 702 /// Formatter for synthetic MapEntry objects used to display contents of a Map
788 /// cleanly. 703 /// cleanly.
789 class MapEntryFormatter implements Formatter { 704 class MapEntryFormatter implements Formatter {
790 accept(object) => object is MapEntry; 705 accept(object, config) => object is MapEntry;
791 706
792 String preview(object) { 707 String preview(object) {
793 MapEntry entry = object; 708 MapEntry entry = object;
794 return '${safePreview(entry.key)} => ${safePreview(entry.value)}'; 709 return '${safePreview(entry.key, JsonMLConfig.none)} => ${safePreview(entry. value, JsonMLConfig.none)}';
795 } 710 }
796 711
797 bool hasChildren(object) => true; 712 bool hasChildren(object) => true;
798 713
799 List<NameValuePair> children(object) => <NameValuePair>[ 714 List<NameValuePair> children(object) => <NameValuePair>[
800 new NameValuePair( 715 new NameValuePair(
801 name: 'key', value: object.key, config: JsonMLConfig.keyToString), 716 name: 'key', value: object.key, config: JsonMLConfig.keyToString),
802 new NameValuePair(name: 'value', value: object.value) 717 new NameValuePair(name: 'value', value: object.value)
803 ]; 718 ];
804 } 719 }
805 720
806 /// Formatter for Dart Iterable objects including List and Set. 721 /// Formatter for Dart Iterable objects including List and Set.
807 class HeritageClauseFormatter implements Formatter { 722 class HeritageClauseFormatter implements Formatter {
808 bool accept(object) => object is HeritageClause; 723 bool accept(object, config) => object is HeritageClause;
809 724
810 String preview(object) { 725 String preview(object) {
811 HeritageClause clause = object; 726 HeritageClause clause = object;
812 var typeNames = clause.types.map(getTypeName); 727 var typeNames = clause.types.map(getTypeName);
813 return '${clause.name} ${typeNames.join(", ")}'; 728 return '${clause.name} ${typeNames.join(", ")}';
814 } 729 }
815 730
816 bool hasChildren(object) => true; 731 bool hasChildren(object) => true;
817 732
818 List<NameValuePair> children(object) { 733 List<NameValuePair> children(object) {
819 HeritageClause clause = object; 734 HeritageClause clause = object;
820 var children = <NameValuePair>[]; 735 var children = <NameValuePair>[];
821 for (var type in clause.types) { 736 for (var type in clause.types) {
822 children.add(new NameValuePair(value: new ClassMetadata(type))); 737 children
738 .add(new NameValuePair(value: type, config: JsonMLConfig.asClass));
823 } 739 }
824 return children; 740 return children;
825 } 741 }
826 } 742 }
827 743
828 /// Formatter for synthetic IterableSpan objects used to display contents of 744 /// Formatter for synthetic IterableSpan objects used to display contents of
829 /// an Iterable cleanly. 745 /// an Iterable cleanly.
830 class IterableSpanFormatter implements Formatter { 746 class IterableSpanFormatter implements Formatter {
831 accept(object) => object is IterableSpan; 747 accept(object, config) => object is IterableSpan;
832 748
833 String preview(object) { 749 String preview(object) {
834 return '[${object.start}...${object.end-1}]'; 750 return '[${object.start}...${object.end-1}]';
835 } 751 }
836 752
837 bool hasChildren(object) => true; 753 bool hasChildren(object) => true;
838 754
839 List<NameValuePair> children(object) => object.children(); 755 List<NameValuePair> children(object) => object.children();
840 } 756 }
841 757
842 class StackTraceFormatter implements Formatter { 758 class StackTraceFormatter implements Formatter {
843 accept(object) => object is StackTrace; 759 accept(object, config) => object is StackTrace;
844 760
845 String preview(object) => 'StackTrace'; 761 String preview(object) => 'StackTrace';
846 762
847 bool hasChildren(object) => true; 763 bool hasChildren(object) => true;
848 764
849 // Using the stack_trace formatting would be ideal, but adding the 765 // Using the stack_trace formatting would be ideal, but adding the
850 // dependency or re-writing the code is too messy, so each line of the 766 // dependency or re-writing the code is too messy, so each line of the
851 // StackTrace will be added as its own child. 767 // StackTrace will be added as its own child.
852 List<NameValuePair> children(object) => object 768 List<NameValuePair> children(object) => object
853 .toString() 769 .toString()
854 .split('\n') 770 .split('\n')
855 .map((line) => new NameValuePair( 771 .map((line) => new NameValuePair(
856 value: line.replaceFirst(new RegExp(r'^\s+at\s'), ''), 772 value: line.replaceFirst(new RegExp(r'^\s+at\s'), ''),
857 hideName: true)) 773 hideName: true))
858 .toList(); 774 .toList();
859 } 775 }
860 776
777 class ClassFormatter implements Formatter {
778 accept(object, config) => object is Type || config == JsonMLConfig.asClass;
779
780 String preview(object) {
781 var typeName = safeGetProperty(object, 'genericTypeName');
782 if (typeName != null) return typeName;
783 var type = _getType(object);
784 var implements = dart.getImplements(type);
785 typeName = getTypeName(type);
786 if (implements != null) {
787 var typeNames = implements().map(getTypeName);
788 return '${typeName} implements ${typeNames.join(", ")}';
789 } else {
790 return typeName;
791 }
792 }
793
794 bool hasChildren(object) => true;
795
796 List<NameValuePair> children(object) {
797 // TODO(jacobr): add other entries describing the class such as
798 // links to the superclass, mixins, implemented interfaces, and methods.
799 var type = _getType(object);
800 var children = <NameValuePair>[];
801 var typeName = getTypeName(_getType(object));
802 var mixins = dart.getMixins(type);
803 if (mixins != null && mixins.isNotEmpty) {
804 children.add(new NameValuePair(
805 name: '[[Mixins]]', value: new HeritageClause('mixins', mixins)));
806 }
807
808 var hiddenProperties = ['length', 'name', 'prototype', 'genericTypeName'];
809 // Addition of NameValuePairs for static variables and named constructors.
810 for (var name in getOwnPropertyNames(object)) {
811 // TODO(bmilligan): Perform more principled checks to filter out spurious
812 // members.
813 if (hiddenProperties.contains(name)) continue;
814 var value = safeGetProperty(object, name);
815 if (value != null && dart.getIsNamedConstructor(value) != null) {
816 value = new NamedConstructor(value);
817 name = '${typeName}.$name';
818 }
819 children.add(new NameValuePair(name: name, value: value));
820 }
821
822 // TODO(bmilligan): Replace the hard coding of $identityHash.
823 var hiddenPrototypeProperties = ['constructor', 'new', r'$identityHash'];
824 // Addition of class methods.
825 var prototype = JS('var', '#["prototype"]', object);
826 if (prototype != null) {
827 for (var name in getOwnPropertyNames(prototype)) {
828 if (hiddenPrototypeProperties.contains(name)) continue;
829 // Simulate dart.bind by using dart.tag and tear off the function
830 // so it will be recognized by the FunctionFormatter.
831 var function = safeGetProperty(prototype, name);
832 var constructor = safeGetProperty(prototype, 'constructor');
833 var sigObj = dart.getMethodSig(constructor);
834 if (sigObj != null) {
835 var value = safeGetProperty(sigObj, name);
836 if (getTypeName(dart.getReifiedType(value)) != 'Null') {
837 dart.tag(function, value);
838 children.add(new NameValuePair(name: name, value: function));
839 }
840 }
841 }
842 }
843 return children;
844 }
845 }
846
861 /// This entry point is automatically invoked by the code generated by 847 /// This entry point is automatically invoked by the code generated by
862 /// Dart Dev Compiler 848 /// Dart Dev Compiler
863 registerDevtoolsFormatter() { 849 registerDevtoolsFormatter() {
864 var formatters = [_devtoolsFormatter]; 850 var formatters = [_devtoolsFormatter];
865 JS('', 'dart.global.devtoolsFormatters = #', formatters); 851 JS('', 'dart.global.devtoolsFormatters = #', formatters);
866 } 852 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_sdk.js ('k') | tool/sdk_expected_errors.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698