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

Unified Diff: runtime/observatory/lib/src/debugger/debugger_location.dart

Issue 1393523002: Support tab completion of line:col in the debugger. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: edits Created 5 years, 2 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
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/script_inset.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/observatory/lib/src/debugger/debugger_location.dart
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index a517cd28ab3fada3c2508bc650be83517ad6461e..05645a39456f21a298f9842e0c32e52b2a338163 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -42,23 +42,29 @@ class DebuggerLocation {
"Invalid source location '${locDesc}'"));
}
- static Future<DebuggerLocation> _currentLocation(Debugger debugger) {
+ static Future<ServiceMap> _currentFrame(Debugger debugger) async {
ServiceMap stack = debugger.stack;
if (stack == null || stack['frames'].length == 0) {
- return new Future.value(new DebuggerLocation.error(
- 'A script must be provided when the stack is empty'));
+ return null;
+ }
+ return stack['frames'][debugger.currentFrame];
+ }
+
+ static Future<DebuggerLocation> _currentLocation(Debugger debugger) async {
+ var frame = await _currentFrame(debugger);
+ if (frame == null) {
+ return new DebuggerLocation.error(
+ 'A script must be provided when the stack is empty');
}
- var frame = stack['frames'][debugger.currentFrame];
Script script = frame.location.script;
- return script.load().then((_) {
- var line = script.tokenToLine(frame.location.tokenPos);
- var col = script.tokenToCol(frame.location.tokenPos);
- return new Future.value(new DebuggerLocation.file(script, line, col));
- });
+ await script.load();
+ var line = script.tokenToLine(frame.location.tokenPos);
+ var col = script.tokenToCol(frame.location.tokenPos);
+ return new DebuggerLocation.file(script, line, col);
}
static Future<DebuggerLocation> _parseScriptLine(Debugger debugger,
- Match match) {
+ Match match) async {
var scriptName = match.group(1);
if (scriptName != null) {
scriptName = scriptName.substring(0, scriptName.length - 1);
@@ -84,28 +90,25 @@ class DebuggerLocation {
if (scriptName != null) {
// Resolve the script.
- return _lookupScript(debugger.isolate, scriptName).then((scripts) {
- if (scripts.length == 0) {
- return new DebuggerLocation.error("Script '${scriptName}' not found");
- } else if (scripts.length == 1) {
- return new DebuggerLocation.file(scripts[0], line, col);
- } else {
- // TODO(turnidge): Allow the user to disambiguate.
- return new DebuggerLocation.error("Script '${scriptName}' is ambigous");
- }
- });
+ var scripts = await _lookupScript(debugger.isolate, scriptName);
+ if (scripts.length == 0) {
+ return new DebuggerLocation.error("Script '${scriptName}' not found");
+ } else if (scripts.length == 1) {
+ return new DebuggerLocation.file(scripts[0], line, col);
+ } else {
+ // TODO(turnidge): Allow the user to disambiguate.
+ return new DebuggerLocation.error("Script '${scriptName}' is ambigous");
+ }
} else {
// No script provided. Default to top of stack for now.
- ServiceMap stack = debugger.stack;
- if (stack == null || stack['frames'].length == 0) {
+ var frame = await _currentFrame(debugger);
+ if (frame == null) {
return new Future.value(new DebuggerLocation.error(
'A script must be provided when the stack is empty'));
}
- var frame = stack['frames'][debugger.currentFrame];
Script script = frame.location.script;
- return script.load().then((_) {
- return new Future.value(new DebuggerLocation.file(script, line, col));
- });
+ await script.load();
+ return new DebuggerLocation.file(script, line, col);
}
}
@@ -161,6 +164,9 @@ class DebuggerLocation {
static Future<List<Class>> _lookupClass(Isolate isolate,
String name,
{ bool allowPrefix: false }) {
+ if (isolate == null) {
+ return [];
+ }
var pending = [];
for (var lib in isolate.libraries) {
assert(lib.loaded);
@@ -255,7 +261,7 @@ class DebuggerLocation {
}
static RegExp partialSourceLocMatcher =
- new RegExp(r'^([^\d:]?[^:]+[:]?)?(\d+)?([:]\d+)?');
+ new RegExp(r'^([^\d:]?[^:]+[:]?)?(\d+)?([:]\d*)?');
static RegExp partialFunctionMatcher = new RegExp(r'^([^.]*)([.][^.]*)?');
/// Completes a partial source location description.
@@ -326,25 +332,105 @@ class DebuggerLocation {
}
}
- static Future<List<String>> _completeFile(Debugger debugger, Match match) {
- var scriptName = match.group(1);
- var lineStr = match.group(2);
- var colStr = match.group(3);
- if (lineStr != null || colStr != null) {
- // TODO(turnidge): Complete valid line and column numbers.
- return new Future.value([]);
+ static bool _startsWithDigit(String s) {
+ return '0'.compareTo(s[0]) <= 0 && '9'.compareTo(s[0]) >= 0;
+ }
+
+ static Future<List<String>> _completeFile(
+ Debugger debugger, Match match) async {
+ var scriptName;
+ var scriptNameComplete = false;
+ var lineStr;
+ var lineStrComplete = false;
+ var colStr;
+ if (_startsWithDigit(match.group(1))) {
+ // CASE 1: We have matched a prefix of (lineStr:)(colStr)
+ var frame = await _currentFrame(debugger);
+ if (frame == null) {
+ return [];
+ }
+ scriptName = frame.location.script.name;
+ scriptNameComplete = true;
+ lineStr = match.group(1);
+ lineStr = (lineStr == null ? '' : lineStr);
Cutch 2015/10/06 18:08:16 lineStr ?= '';
turnidge 2015/10/06 18:33:37 Done.
+ if (lineStr.endsWith(':')) {
+ lineStr = lineStr.substring(0, lineStr.length - 1);
+ lineStrComplete = true;
+ }
+ colStr = match.group(2);
+ colStr = (colStr == null ? '' : colStr);
Cutch 2015/10/06 18:08:16 colStr ?= '';
turnidge 2015/10/06 18:33:37 Done.
+ } else {
+ // CASE 2: We have matched a prefix of (scriptName:)(lineStr)(:colStr)
+ scriptName = match.group(1);
+ scriptName = (scriptName == null ? '' : scriptName);
+ if (scriptName.endsWith(':')) {
Cutch 2015/10/06 18:08:16 Not necessarily an issue for the current CL but co
turnidge 2015/10/06 18:33:37 True. Currently the script name that we use is ju
+ scriptName = scriptName.substring(0, scriptName.length - 1);
+ scriptNameComplete = true;
+ }
+ lineStr = match.group(2);
+ lineStr = (lineStr == null ? '' : lineStr);
+ colStr = match.group(3);
+ colStr = (colStr == null ? '' : colStr);
+ if (colStr.startsWith(':')) {
+ lineStrComplete = true;
+ colStr = colStr.substring(1);
+ }
}
- scriptName = (scriptName == null ? '' : scriptName);
- return _lookupScript(debugger.isolate, scriptName, allowPrefix:true)
- .then((scripts) {
+ if (!scriptNameComplete) {
+ // The script name is incomplete. Complete it.
+ var scripts =
+ await _lookupScript(debugger.isolate, scriptName, allowPrefix:true);
+ List completions = [];
+ for (var script in scripts) {
+ completions.add(script.name + ':');
+ }
+ completions.sort();
+ return completions;
+
+ } else {
+ // The script name is complete. Look it up.
+ var scripts =
+ await _lookupScript(debugger.isolate, scriptName, allowPrefix:false);
+ if (scripts.isEmpty) {
+ return [];
+ }
+ var script = scripts[0];
+ await script.load();
+ if (!lineStrComplete) {
+ // Complete the line.
+ var sharedPrefix = '${script.name}:';
List completions = [];
- for (var script in scripts) {
- completions.add(script.name + ':');
+ for (var line in script.lines) {
+ if (line.possibleBpt) {
+ var currentLineStr = line.line.toString();
+ if (currentLineStr.startsWith(lineStr)) {
+ completions.add('${sharedPrefix}${currentLineStr} ');
+ completions.add('${sharedPrefix}${currentLineStr}:');
+ }
+ }
}
- completions.sort();
return completions;
- });
+
+ } else {
+ // Complete the column.
+ int lineNum = int.parse(lineStr);
+ var scriptLine = script.getLine(lineNum);
+ if (!scriptLine.possibleBpt) {
+ return [];
+ }
+ var sharedPrefix = '${script.name}:${lineStr}:';
+ List completions = [];
+ int maxCol = scriptLine.text.runes.length;
+ for (int i = 1; i <= maxCol; i++) {
+ var currentColStr = i.toString();
+ if (currentColStr.startsWith(colStr)) {
+ completions.add('${sharedPrefix}${currentColStr} ');
+ }
+ }
+ return completions;
+ }
+ }
}
String toString() {
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/script_inset.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698