| Index: runtime/observatory/lib/src/service/object.dart
|
| diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
|
| index b0876e07cdae0a1cd2a86c092dc56b60cd5cc804..fb119f8c5f13019029c6488c05491876aa0fb8eb 100644
|
| --- a/runtime/observatory/lib/src/service/object.dart
|
| +++ b/runtime/observatory/lib/src/service/object.dart
|
| @@ -1830,7 +1830,15 @@ class Instance extends ServiceObject {
|
| _loaded = true;
|
| }
|
|
|
| - String get shortName => valueAsString != null ? valueAsString : 'a ${clazz.name}';
|
| + String get shortName {
|
| + if (isClosure) {
|
| + return closureFunc.qualifiedName;
|
| + }
|
| + if (valueAsString != null) {
|
| + return valueAsString;
|
| + }
|
| + return 'a ${clazz.name}';
|
| + }
|
|
|
| String toString() => 'Instance($shortName)';
|
| }
|
| @@ -2068,6 +2076,8 @@ class ScriptLine extends Observable {
|
| }
|
| bool _isBlank;
|
|
|
| + bool get isTrivialLine => !possibleBpt;
|
| +
|
| static bool _isTrivialToken(String token) {
|
| if (token == 'else') {
|
| return true;
|
| @@ -2088,6 +2098,9 @@ class ScriptLine extends Observable {
|
| }
|
|
|
| static bool _isTrivialLine(String text) {
|
| + if (text.trimLeft().startsWith('//')) {
|
| + return true;
|
| + }
|
| var wsTokens = text.split(new RegExp(r"(\s)+"));
|
| for (var wsToken in wsTokens) {
|
| var tokens = wsToken.split(new RegExp(r"(\b)"));
|
| @@ -2175,6 +2188,14 @@ class CallSiteEntry {
|
| String toString() => "CallSiteEntry(${receiverContainer.name}, $count)";
|
| }
|
|
|
| +/// The location of a local variable reference in a script.
|
| +class LocalVarLocation {
|
| + final int line;
|
| + final int column;
|
| + final int endColumn;
|
| + LocalVarLocation(this.line, this.column, this.endColumn);
|
| +}
|
| +
|
| class Script extends ServiceObject with Coverage {
|
| Set<CallSite> callSites = new Set<CallSite>();
|
| final lines = new ObservableList<ScriptLine>();
|
| @@ -2331,6 +2352,120 @@ class Script extends ServiceObject with Coverage {
|
| getLine(line).removeBreakpoint(bpt);
|
| }
|
| }
|
| +
|
| + List<LocalVarLocation> scanLineForLocalVariableLocations(Pattern pattern,
|
| + String name,
|
| + String lineContents,
|
| + int lineNumber,
|
| + int columnOffset) {
|
| + var r = <LocalVarLocation>[];
|
| +
|
| + pattern.allMatches(lineContents).forEach((Match match) {
|
| + // We have a match but our regular expression may have matched extra
|
| + // characters on either side of the name. Tighten the location.
|
| + var nameStart = match.input.indexOf(name, match.start);
|
| + var column = nameStart + columnOffset;
|
| + var endColumn = column + name.length;
|
| + var localVarLocation = new LocalVarLocation(lineNumber,
|
| + column,
|
| + endColumn);
|
| + r.add(localVarLocation);
|
| + });
|
| +
|
| + return r;
|
| + }
|
| +
|
| + List<LocalVarLocation> scanForLocalVariableLocations(String name,
|
| + int tokenPos,
|
| + int endTokenPos) {
|
| + // A pattern that matches:
|
| + // start of line OR non-(alpha numeric OR period) character followed by
|
| + // name followed by
|
| + // a non-alpha numerc character.
|
| + //
|
| + // NOTE: This pattern can over match on both ends. This is corrected for
|
| + // [scanLineForLocalVariableLocationse].
|
| + var pattern = new RegExp("(^|[^A-Za-z0-9\.])$name[^A-Za-z0-9]");
|
| +
|
| + // Result.
|
| + var r = <LocalVarLocation>[];
|
| +
|
| + // Limits.
|
| + final lastLine = tokenToLine(endTokenPos);
|
| + if (lastLine == null) {
|
| + return r;
|
| + }
|
| +
|
| + final lastColumn = tokenToCol(endTokenPos);
|
| + if (lastColumn == null) {
|
| + return r;
|
| + }
|
| + // Current scan position.
|
| + var line = tokenToLine(tokenPos);
|
| + if (line == null) {
|
| + return r;
|
| + }
|
| + var column = tokenToCol(tokenPos);
|
| + if (column == null) {
|
| + return r;
|
| + }
|
| +
|
| + // Move back by name length.
|
| + // TODO(johnmccutchan): Fix LocalVarDescriptor to set column before the
|
| + // identifier name.
|
| + column = math.max(0, column - name.length);
|
| +
|
| + var lineContents;
|
| +
|
| + if (line == lastLine) {
|
| + // Only one line.
|
| + if (!getLine(line).isTrivialLine) {
|
| + lineContents = getLine(line).text.substring(column, lastColumn - 1);
|
| + return scanLineForLocalVariableLocations(pattern,
|
| + name,
|
| + lineContents,
|
| + line,
|
| + column);
|
| + }
|
| + }
|
| +
|
| + // Scan first line.
|
| + if (!getLine(line).isTrivialLine) {
|
| + lineContents = getLine(line).text.substring(column);
|
| + r.addAll(scanLineForLocalVariableLocations(pattern,
|
| + name,
|
| + lineContents,
|
| + line++,
|
| + column));
|
| + }
|
| +
|
| + // Scan middle lines.
|
| + while (line < (lastLine - 1)) {
|
| + if (getLine(line).isTrivialLine) {
|
| + line++;
|
| + continue;
|
| + }
|
| + lineContents = getLine(line).text;
|
| + r.addAll(
|
| + scanLineForLocalVariableLocations(pattern,
|
| + name,
|
| + lineContents,
|
| + line++,
|
| + 0));
|
| + }
|
| +
|
| + // Scan last line.
|
| + if (!getLine(line).isTrivialLine) {
|
| + lineContents = getLine(line).text.substring(0, lastColumn - 1);
|
| + r.addAll(
|
| + scanLineForLocalVariableLocations(pattern,
|
| + name,
|
| + lineContents,
|
| + line,
|
| + 0));
|
| + }
|
| + return r;
|
| + }
|
| }
|
|
|
| class PcDescriptor extends Observable {
|
|
|