| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 script_inset_element; | 5 library script_inset_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'dart:svg'; | 9 import 'dart:svg'; |
| 10 import 'package:observatory/app.dart'; | 10 import 'package:observatory/app.dart'; |
| 11 import 'package:observatory/models.dart' as M; | 11 import 'package:observatory/models.dart' as M; |
| 12 import 'package:observatory/service.dart' as S; | 12 import 'package:observatory/service.dart' as S; |
| 13 import 'package:observatory/src/elements/helpers/any_ref.dart'; | 13 import 'package:observatory/src/elements/helpers/any_ref.dart'; |
| 14 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | 14 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
| 15 import 'package:observatory/src/elements/helpers/tag.dart'; | 15 import 'package:observatory/src/elements/helpers/tag.dart'; |
| 16 import 'package:observatory/src/elements/helpers/uris.dart'; | 16 import 'package:observatory/src/elements/helpers/uris.dart'; |
| 17 import 'package:observatory/utils.dart'; | 17 import 'package:observatory/utils.dart'; |
| 18 | 18 |
| 19 class ScriptInsetElement extends HtmlElement implements Renderable { | 19 class ScriptInsetElement extends HtmlElement implements Renderable { |
| 20 static const tag = const Tag<ScriptInsetElement>('script-inset'); | 20 static const tag = const Tag<ScriptInsetElement>('script-inset'); |
| 21 | 21 |
| 22 RenderingScheduler _r; | 22 RenderingScheduler _r; |
| 23 | 23 |
| 24 Stream<RenderedEvent<ScriptInsetElement>> get onRendered => _r.onRendered; | 24 Stream<RenderedEvent<ScriptInsetElement>> get onRendered => _r.onRendered; |
| 25 | 25 |
| 26 | |
| 27 M.IsolateRef _isolate; | 26 M.IsolateRef _isolate; |
| 28 M.ScriptRef _script; | 27 M.ScriptRef _script; |
| 29 M.Script _loadedScript; | 28 M.Script _loadedScript; |
| 30 M.ScriptRepository _scripts; | 29 M.ScriptRepository _scripts; |
| 31 M.InstanceRepository _instances; | 30 M.InstanceRepository _instances; |
| 32 M.EventRepository _events; | 31 M.EventRepository _events; |
| 33 StreamSubscription _subscription; | 32 StreamSubscription _subscription; |
| 34 int _startPos; | 33 int _startPos; |
| 35 int _endPos; | 34 int _endPos; |
| 36 int _currentPos; | 35 int _currentPos; |
| 37 bool _inDebuggerContext; | 36 bool _inDebuggerContext; |
| 38 Iterable _variables; | 37 Iterable _variables; |
| 39 | 38 |
| 40 M.IsolateRef get isolate => _isolate; | 39 M.IsolateRef get isolate => _isolate; |
| 41 M.ScriptRef get script => _script; | 40 M.ScriptRef get script => _script; |
| 42 | 41 |
| 43 factory ScriptInsetElement(M.IsolateRef isolate, M.ScriptRef script, | 42 factory ScriptInsetElement( |
| 44 M.ScriptRepository scripts, | 43 M.IsolateRef isolate, |
| 45 M.InstanceRepository instances, | 44 M.ScriptRef script, |
| 46 M.EventRepository events, | 45 M.ScriptRepository scripts, |
| 47 {int startPos, int endPos, int currentPos, | 46 M.InstanceRepository instances, |
| 48 bool inDebuggerContext: false, | 47 M.EventRepository events, |
| 49 Iterable variables: const [], | 48 {int startPos, |
| 50 RenderingQueue queue}) { | 49 int endPos, |
| 50 int currentPos, |
| 51 bool inDebuggerContext: false, |
| 52 Iterable variables: const [], |
| 53 RenderingQueue queue}) { |
| 51 assert(isolate != null); | 54 assert(isolate != null); |
| 52 assert(script != null); | 55 assert(script != null); |
| 53 assert(scripts != null); | 56 assert(scripts != null); |
| 54 assert(instances != null); | 57 assert(instances != null); |
| 55 assert(events != null); | 58 assert(events != null); |
| 56 assert(inDebuggerContext != null); | 59 assert(inDebuggerContext != null); |
| 57 assert(variables != null); | 60 assert(variables != null); |
| 58 ScriptInsetElement e = document.createElement(tag.name); | 61 ScriptInsetElement e = document.createElement(tag.name); |
| 59 e._r = new RenderingScheduler(e, queue: queue); | 62 e._r = new RenderingScheduler(e, queue: queue); |
| 60 e._isolate = isolate; | 63 e._isolate = isolate; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 72 | 75 |
| 73 ScriptInsetElement.created() : super.created(); | 76 ScriptInsetElement.created() : super.created(); |
| 74 | 77 |
| 75 bool get noSource => _startPos == -1; | 78 bool get noSource => _startPos == -1; |
| 76 | 79 |
| 77 @override | 80 @override |
| 78 void attached() { | 81 void attached() { |
| 79 super.attached(); | 82 super.attached(); |
| 80 _r.enable(); | 83 _r.enable(); |
| 81 _subscription = _events.onDebugEvent | 84 _subscription = _events.onDebugEvent |
| 82 .where((e) => (e is M.BreakpointAddedEvent) || | 85 .where((e) => |
| 83 (e is M.BreakpointResolvedEvent) || | 86 (e is M.BreakpointAddedEvent) || |
| 84 (e is M.BreakpointRemovedEvent)) | 87 (e is M.BreakpointResolvedEvent) || |
| 85 .map((e) => e.breakpoint) | 88 (e is M.BreakpointRemovedEvent)) |
| 86 .listen((M.Breakpoint b) { | 89 .map((e) => e.breakpoint) |
| 87 final loc = b.location; | 90 .listen((M.Breakpoint b) { |
| 88 int line; | 91 final loc = b.location; |
| 89 if (loc.script.id == script.id) { | 92 int line; |
| 90 if (loc.tokenPos != null) { | 93 if (loc.script.id == script.id) { |
| 91 line = _loadedScript.tokenToLine(loc.tokenPos); | 94 if (loc.tokenPos != null) { |
| 92 } else { | 95 line = _loadedScript.tokenToLine(loc.tokenPos); |
| 93 line = loc.line; | 96 } else { |
| 94 } | 97 line = loc.line; |
| 95 } else { | 98 } |
| 96 line = loc.line; | 99 } else { |
| 97 } | 100 line = loc.line; |
| 98 if ((line == null) || ((line >= _startLine) && (line <= _endLine))) { | 101 } |
| 99 _r.dirty(); | 102 if ((line == null) || ((line >= _startLine) && (line <= _endLine))) { |
| 100 } | 103 _r.dirty(); |
| 101 }); | 104 } |
| 105 }); |
| 102 _refresh(); | 106 _refresh(); |
| 103 } | 107 } |
| 104 | 108 |
| 105 @override | 109 @override |
| 106 void detached() { | 110 void detached() { |
| 107 super.detached(); | 111 super.detached(); |
| 108 children = []; | 112 children = []; |
| 109 _r.disable(notify: true); | 113 _r.disable(notify: true); |
| 110 _subscription.cancel(); | 114 _subscription.cancel(); |
| 111 } | 115 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 175 } |
| 172 | 176 |
| 173 Element a(String text) => new AnchorElement()..text = text; | 177 Element a(String text) => new AnchorElement()..text = text; |
| 174 Element span(String text) => new SpanElement()..text = text; | 178 Element span(String text) => new SpanElement()..text = text; |
| 175 | 179 |
| 176 Element hitsCurrent(Element element) { | 180 Element hitsCurrent(Element element) { |
| 177 element.classes.add('hitsCurrent'); | 181 element.classes.add('hitsCurrent'); |
| 178 element.title = ""; | 182 element.title = ""; |
| 179 return element; | 183 return element; |
| 180 } | 184 } |
| 185 |
| 181 Element hitsUnknown(Element element) { | 186 Element hitsUnknown(Element element) { |
| 182 element.classes.add('hitsNone'); | 187 element.classes.add('hitsNone'); |
| 183 element.title = ""; | 188 element.title = ""; |
| 184 return element; | 189 return element; |
| 185 } | 190 } |
| 191 |
| 186 Element hitsNotExecuted(Element element) { | 192 Element hitsNotExecuted(Element element) { |
| 187 element.classes.add('hitsNotExecuted'); | 193 element.classes.add('hitsNotExecuted'); |
| 188 element.title = "Line did not execute"; | 194 element.title = "Line did not execute"; |
| 189 return element; | 195 return element; |
| 190 } | 196 } |
| 197 |
| 191 Element hitsExecuted(Element element) { | 198 Element hitsExecuted(Element element) { |
| 192 element.classes.add('hitsExecuted'); | 199 element.classes.add('hitsExecuted'); |
| 193 element.title = "Line did execute"; | 200 element.title = "Line did execute"; |
| 194 return element; | 201 return element; |
| 195 } | 202 } |
| 203 |
| 196 Element hitsCompiled(Element element) { | 204 Element hitsCompiled(Element element) { |
| 197 element.classes.add('hitsCompiled'); | 205 element.classes.add('hitsCompiled'); |
| 198 element.title = "Line in compiled function"; | 206 element.title = "Line in compiled function"; |
| 199 return element; | 207 return element; |
| 200 } | 208 } |
| 209 |
| 201 Element hitsNotCompiled(Element element) { | 210 Element hitsNotCompiled(Element element) { |
| 202 element.classes.add('hitsNotCompiled'); | 211 element.classes.add('hitsNotCompiled'); |
| 203 element.title = "Line in uncompiled function"; | 212 element.title = "Line in uncompiled function"; |
| 204 return element; | 213 return element; |
| 205 } | 214 } |
| 206 | 215 |
| 207 Element container; | 216 Element container; |
| 208 | 217 |
| 209 // Build _rangeMap and _callSites from a source report. | 218 // Build _rangeMap and _callSites from a source report. |
| 210 Future _refreshSourceReport() async { | 219 Future _refreshSourceReport() async { |
| 211 if (noSource) return; | 220 if (noSource) return; |
| 212 | 221 |
| 213 var reports = [S.Isolate.kCallSitesReport, | 222 var reports = [ |
| 214 S.Isolate.kPossibleBreakpointsReport]; | 223 S.Isolate.kCallSitesReport, |
| 224 S.Isolate.kPossibleBreakpointsReport |
| 225 ]; |
| 215 if (_includeProfile) { | 226 if (_includeProfile) { |
| 216 reports.add(S.Isolate.kProfileReport); | 227 reports.add(S.Isolate.kProfileReport); |
| 217 } | 228 } |
| 218 S.Isolate isolate = _isolate as S.Isolate; | 229 S.Isolate isolate = _isolate as S.Isolate; |
| 219 var sourceReport = await isolate.getSourceReport( | 230 var sourceReport = |
| 220 reports, | 231 await isolate.getSourceReport(reports, script, _startPos, _endPos); |
| 221 script, _startPos, _endPos); | 232 _possibleBreakpointLines = |
| 222 _possibleBreakpointLines = S.getPossibleBreakpointLines(sourceReport, | 233 S.getPossibleBreakpointLines(sourceReport, script); |
| 223 script); | |
| 224 _rangeMap.clear(); | 234 _rangeMap.clear(); |
| 225 _callSites.clear(); | 235 _callSites.clear(); |
| 226 _profileMap.clear(); | 236 _profileMap.clear(); |
| 227 for (var range in sourceReport['ranges']) { | 237 for (var range in sourceReport['ranges']) { |
| 228 int startLine = _loadedScript.tokenToLine(range['startPos']); | 238 int startLine = _loadedScript.tokenToLine(range['startPos']); |
| 229 int endLine = _loadedScript.tokenToLine(range['endPos']); | 239 int endLine = _loadedScript.tokenToLine(range['endPos']); |
| 230 // TODO(turnidge): Track down the root cause of null startLine/endLine. | 240 // TODO(turnidge): Track down the root cause of null startLine/endLine. |
| 231 if ((startLine != null) && (endLine != null)) { | 241 if ((startLine != null) && (endLine != null)) { |
| 232 for (var line = startLine; line <= endLine; line++) { | 242 for (var line = startLine; line <= endLine; line++) { |
| 233 var rangeList = _rangeMap[line]; | 243 var rangeList = _rangeMap[line]; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 for (var callSiteMap in rangeCallSites) { | 276 for (var callSiteMap in rangeCallSites) { |
| 267 _callSites.add(new S.CallSite.fromMap(callSiteMap, script)); | 277 _callSites.add(new S.CallSite.fromMap(callSiteMap, script)); |
| 268 } | 278 } |
| 269 } | 279 } |
| 270 } | 280 } |
| 271 } | 281 } |
| 272 } | 282 } |
| 273 | 283 |
| 274 Future _computeAnnotations() async { | 284 Future _computeAnnotations() async { |
| 275 _startLine = (_startPos != null | 285 _startLine = (_startPos != null |
| 276 ? _loadedScript.tokenToLine(_startPos) | 286 ? _loadedScript.tokenToLine(_startPos) |
| 277 : 1 + _loadedScript.lineOffset); | 287 : 1 + _loadedScript.lineOffset); |
| 278 _currentLine = (_currentPos != null | 288 _currentLine = |
| 279 ? _loadedScript.tokenToLine(_currentPos) | 289 (_currentPos != null ? _loadedScript.tokenToLine(_currentPos) : null); |
| 280 : null); | 290 _currentCol = |
| 281 _currentCol = (_currentPos != null | 291 (_currentPos != null ? (_loadedScript.tokenToCol(_currentPos)) : null); |
| 282 ? (_loadedScript.tokenToCol(_currentPos)) | |
| 283 : null); | |
| 284 if (_currentCol != null) { | 292 if (_currentCol != null) { |
| 285 _currentCol--; // make this 0-based. | 293 _currentCol--; // make this 0-based. |
| 286 } | 294 } |
| 287 | 295 |
| 288 S.Script script = _loadedScript as S.Script; | 296 S.Script script = _loadedScript as S.Script; |
| 289 | 297 |
| 290 _endLine = (_endPos != null | 298 _endLine = (_endPos != null |
| 291 ? _loadedScript.tokenToLine(_endPos) | 299 ? _loadedScript.tokenToLine(_endPos) |
| 292 : script.lines.length + _loadedScript.lineOffset); | 300 : script.lines.length + _loadedScript.lineOffset); |
| 293 | 301 |
| 294 if (_startLine == null || _endLine == null) { | 302 if (_startLine == null || _endLine == null) { |
| 295 return; | 303 return; |
| 296 } | 304 } |
| 297 | 305 |
| 298 _annotations.clear(); | 306 _annotations.clear(); |
| 299 | 307 |
| 300 addCurrentExecutionAnnotation(); | 308 addCurrentExecutionAnnotation(); |
| 301 addBreakpointAnnotations(); | 309 addBreakpointAnnotations(); |
| 302 | 310 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 331 } | 339 } |
| 332 } | 340 } |
| 333 | 341 |
| 334 void addBreakpointAnnotations() { | 342 void addBreakpointAnnotations() { |
| 335 S.Script script = _loadedScript as S.Script; | 343 S.Script script = _loadedScript as S.Script; |
| 336 for (var line = _startLine; line <= _endLine; line++) { | 344 for (var line = _startLine; line <= _endLine; line++) { |
| 337 var bpts = script.getLine(line).breakpoints; | 345 var bpts = script.getLine(line).breakpoints; |
| 338 if (bpts != null) { | 346 if (bpts != null) { |
| 339 for (var bpt in bpts) { | 347 for (var bpt in bpts) { |
| 340 if (bpt.location != null) { | 348 if (bpt.location != null) { |
| 341 _annotations.add(new BreakpointAnnotation(_isolate, _instances, | 349 _annotations.add( |
| 342 _r.queue, bpt)); | 350 new BreakpointAnnotation(_isolate, _instances, _r.queue, bpt)); |
| 343 } | 351 } |
| 344 } | 352 } |
| 345 } | 353 } |
| 346 } | 354 } |
| 347 } | 355 } |
| 348 | 356 |
| 349 Future loadDeclarationsOfLibrary(S.Library lib) { | 357 Future loadDeclarationsOfLibrary(S.Library lib) { |
| 350 return lib.load().then((lib) { | 358 return lib.load().then((lib) { |
| 351 var loads = []; | 359 var loads = []; |
| 352 for (var func in lib.functions) { | 360 for (var func in lib.functions) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 375 }); | 383 }); |
| 376 } | 384 } |
| 377 | 385 |
| 378 void addLibraryAnnotations() { | 386 void addLibraryAnnotations() { |
| 379 S.Script script = _loadedScript as S.Script; | 387 S.Script script = _loadedScript as S.Script; |
| 380 for (S.ScriptLine line in script.lines) { | 388 for (S.ScriptLine line in script.lines) { |
| 381 // TODO(rmacnak): Use a real scanner. | 389 // TODO(rmacnak): Use a real scanner. |
| 382 var pattern = new RegExp("library ${script.library.name}"); | 390 var pattern = new RegExp("library ${script.library.name}"); |
| 383 var match = pattern.firstMatch(line.text); | 391 var match = pattern.firstMatch(line.text); |
| 384 if (match != null) { | 392 if (match != null) { |
| 385 var anno = new LibraryAnnotation(_isolate, _instances, _r.queue, | 393 var anno = new LibraryAnnotation( |
| 386 _loadedScript.library, | 394 _isolate, |
| 387 Uris.inspect(isolate, object: _loadedScript.library)); | 395 _instances, |
| 396 _r.queue, |
| 397 _loadedScript.library, |
| 398 Uris.inspect(isolate, object: _loadedScript.library)); |
| 388 anno.line = line.line; | 399 anno.line = line.line; |
| 389 anno.columnStart = match.start + 8; | 400 anno.columnStart = match.start + 8; |
| 390 anno.columnStop = match.end; | 401 anno.columnStop = match.end; |
| 391 _annotations.add(anno); | 402 _annotations.add(anno); |
| 392 } | 403 } |
| 393 // TODO(rmacnak): Use a real scanner. | 404 // TODO(rmacnak): Use a real scanner. |
| 394 pattern = new RegExp("part of ${script.library.name}"); | 405 pattern = new RegExp("part of ${script.library.name}"); |
| 395 match = pattern.firstMatch(line.text); | 406 match = pattern.firstMatch(line.text); |
| 396 if (match != null) { | 407 if (match != null) { |
| 397 var anno = new LibraryAnnotation(_isolate, _instances, _r.queue, | 408 var anno = new LibraryAnnotation( |
| 398 _loadedScript.library, | 409 _isolate, |
| 399 Uris.inspect(isolate, object: _loadedScript.library)); | 410 _instances, |
| 411 _r.queue, |
| 412 _loadedScript.library, |
| 413 Uris.inspect(isolate, object: _loadedScript.library)); |
| 400 anno.line = line.line; | 414 anno.line = line.line; |
| 401 anno.columnStart = match.start + 8; | 415 anno.columnStart = match.start + 8; |
| 402 anno.columnStop = match.end; | 416 anno.columnStop = match.end; |
| 403 _annotations.add(anno); | 417 _annotations.add(anno); |
| 404 } | 418 } |
| 405 } | 419 } |
| 406 } | 420 } |
| 407 | 421 |
| 408 M.Library resolveDependency(String relativeUri) { | 422 M.Library resolveDependency(String relativeUri) { |
| 409 S.Script script = _loadedScript as S.Script; | 423 S.Script script = _loadedScript as S.Script; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 438 new RegExp("export '(.*)'"), | 452 new RegExp("export '(.*)'"), |
| 439 new RegExp('export "(.*)"'), | 453 new RegExp('export "(.*)"'), |
| 440 ]; | 454 ]; |
| 441 for (S.ScriptLine line in script.lines) { | 455 for (S.ScriptLine line in script.lines) { |
| 442 for (var pattern in patterns) { | 456 for (var pattern in patterns) { |
| 443 var match = pattern.firstMatch(line.text); | 457 var match = pattern.firstMatch(line.text); |
| 444 if (match != null) { | 458 if (match != null) { |
| 445 M.Library target = resolveDependency(match[1]); | 459 M.Library target = resolveDependency(match[1]); |
| 446 if (target != null) { | 460 if (target != null) { |
| 447 var anno = new LibraryAnnotation(_isolate, _instances, _r.queue, | 461 var anno = new LibraryAnnotation(_isolate, _instances, _r.queue, |
| 448 target, Uris.inspect(isolate, object: target)); | 462 target, Uris.inspect(isolate, object: target)); |
| 449 anno.line = line.line; | 463 anno.line = line.line; |
| 450 anno.columnStart = match.start + 8; | 464 anno.columnStart = match.start + 8; |
| 451 anno.columnStop = match.end - 1; | 465 anno.columnStop = match.end - 1; |
| 452 _annotations.add(anno); | 466 _annotations.add(anno); |
| 453 } | 467 } |
| 454 } | 468 } |
| 455 } | 469 } |
| 456 } | 470 } |
| 457 } | 471 } |
| 458 | 472 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 480 new RegExp("part '(.*)'"), | 494 new RegExp("part '(.*)'"), |
| 481 new RegExp('part "(.*)"'), | 495 new RegExp('part "(.*)"'), |
| 482 ]; | 496 ]; |
| 483 for (S.ScriptLine line in script.lines) { | 497 for (S.ScriptLine line in script.lines) { |
| 484 for (var pattern in patterns) { | 498 for (var pattern in patterns) { |
| 485 var match = pattern.firstMatch(line.text); | 499 var match = pattern.firstMatch(line.text); |
| 486 if (match != null) { | 500 if (match != null) { |
| 487 S.Script part = resolvePart(match[1]); | 501 S.Script part = resolvePart(match[1]); |
| 488 if (part != null) { | 502 if (part != null) { |
| 489 var anno = new PartAnnotation(_isolate, _instances, _r.queue, part, | 503 var anno = new PartAnnotation(_isolate, _instances, _r.queue, part, |
| 490 Uris.inspect(isolate, object: part)); | 504 Uris.inspect(isolate, object: part)); |
| 491 anno.line = line.line; | 505 anno.line = line.line; |
| 492 anno.columnStart = match.start + 6; | 506 anno.columnStart = match.start + 6; |
| 493 anno.columnStop = match.end - 1; | 507 anno.columnStop = match.end - 1; |
| 494 _annotations.add(anno); | 508 _annotations.add(anno); |
| 495 } | 509 } |
| 496 } | 510 } |
| 497 } | 511 } |
| 498 } | 512 } |
| 499 } | 513 } |
| 500 | 514 |
| 501 void addClassAnnotations() { | 515 void addClassAnnotations() { |
| 502 S.Script script = _loadedScript as S.Script; | 516 S.Script script = _loadedScript as S.Script; |
| 503 for (var cls in script.library.classes) { | 517 for (var cls in script.library.classes) { |
| 504 if ((cls.location != null) && (cls.location.script == script)) { | 518 if ((cls.location != null) && (cls.location.script == script)) { |
| 505 var a = new ClassDeclarationAnnotation(_isolate, _instances, _r.queue, | 519 var a = new ClassDeclarationAnnotation(_isolate, _instances, _r.queue, |
| 506 cls, Uris.inspect(isolate, object: cls)); | 520 cls, Uris.inspect(isolate, object: cls)); |
| 507 _annotations.add(a); | 521 _annotations.add(a); |
| 508 } | 522 } |
| 509 } | 523 } |
| 510 } | 524 } |
| 511 | 525 |
| 512 void addFieldAnnotations() { | 526 void addFieldAnnotations() { |
| 513 S.Script script = _loadedScript as S.Script; | 527 S.Script script = _loadedScript as S.Script; |
| 514 for (var field in script.library.variables) { | 528 for (var field in script.library.variables) { |
| 515 if ((field.location != null) && (field.location.script == script)) { | 529 if ((field.location != null) && (field.location.script == script)) { |
| 516 var a = new FieldDeclarationAnnotation(_isolate, _instances, _r.queue, | 530 var a = new FieldDeclarationAnnotation(_isolate, _instances, _r.queue, |
| 517 field, Uris.inspect(isolate, object: field)); | 531 field, Uris.inspect(isolate, object: field)); |
| 518 _annotations.add(a); | 532 _annotations.add(a); |
| 519 } | 533 } |
| 520 } | 534 } |
| 521 for (var cls in script.library.classes) { | 535 for (var cls in script.library.classes) { |
| 522 for (var field in cls.fields) { | 536 for (var field in cls.fields) { |
| 523 if ((field.location != null) && (field.location.script == script)) { | 537 if ((field.location != null) && (field.location.script == script)) { |
| 524 var a = new FieldDeclarationAnnotation(_isolate, _instances, _r.queue, | 538 var a = new FieldDeclarationAnnotation(_isolate, _instances, _r.queue, |
| 525 field, Uris.inspect(isolate, object: field)); | 539 field, Uris.inspect(isolate, object: field)); |
| 526 _annotations.add(a); | 540 _annotations.add(a); |
| 527 } | 541 } |
| 528 } | 542 } |
| 529 } | 543 } |
| 530 } | 544 } |
| 531 | 545 |
| 532 void addFunctionAnnotations() { | 546 void addFunctionAnnotations() { |
| 533 S.Script script = _loadedScript as S.Script; | 547 S.Script script = _loadedScript as S.Script; |
| 534 for (var func in script.library.functions) { | 548 for (var func in script.library.functions) { |
| 535 if ((func.location != null) && | 549 if ((func.location != null) && |
| 536 (func.location.script == script) && | 550 (func.location.script == script) && |
| 537 (func.kind != M.FunctionKind.implicitGetter) && | 551 (func.kind != M.FunctionKind.implicitGetter) && |
| 538 (func.kind != M.FunctionKind.implicitSetter)) { | 552 (func.kind != M.FunctionKind.implicitSetter)) { |
| 539 // We annotate a field declaration with the field instead of the | 553 // We annotate a field declaration with the field instead of the |
| 540 // implicit getter or setter. | 554 // implicit getter or setter. |
| 541 var a = new FunctionDeclarationAnnotation(_isolate, _instances, | 555 var a = new FunctionDeclarationAnnotation(_isolate, _instances, |
| 542 _r.queue, func, Uris.inspect(isolate, object: func)); | 556 _r.queue, func, Uris.inspect(isolate, object: func)); |
| 543 _annotations.add(a); | 557 _annotations.add(a); |
| 544 } | 558 } |
| 545 } | 559 } |
| 546 for (var cls in script.library.classes) { | 560 for (var cls in script.library.classes) { |
| 547 S.Script script = _loadedScript as S.Script; | 561 S.Script script = _loadedScript as S.Script; |
| 548 for (var func in cls.functions) { | 562 for (var func in cls.functions) { |
| 549 if ((func.location != null) && | 563 if ((func.location != null) && |
| 550 (func.location.script == script) && | 564 (func.location.script == script) && |
| 551 (func.kind != M.FunctionKind.implicitGetter) && | 565 (func.kind != M.FunctionKind.implicitGetter) && |
| 552 (func.kind != M.FunctionKind.implicitSetter)) { | 566 (func.kind != M.FunctionKind.implicitSetter)) { |
| 553 // We annotate a field declaration with the field instead of the | 567 // We annotate a field declaration with the field instead of the |
| 554 // implicit getter or setter. | 568 // implicit getter or setter. |
| 555 var a = new FunctionDeclarationAnnotation(_isolate, _instances, | 569 var a = new FunctionDeclarationAnnotation(_isolate, _instances, |
| 556 _r.queue, func, Uris.inspect(isolate, object: func)); | 570 _r.queue, func, Uris.inspect(isolate, object: func)); |
| 557 _annotations.add(a); | 571 _annotations.add(a); |
| 558 } | 572 } |
| 559 } | 573 } |
| 560 } | 574 } |
| 561 } | 575 } |
| 562 | 576 |
| 563 void addCallSiteAnnotations() { | 577 void addCallSiteAnnotations() { |
| 564 for (var callSite in _callSites) { | 578 for (var callSite in _callSites) { |
| 565 _annotations.add(new CallSiteAnnotation(_isolate, _instances, _r.queue, | 579 _annotations.add( |
| 566 callSite)); | 580 new CallSiteAnnotation(_isolate, _instances, _r.queue, callSite)); |
| 567 } | 581 } |
| 568 } | 582 } |
| 569 | 583 |
| 570 void addLocalVariableAnnotations() { | 584 void addLocalVariableAnnotations() { |
| 571 S.Script script = _loadedScript as S.Script; | 585 S.Script script = _loadedScript as S.Script; |
| 572 // We have local variable information. | 586 // We have local variable information. |
| 573 if (_variables != null) { | 587 if (_variables != null) { |
| 574 // For each variable. | 588 // For each variable. |
| 575 for (var variable in _variables) { | 589 for (var variable in _variables) { |
| 576 // Find variable usage locations. | 590 // Find variable usage locations. |
| 577 var locations = script.scanForLocalVariableLocations( | 591 var locations = script.scanForLocalVariableLocations( |
| 578 variable['name'], | 592 variable['name'], variable['_tokenPos'], variable['_endTokenPos']); |
| 579 variable['_tokenPos'], | |
| 580 variable['_endTokenPos']); | |
| 581 | 593 |
| 582 // Annotate locations. | 594 // Annotate locations. |
| 583 for (var location in locations) { | 595 for (var location in locations) { |
| 584 _annotations.add(new LocalVariableAnnotation(_isolate, _instances, | 596 _annotations.add(new LocalVariableAnnotation( |
| 585 _r.queue, location, | 597 _isolate, _instances, _r.queue, location, variable['value'])); |
| 586 variable['value'])); | |
| 587 } | 598 } |
| 588 } | 599 } |
| 589 } | 600 } |
| 590 } | 601 } |
| 591 | 602 |
| 592 ButtonElement _newRefreshButton() { | 603 ButtonElement _newRefreshButton() { |
| 593 var button = new ButtonElement(); | 604 var button = new ButtonElement(); |
| 594 button.classes = ['refresh']; | 605 button.classes = ['refresh']; |
| 595 button.onClick.listen((_) async { | 606 button.onClick.listen((_) async { |
| 596 button.disabled = true; | 607 button.disabled = true; |
| 597 await _refresh(); | 608 await _refresh(); |
| 598 button.disabled = false; | 609 button.disabled = false; |
| 599 }); | 610 }); |
| 600 button.title = 'Refresh coverage'; | 611 button.title = 'Refresh coverage'; |
| 601 button.children = [ | 612 button.children = [_iconRefresh.clone(true)]; |
| 602 _iconRefresh.clone(true) | |
| 603 ]; | |
| 604 return button; | 613 return button; |
| 605 } | 614 } |
| 606 | 615 |
| 607 ButtonElement _newToggleProfileButton() { | 616 ButtonElement _newToggleProfileButton() { |
| 608 ButtonElement button = new ButtonElement(); | 617 ButtonElement button = new ButtonElement(); |
| 609 button.classes = _includeProfile ? ['toggle-profile', 'enabled'] | 618 button.classes = |
| 610 : ['toggle-profile']; | 619 _includeProfile ? ['toggle-profile', 'enabled'] : ['toggle-profile']; |
| 611 button.title = 'Toggle CPU profile information'; | 620 button.title = 'Toggle CPU profile information'; |
| 612 button.onClick.listen((_) async { | 621 button.onClick.listen((_) async { |
| 613 _includeProfile = !_includeProfile; | 622 _includeProfile = !_includeProfile; |
| 614 button.classes.toggle('enabled'); | 623 button.classes.toggle('enabled'); |
| 615 button.disabled = true; | 624 button.disabled = true; |
| 616 _refresh(); | 625 _refresh(); |
| 617 button.disabled = false; | 626 button.disabled = false; |
| 618 }); | 627 }); |
| 619 button.children = [ | 628 button.children = [_iconWhatsHot.clone(true)]; |
| 620 _iconWhatsHot.clone(true) | |
| 621 ]; | |
| 622 return button; | 629 return button; |
| 623 } | 630 } |
| 624 | 631 |
| 625 Element linesTable() { | 632 Element linesTable() { |
| 626 S.Script script = _loadedScript as S.Script; | 633 S.Script script = _loadedScript as S.Script; |
| 627 var table = new DivElement(); | 634 var table = new DivElement(); |
| 628 table.classes.add("sourceTable"); | 635 table.classes.add("sourceTable"); |
| 629 | 636 |
| 630 _refreshButton = _newRefreshButton(); | 637 _refreshButton = _newRefreshButton(); |
| 631 _toggleProfileButton = _newToggleProfileButton(); | 638 _toggleProfileButton = _newToggleProfileButton(); |
| 632 table.append(_refreshButton); | 639 table.append(_refreshButton); |
| 633 table.append(_toggleProfileButton); | 640 table.append(_toggleProfileButton); |
| 634 | 641 |
| 635 if (_startLine == null || _endLine == null) { | 642 if (_startLine == null || _endLine == null) { |
| 636 return table; | 643 return table; |
| 637 } | 644 } |
| 638 | 645 |
| 639 var endLine = (_endPos != null | 646 var endLine = (_endPos != null |
| 640 ? _loadedScript.tokenToLine(_endPos) | 647 ? _loadedScript.tokenToLine(_endPos) |
| 641 : script.lines.length + _loadedScript.lineOffset); | 648 : script.lines.length + _loadedScript.lineOffset); |
| 642 var lineNumPad = endLine.toString().length; | 649 var lineNumPad = endLine.toString().length; |
| 643 | 650 |
| 644 _annotationsCursor = 0; | 651 _annotationsCursor = 0; |
| 645 | 652 |
| 646 int blankLineCount = 0; | 653 int blankLineCount = 0; |
| 647 for (int i = _startLine; i <= _endLine; i++) { | 654 for (int i = _startLine; i <= _endLine; i++) { |
| 648 var line = script.getLine(i); | 655 var line = script.getLine(i); |
| 649 if (line.isBlank) { | 656 if (line.isBlank) { |
| 650 // Try to introduce elipses if there are 4 or more contiguous | 657 // Try to introduce elipses if there are 4 or more contiguous |
| 651 // blank lines. | 658 // blank lines. |
| 652 blankLineCount++; | 659 blankLineCount++; |
| 653 } else { | 660 } else { |
| 654 if (blankLineCount > 0) { | 661 if (blankLineCount > 0) { |
| 655 int firstBlank = i - blankLineCount; | 662 int firstBlank = i - blankLineCount; |
| 656 int lastBlank = i - 1; | 663 int lastBlank = i - 1; |
| 657 if (blankLineCount < 4) { | 664 if (blankLineCount < 4) { |
| 658 // Too few blank lines for an elipsis. | 665 // Too few blank lines for an elipsis. |
| 659 for (int j = firstBlank; j <= lastBlank; j++) { | 666 for (int j = firstBlank; j <= lastBlank; j++) { |
| 660 table.append(lineElement(script.getLine(j), lineNumPad)); | 667 table.append(lineElement(script.getLine(j), lineNumPad)); |
| 661 } | 668 } |
| 662 } else { | 669 } else { |
| 663 // Add an elipsis for the skipped region. | 670 // Add an elipsis for the skipped region. |
| 664 table.append(lineElement(script.getLine(firstBlank), lineNumPad)); | 671 table.append(lineElement(script.getLine(firstBlank), lineNumPad)); |
| 665 table.append(lineElement(null, lineNumPad)); | 672 table.append(lineElement(null, lineNumPad)); |
| 666 table.append(lineElement(script.getLine(lastBlank), lineNumPad)); | 673 table.append(lineElement(script.getLine(lastBlank), lineNumPad)); |
| 667 } | 674 } |
| 668 blankLineCount = 0; | 675 blankLineCount = 0; |
| 669 } | 676 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 } | 793 } |
| 787 } | 794 } |
| 788 | 795 |
| 789 e.onClick.listen((event) { | 796 e.onClick.listen((event) { |
| 790 if (busy) { | 797 if (busy) { |
| 791 return; | 798 return; |
| 792 } | 799 } |
| 793 busy = true; | 800 busy = true; |
| 794 if (line.breakpoints == null) { | 801 if (line.breakpoints == null) { |
| 795 // No breakpoint. Add it. | 802 // No breakpoint. Add it. |
| 796 line.script.isolate.addBreakpoint(line.script, line.line) | 803 line.script.isolate |
| 797 .catchError((e, st) { | 804 .addBreakpoint(line.script, line.line) |
| 798 if (e is! S.ServerRpcException || | 805 .catchError((e, st) { |
| 799 (e as S.ServerRpcException).code != | 806 if (e is! S.ServerRpcException || |
| 800 S.ServerRpcException.kCannotAddBreakpoint) { | 807 (e as S.ServerRpcException).code != |
| 801 ObservatoryApplication.app.handleException(e, st); | 808 S.ServerRpcException.kCannotAddBreakpoint) { |
| 802 }}) | 809 ObservatoryApplication.app.handleException(e, st); |
| 803 .whenComplete(() { | 810 } |
| 804 busy = false; | 811 }).whenComplete(() { |
| 805 update(); | 812 busy = false; |
| 806 }); | 813 update(); |
| 814 }); |
| 807 } else { | 815 } else { |
| 808 // Existing breakpoint. Remove it. | 816 // Existing breakpoint. Remove it. |
| 809 List pending = []; | 817 List pending = []; |
| 810 for (var bpt in line.breakpoints) { | 818 for (var bpt in line.breakpoints) { |
| 811 pending.add(line.script.isolate.removeBreakpoint(bpt)); | 819 pending.add(line.script.isolate.removeBreakpoint(bpt)); |
| 812 } | 820 } |
| 813 Future.wait(pending).then((_) { | 821 Future.wait(pending).then((_) { |
| 814 busy = false; | 822 busy = false; |
| 815 update(); | 823 update(); |
| 816 }); | 824 }); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 | 887 |
| 880 if (line != null) { | 888 if (line != null) { |
| 881 e.classes.add(makeLineClass(line.line)); | 889 e.classes.add(makeLineClass(line.line)); |
| 882 if (line.line == _currentLine) { | 890 if (line.line == _currentLine) { |
| 883 e.classes.add("currentLine"); | 891 e.classes.add("currentLine"); |
| 884 } | 892 } |
| 885 | 893 |
| 886 var position = 0; | 894 var position = 0; |
| 887 consumeUntil(var stop) { | 895 consumeUntil(var stop) { |
| 888 if (stop <= position) { | 896 if (stop <= position) { |
| 889 return null; // Empty gap between annotations/boundries. | 897 return null; // Empty gap between annotations/boundries. |
| 890 } | 898 } |
| 891 if (stop > line.text.length) { | 899 if (stop > line.text.length) { |
| 892 // Approximated token length can run past the end of the line. | 900 // Approximated token length can run past the end of the line. |
| 893 stop = line.text.length; | 901 stop = line.text.length; |
| 894 } | 902 } |
| 895 | 903 |
| 896 var chunk = line.text.substring(position, stop); | 904 var chunk = line.text.substring(position, stop); |
| 897 var chunkNode = span(chunk); | 905 var chunkNode = span(chunk); |
| 898 e.append(chunkNode); | 906 e.append(chunkNode); |
| 899 position = stop; | 907 position = stop; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 infoBox.style.position = 'absolute'; | 961 infoBox.style.position = 'absolute'; |
| 954 infoBox.style.padding = '1em'; | 962 infoBox.style.padding = '1em'; |
| 955 infoBox.style.border = 'solid black 2px'; | 963 infoBox.style.border = 'solid black 2px'; |
| 956 infoBox.style.zIndex = '10'; | 964 infoBox.style.zIndex = '10'; |
| 957 infoBox.style.backgroundColor = 'white'; | 965 infoBox.style.backgroundColor = 'white'; |
| 958 infoBox.style.cursor = 'auto'; | 966 infoBox.style.cursor = 'auto'; |
| 959 // Don't inherit pre formating from the script lines. | 967 // Don't inherit pre formating from the script lines. |
| 960 infoBox.style.whiteSpace = 'normal'; | 968 infoBox.style.whiteSpace = 'normal'; |
| 961 content.append(infoBox); | 969 content.append(infoBox); |
| 962 } | 970 } |
| 971 |
| 963 content.onClick.listen((event) { | 972 content.onClick.listen((event) { |
| 964 show = !show; | 973 show = !show; |
| 965 if (infoBox == null) buildInfoBox(); // Created lazily on the first click. | 974 if (infoBox == null) buildInfoBox(); // Created lazily on the first click. |
| 966 infoBox.style.display = show ? 'block' : 'none'; | 975 infoBox.style.display = show ? 'block' : 'none'; |
| 967 content.style.backgroundColor = show ? 'white' : originalBackground; | 976 content.style.backgroundColor = show ? 'white' : originalBackground; |
| 968 }); | 977 }); |
| 969 | 978 |
| 970 // Causes infoBox to be positioned relative to the bottom-left of content. | 979 // Causes infoBox to be positioned relative to the bottom-left of content. |
| 971 content.style.display = 'inline-block'; | 980 content.style.display = 'inline-block'; |
| 972 content.style.cursor = 'pointer'; | 981 content.style.cursor = 'pointer'; |
| 973 } | 982 } |
| 974 | 983 |
| 975 | |
| 976 void addLink(Element content, String target) { | 984 void addLink(Element content, String target) { |
| 977 // Ick, destructive but still compatible with also adding an info box. | 985 // Ick, destructive but still compatible with also adding an info box. |
| 978 var a = new AnchorElement(href: target); | 986 var a = new AnchorElement(href: target); |
| 979 a.text = content.text; | 987 a.text = content.text; |
| 980 content.text = ''; | 988 content.text = ''; |
| 981 content.append(a); | 989 content.append(a); |
| 982 } | 990 } |
| 983 | 991 |
| 984 | |
| 985 abstract class Annotation implements Comparable<Annotation> { | 992 abstract class Annotation implements Comparable<Annotation> { |
| 986 M.IsolateRef _isolate; | 993 M.IsolateRef _isolate; |
| 987 M.InstanceRepository _instances; | 994 M.InstanceRepository _instances; |
| 988 RenderingQueue queue; | 995 RenderingQueue queue; |
| 989 int line; | 996 int line; |
| 990 int columnStart; | 997 int columnStart; |
| 991 int columnStop; | 998 int columnStop; |
| 992 int get priority; | 999 int get priority; |
| 993 | 1000 |
| 994 Annotation(this._isolate, this._instances, this.queue); | 1001 Annotation(this._isolate, this._instances, this.queue); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 if (content is Element) e.children.add(content); | 1036 if (content is Element) e.children.add(content); |
| 1030 return e; | 1037 return e; |
| 1031 } | 1038 } |
| 1032 | 1039 |
| 1033 Element serviceRef(object) { | 1040 Element serviceRef(object) { |
| 1034 return anyRef(_isolate, object, _instances, queue: queue); | 1041 return anyRef(_isolate, object, _instances, queue: queue); |
| 1035 } | 1042 } |
| 1036 } | 1043 } |
| 1037 | 1044 |
| 1038 class CurrentExecutionAnnotation extends Annotation { | 1045 class CurrentExecutionAnnotation extends Annotation { |
| 1039 int priority = 0; // highest priority. | 1046 int priority = 0; // highest priority. |
| 1040 | 1047 |
| 1041 CurrentExecutionAnnotation(M.IsolateRef isolate, | 1048 CurrentExecutionAnnotation(M.IsolateRef isolate, |
| 1042 M.InstanceRepository instances, | 1049 M.InstanceRepository instances, RenderingQueue queue) |
| 1043 RenderingQueue queue) | 1050 : super(isolate, instances, queue); |
| 1044 : super(isolate, instances, queue); | |
| 1045 | 1051 |
| 1046 void applyStyleTo(element) { | 1052 void applyStyleTo(element) { |
| 1047 if (element == null) { | 1053 if (element == null) { |
| 1048 return; // TODO(rmacnak): Handling overlapping annotations. | 1054 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1049 } | 1055 } |
| 1050 element.classes.add("currentCol"); | 1056 element.classes.add("currentCol"); |
| 1051 element.title = "Current execution"; | 1057 element.title = "Current execution"; |
| 1052 } | 1058 } |
| 1053 } | 1059 } |
| 1054 | 1060 |
| 1055 class BreakpointAnnotation extends Annotation { | 1061 class BreakpointAnnotation extends Annotation { |
| 1056 M.Breakpoint bpt; | 1062 M.Breakpoint bpt; |
| 1057 int priority = 1; | 1063 int priority = 1; |
| 1058 | 1064 |
| 1059 BreakpointAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1065 BreakpointAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1060 RenderingQueue queue, this.bpt) | 1066 RenderingQueue queue, this.bpt) |
| 1061 : super(isolate, instances, queue) { | 1067 : super(isolate, instances, queue) { |
| 1062 var script = bpt.location.script; | 1068 var script = bpt.location.script; |
| 1063 var location = bpt.location; | 1069 var location = bpt.location; |
| 1064 if (location.tokenPos != null) { | 1070 if (location.tokenPos != null) { |
| 1065 var pos = location.tokenPos; | 1071 var pos = location.tokenPos; |
| 1066 line = script.tokenToLine(pos); | 1072 line = script.tokenToLine(pos); |
| 1067 columnStart = script.tokenToCol(pos) - 1; // tokenToCol is 1-origin. | 1073 columnStart = script.tokenToCol(pos) - 1; // tokenToCol is 1-origin. |
| 1068 } else if (location is M.UnresolvedSourceLocation) { | 1074 } else if (location is M.UnresolvedSourceLocation) { |
| 1069 line = location.line; | 1075 line = location.line; |
| 1070 columnStart = location.column; | 1076 columnStart = location.column; |
| 1071 if (columnStart == null) { | 1077 if (columnStart == null) { |
| 1072 columnStart = 0; | 1078 columnStart = 0; |
| 1073 } | 1079 } |
| 1074 } | 1080 } |
| 1075 var length = script.guessTokenLength(line, columnStart); | 1081 var length = script.guessTokenLength(line, columnStart); |
| 1076 if (length == null) { | 1082 if (length == null) { |
| 1077 length = 1; | 1083 length = 1; |
| 1078 } | 1084 } |
| 1079 columnStop = columnStart + length; | 1085 columnStop = columnStart + length; |
| 1080 } | 1086 } |
| 1081 | 1087 |
| 1082 void applyStyleTo(element) { | 1088 void applyStyleTo(element) { |
| 1083 if (element == null) { | 1089 if (element == null) { |
| 1084 return; // TODO(rmacnak): Handling overlapping annotations. | 1090 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1085 } | 1091 } |
| 1086 var script = bpt.location.script; | 1092 var script = bpt.location.script; |
| 1087 var pos = bpt.location.tokenPos; | 1093 var pos = bpt.location.tokenPos; |
| 1088 int line = script.tokenToLine(pos); | 1094 int line = script.tokenToLine(pos); |
| 1089 int column = script.tokenToCol(pos); | 1095 int column = script.tokenToCol(pos); |
| 1090 if (bpt.resolved) { | 1096 if (bpt.resolved) { |
| 1091 element.classes.add("resolvedBreakAnnotation"); | 1097 element.classes.add("resolvedBreakAnnotation"); |
| 1092 } else { | 1098 } else { |
| 1093 element.classes.add("unresolvedBreakAnnotation"); | 1099 element.classes.add("unresolvedBreakAnnotation"); |
| 1094 } | 1100 } |
| 1095 element.title = "Breakpoint ${bpt.number} at ${line}:${column}"; | 1101 element.title = "Breakpoint ${bpt.number} at ${line}:${column}"; |
| 1096 } | 1102 } |
| 1097 } | 1103 } |
| 1098 | 1104 |
| 1099 class LibraryAnnotation extends Annotation { | 1105 class LibraryAnnotation extends Annotation { |
| 1100 S.Library target; | 1106 S.Library target; |
| 1101 String url; | 1107 String url; |
| 1102 int priority = 2; | 1108 int priority = 2; |
| 1103 | 1109 |
| 1104 LibraryAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1110 LibraryAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1105 RenderingQueue queue, this.target, this.url) | 1111 RenderingQueue queue, this.target, this.url) |
| 1106 : super(isolate, instances, queue); | 1112 : super(isolate, instances, queue); |
| 1107 | 1113 |
| 1108 void applyStyleTo(element) { | 1114 void applyStyleTo(element) { |
| 1109 if (element == null) { | 1115 if (element == null) { |
| 1110 return; // TODO(rmacnak): Handling overlapping annotations. | 1116 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1111 } | 1117 } |
| 1112 element.title = "library ${target.uri}"; | 1118 element.title = "library ${target.uri}"; |
| 1113 addLink(element, url); | 1119 addLink(element, url); |
| 1114 } | 1120 } |
| 1115 } | 1121 } |
| 1116 | 1122 |
| 1117 class PartAnnotation extends Annotation { | 1123 class PartAnnotation extends Annotation { |
| 1118 S.Script part; | 1124 S.Script part; |
| 1119 String url; | 1125 String url; |
| 1120 int priority = 2; | 1126 int priority = 2; |
| 1121 | 1127 |
| 1122 PartAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1128 PartAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1123 RenderingQueue queue, this.part, this.url) | 1129 RenderingQueue queue, this.part, this.url) |
| 1124 : super(isolate, instances, queue); | 1130 : super(isolate, instances, queue); |
| 1125 | 1131 |
| 1126 void applyStyleTo(element) { | 1132 void applyStyleTo(element) { |
| 1127 if (element == null) { | 1133 if (element == null) { |
| 1128 return; // TODO(rmacnak): Handling overlapping annotations. | 1134 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1129 } | 1135 } |
| 1130 element.title = "script ${part.uri}"; | 1136 element.title = "script ${part.uri}"; |
| 1131 addLink(element, url); | 1137 addLink(element, url); |
| 1132 } | 1138 } |
| 1133 } | 1139 } |
| 1134 | 1140 |
| 1135 class LocalVariableAnnotation extends Annotation { | 1141 class LocalVariableAnnotation extends Annotation { |
| 1136 final value; | 1142 final value; |
| 1137 int priority = 2; | 1143 int priority = 2; |
| 1138 | 1144 |
| 1139 LocalVariableAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1145 LocalVariableAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1140 RenderingQueue queue, S.LocalVarLocation location, | 1146 RenderingQueue queue, S.LocalVarLocation location, this.value) |
| 1141 this.value): super(isolate, instances, queue) { | 1147 : super(isolate, instances, queue) { |
| 1142 line = location.line; | 1148 line = location.line; |
| 1143 columnStart = location.column; | 1149 columnStart = location.column; |
| 1144 columnStop = location.endColumn; | 1150 columnStop = location.endColumn; |
| 1145 } | 1151 } |
| 1146 | 1152 |
| 1147 void applyStyleTo(element) { | 1153 void applyStyleTo(element) { |
| 1148 if (element == null) { | 1154 if (element == null) { |
| 1149 return; // TODO(rmacnak): Handling overlapping annotations. | 1155 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1150 } | 1156 } |
| 1151 element.style.fontWeight = "bold"; | 1157 element.style.fontWeight = "bold"; |
| 1152 element.title = "${value.shortName}"; | 1158 element.title = "${value.shortName}"; |
| 1153 } | 1159 } |
| 1154 } | 1160 } |
| 1155 | 1161 |
| 1156 class CallSiteAnnotation extends Annotation { | 1162 class CallSiteAnnotation extends Annotation { |
| 1157 S.CallSite callSite; | 1163 S.CallSite callSite; |
| 1158 int priority = 2; | 1164 int priority = 2; |
| 1159 | 1165 |
| 1160 CallSiteAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1166 CallSiteAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1161 RenderingQueue queue, this.callSite) | 1167 RenderingQueue queue, this.callSite) |
| 1162 : super(isolate, instances, queue) { | 1168 : super(isolate, instances, queue) { |
| 1163 line = callSite.line; | 1169 line = callSite.line; |
| 1164 columnStart = callSite.column - 1; // Call site is 1-origin. | 1170 columnStart = callSite.column - 1; // Call site is 1-origin. |
| 1165 var tokenLength = callSite.script.guessTokenLength(line, columnStart); | 1171 var tokenLength = callSite.script.guessTokenLength(line, columnStart); |
| 1166 if (tokenLength == null) { | 1172 if (tokenLength == null) { |
| 1167 tokenLength = callSite.name.length; // Approximate. | 1173 tokenLength = callSite.name.length; // Approximate. |
| 1168 if (callSite.name.startsWith("get:") || | 1174 if (callSite.name.startsWith("get:") || callSite.name.startsWith("set:")) |
| 1169 callSite.name.startsWith("set:")) tokenLength -= 4; | 1175 tokenLength -= 4; |
| 1170 } | 1176 } |
| 1171 columnStop = columnStart + tokenLength; | 1177 columnStop = columnStart + tokenLength; |
| 1172 } | 1178 } |
| 1173 | 1179 |
| 1174 void applyStyleTo(element) { | 1180 void applyStyleTo(element) { |
| 1175 if (element == null) { | 1181 if (element == null) { |
| 1176 return; // TODO(rmacnak): Handling overlapping annotations. | 1182 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1177 } | 1183 } |
| 1178 element.style.fontWeight = "bold"; | 1184 element.style.fontWeight = "bold"; |
| 1179 element.title = "Call site: ${callSite.name}"; | 1185 element.title = "Call site: ${callSite.name}"; |
| 1180 | 1186 |
| 1181 addInfoBox(element, () { | 1187 addInfoBox(element, () { |
| 1182 var details = table(); | 1188 var details = table(); |
| 1183 if (callSite.entries.isEmpty) { | 1189 if (callSite.entries.isEmpty) { |
| 1184 details.append(row('Call of "${callSite.name}" did not execute')); | 1190 details.append(row('Call of "${callSite.name}" did not execute')); |
| 1185 } else { | 1191 } else { |
| 1186 var r = row(); | 1192 var r = row(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1204 return details; | 1210 return details; |
| 1205 }); | 1211 }); |
| 1206 } | 1212 } |
| 1207 } | 1213 } |
| 1208 | 1214 |
| 1209 abstract class DeclarationAnnotation extends Annotation { | 1215 abstract class DeclarationAnnotation extends Annotation { |
| 1210 String url; | 1216 String url; |
| 1211 int priority = 2; | 1217 int priority = 2; |
| 1212 | 1218 |
| 1213 DeclarationAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, | 1219 DeclarationAnnotation(M.IsolateRef isolate, M.InstanceRepository instances, |
| 1214 RenderingQueue queue, decl, this.url) | 1220 RenderingQueue queue, decl, this.url) |
| 1215 : super(isolate, instances, queue) { | 1221 : super(isolate, instances, queue) { |
| 1216 assert(decl.loaded); | 1222 assert(decl.loaded); |
| 1217 S.SourceLocation location = decl.location; | 1223 S.SourceLocation location = decl.location; |
| 1218 if (location == null) { | 1224 if (location == null) { |
| 1219 line = 0; | 1225 line = 0; |
| 1220 columnStart = 0; | 1226 columnStart = 0; |
| 1221 columnStop = 0; | 1227 columnStop = 0; |
| 1222 return; | 1228 return; |
| 1223 } | 1229 } |
| 1224 | 1230 |
| 1225 S.Script script = location.script; | 1231 S.Script script = location.script; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1242 columnStart = betterStart; | 1248 columnStart = betterStart; |
| 1243 } | 1249 } |
| 1244 columnStop = columnStart + decl.name.length; | 1250 columnStop = columnStart + decl.name.length; |
| 1245 } | 1251 } |
| 1246 } | 1252 } |
| 1247 } | 1253 } |
| 1248 | 1254 |
| 1249 class ClassDeclarationAnnotation extends DeclarationAnnotation { | 1255 class ClassDeclarationAnnotation extends DeclarationAnnotation { |
| 1250 S.Class klass; | 1256 S.Class klass; |
| 1251 | 1257 |
| 1252 ClassDeclarationAnnotation(M.IsolateRef isolate, | 1258 ClassDeclarationAnnotation( |
| 1253 M.InstanceRepository instances, | 1259 M.IsolateRef isolate, |
| 1254 RenderingQueue queue, S.Class cls, String url) | 1260 M.InstanceRepository instances, |
| 1255 : klass = cls, | 1261 RenderingQueue queue, |
| 1256 super(isolate, instances, queue, cls, url); | 1262 S.Class cls, |
| 1263 String url) |
| 1264 : klass = cls, |
| 1265 super(isolate, instances, queue, cls, url); |
| 1257 | 1266 |
| 1258 void applyStyleTo(element) { | 1267 void applyStyleTo(element) { |
| 1259 if (element == null) { | 1268 if (element == null) { |
| 1260 return; // TODO(rmacnak): Handling overlapping annotations. | 1269 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1261 } | 1270 } |
| 1262 element.title = "class ${klass.name}"; | 1271 element.title = "class ${klass.name}"; |
| 1263 addLink(element, url); | 1272 addLink(element, url); |
| 1264 } | 1273 } |
| 1265 } | 1274 } |
| 1266 | 1275 |
| 1267 class FieldDeclarationAnnotation extends DeclarationAnnotation { | 1276 class FieldDeclarationAnnotation extends DeclarationAnnotation { |
| 1268 S.Field field; | 1277 S.Field field; |
| 1269 | 1278 |
| 1270 FieldDeclarationAnnotation(M.IsolateRef isolate, | 1279 FieldDeclarationAnnotation( |
| 1271 M.InstanceRepository instances, | 1280 M.IsolateRef isolate, |
| 1272 RenderingQueue queue, S.Field fld, String url) | 1281 M.InstanceRepository instances, |
| 1273 : field = fld, | 1282 RenderingQueue queue, |
| 1274 super(isolate, instances, queue, fld, url); | 1283 S.Field fld, |
| 1284 String url) |
| 1285 : field = fld, |
| 1286 super(isolate, instances, queue, fld, url); |
| 1275 | 1287 |
| 1276 void applyStyleTo(element) { | 1288 void applyStyleTo(element) { |
| 1277 if (element == null) { | 1289 if (element == null) { |
| 1278 return; // TODO(rmacnak): Handling overlapping annotations. | 1290 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1279 } | 1291 } |
| 1280 var tooltip = "field ${field.name}"; | 1292 var tooltip = "field ${field.name}"; |
| 1281 element.title = tooltip; | 1293 element.title = tooltip; |
| 1282 addLink(element, url); | 1294 addLink(element, url); |
| 1283 } | 1295 } |
| 1284 } | 1296 } |
| 1285 | 1297 |
| 1286 class FunctionDeclarationAnnotation extends DeclarationAnnotation { | 1298 class FunctionDeclarationAnnotation extends DeclarationAnnotation { |
| 1287 S.ServiceFunction function; | 1299 S.ServiceFunction function; |
| 1288 | 1300 |
| 1289 FunctionDeclarationAnnotation(M.IsolateRef isolate, | 1301 FunctionDeclarationAnnotation( |
| 1290 M.InstanceRepository instances, | 1302 M.IsolateRef isolate, |
| 1291 RenderingQueue queue, S.ServiceFunction func, | 1303 M.InstanceRepository instances, |
| 1292 String url) | 1304 RenderingQueue queue, |
| 1293 : function = func, | 1305 S.ServiceFunction func, |
| 1294 super(isolate, instances, queue, func, url); | 1306 String url) |
| 1307 : function = func, |
| 1308 super(isolate, instances, queue, func, url); |
| 1295 | 1309 |
| 1296 void applyStyleTo(element) { | 1310 void applyStyleTo(element) { |
| 1297 if (element == null) { | 1311 if (element == null) { |
| 1298 return; // TODO(rmacnak): Handling overlapping annotations. | 1312 return; // TODO(rmacnak): Handling overlapping annotations. |
| 1299 } | 1313 } |
| 1300 var tooltip = "method ${function.name}"; | 1314 var tooltip = "method ${function.name}"; |
| 1301 if (function.isOptimizable == false) { | 1315 if (function.isOptimizable == false) { |
| 1302 tooltip += "\nUnoptimizable!"; | 1316 tooltip += "\nUnoptimizable!"; |
| 1303 } | 1317 } |
| 1304 if (function.isInlinable == false) { | 1318 if (function.isInlinable == false) { |
| 1305 tooltip += "\nNot inlinable!"; | 1319 tooltip += "\nNot inlinable!"; |
| 1306 } | 1320 } |
| 1307 if (function.deoptimizations > 0) { | 1321 if (function.deoptimizations > 0) { |
| 1308 tooltip += "\nDeoptimized ${function.deoptimizations} times!"; | 1322 tooltip += "\nDeoptimized ${function.deoptimizations} times!"; |
| 1309 } | 1323 } |
| 1310 element.title = tooltip; | 1324 element.title = tooltip; |
| 1311 | 1325 |
| 1312 if (function.isOptimizable == false || | 1326 if (function.isOptimizable == false || |
| 1313 function.isInlinable == false || | 1327 function.isInlinable == false || |
| 1314 function.deoptimizations >0) { | 1328 function.deoptimizations > 0) { |
| 1315 element.style.backgroundColor = "#EEA7A7"; // Low-saturation red. | 1329 element.style.backgroundColor = "#EEA7A7"; // Low-saturation red. |
| 1316 } | 1330 } |
| 1317 | 1331 |
| 1318 addLink(element, url); | 1332 addLink(element, url); |
| 1319 } | 1333 } |
| 1320 } | 1334 } |
| 1321 | 1335 |
| 1322 class ScriptLineProfile { | 1336 class ScriptLineProfile { |
| 1323 ScriptLineProfile(this.line, this.sampleCount); | 1337 ScriptLineProfile(this.line, this.sampleCount); |
| 1324 | 1338 |
| 1325 static const kHotThreshold = 0.05; // 5%. | 1339 static const kHotThreshold = 0.05; // 5%. |
| 1326 static const kMediumThreshold = 0.02; // 2%. | 1340 static const kMediumThreshold = 0.02; // 2%. |
| 1327 | 1341 |
| 1328 final int line; | 1342 final int line; |
| 1329 final int sampleCount; | 1343 final int sampleCount; |
| 1330 | 1344 |
| 1331 int selfTicks = 0; | 1345 int selfTicks = 0; |
| 1332 int totalTicks = 0; | 1346 int totalTicks = 0; |
| 1333 | 1347 |
| 1334 void process(int exclusive, int inclusive) { | 1348 void process(int exclusive, int inclusive) { |
| 1335 selfTicks += exclusive; | 1349 selfTicks += exclusive; |
| 1336 totalTicks += inclusive; | 1350 totalTicks += inclusive; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1353 } else { | 1367 } else { |
| 1354 return totalTicks / sampleCount; | 1368 return totalTicks / sampleCount; |
| 1355 } | 1369 } |
| 1356 } | 1370 } |
| 1357 | 1371 |
| 1358 bool isHot(bool self) => _percent(self) > kHotThreshold; | 1372 bool isHot(bool self) => _percent(self) > kHotThreshold; |
| 1359 bool isMedium(bool self) => _percent(self) > kMediumThreshold; | 1373 bool isMedium(bool self) => _percent(self) > kMediumThreshold; |
| 1360 } | 1374 } |
| 1361 | 1375 |
| 1362 final SvgSvgElement _iconRefresh = new SvgSvgElement() | 1376 final SvgSvgElement _iconRefresh = new SvgSvgElement() |
| 1363 ..setAttribute('width', '24') | 1377 ..setAttribute('width', '24') |
| 1364 ..setAttribute('height', '24') | 1378 ..setAttribute('height', '24') |
| 1365 ..children = [ | 1379 ..children = [ |
| 1366 new PathElement() | 1380 new PathElement() |
| 1367 ..setAttribute('d', 'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 ' | 1381 ..setAttribute( |
| 1368 '3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 ' | 1382 'd', |
| 1369 '7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 ' | 1383 'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 ' |
| 1370 '0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 ' | 1384 '3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 ' |
| 1371 '1.78L13 11h7V4l-2.35 2.35z') | 1385 '7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 ' |
| 1372 ]; | 1386 '0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 ' |
| 1387 '1.78L13 11h7V4l-2.35 2.35z') |
| 1388 ]; |
| 1373 | 1389 |
| 1374 final SvgSvgElement _iconWhatsHot = new SvgSvgElement() | 1390 final SvgSvgElement _iconWhatsHot = new SvgSvgElement() |
| 1375 ..setAttribute('width', '24') | 1391 ..setAttribute('width', '24') |
| 1376 ..setAttribute('height', '24') | 1392 ..setAttribute('height', '24') |
| 1377 ..children = [ | 1393 ..children = [ |
| 1378 new PathElement() | 1394 new PathElement() |
| 1379 ..setAttribute('d', 'M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 ' | 1395 ..setAttribute( |
| 1380 '3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 ' | 1396 'd', |
| 1381 '4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 ' | 1397 'M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 ' |
| 1382 '17.41 3.8 13.5.67zM11.71 19c-1.78 ' | 1398 '3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 ' |
| 1383 '0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 ' | 1399 '4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 ' |
| 1384 '1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 ' | 1400 '17.41 3.8 13.5.67zM11.71 19c-1.78 ' |
| 1385 '4.04 0 2.65-2.15 4.8-4.8 4.8z') | 1401 '0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 ' |
| 1386 ]; | 1402 '1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 ' |
| 1403 '4.04 0 2.65-2.15 4.8-4.8 4.8z') |
| 1404 ]; |
| OLD | NEW |