OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'package:compiler/src/commandline_options.dart'; | 6 import 'package:compiler/src/commandline_options.dart'; |
7 import 'package:compiler/src/common.dart'; | 7 import 'package:compiler/src/common.dart'; |
8 import 'package:compiler/src/common_elements.dart'; | 8 import 'package:compiler/src/common_elements.dart'; |
9 import 'package:compiler/src/compiler.dart'; | 9 import 'package:compiler/src/compiler.dart'; |
10 import 'package:compiler/src/elements/elements.dart'; | |
11 import 'package:compiler/src/elements/entities.dart'; | 10 import 'package:compiler/src/elements/entities.dart'; |
12 import 'package:compiler/src/resolution/tree_elements.dart'; | |
13 import 'package:compiler/src/tree/nodes.dart' as ast; | |
14 import 'package:expect/expect.dart'; | 11 import 'package:expect/expect.dart'; |
15 import 'package:kernel/ast.dart' as ir; | |
16 | 12 |
17 import '../annotated_code_helper.dart'; | 13 import '../annotated_code_helper.dart'; |
18 import '../memory_compiler.dart'; | 14 import '../memory_compiler.dart'; |
19 import '../equivalence/id_equivalence.dart'; | 15 import '../equivalence/id_equivalence.dart'; |
20 import '../kernel/compiler_helper.dart'; | 16 import '../kernel/compiler_helper.dart'; |
21 | 17 |
22 /// Function that compiles [code] with [options] and returns the [Compiler] obje
ct. | 18 /// Function that compiles [code] with [options] and returns the [Compiler] obje
ct. |
23 typedef Future<Compiler> CompileFunction( | 19 typedef Future<Compiler> CompileFunction( |
24 AnnotatedCode code, Uri mainUri, List<String> options); | 20 AnnotatedCode code, Uri mainUri, List<String> options); |
25 | 21 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 } | 77 } |
82 }); | 78 }); |
83 }); | 79 }); |
84 elementEnvironment.forEachLibraryMember(mainLibrary, (MemberEntity member) { | 80 elementEnvironment.forEachLibraryMember(mainLibrary, (MemberEntity member) { |
85 computeMemberData(compiler, member, actualMap, verbose: verbose); | 81 computeMemberData(compiler, member, actualMap, verbose: verbose); |
86 }); | 82 }); |
87 return new IdData( | 83 return new IdData( |
88 code, compiler, elementEnvironment, mainUri, expectedMap, actualMap); | 84 code, compiler, elementEnvironment, mainUri, expectedMap, actualMap); |
89 } | 85 } |
90 | 86 |
91 class ActualData { | |
92 final Id id; | |
93 final String value; | |
94 final SourceSpan sourceSpan; | |
95 final Object object; | |
96 | |
97 ActualData(this.id, this.value, this.sourceSpan, this.object); | |
98 } | |
99 | |
100 /// Data collected by [computeData]. | 87 /// Data collected by [computeData]. |
101 class IdData { | 88 class IdData { |
102 final AnnotatedCode code; | 89 final AnnotatedCode code; |
103 final Compiler compiler; | 90 final Compiler compiler; |
104 final ElementEnvironment elementEnvironment; | 91 final ElementEnvironment elementEnvironment; |
105 final Uri mainUri; | 92 final Uri mainUri; |
106 final Map<Id, String> expectedMap; | 93 final Map<Id, String> expectedMap; |
107 final Map<Id, ActualData> actualMap; | 94 final Map<Id, ActualData> actualMap; |
108 | 95 |
109 IdData(this.code, this.compiler, this.elementEnvironment, this.mainUri, | 96 IdData(this.code, this.compiler, this.elementEnvironment, this.mainUri, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 if (!actualMap.containsKey(id)) { | 135 if (!actualMap.containsKey(id)) { |
149 int offset = compiler.reporter | 136 int offset = compiler.reporter |
150 .spanFromSpannable( | 137 .spanFromSpannable( |
151 computeSpannable(elementEnvironment, mainUri, id)) | 138 computeSpannable(elementEnvironment, mainUri, id)) |
152 .begin; | 139 .begin; |
153 annotations[offset] = '${expected} | ---'; | 140 annotations[offset] = '${expected} | ---'; |
154 } | 141 } |
155 }); | 142 }); |
156 return withAnnotations(annotations); | 143 return withAnnotations(annotations); |
157 } | 144 } |
| 145 |
| 146 String computeDiffCodeFor(IdData other) { |
| 147 Map<int, String> annotations = <int, String>{}; |
| 148 actualMap.forEach((Id id, ActualData data1) { |
| 149 ActualData data2 = other.actualMap[id]; |
| 150 if (data1.value != data2?.value) { |
| 151 annotations[data1.sourceSpan.begin] = |
| 152 '${data1.value} | ${data2?.value ?? '---'}'; |
| 153 } |
| 154 }); |
| 155 other.actualMap.forEach((Id id, ActualData data2) { |
| 156 if (!actualMap.containsKey(id)) { |
| 157 int offset = compiler.reporter |
| 158 .spanFromSpannable( |
| 159 computeSpannable(elementEnvironment, mainUri, id)) |
| 160 .begin; |
| 161 annotations[offset] = '--- | ${data2.value}'; |
| 162 } |
| 163 }); |
| 164 return withAnnotations(annotations); |
| 165 } |
158 } | 166 } |
159 | 167 |
160 /// Compiles the [annotatedCode] with the provided [options] and calls | 168 /// Compiles the [annotatedCode] with the provided [options] and calls |
161 /// [computeMemberData] for each member. The result is checked against the | 169 /// [computeMemberData] for each member. The result is checked against the |
162 /// expected data derived from [annotatedCode]. | 170 /// expected data derived from [annotatedCode]. |
163 Future checkCode( | 171 Future checkCode( |
164 String annotatedCode, | 172 String annotatedCode, |
165 ComputeMemberDataFunction computeMemberData, | 173 ComputeMemberDataFunction computeMemberData, |
166 CompileFunction compileFunction, | 174 CompileFunction compileFunction, |
167 {List<String> options: const <String>[], | 175 {List<String> options: const <String>[], |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 id = new NodeId(annotation.offset); | 249 id = new NodeId(annotation.offset); |
242 expected = text; | 250 expected = text; |
243 } else { | 251 } else { |
244 id = new ElementId(text.substring(0, colonPos)); | 252 id = new ElementId(text.substring(0, colonPos)); |
245 expected = text.substring(colonPos + 1); | 253 expected = text.substring(colonPos + 1); |
246 } | 254 } |
247 map[id] = expected; | 255 map[id] = expected; |
248 } | 256 } |
249 return map; | 257 return map; |
250 } | 258 } |
251 | |
252 /// Mixin used for computing [Id] data. | |
253 abstract class ComputerMixin { | |
254 Map<Id, ActualData> get actualMap; | |
255 | |
256 void registerValue( | |
257 SourceSpan sourceSpan, Id id, String value, Object object) { | |
258 if (id != null && value != null) { | |
259 actualMap[id] = new ActualData(id, value, sourceSpan, object); | |
260 } | |
261 } | |
262 } | |
263 | |
264 /// Abstract AST visitor for computing [Id] data. | |
265 abstract class AbstractResolvedAstComputer extends ast.Visitor | |
266 with AstEnumeratorMixin, ComputerMixin { | |
267 final DiagnosticReporter reporter; | |
268 final Map<Id, ActualData> actualMap; | |
269 final ResolvedAst resolvedAst; | |
270 | |
271 AbstractResolvedAstComputer(this.reporter, this.actualMap, this.resolvedAst); | |
272 | |
273 TreeElements get elements => resolvedAst.elements; | |
274 | |
275 void computeForElement(AstElement element) { | |
276 ElementId id = computeElementId(element); | |
277 if (id == null) return; | |
278 String value = computeElementValue(element); | |
279 registerValue(element.sourcePosition, id, value, element); | |
280 } | |
281 | |
282 void computeForNode(ast.Node node, AstElement element) { | |
283 NodeId id = computeNodeId(node, element); | |
284 if (id == null) return; | |
285 String value = computeNodeValue(node, element); | |
286 SourceSpan sourceSpan = new SourceSpan(resolvedAst.sourceUri, | |
287 node.getBeginToken().charOffset, node.getEndToken().charEnd); | |
288 registerValue(sourceSpan, id, value, element ?? node); | |
289 } | |
290 | |
291 String computeElementValue(AstElement element); | |
292 | |
293 String computeNodeValue(ast.Node node, AstElement element); | |
294 | |
295 void run() { | |
296 resolvedAst.node.accept(this); | |
297 } | |
298 | |
299 visitNode(ast.Node node) { | |
300 node.visitChildren(this); | |
301 } | |
302 | |
303 visitVariableDefinitions(ast.VariableDefinitions node) { | |
304 for (ast.Node child in node.definitions) { | |
305 AstElement element = elements[child]; | |
306 if (element == null) { | |
307 reportHere(reporter, child, 'No element for variable.'); | |
308 } else if (!element.isLocal) { | |
309 computeForElement(element); | |
310 } else { | |
311 computeForNode(child, element); | |
312 } | |
313 } | |
314 visitNode(node); | |
315 } | |
316 | |
317 visitFunctionExpression(ast.FunctionExpression node) { | |
318 AstElement element = elements.getFunctionDefinition(node); | |
319 if (!element.isLocal) { | |
320 computeForElement(element); | |
321 } else { | |
322 computeForNode(node, element); | |
323 } | |
324 visitNode(node); | |
325 } | |
326 | |
327 visitSend(ast.Send node) { | |
328 computeForNode(node, null); | |
329 visitNode(node); | |
330 } | |
331 | |
332 visitSendSet(ast.SendSet node) { | |
333 computeForNode(node, null); | |
334 visitNode(node); | |
335 } | |
336 } | |
337 | |
338 /// Abstract IR visitor for computing [Id] data. | |
339 abstract class AbstractIrComputer extends ir.Visitor | |
340 with IrEnumeratorMixin, ComputerMixin { | |
341 final Map<Id, ActualData> actualMap; | |
342 | |
343 AbstractIrComputer(this.actualMap); | |
344 | |
345 void computeForMember(ir.Member member) { | |
346 ElementId id = computeElementId(member); | |
347 if (id == null) return; | |
348 String value = computeMemberValue(member); | |
349 registerValue(computeSpannable(member), id, value, member); | |
350 } | |
351 | |
352 void computeForNode(ir.TreeNode node) { | |
353 NodeId id = computeNodeId(node); | |
354 if (id == null) return; | |
355 String value = computeNodeValue(node); | |
356 registerValue(computeSpannable(node), id, value, node); | |
357 } | |
358 | |
359 Spannable computeSpannable(ir.TreeNode node) { | |
360 return new SourceSpan( | |
361 Uri.parse(node.location.file), node.fileOffset, node.fileOffset + 1); | |
362 } | |
363 | |
364 String computeMemberValue(ir.Member member); | |
365 | |
366 String computeNodeValue(ir.TreeNode node); | |
367 | |
368 void run(ir.Node root) { | |
369 root.accept(this); | |
370 } | |
371 | |
372 defaultNode(ir.Node node) { | |
373 node.visitChildren(this); | |
374 } | |
375 | |
376 defaultMember(ir.Member node) { | |
377 computeForMember(node); | |
378 super.defaultMember(node); | |
379 } | |
380 | |
381 visitMethodInvocation(ir.MethodInvocation node) { | |
382 computeForNode(node); | |
383 super.visitMethodInvocation(node); | |
384 } | |
385 | |
386 visitPropertyGet(ir.PropertyGet node) { | |
387 computeForNode(node); | |
388 super.visitPropertyGet(node); | |
389 } | |
390 | |
391 visitVariableDeclaration(ir.VariableDeclaration node) { | |
392 computeForNode(node); | |
393 super.visitVariableDeclaration(node); | |
394 } | |
395 | |
396 visitFunctionDeclaration(ir.FunctionDeclaration node) { | |
397 computeForNode(node); | |
398 super.visitFunctionDeclaration(node); | |
399 } | |
400 | |
401 visitFunctionExpression(ir.FunctionExpression node) { | |
402 computeForNode(node); | |
403 super.visitFunctionExpression(node); | |
404 } | |
405 } | |
OLD | NEW |