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

Side by Side Diff: runtime/observatory/lib/src/service/object.dart

Issue 1312763010: Support column-based breakpoints in the VM and Observatory. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: hausner review Created 5 years, 3 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 part of service; 5 part of service;
6 6
7 /// Helper function for canceling a Future<StreamSubscription>. 7 /// Helper function for canceling a Future<StreamSubscription>.
8 Future cancelFutureSubscription( 8 Future cancelFutureSubscription(
9 Future<StreamSubscription> subscriptionFuture) async { 9 Future<StreamSubscription> subscriptionFuture) async {
10 if (subscriptionFuture != null) { 10 if (subscriptionFuture != null) {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 break; 210 break;
211 case 'Library': 211 case 'Library':
212 obj = new Library._empty(owner); 212 obj = new Library._empty(owner);
213 break; 213 break;
214 case 'Message': 214 case 'Message':
215 obj = new ServiceMessage._empty(owner); 215 obj = new ServiceMessage._empty(owner);
216 break; 216 break;
217 case 'SourceLocation': 217 case 'SourceLocation':
218 obj = new SourceLocation._empty(owner); 218 obj = new SourceLocation._empty(owner);
219 break; 219 break;
220 case 'UnresolvedSourceLocation':
221 obj = new UnresolvedSourceLocation._empty(owner);
222 break;
220 case 'Object': 223 case 'Object':
221 switch (vmType) { 224 switch (vmType) {
222 case 'ICData': 225 case 'ICData':
223 obj = new ICData._empty(owner); 226 obj = new ICData._empty(owner);
224 break; 227 break;
225 case 'Instructions': 228 case 'Instructions':
226 obj = new Instructions._empty(owner); 229 obj = new Instructions._empty(owner);
227 break; 230 break;
228 case 'LocalVarDescriptors': 231 case 'LocalVarDescriptors':
229 obj = new LocalVarDescriptors._empty(owner); 232 obj = new LocalVarDescriptors._empty(owner);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 /// be [loaded]. 428 /// be [loaded].
426 ServiceObject getFromMap(ObservableMap map); 429 ServiceObject getFromMap(ObservableMap map);
427 } 430 }
428 431
429 /// A [SourceLocation] represents a location or range in the source code. 432 /// A [SourceLocation] represents a location or range in the source code.
430 class SourceLocation extends ServiceObject { 433 class SourceLocation extends ServiceObject {
431 Script script; 434 Script script;
432 int tokenPos; 435 int tokenPos;
433 int endTokenPos; 436 int endTokenPos;
434 437
438 Future<int> getLine() async {
439 await script.load();
440 return script.tokenToLine(tokenPos);
441 }
442
443 Future<int> getColumn() async {
444 await script.load();
445 return script.tokenToCol(tokenPos);
446 }
447
435 SourceLocation._empty(ServiceObject owner) : super._empty(owner); 448 SourceLocation._empty(ServiceObject owner) : super._empty(owner);
436 449
437 void _update(ObservableMap map, bool mapIsRef) { 450 void _update(ObservableMap map, bool mapIsRef) {
438 assert(!mapIsRef); 451 assert(!mapIsRef);
439 _upgradeCollection(map, owner); 452 _upgradeCollection(map, owner);
440 script = map['script']; 453 script = map['script'];
441 tokenPos = map['tokenPos']; 454 tokenPos = map['tokenPos'];
455 endTokenPos = map['endTokenPos'];
456
442 assert(script != null && tokenPos != null); 457 assert(script != null && tokenPos != null);
443 endTokenPos = map['endTokenPos']; 458 }
459
460 Future<String> toUserString() async {
461 int line = await getLine();
462 int column = await getColumn();
463 return '${script.name}:${line}:${column}';
444 } 464 }
445 465
446 String toString() { 466 String toString() {
447 if (endTokenPos == null) { 467 if (endTokenPos == null) {
448 return '${script.name}:token(${tokenPos})'; 468 return '${script.name}:token(${tokenPos})';
449 } else { 469 } else {
450 return '${script.name}:tokens(${tokenPos}-${endTokenPos})'; 470 return '${script.name}:tokens(${tokenPos}-${endTokenPos})';
451 } 471 }
452 } 472 }
453 } 473 }
454 474
475 /// An [UnresolvedSourceLocation] represents a location in the source
476 // code which has not been precisely mapped to a token position.
477 class UnresolvedSourceLocation extends ServiceObject {
478 Script script;
479 String scriptUri;
480 int line;
481 int column;
482 int tokenPos;
483
484 Future<int> getLine() async {
485 if (tokenPos != null) {
486 await script.load();
487 return script.tokenToLine(tokenPos);
488 } else {
489 return line;
490 }
491 }
492
493 Future<int> getColumn() async {
494 if (tokenPos != null) {
495 await script.load();
496 return script.tokenToCol(tokenPos);
497 } else {
498 return column;
499 }
500 }
501
502 UnresolvedSourceLocation._empty(ServiceObject owner) : super._empty(owner);
503
504 void _update(ObservableMap map, bool mapIsRef) {
505 assert(!mapIsRef);
506 _upgradeCollection(map, owner);
507 script = map['script'];
508 scriptUri = map['scriptUri'];
509 line = map['line'];
510 column = map['column'];
511 tokenPos = map['tokenPos'];
512
513 assert(script != null || scriptUri != null);
514 assert(line != null || tokenPos != null);
515 }
516
517 Future<String> toUserString() async {
518 StringBuffer sb = new StringBuffer();
519
520 int line = await getLine();
521 int column = await getColumn();
522
523 if (script != null) {
524 sb.write('${script.name}:');
525 } else {
526 sb.write('${scriptUri}:');
527 }
528 if (column != null) {
529 sb.write('${line}:${column}');
530 } else {
531 sb.write('${line}');
532 }
533 return sb.toString();
534 }
535
536 String toString() {
537 StringBuffer sb = new StringBuffer();
538 if (script != null) {
539 sb.write('${script.name}:');
540 } else {
541 sb.write('${scriptUri}:');
542 }
543 if (tokenPos != null) {
544 sb.write('token(${tokenPos})');
545 } else if (column != null) {
546 sb.write('${line}:${column}');
547 } else {
548 sb.write('${line}');
549 }
550 sb.write('[unresolved]');
551 return sb.toString();
552 }
553 }
554
455 class _EventStreamState { 555 class _EventStreamState {
456 VM _vm; 556 VM _vm;
457 String streamId; 557 String streamId;
458 558
459 Function _onDone; 559 Function _onDone;
460 560
461 // A list of all subscribed controllers for this stream. 561 // A list of all subscribed controllers for this stream.
462 List _controllers = []; 562 List _controllers = [];
463 563
464 // Completes when the listen rpc is finished. 564 // Completes when the listen rpc is finished.
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after
1383 // Ignore GC events for now. 1483 // Ignore GC events for now.
1384 break; 1484 break;
1385 1485
1386 default: 1486 default:
1387 // Log unrecognized events. 1487 // Log unrecognized events.
1388 Logger.root.severe('Unrecognized event: $event'); 1488 Logger.root.severe('Unrecognized event: $event');
1389 break; 1489 break;
1390 } 1490 }
1391 } 1491 }
1392 1492
1393 Future<ServiceObject> addBreakpoint(Script script, int line) async { 1493 Future<ServiceObject> addBreakpoint(
1494 Script script, int line, [int col]) async {
1394 // TODO(turnidge): Pass line as an int instead of a string. 1495 // TODO(turnidge): Pass line as an int instead of a string.
1395 try { 1496 try {
1396 Map params = { 1497 Map params = {
1397 'scriptId': script.id, 1498 'scriptId': script.id,
1398 'line': '$line', 1499 'line': line.toString(),
1399 }; 1500 };
1501 if (col != null) {
1502 params['column'] = col.toString();
1503 }
1400 Breakpoint bpt = await invokeRpc('addBreakpoint', params); 1504 Breakpoint bpt = await invokeRpc('addBreakpoint', params);
1401 if (bpt.resolved && 1505 if (bpt.resolved &&
1402 script.loaded && 1506 script.loaded &&
1403 script.tokenToLine(bpt.location.tokenPos) != line) { 1507 script.tokenToLine(bpt.location.tokenPos) != line) {
1404 // TODO(turnidge): Can this still happen? 1508 // TODO(turnidge): Can this still happen?
1405 script.getLine(line).possibleBpt = false; 1509 script.getLine(line).possibleBpt = false;
1406 } 1510 }
1407 return bpt; 1511 return bpt;
1408 } on ServerRpcException catch(e) { 1512 } on ServerRpcException catch(e) {
1409 if (e.code == ServerRpcException.kCannotAddBreakpoint) { 1513 if (e.code == ServerRpcException.kCannotAddBreakpoint) {
1410 // Unable to set a breakpoint at the desired line. 1514 // Unable to set a breakpoint at the desired line.
1411 script.getLine(line).possibleBpt = false; 1515 script.getLine(line).possibleBpt = false;
1412 } 1516 }
1413 rethrow; 1517 rethrow;
1414 } 1518 }
1415 } 1519 }
1416 1520
1521 Future<ServiceObject> addBreakpointByScriptUri(
1522 String uri, int line, [int col]) {
1523 Map params = {
1524 'scriptUri': uri,
1525 'line': line.toString(),
1526 };
1527 if (col != null) {
1528 params['column'] = col.toString();
1529 }
1530 return invokeRpc('addBreakpoint', params);
1531 }
1532
1417 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) { 1533 Future<ServiceObject> addBreakpointAtEntry(ServiceFunction function) {
1418 return invokeRpc('addBreakpointAtEntry', 1534 return invokeRpc('addBreakpointAtEntry',
1419 { 'functionId': function.id }); 1535 { 'functionId': function.id });
1420 } 1536 }
1421 1537
1422 Future<ServiceObject> addBreakOnActivation(Instance closure) { 1538 Future<ServiceObject> addBreakOnActivation(Instance closure) {
1423 return invokeRpc('_addBreakpointAtActivation', 1539 return invokeRpc('_addBreakpointAtActivation',
1424 { 'objectId': closure.id }); 1540 { 'objectId': closure.id });
1425 } 1541 }
1426 1542
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 Breakpoint._empty(ServiceObjectOwner owner) : super._empty(owner); 1964 Breakpoint._empty(ServiceObjectOwner owner) : super._empty(owner);
1849 1965
1850 // TODO(turnidge): Add state to track if a breakpoint has been 1966 // TODO(turnidge): Add state to track if a breakpoint has been
1851 // removed from the program. Remove from the cache when deleted. 1967 // removed from the program. Remove from the cache when deleted.
1852 bool get canCache => true; 1968 bool get canCache => true;
1853 bool get immutable => false; 1969 bool get immutable => false;
1854 1970
1855 // A unique integer identifier for this breakpoint. 1971 // A unique integer identifier for this breakpoint.
1856 @observable int number; 1972 @observable int number;
1857 1973
1858 // Source location information. 1974 // Either SourceLocation or UnresolvedSourceLocation.
1859 @observable SourceLocation location; 1975 @observable ServiceObject location;
1976
1977 // The breakpoint is in a file which is not yet loaded.
1978 @observable bool latent;
1860 1979
1861 // The breakpoint has been assigned to a final source location. 1980 // The breakpoint has been assigned to a final source location.
1862 @observable bool resolved; 1981 @observable bool resolved;
1863 1982
1864 void _update(ObservableMap map, bool mapIsRef) { 1983 void _update(ObservableMap map, bool mapIsRef) {
1865 _loaded = true; 1984 _loaded = true;
1866 _upgradeCollection(map, owner); 1985 _upgradeCollection(map, owner);
1867 1986
1868 var newNumber = map['breakpointNumber']; 1987 var newNumber = map['breakpointNumber'];
1869 // number never changes. 1988 // number never changes.
1870 assert((number == null) || (number == newNumber)); 1989 assert((number == null) || (number == newNumber));
1871 number = newNumber; 1990 number = newNumber;
1872
1873 resolved = map['resolved']; 1991 resolved = map['resolved'];
1874 1992
1875 var oldLocation = location; 1993 var oldLocation = location;
1876 var newLocation = map['location']; 1994 var newLocation = map['location'];
1877 var oldScript; 1995 if (oldLocation is UnresolvedSourceLocation &&
1878 var newScript; 1996 newLocation is SourceLocation) {
1879 var oldTokenPos; 1997 // Breakpoint has been resolved. Remove old breakpoint.
1880 var newTokenPos; 1998 var oldScript = oldLocation.script;
1881 if (oldLocation != null) { 1999 if (oldScript != null && oldScript.loaded) {
1882 oldScript = location.script;
1883 oldTokenPos = location.tokenPos;
1884 }
1885 if (newLocation != null) {
1886 newScript = newLocation.script;
1887 newTokenPos = newLocation.tokenPos;
1888 }
1889 // script never changes
1890 assert((oldScript == null) || (oldScript == newScript));
1891 bool tokenPosChanged = oldTokenPos != newTokenPos;
1892 if (newScript.loaded &&
1893 (newTokenPos != null) &&
1894 tokenPosChanged) {
1895 // The breakpoint has moved. Remove it and add it later.
1896 if (oldScript != null) {
1897 oldScript._removeBreakpoint(this); 2000 oldScript._removeBreakpoint(this);
1898 } 2001 }
1899 } 2002 }
1900 location = newLocation; 2003 location = newLocation;
1901 if (newScript.loaded && tokenPosChanged) { 2004 var newScript = location.script;
2005 if (newScript != null && newScript.loaded) {
1902 newScript._addBreakpoint(this); 2006 newScript._addBreakpoint(this);
1903 } 2007 }
2008
2009 assert(resolved || location is UnresolvedSourceLocation);
1904 } 2010 }
1905 2011
1906 void remove() { 2012 void remove() {
1907 // Remove any references to this breakpoint. It has been removed. 2013 // Remove any references to this breakpoint. It has been removed.
1908 location.script._removeBreakpoint(this); 2014 location.script._removeBreakpoint(this);
1909 if ((isolate.pauseEvent != null) && 2015 if ((isolate.pauseEvent != null) &&
1910 (isolate.pauseEvent.breakpoint != null) && 2016 (isolate.pauseEvent.breakpoint != null) &&
1911 (isolate.pauseEvent.breakpoint.id == id)) { 2017 (isolate.pauseEvent.breakpoint.id == id)) {
1912 isolate.pauseEvent.breakpoint = null; 2018 isolate.pauseEvent.breakpoint = null;
1913 } 2019 }
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after
2886 } 2992 }
2887 2993
2888 void _applyHitsToLines() { 2994 void _applyHitsToLines() {
2889 for (var line in lines) { 2995 for (var line in lines) {
2890 var hits = _hits[line.line]; 2996 var hits = _hits[line.line];
2891 line.hits = hits; 2997 line.hits = hits;
2892 } 2998 }
2893 } 2999 }
2894 3000
2895 void _addBreakpoint(Breakpoint bpt) { 3001 void _addBreakpoint(Breakpoint bpt) {
2896 var line = tokenToLine(bpt.location.tokenPos); 3002 var line;
3003 if (bpt.location.tokenPos != null) {
3004 line = tokenToLine(bpt.location.tokenPos);
3005 } else {
3006 line = bpt.location.line;
3007 }
2897 getLine(line).addBreakpoint(bpt); 3008 getLine(line).addBreakpoint(bpt);
2898 } 3009 }
2899 3010
2900 void _removeBreakpoint(Breakpoint bpt) { 3011 void _removeBreakpoint(Breakpoint bpt) {
2901 var line = tokenToLine(bpt.location.tokenPos); 3012 var line;
3013 if (bpt.location.tokenPos != null) {
3014 line = tokenToLine(bpt.location.tokenPos);
3015 } else {
3016 line = bpt.location.line;
3017 }
2902 if (line != null) { 3018 if (line != null) {
2903 getLine(line).removeBreakpoint(bpt); 3019 getLine(line).removeBreakpoint(bpt);
2904 } 3020 }
2905 } 3021 }
2906 3022
2907 List<LocalVarLocation> scanLineForLocalVariableLocations(Pattern pattern, 3023 List<LocalVarLocation> scanLineForLocalVariableLocations(Pattern pattern,
2908 String name, 3024 String name,
2909 String lineContents, 3025 String lineContents,
2910 int lineNumber, 3026 int lineNumber,
2911 int columnOffset) { 3027 int columnOffset) {
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after
3820 var v = list[i]; 3936 var v = list[i];
3821 if ((v is ObservableMap) && _isServiceMap(v)) { 3937 if ((v is ObservableMap) && _isServiceMap(v)) {
3822 list[i] = owner.getFromMap(v); 3938 list[i] = owner.getFromMap(v);
3823 } else if (v is ObservableList) { 3939 } else if (v is ObservableList) {
3824 _upgradeObservableList(v, owner); 3940 _upgradeObservableList(v, owner);
3825 } else if (v is ObservableMap) { 3941 } else if (v is ObservableMap) {
3826 _upgradeObservableMap(v, owner); 3942 _upgradeObservableMap(v, owner);
3827 } 3943 }
3828 } 3944 }
3829 } 3945 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/script_inset.html ('k') | runtime/observatory/tests/service/add_breakpoint_rpc_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698