Index: tests/compiler/dart2js/equivalence/id_equivalence_helper.dart |
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart |
index 8aedb91c2fe7e1a8c30b29d20e9e5fe08fce1259..0219bc108ec5786d102e3b4c07812b95361532df 100644 |
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart |
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart |
@@ -27,8 +27,8 @@ typedef Future<Compiler> CompileFunction( |
/// |
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans |
/// for the data origin. |
-typedef void ComputeMemberDataFunction(Compiler compiler, MemberEntity member, |
- Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap, |
+typedef void ComputeMemberDataFunction( |
+ Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap, |
{bool verbose}); |
/// Compile [code] from .dart sources. |
@@ -67,8 +67,7 @@ Future<IdData> computeData( |
AnnotatedCode code = |
new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd); |
Map<Id, String> expectedMap = computeExpectedMap(code); |
- Map<Id, String> actualMap = <Id, String>{}; |
- Map<Id, SourceSpan> sourceSpanMap = <Id, SourceSpan>{}; |
+ Map<Id, ActualData> actualMap = <Id, ActualData>{}; |
Uri mainUri = Uri.parse('memory:main.dart'); |
Compiler compiler = await compileFunction(code, mainUri, options); |
ElementEnvironment elementEnvironment = |
@@ -78,30 +77,84 @@ Future<IdData> computeData( |
elementEnvironment.forEachClassMember(cls, |
(ClassEntity declarer, MemberEntity member) { |
if (cls == declarer) { |
- computeMemberData(compiler, member, actualMap, sourceSpanMap, |
- verbose: verbose); |
+ computeMemberData(compiler, member, actualMap, verbose: verbose); |
} |
}); |
}); |
elementEnvironment.forEachLibraryMember(mainLibrary, (MemberEntity member) { |
- computeMemberData(compiler, member, actualMap, sourceSpanMap, |
- verbose: verbose); |
+ computeMemberData(compiler, member, actualMap, verbose: verbose); |
}); |
- return new IdData(compiler, elementEnvironment, mainUri, expectedMap, |
- actualMap, sourceSpanMap); |
+ return new IdData( |
+ code, compiler, elementEnvironment, mainUri, expectedMap, actualMap); |
+} |
+ |
+class ActualData { |
+ final Id id; |
+ final String value; |
+ final SourceSpan sourceSpan; |
+ final Object object; |
+ |
+ ActualData(this.id, this.value, this.sourceSpan, this.object); |
} |
/// Data collected by [computeData]. |
class IdData { |
+ final AnnotatedCode code; |
final Compiler compiler; |
final ElementEnvironment elementEnvironment; |
final Uri mainUri; |
final Map<Id, String> expectedMap; |
- final Map<Id, String> actualMap; |
- final Map<Id, SourceSpan> sourceSpanMap; |
+ final Map<Id, ActualData> actualMap; |
+ |
+ IdData(this.code, this.compiler, this.elementEnvironment, this.mainUri, |
+ this.expectedMap, this.actualMap); |
+ |
+ String withAnnotations(Map<int, String> annotations) { |
+ StringBuffer sb = new StringBuffer(); |
+ int end = 0; |
+ for (int offset in annotations.keys.toList()..sort()) { |
+ if (offset > end) { |
+ sb.write(code.sourceCode.substring(end, offset)); |
+ } |
+ sb.write('/* '); |
+ sb.write(annotations[offset]); |
+ sb.write(' */'); |
+ end = offset; |
+ } |
+ if (end < code.sourceCode.length) { |
+ sb.write(code.sourceCode.substring(end)); |
+ } |
+ return sb.toString(); |
+ } |
- IdData(this.compiler, this.elementEnvironment, this.mainUri, this.expectedMap, |
- this.actualMap, this.sourceSpanMap); |
+ String get actualCode { |
+ Map<int, String> annotations = <int, String>{}; |
+ actualMap.forEach((Id id, ActualData data) { |
+ annotations[data.sourceSpan.begin] = data.value; |
+ }); |
+ return withAnnotations(annotations); |
+ } |
+ |
+ String get diffCode { |
+ Map<int, String> annotations = <int, String>{}; |
+ actualMap.forEach((Id id, ActualData data) { |
+ String expected = expectedMap[id]; |
+ if (data.value != expected) { |
+ expected ??= '---'; |
+ annotations[data.sourceSpan.begin] = '${expected} | ${data.value}'; |
+ } |
+ }); |
+ expectedMap.forEach((Id id, String expected) { |
+ if (!actualMap.containsKey(id)) { |
+ int offset = compiler.reporter |
+ .spanFromSpannable( |
+ computeSpannable(elementEnvironment, mainUri, id)) |
+ .begin; |
+ annotations[offset] = '${expected} | ---'; |
+ } |
+ }); |
+ return withAnnotations(annotations); |
+ } |
} |
/// Compiles the [annotatedCode] with the provided [options] and calls |
@@ -117,18 +170,32 @@ Future checkCode( |
annotatedCode, computeMemberData, compileFunction, |
options: options, verbose: verbose); |
- data.actualMap.forEach((Id id, String actual) { |
+ data.actualMap.forEach((Id id, ActualData actualData) { |
+ String actual = actualData.value; |
if (!data.expectedMap.containsKey(id)) { |
if (actual != '') { |
- reportHere(data.compiler.reporter, data.sourceSpanMap[id], |
- 'Id $id not expected in ${data.expectedMap.keys}'); |
+ reportHere( |
+ data.compiler.reporter, |
+ actualData.sourceSpan, |
+ 'Id $id for ${actualData.object} ' |
+ '(${actualData.object.runtimeType}) ' |
+ 'not expected in ${data.expectedMap.keys}'); |
+ print('--annotations diff--------------------------------------------'); |
+ print(data.diffCode); |
+ print('--------------------------------------------------------------'); |
} |
Expect.equals('', actual); |
} else { |
String expected = data.expectedMap.remove(id); |
if (actual != expected) { |
- reportHere(data.compiler.reporter, data.sourceSpanMap[id], |
- 'expected:${expected},actual:${actual}'); |
+ reportHere( |
+ data.compiler.reporter, |
+ actualData.sourceSpan, |
+ 'Object: ${actualData.object} (${actualData.object.runtimeType}), ' |
+ 'expected: ${expected}, actual: ${actual}'); |
+ print('--annotations diff--------------------------------------------'); |
+ print(data.diffCode); |
+ print('--------------------------------------------------------------'); |
} |
Expect.equals(expected, actual); |
} |
@@ -138,7 +205,7 @@ Future checkCode( |
reportHere( |
data.compiler.reporter, |
computeSpannable(data.elementEnvironment, data.mainUri, id), |
- 'expected:${expected},actual:null'); |
+ 'Expected $expected for id $id missing in ${data.actualMap.keys}'); |
}); |
Expect.isTrue( |
data.expectedMap.isEmpty, "Ids not found: ${data.expectedMap}."); |
@@ -184,13 +251,12 @@ Map<Id, String> computeExpectedMap(AnnotatedCode code) { |
/// Mixin used for computing [Id] data. |
abstract class ComputerMixin { |
- Map<Id, String> get actualMap; |
- Map<Id, SourceSpan> get sourceSpanMap; |
+ Map<Id, ActualData> get actualMap; |
- void registerValue(SourceSpan sourceSpan, Id id, String value) { |
+ void registerValue( |
+ SourceSpan sourceSpan, Id id, String value, Object object) { |
if (id != null && value != null) { |
- sourceSpanMap[id] = sourceSpan; |
- actualMap[id] = value; |
+ actualMap[id] = new ActualData(id, value, sourceSpan, object); |
} |
} |
} |
@@ -199,12 +265,10 @@ abstract class ComputerMixin { |
abstract class AbstractResolvedAstComputer extends ast.Visitor |
with AstEnumeratorMixin, ComputerMixin { |
final DiagnosticReporter reporter; |
- final Map<Id, String> actualMap; |
- final Map<Id, SourceSpan> sourceSpanMap; |
+ final Map<Id, ActualData> actualMap; |
final ResolvedAst resolvedAst; |
- AbstractResolvedAstComputer( |
- this.reporter, this.actualMap, this.sourceSpanMap, this.resolvedAst); |
+ AbstractResolvedAstComputer(this.reporter, this.actualMap, this.resolvedAst); |
TreeElements get elements => resolvedAst.elements; |
@@ -212,7 +276,7 @@ abstract class AbstractResolvedAstComputer extends ast.Visitor |
ElementId id = computeElementId(element); |
if (id == null) return; |
String value = computeElementValue(element); |
- registerValue(element.sourcePosition, id, value); |
+ registerValue(element.sourcePosition, id, value, element); |
} |
void computeForNode(ast.Node node, AstElement element) { |
@@ -221,7 +285,7 @@ abstract class AbstractResolvedAstComputer extends ast.Visitor |
String value = computeNodeValue(node, element); |
SourceSpan sourceSpan = new SourceSpan(resolvedAst.sourceUri, |
node.getBeginToken().charOffset, node.getEndToken().charEnd); |
- registerValue(sourceSpan, id, value); |
+ registerValue(sourceSpan, id, value, element ?? node); |
} |
String computeElementValue(AstElement element); |
@@ -274,23 +338,22 @@ abstract class AbstractResolvedAstComputer extends ast.Visitor |
/// Abstract IR visitor for computing [Id] data. |
abstract class AbstractIrComputer extends ir.Visitor |
with IrEnumeratorMixin, ComputerMixin { |
- final Map<Id, String> actualMap; |
- final Map<Id, SourceSpan> sourceSpanMap; |
+ final Map<Id, ActualData> actualMap; |
- AbstractIrComputer(this.actualMap, this.sourceSpanMap); |
+ AbstractIrComputer(this.actualMap); |
void computeForMember(ir.Member member) { |
ElementId id = computeElementId(member); |
if (id == null) return; |
String value = computeMemberValue(member); |
- registerValue(computeSpannable(member), id, value); |
+ registerValue(computeSpannable(member), id, value, member); |
} |
void computeForNode(ir.TreeNode node) { |
NodeId id = computeNodeId(node); |
if (id == null) return; |
String value = computeNodeValue(node); |
- registerValue(computeSpannable(node), id, value); |
+ registerValue(computeSpannable(node), id, value, node); |
} |
Spannable computeSpannable(ir.TreeNode node) { |