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

Unified Diff: runtime/observatory/lib/src/service/scanner.dart

Issue 1126363005: Show tooltip with local variable value in Observatory debugger (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 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/service/scanner.dart
diff --git a/runtime/observatory/lib/src/service/scanner.dart b/runtime/observatory/lib/src/service/scanner.dart
new file mode 100644
index 0000000000000000000000000000000000000000..aff1008ac77ea7be7a015637175b24142a1b1ba2
--- /dev/null
+++ b/runtime/observatory/lib/src/service/scanner.dart
@@ -0,0 +1,236 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of service;
+
+/// A text scanner that keeps track of token position, line, and column.
+class Scanner {
+ final String string;
+
+ /// The current position of the scanner in the string, in characters.
+ int get tokenPos => _tokenPos;
+ set tokenPos(int newTokenPos) {
+ if (newTokenPos < 0 || newTokenPos > string.length) {
+ throw new ArgumentError("Invalid tokenPos $tokenPos");
+ }
+
+ var oldTokenPos = _tokenPos;
+ _tokenPos = newTokenPos;
+
+ if (newTokenPos > oldTokenPos) {
+ var newlines =
+ "\n".allMatches(string.substring(oldTokenPos, newTokenPos)).toList();
+ _line += newlines.length;
+ if (newlines.isEmpty) {
+ _column += newTokenPos - oldTokenPos;
+ } else {
+ _column = newTokenPos - newlines.last.end;
+ }
+ } else {
+ var newlines =
+ "\n".allMatches(string.substring(newTokenPos, oldTokenPos)).toList();
+ _line -= newlines.length;
+ if (newlines.isEmpty) {
+ _column -= oldTokenPos - newTokenPos;
+ } else {
+ _column = newTokenPos - string.lastIndexOf("\n", newTokenPos) - 1;
+ }
+ }
+ }
+ int _tokenPos = 0;
+
+ /// The scanner's current (zero-based) line number.
+ int get line => _line;
+ int _line = 0;
+
+ /// The scanner's current (zero-based) column number.
+ int get column => _column;
+ int _column = 0;
+
+ /// The scanner's state, including line and column information.
+ ///
+ /// This can be used to efficiently save and restore the state of the scanner
+ /// when backtracking. A given [ScannerState] is only valid for the
+ /// [Scanner] that created it.
+ ScannerState get state => new ScannerState._(this, tokenPos, line, column);
+ set state(ScannerState state) {
+ if (!identical(state._scanner, this)) {
+ throw new ArgumentError("The given LineScannerState was not returned by "
+ "this LineScanner.");
+ }
+
+ _tokenPos = state.tokenPos;
+ _line = state.line;
+ _column = state.column;
+ }
+
+ /// The data about the previous match made by the scanner.
+ ///
+ /// If the last match failed, this will be `null`.
+ Match get lastMatch => _lastMatch;
+ Match _lastMatch;
+
+ /// Whether the scanner has completely consumed [string].
+ bool get isDone => tokenPos == string.length;
+
+ Scanner(this.string, {int tokenPos: 0, int line: 0, int column: 0}) {
+ this._tokenPos = tokenPos;
+ this._line = line;
+ this._column = column;
+ }
+
+ /// Consumes a single character and returns its character code.
+ ///
+ /// This throws a [FormatException] if the string has been fully consumed. It
+ /// doesn't affect [lastMatch].
+ int readChar() {
+ if (isDone) {
+ throw new FormatException('no more input');
+ }
+ var char = string.codeUnitAt(_tokenPos++);
+ if (char == 0xA) {
+ _line += 1;
+ _column = 0;
+ } else {
+ _column += 1;
+ }
+ return char;
+ }
+
+ /// Returns the character code of the character [offset] away from [tokenPos].
+ ///
+ /// [offset] defaults to zero, and may be negative to inspect already-consumed
+ /// characters.
+ ///
+ /// This returns `null` if [offset] points outside the string. It doesn't
+ /// affect [lastMatch].
+ int peekChar([int offset = 0]) {
+ var index = tokenPos + offset;
+ if (index < 0 || index >= string.length) {
+ return null;
+ }
+ return string.codeUnitAt(index);
+ }
+
+ /// If [pattern] matches at the current tokenPos of the string, scans forward
+ /// until the end of the match.
+ ///
+ /// Returns whether or not [pattern] matched.
+ bool scan(Pattern pattern) {
+ var success = matches(pattern);
+ if (!success) {
+ return success;
+ }
+ _tokenPos = _lastMatch.end;
+ var newlines = "\n".allMatches(lastMatch[0]).toList();
+ _line += newlines.length;
+ if (newlines.isEmpty) {
+ _column += lastMatch[0].length;
+ } else {
+ _column = lastMatch[0].length - newlines.last.end;
+ }
+
+ return true;
+ }
+
+ /// If [pattern] matches at the current tokenPos of the string, scans forward
+ /// until the end of the match.
+ ///
+ /// If [pattern] did not match, throws a [FormatException] describing the
+ /// tokenPos of the failure.
+ void expect(Pattern pattern, {String name}) {
+ if (scan(pattern)) {
+ return;
+ }
+ throw new FormatException('expect($pattern) failed.');
+ }
+
+ /// If the string has not been fully consumed, this throws a
+ /// [FormatException].
+ void expectDone() {
+ if (isDone) {
+ return;
+ }
+ throw new FormatException('not done');
+ }
+
+ /// Returns whether or not [pattern] matches at the current tokenPos of the
+ /// string.
+ ///
+ /// This doesn't move the scan pointer forward.
+ bool matches(Pattern pattern) {
+ _lastMatch = pattern.matchAsPrefix(string, tokenPos);
+ return _lastMatch != null;
+ }
+
+ /// Returns the substring of [string] between [start] and [end].
+ ///
+ /// Unlike [String.substring], [end] defaults to [tokenPos] rather than the
+ /// end of the string.
+ String substring(int start, [int end]) {
+ if (end == null) end = tokenPos;
+ return string.substring(start, end);
+ }
+}
+
+/// A class representing the state of a [LineScanner].
+class ScannerState {
+ /// The [LineScanner] that created this.
+ final Scanner _scanner;
+
+ /// The position of the scanner in this state.
+ final int tokenPos;
+
+ /// The zero-based line number of the scanner in this state.
+ final int line;
+
+ /// The zero-based column number of the scanner in this state.
+ final int column;
+
+ ScannerState._(this._scanner, this.tokenPos, this.line, this.column);
+}
+
+class ScannedRegion {
+ final ScannerState start;
+ final ScannerState end;
+ ScannedRegion(this.start, this.end);
+
+ bool contained(int line, int column) {
+ // TODO(johnmccutchan): Fix.
+ return false;
+ }
+}
+
+/// Computes a list of source regions that are Dart source code comments.
+/// Handles comments that span multiple lines.
+class CommentScanner {
+ Scanner _scanner;
+
+ CommentScanner(String source, {int tokenPos: 0, int line: 0, int column: 0}) {
+ _scanner =
+ new Scanner(source, tokenPos: tokenPos, line: line, column: column);
+ }
+
+ void scan() {
+ }
+
+ final List<ScannedRegion> comments = [];
+}
+
+/// Computes a list of source regions that are Dart string literals. Will split
+/// string literal regions that include $expr or ${expr} regions into two string
+/// literals (one before and one after). Handles string literals that span
+/// multiple lines.
+class StringLiteralScanner {
+ Scanner _scanner;
+ CommentScanner(String source, {int tokenPos: 0, int line: 0, int column: 0}) {
+ _scanner =
+ new Scanner(source, tokenPos: tokenPos, line: line, column: column);
+ }
+
+ void scan() {
+ }
+
+ final List<ScannedRegion> stringLiterals = [];
+}

Powered by Google App Engine
This is Rietveld 408576698