[kernel/DDC] Fix failing DDC tests; if finding no scope for offset find for a close previous offset instead
When landing https://dart-review.googlesource.com/c/sdk/+/342400
the ddc-mac builder (but not Linux and Windows) started failing.
I could reproduce on Linux though so I'm not sure why those builders
didn't fail (nor why it wasn't caught by the try bot), either way this
fixes the issues:
* Test update: E.g. a breakpoint at the end of the scope doesn't work
because it will not be inside the (wanted) scope.
* Test update: Evalating "this" now actually works.
* Scope finding update: DDC adds sourcemapping entries for the *end* of
things so e.g. the getter "c" will have offset and offset+1 added as
source mappings. When translating from javascript position to dart
position we might pick that and thus ask for the scope of offset+1,
but nothing will be found because no node has that offset.
Here I add a fall-back saying that if we get no results we ask again
for the nearest lower offset.
Change-Id: I7e4430d9954466494b514cf51d999358483c9f8c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345501
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Anna Gringauze <annagrin@google.com>
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 2310cdf..0a35a3d 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -806,6 +806,7 @@
List<int> list = [];
list.add(0);
// Breakpoint: bp
+ print(list);
}
''';
@@ -854,7 +855,7 @@
await driver.checkInFrame(
breakpointId: 'bp',
expression: 'typo',
- expectedError: "Error: Undefined name 'typo'");
+ expectedError: "Error: The getter 'typo' isn't defined");
});
test('local (trimmed scope)', () async {
@@ -863,13 +864,8 @@
});
test('this (full scope)', () async {
- // Note: this currently fails due to
- // - incremental compiler not mapping 'this' from user input to '#this'
- // - incremental compiler not allowing #this as a parameter name
await driver.checkInFrame(
- breakpointId: 'bp',
- expression: 'this',
- expectedError: "Error: Expected identifier, but got 'this'");
+ breakpointId: 'bp', expression: 'this', expectedResult: '1234');
});
test('scope', () async {
diff --git a/pkg/kernel/lib/dart_scope_calculator.dart b/pkg/kernel/lib/dart_scope_calculator.dart
index 8b645eb..8d46f0e 100644
--- a/pkg/kernel/lib/dart_scope_calculator.dart
+++ b/pkg/kernel/lib/dart_scope_calculator.dart
@@ -262,6 +262,7 @@
final Uri _scriptUri;
final int _offset;
final List<DartScope2> findScopes = [];
+ final Set<int> foundOffsets = {};
final Set<VariableDeclaration> hoistedUnwritten = {};
final List<List<VariableDeclaration>> scopes = [];
@@ -537,12 +538,14 @@
void _checkOffset(TreeNode node) {
if (_currentUri == _scriptUri) {
+ foundOffsets.add(node.fileOffset);
if (node.fileOffset == _offset) {
addFound(node);
} else {
List<int>? allOffsets = node.fileOffsetsIfMultiple;
if (allOffsets != null) {
for (final int offset in allOffsets) {
+ foundOffsets.add(offset);
if (offset == _offset) {
addFound(node);
break;
@@ -555,8 +558,36 @@
static DartScope findScopeFromOffsetAndClass(
Library library, Uri scriptUri, Class? cls, int offset) {
- List<DartScope2> scopes = _raw(library, scriptUri, cls, offset);
- return _findScopePick(scopes, library, cls, offset);
+ DartScopeBuilder2 data = _raw(library, scriptUri, cls, offset);
+ if (data.findScopes.isEmpty) {
+ int? closestMatchingOrSmallerOffset =
+ _findClosestMatchingOrSmallerOffset(data, offset);
+ if (closestMatchingOrSmallerOffset != null) {
+ offset = closestMatchingOrSmallerOffset;
+ data = _raw(library, scriptUri, cls, offset);
+ }
+ }
+ return _findScopePick(data.findScopes, library, cls, offset);
+ }
+
+ static int? _findClosestMatchingOrSmallerOffset(
+ DartScopeBuilder2 data, int offset) {
+ List<int> foundOffsets = data.foundOffsets.toList()..sort();
+ if (foundOffsets.isEmpty) return null;
+ int low = 0;
+ int high = foundOffsets.length - 1;
+ while (low < high) {
+ int mid = high - ((high - low) >> 1); // Get middle, rounding up.
+ int pivot = foundOffsets[mid];
+ if (pivot <= offset) {
+ low = mid;
+ } else {
+ high = mid - 1;
+ }
+ }
+ int result = foundOffsets[low];
+ if (result < 0) return null;
+ return result;
}
static DartScope _findScopePick(
@@ -593,8 +624,16 @@
static DartScope findScopeFromOffset(
Library library, Uri scriptUri, int offset) {
- List<DartScope2> scopes = _rawNoClass(library, scriptUri, offset);
- return _findScopePick(scopes, library, null, offset);
+ DartScopeBuilder2 data = _rawNoClass(library, scriptUri, offset);
+ if (data.findScopes.isEmpty) {
+ int? closestMatchingOrSmallerOffset =
+ _findClosestMatchingOrSmallerOffset(data, offset);
+ if (closestMatchingOrSmallerOffset != null) {
+ offset = closestMatchingOrSmallerOffset;
+ data = _rawNoClass(library, scriptUri, offset);
+ }
+ }
+ return _findScopePick(data.findScopes, library, null, offset);
}
static List<DartScope2> _filterAll(
@@ -1153,7 +1192,7 @@
return null;
}
- static List<DartScope2> _raw(
+ static DartScopeBuilder2 _raw(
Library library, Uri scriptUri, Class? cls, int offset) {
DartScopeBuilder2 builder = DartScopeBuilder2._(library, scriptUri, offset);
if (cls != null) {
@@ -1163,17 +1202,17 @@
builder.visitLibrary(library);
}
- return builder.findScopes;
+ return builder;
}
- static List<DartScope2> _rawNoClass(
+ static DartScopeBuilder2 _rawNoClass(
Library library, Uri scriptUri, int offset) {
DartScopeBuilder2 builder = DartScopeBuilder2._(library, scriptUri, offset);
builder.visitLibrary(library);
- return builder.findScopes;
+ return builder;
}
static List<DartScope2> findScopeFromOffsetAndClassRawForTesting(
Library library, Uri scriptUri, Class? cls, int offset) =>
- _raw(library, scriptUri, cls, offset);
+ _raw(library, scriptUri, cls, offset).findScopes;
}