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

Unified Diff: runtime/bin/vmservice/client/lib/src/service/object.dart

Issue 361743002: observatory/vm: add support for computing/passing end tokens on classes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 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/bin/vmservice/client/lib/src/service/object.dart
diff --git a/runtime/bin/vmservice/client/lib/src/service/object.dart b/runtime/bin/vmservice/client/lib/src/service/object.dart
index 09b0de853ab1bc0a891d5aa9d999b71d3a811573..5fe97e6bec5e4ae4ffe1f92348e401c653972e5e 100644
--- a/runtime/bin/vmservice/client/lib/src/service/object.dart
+++ b/runtime/bin/vmservice/client/lib/src/service/object.dart
@@ -1103,6 +1103,146 @@ class Allocations {
bool get empty => accumulated.empty && current.empty;
}
+class ClassParser {
hausner 2014/07/01 23:49:07 When we spoke offline I was under the impression t
+ List<ScriptLine> _source;
+ int _offset;
+
+ ClassParser(this._source) {
+ assert(_source != null && _source.length > 0);
+ _offset = this._source.first.line;
+ }
+
+ // Internal state for parsing the class.
+ var _line;
+ var _col;
+ int _currentToken;
+
+ int _char(String str) => str.codeUnitAt(0);
+
+ void _initTokens() {
+ _line = 0;
+ _col = 0;
+ _currentToken = _source[_line].text.codeUnitAt(_col);
+ }
+
+ int _advanceToken([int num, stripWhite=true]) {
+ _col++;
+ if (_col >= _source[_line].text.codeUnits.length) {
+ var col = _col;
+ _col = 0;
+ _line++;
+ if (_line == _source.length) {
+ _line--;
+ _col = col;
+ _currentToken = 0;
+ return 0;
+ }
+ }
+
+ while (_source[_line].text.length == 0) { _line++; }
+ _currentToken = _source[_line].text.codeUnitAt(_col);
+ if (stripWhite && _currentToken == _char(' ')) {
+ _advanceToken();
+ }
+ if (num != null) {
+ for (int i = 1; i < num; i++) {
+ _advanceToken();
+ }
+ }
+ return _currentToken;
+ }
+
+ int _peek(int len, [stripWhite=true]) {
+ int saved_line = _line;
+ int saved_col = _col;
+ int c = _advanceToken(len,stripWhite);
+ _line = saved_line;
+ _col = saved_col;
+ return c;
+ }
+
+ void _consumeMultilineString(int quote) {
+ _advanceToken(3);
+ for (int c = _currentToken; c != 0; c = _advanceToken()) {
+ if (c == quote && _peek(1) == quote && _peek(2) == quote) {
+ _advanceToken(3);
+ break;
+ }
+ }
+ }
+
+ void _consumeString(int quote) {
+ _advanceToken();
+ for (int c = _currentToken; c != 0; c = _advanceToken()) {
+ if (c == _char('\\')) {
+ _advanceToken();
+ }
+ if (c == quote) {
+ _advanceToken();
+ break;
+ }
+ }
+ }
+
+ void _consumeComment() {
+ _col = _source[_line].text.codeUnits.length;
+ }
+
+ void _consumeMultilineComment() {
+ _advanceToken(2);
+ int commentLevel = 1;
+ for (int c = _currentToken; c != 0; c = _advanceToken()) {
+ if (c == _char('/') && _peek(1, false) == _char('*')) {
+ commentLevel++;
+ _advanceToken();
+ } else if (c == _char('*') && _peek(1, false) == _char('/')) {
+ commentLevel--;
+ _advanceToken();
+ if (commentLevel == 0) {
+ _advanceToken();
+ break;
+ }
+ }
+ }
+ }
+
+ /// Finds the end position, i.e., the closing curly brackets of the given
+ /// class.
+ /// Returns a tuple [line, col].
+ List findEndPos() {
+ int level = 0;
+ _initTokens();
+ for (int c = _currentToken; c != 0; c=_currentToken) {
+ if ((c == _char("'") &&
+ _peek(1) == _char("'") &&
+ _peek(2) == _char("'")) ||
+ (c == _char('"') &&
+ _peek(1) == _char('"') &&
+ _peek(2) == _char('"'))) {
+ _consumeMultilineString(c);
+ continue;
+ } else if (c == _char("'") || c == _char('"')) {
+ _consumeString(c);
+ continue;
+ } else if (c == _char('/') && _peek(1, false) == _char('/')) {
+ _consumeComment();
+ continue;
+ } else if (c == _char('/') && _peek(1, false) == _char('*')) {
+ _consumeMultilineComment();
+ continue;
+ } else if (c == _char('{')) {
+ level++;
+ } else if (c == _char('}')) {
+ if (--level == 0) {
+ break;
+ }
+ }
+ c = _advanceToken();
+ }
+ return [_line + _offset, _col + 1];
+ }
+}
+
class Class extends ServiceObject with Coverage {
@observable Library library;
@observable Script script;
@@ -1116,6 +1256,14 @@ class Class extends ServiceObject with Coverage {
@observable int tokenPos;
+ int _endTokenPos = null;
+ @observable int get endTokenPos {
+ if (_endTokenPos == null) {
+ _computeEndTokenPos();
+ }
+ return _endTokenPos;
+ }
+
@observable ServiceMap error;
final Allocations newSpace = new Allocations();
@@ -1201,6 +1349,26 @@ class Class extends ServiceObject with Coverage {
Future<ServiceObject> get(String command) {
return isolate.get(id + "/$command");
}
+
+ void _computeEndTokenPos() {
+ script.load().whenComplete(() {
+ int line = script.tokenToLine(tokenPos); // Lines are 1-based.
+ ClassParser clsp = new ClassParser(script.lines.sublist(line - 1));
+ List posTuple = clsp.findEndPos();
+ // Search for the token one this line and column.
+ List tokenCandidates = [];
+ script._tokenToLine.forEach((k,v) {
+ if (script._tokenToLine[k] == posTuple[0]) {
+ tokenCandidates.add(k);
+ }
+ });
+ Iterable tokenIndex =
+ tokenCandidates.where((e) => script._tokenToCol[e] == posTuple[1]);
+ assert(tokenIndex.length == 1);
+ _endTokenPos = tokenIndex.first;
+ notifyPropertyChange(#endTokenPos, null, _endTokenPos);
+ });
+ }
}
class ScriptLine extends Observable {
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/elements/class_view.html ('k') | runtime/bin/vmservice/client/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698