Skip to content

Commit 86b1b9d

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Enhance member depth completion metrics
This now looks in mixins (which were ignored before) and finds matches from interfaces, reporting the interfaces separately from the superclass and mixin chain. Change-Id: Id5f3379261e1ec184dc347abb371693481b65680 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135528 Reviewed-by: Jaime Wren <jwren@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
1 parent dd9adeb commit 86b1b9d

1 file changed

Lines changed: 58 additions & 9 deletions

File tree

pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import 'package:analyzer/dart/ast/ast.dart';
1515
import 'package:analyzer/dart/ast/token.dart';
1616
import 'package:analyzer/dart/ast/visitor.dart';
1717
import 'package:analyzer/dart/element/element.dart'
18-
show ClassElement, Element, LibraryElement, LocalElement;
18+
show ClassElement, Element, ExtensionElement, LibraryElement, LocalElement;
1919
import 'package:analyzer/dart/element/type.dart';
2020
import 'package:analyzer/dart/element/type_system.dart';
2121
import 'package:analyzer/diagnostic/diagnostic.dart';
@@ -1211,17 +1211,66 @@ class RelevanceDataCollector extends RecursiveAstVisitor<void> {
12111211
void _recordMemberDepth(DartType targetType, Element element) {
12121212
if (targetType is InterfaceType) {
12131213
var subclass = targetType.element;
1214+
var extension = element.thisOrAncestorOfType<ExtensionElement>();
1215+
if (extension != null) {
1216+
// TODO(brianwilkerson) It might be interesting to also know whether the
1217+
// [element] was found in a class, interface, mixin or extension.
1218+
return;
1219+
}
12141220
var superclass = element.thisOrAncestorOfType<ClassElement>();
12151221
if (superclass != null) {
1216-
var depth = 0;
1217-
while (subclass != null && subclass != superclass) {
1218-
depth++;
1219-
subclass = subclass.supertype?.element;
1222+
int getSuperclassDepth() {
1223+
var depth = 0;
1224+
var currentClass = subclass;
1225+
while (currentClass != null) {
1226+
if (currentClass == superclass) {
1227+
return depth;
1228+
}
1229+
for (var mixin in currentClass.mixins.reversed) {
1230+
depth++;
1231+
if (mixin.element == superclass) {
1232+
return depth;
1233+
}
1234+
}
1235+
depth++;
1236+
currentClass = currentClass.supertype?.element;
1237+
}
1238+
return -1;
1239+
}
1240+
1241+
var notFound = 0xFFFF;
1242+
int getInterfaceDepth(ClassElement currentClass) {
1243+
if (currentClass == null) {
1244+
return notFound;
1245+
} else if (currentClass == superclass) {
1246+
return 0;
1247+
}
1248+
var minDepth = getInterfaceDepth(currentClass.supertype?.element);
1249+
for (var mixin in currentClass.mixins) {
1250+
var depth = getInterfaceDepth(mixin.element);
1251+
if (depth < minDepth) {
1252+
minDepth = depth;
1253+
}
1254+
}
1255+
for (var interface in currentClass.interfaces) {
1256+
var depth = getInterfaceDepth(interface.element);
1257+
if (depth < minDepth) {
1258+
minDepth = depth;
1259+
}
1260+
}
1261+
return minDepth + 1;
12201262
}
1221-
// TODO(brianwilkerson) Handle the case where the member is defined in
1222-
// an interface not on the superclass chain.
1223-
if (subclass != null) {
1224-
_recordDistance('member', depth);
1263+
1264+
int superclassDepth = getSuperclassDepth();
1265+
if (superclassDepth >= 0) {
1266+
_recordDistance('member (superclass)', superclassDepth);
1267+
} else {
1268+
int interfaceDepth = getInterfaceDepth(subclass);
1269+
if (interfaceDepth < notFound) {
1270+
_recordDistance('member (interface)', interfaceDepth);
1271+
} else {
1272+
_recordDistance('member (not found)', 0);
1273+
}
12251274
}
12261275
}
12271276
}

0 commit comments

Comments
 (0)