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

Unified Diff: runtime/observatory/lib/src/elements/script_inset.dart

Issue 959043003: Build script views programmatically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/src/elements/script_inset.dart
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index aef3fe3dde57d321ee2f8a107482a897802cf8a6..d5c4625231618cf147630933054c054794d656a9 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -9,6 +9,22 @@ import 'observatory_element.dart';
import 'package:observatory/service.dart';
import 'package:polymer/polymer.dart';
+const nbsp = "\u00A0";
+
+class Annotation {
+ int line;
+ int columnStart;
+ int columnStop;
+ String title;
+
+ void applyStyleTo(element) {
+ element.style.color = "blue";
+ element.style.textDecoration = "underline";
+ element.title = title;
+ print("Annotated ${element.text} as $title");
Cutch 2015/02/27 14:44:33 Remove before committing.
rmacnak 2015/02/27 20:55:34 Done.
+ }
+}
+
/// Box with script source code in it.
@CustomTag('script-inset')
class ScriptInsetElement extends ObservatoryElement {
@@ -28,91 +44,98 @@ class ScriptInsetElement extends ObservatoryElement {
@observable int endLine;
@observable bool linesReady = false;
- // Contents are either ScriptLine or ScriptElipsis.
- @observable List lines = toObservable([]);
+ var annotations = [];
+ var annotationsCursor;
+
+ StreamSubscription scriptChangeSubscription;
String makeLineId(int line) {
return 'line-$line';
}
- String clip(String line, int start, [int limit]) {
- try {
- return line.substring(start, limit);
- } catch (_) {
- // NOTE(turnidge): Sometimes polymer updates give us garbage
- // starts and limits during page updates.
- return "OOB";
- }
- }
-
- MutationObserver _observer;
-
void _scrollToCurrentPos() {
- var line = shadowRoot.querySelector('#line-$currentLine');
+ var line = querySelector('#${makeLineId(currentLine)}');
if (line != null) {
line.scrollIntoView();
}
}
- void _onMutation(mutations, observer) {
- _scrollToCurrentPos();
- }
-
- void attached() {
- super.attached();
- var table = shadowRoot.querySelector('.sourceTable');
- if (table != null) {
- _observer = new MutationObserver(_onMutation);
- _observer.observe(table, childList:true);
- }
- }
-
void detached() {
- if (_observer != null) {
- _observer.disconnect();
- _observer = null;
+ if (scriptChangeSubscription != null) {
+ // Don't leak. If only Dart and Javascript exposed weak references...
+ scriptChangeSubscription.cancel();
+ scriptChangeSubscription = null;
}
super.detached();
}
void currentPosChanged(oldValue) {
- _updateLines();
+ update();
_scrollToCurrentPos();
}
void startPosChanged(oldValue) {
- _updateLines();
+ update();
}
void endPosChanged(oldValue) {
- _updateLines();
+ update();
}
void scriptChanged(oldValue) {
- _updateLines();
+ update();
}
- var _updateFuture;
+ // Styles.
+ Element a(String text) => new AnchorElement()..text = text;
+ Element span(String text) => new SpanElement()..text = text;
+ Element monospace(Element element) {
+ element.style.fontFamily = "consolas, courier, monospace";
+ return element;
+ }
+ Element row(Element element) {
+ element.style.display = "table-row";
+ return element;
+ }
+ Element cell(Element element) {
+ element.style.display = "table-cell";
+ element.style.verticalAlign = "top";
+ return element;
+ }
+ Element hitsUnknown(Element element) {
+ element.style.backgroundColor = "";
+ element.title = "";
+ return element;
+ }
+ Element hitsNotExecuted(Element element) {
+ element.style.backgroundColor = "#e66";
+ element.title = "Line did not execute";
+ return element;
+ }
+ Element hitsExecuted(Element element) {
+ element.style.backgroundColor = "#6d6";
+ element.title = "Line did execute";
+ return element;
+ }
- void _updateLines() {
- linesReady = false;
- if (_updateFuture != null) {
- // Already scheduled.
- return;
- }
- if (script == null) {
- // Wait for script to be assigned.
- return;
- }
+ void update() {
+ if (script == null) return;
Cutch 2015/02/27 14:44:33 curlies- if ( ... ) { return; } should you ensure
rmacnak 2015/02/27 20:55:34 Done.
if (!script.loaded) {
- _updateFuture = script.load().then((_) {
- if (script.loaded) {
- _updateFuture = null;
- _updateLines();
- }
- });
- return;
+ return script.load().then((_) => update());
+ }
+
+ if (scriptChangeSubscription == null) {
+ scriptChangeSubscription = script.changes.listen((_) => update());
}
+
+ computeAnnotations();
+
+ var table = linesTable();
+ children.clear();
+ children.add(table);
+ }
+
+ void computeAnnotations() {
startLine = (startPos != null
? script.tokenToLine(startPos)
: 1);
@@ -126,33 +149,100 @@ class ScriptInsetElement extends ObservatoryElement {
? script.tokenToLine(endPos)
: script.lines.length);
- lines.clear();
- int blankLineCount = 0;
- for (int i = (startLine - 1); i <= (endLine - 1); i++) {
- if (script.lines[i].isBlank) {
- // Try to introduce elipses if there are 4 or more contiguous blank lines.
- blankLineCount++;
- } else {
- if (blankLineCount > 0) {
- int firstBlank = i - blankLineCount;
- int lastBlank = i - 1;
- if (blankLineCount < 4) {
- // Too few blank lines for an elipsis.
- for (int j = firstBlank; j <= lastBlank; j++) {
- lines.add(script.lines[j]);
- }
- } else {
- // Add an elipsis for the skipped region.
- lines.add(script.lines[firstBlank]);
- lines.add(null);
- lines.add(script.lines[lastBlank]);
- }
- blankLineCount = 0;
- }
- lines.add(script.lines[i]);
+ annotations.clear();
+ if (currentLine != null) {
+ var a = new Annotation();
+ a.line = currentLine;
+ a.columnStart = currentCol;
+ a.columnStop = currentCol + 1;
+ a.title = "Current invocation";
+ annotations.add(a);
+ }
+
+ // TODO(rmacnak): Call site data.
+ }
+
+ Element linesTable() {
+ var table = new DivElement();
+ table.style.fontFamily = "monospace";
Cutch 2015/02/27 14:44:33 use css classes defined in html instead of setting
rmacnak 2015/02/27 20:55:34 Done.
+ table.style.fontWeight = "400";
+ table.style.display = "table";
+ table.style.backgroundColor = "#f5f5f5";
+ table.style.border = "1px solid #ccc";
+ table.style.padding = "10px";
+ table.style.overflowY = "auto";
+ table.style.width = "100%";
+
+ int lineNumber = 1;
+ annotationsCursor = 0;
+ for (ScriptLine line in script.lines) {
+ if (startLine <= lineNumber && lineNumber <= endLine) {
+ table.append(lineElement(line));
}
+ lineNumber++;
}
- linesReady = true;
+
+ return table;
+ }
+
+ // Assumes annotations are sorted.
+ Annotation nextAnnotationOnLine(int line) {
+ if (annotationsCursor >= annotations.length) return null;
+ var annotation = annotations[annotationsCursor];
+ if (annotation.line != line) return null;
+ annotationsCursor++;
+ return annotation;
+ }
+
+ Element lineElement(ScriptLine line) {
+ return row(new DivElement())
+ ..append(cell(lineBreakpointElement(line)))
+ ..append(cell(lineNumberElement(line)))
+ ..append(cell(lineSourceElement(line)));
+ }
+
+ Element lineBreakpointElement(ScriptLine line) {
+ return new Element.tag("breakpoint-toggle")
+ ..line = line;
+ }
+
+ Element lineNumberElement(ScriptLine line) {
+ var lineNumber = line.line;
+ var node = monospace(span("$nbsp$lineNumber$nbsp"));
+ node.style.textAlign = "right";
+ node.style.color = "#a8a8a8";
+
+ if (line.hits == null) hitsUnknown(node);
Cutch 2015/02/27 14:44:33 braces and new lines please
rmacnak 2015/02/27 20:55:34 Done.
+ else if (line.hits == 0) hitsNotExecuted(node);
+ else hitsExecuted(node);
+
+ return node;
+ }
+
+ Element lineSourceElement(ScriptLine line) {
+ var node = new DivElement();
+ node.style.whiteSpace = "pre";
+ node.id = makeLineId(line.line);
+
+ var position = 0;
+ consumeUntil(var stop) {
+ if (stop <= position) return; // Empty gap between annotations/boundries.
+ var chunk = line.text.substring(position, stop);
+ var chunkNode = monospace(span(chunk));
+ node.append(chunkNode);
+ position = stop;
+ return chunkNode;
+ }
+
+ // TODO(rmacnak): Tolerate overlapping annotations.
+ var annotation;
+ while ((annotation = nextAnnotationOnLine(line.line)) != null) {
+ consumeUntil(annotation.columnStart);
+ annotation.applyStyleTo(consumeUntil(annotation.columnStop));
+ }
+ consumeUntil(line.text.length);
+
+ return node;
}
ScriptInsetElement.created() : super.created();

Powered by Google App Engine
This is Rietveld 408576698