Make extension methods more readable on dart2js stacktraces

Change-Id: I776b78c5a8742aad5ccc9aa4ffbc86827aacba96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118205
Commit-Queue: Sigmund Cherem <sigmund@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Sigmund Cherem 2019-09-20 19:01:36 +00:00 committed by commit-bot@chromium.org
parent 3f8c7e5fa2
commit ff0e8f8035
4 changed files with 106 additions and 1 deletions

View file

@ -42,6 +42,11 @@ String computeKernelElementNameForSourceMaps(
[CallStructure callStructure]) {
MemberDefinition definition = elementMap.getMemberDefinition(member);
switch (definition.kind) {
case MemberKind.regular:
ir.Member node = definition.node;
if (node.isExtensionMember) return _findExtensionMemberName(node);
return computeElementNameForSourceMaps(member, callStructure);
case MemberKind.closureCall:
ir.TreeNode node = definition.node;
String name;
@ -70,6 +75,32 @@ String computeKernelElementNameForSourceMaps(
}
}
/// Extract a simple readable name for an extension member.
String _findExtensionMemberName(ir.Member member) {
assert(member.isExtensionMember);
for (ir.Extension extension in member.enclosingLibrary.extensions) {
for (ir.ExtensionMemberDescriptor descriptor in extension.members) {
if (descriptor.member == member.reference) {
String extensionName;
// Anonymous extensions contain a # on their synthetic name.
if (extension.name.contains('#')) {
ir.DartType type = extension.onType;
if (type is ir.InterfaceType) {
extensionName = "${type.classNode.name}.<anonymous extension>";
} else {
extensionName = "<anonymous extension>";
}
} else {
extensionName = extension.name;
}
String memberName = descriptor.name.name;
return '$extensionName.$memberName';
}
}
}
throw StateError('No original name found for extension member $member.');
}
/// [SourceInformationBuilder] that generates [PositionSourceInformation] from
/// Kernel nodes.
class KernelSourceInformationBuilder implements SourceInformationBuilder {

View file

@ -16,7 +16,8 @@
"exclude": [
"^tests/compiler/dart2js/.*/data/.*",
"^tests/compiler/dart2js/.*/model_data/.*",
"^tests/compiler/dart2js/deferred_loading/libs/.*"
"^tests/compiler/dart2js/deferred_loading/libs/.*",
"^tests/compiler/dart2js/sourcemaps/stacktrace/extension_method.dart"
]
}
}

View file

@ -0,0 +1,72 @@
class MyClass {
MyClass();
@pragma('dart2js:noInline')
set internalSetter(int v) {
/*7:MyClass.internalSetter*/ throw "error";
}
}
int q = 3;
extension Ext on MyClass {
@pragma('dart2js:noInline')
int method() {
this./*6:Ext.method*/ internalSetter = 1;
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 29) return 3;
return 2;
}
@pragma('dart2js:noInline')
int get propertyB {
/*5:Ext.propertyB*/ method();
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 29) return 3;
return 2;
}
@pragma('dart2js:noInline')
set propertyA(int v) {
/*4:Ext.propertyA*/ propertyB;
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 29) return null;
return null;
}
@pragma('dart2js:noInline')
int operator+(int v) {
this./*3:Ext.+*/ propertyA = 2;
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 30) return 1;
return 3;
}
@pragma('dart2js:noInline')
int operator[](int v) {
this /*2:Ext.[]*/ + 2;
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 30) return 1;
return 3;
}
}
extension on MyClass {
@pragma('dart2js:noInline')
int method2() {
this/*1:MyClass.<anonymous extension>.method2*/[0];
// TODO(sigmund): remove once kernel preserves noInline pragmas. #38439
if (q > 29) return 3;
return 2;
}
}
@pragma('dart2js:noInline')
confuse(x) => x;
main() {
q++;
confuse(null);
MyClass x = confuse(new MyClass());
x. /*0:main*/method2();
}

View file

@ -85,6 +85,7 @@ Future runTest(Test test, String config,
'--libraries-spec=sdk/lib/libraries.json',
'--packages=${Platform.packageConfig}',
Flags.testMode,
'--enable-experiment=extension-methods',
input,
]..addAll(options);
print("Compiling dart2js ${arguments.join(' ')}");