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 |