Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: packages/analyzer/test/generated/resolver_test_case.dart

Issue 2990843002: Removed fixed dependencies (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4
5 library analyzer.test.generated.resolver_test_case;
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/ast/visitor.dart';
9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart';
11 import 'package:analyzer/error/error.dart';
12 import 'package:analyzer/file_system/memory_file_system.dart';
13 import 'package:analyzer/src/dart/element/element.dart';
14 import 'package:analyzer/src/dart/element/type.dart';
15 import 'package:analyzer/src/error/codes.dart';
16 import 'package:analyzer/src/generated/engine.dart';
17 import 'package:analyzer/src/generated/java_engine.dart';
18 import 'package:analyzer/src/generated/resolver.dart';
19 import 'package:analyzer/src/generated/source_io.dart';
20 import 'package:analyzer/src/generated/testing/ast_factory.dart';
21 import 'package:analyzer/src/generated/testing/element_factory.dart';
22 import 'package:unittest/unittest.dart';
23
24 import 'analysis_context_factory.dart';
25 import 'test_support.dart';
26
27 /**
28 * An AST visitor used to verify that all of the nodes in an AST structure that
29 * should have been resolved were resolved.
30 */
31 class ResolutionVerifier extends RecursiveAstVisitor<Object> {
32 /**
33 * A set containing nodes that are known to not be resolvable and should
34 * therefore not cause the test to fail.
35 */
36 final Set<AstNode> _knownExceptions;
37
38 /**
39 * A list containing all of the AST nodes that were not resolved.
40 */
41 List<AstNode> _unresolvedNodes = new List<AstNode>();
42
43 /**
44 * A list containing all of the AST nodes that were resolved to an element of
45 * the wrong type.
46 */
47 List<AstNode> _wrongTypedNodes = new List<AstNode>();
48
49 /**
50 * Initialize a newly created verifier to verify that all of the identifiers
51 * in the visited AST structures that are expected to have been resolved have
52 * an element associated with them. Nodes in the set of [_knownExceptions] are
53 * not expected to have been resolved, even if they normally would have been
54 * expected to have been resolved.
55 */
56 ResolutionVerifier([this._knownExceptions]);
57
58 /**
59 * Assert that all of the visited identifiers were resolved.
60 */
61 void assertResolved() {
62 if (!_unresolvedNodes.isEmpty || !_wrongTypedNodes.isEmpty) {
63 StringBuffer buffer = new StringBuffer();
64 if (!_unresolvedNodes.isEmpty) {
65 buffer.write("Failed to resolve ");
66 buffer.write(_unresolvedNodes.length);
67 buffer.writeln(" nodes:");
68 _printNodes(buffer, _unresolvedNodes);
69 }
70 if (!_wrongTypedNodes.isEmpty) {
71 buffer.write("Resolved ");
72 buffer.write(_wrongTypedNodes.length);
73 buffer.writeln(" to the wrong type of element:");
74 _printNodes(buffer, _wrongTypedNodes);
75 }
76 fail(buffer.toString());
77 }
78 }
79
80 @override
81 Object visitAnnotation(Annotation node) {
82 node.visitChildren(this);
83 ElementAnnotation elementAnnotation = node.elementAnnotation;
84 if (elementAnnotation == null) {
85 if (_knownExceptions == null || !_knownExceptions.contains(node)) {
86 _unresolvedNodes.add(node);
87 }
88 } else if (elementAnnotation is! ElementAnnotation) {
89 _wrongTypedNodes.add(node);
90 }
91 return null;
92 }
93
94 @override
95 Object visitBinaryExpression(BinaryExpression node) {
96 node.visitChildren(this);
97 if (!node.operator.isUserDefinableOperator) {
98 return null;
99 }
100 DartType operandType = node.leftOperand.staticType;
101 if (operandType == null || operandType.isDynamic) {
102 return null;
103 }
104 return _checkResolved(
105 node, node.staticElement, (node) => node is MethodElement);
106 }
107
108 @override
109 Object visitCommentReference(CommentReference node) => null;
110
111 @override
112 Object visitCompilationUnit(CompilationUnit node) {
113 node.visitChildren(this);
114 return _checkResolved(
115 node, node.element, (node) => node is CompilationUnitElement);
116 }
117
118 @override
119 Object visitExportDirective(ExportDirective node) =>
120 _checkResolved(node, node.element, (node) => node is ExportElement);
121
122 @override
123 Object visitFunctionDeclaration(FunctionDeclaration node) {
124 node.visitChildren(this);
125 if (node.element is LibraryElement) {
126 _wrongTypedNodes.add(node);
127 }
128 return null;
129 }
130
131 @override
132 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
133 node.visitChildren(this);
134 // TODO(brianwilkerson) If we start resolving function expressions, then
135 // conditionally check to see whether the node was resolved correctly.
136 return null;
137 //checkResolved(node, node.getElement(), FunctionElement.class);
138 }
139
140 @override
141 Object visitImportDirective(ImportDirective node) {
142 // Not sure how to test the combinators given that it isn't an error if the
143 // names are not defined.
144 _checkResolved(node, node.element, (node) => node is ImportElement);
145 SimpleIdentifier prefix = node.prefix;
146 if (prefix == null) {
147 return null;
148 }
149 return _checkResolved(
150 prefix, prefix.staticElement, (node) => node is PrefixElement);
151 }
152
153 @override
154 Object visitIndexExpression(IndexExpression node) {
155 node.visitChildren(this);
156 DartType targetType = node.realTarget.staticType;
157 if (targetType == null || targetType.isDynamic) {
158 return null;
159 }
160 return _checkResolved(
161 node, node.staticElement, (node) => node is MethodElement);
162 }
163
164 @override
165 Object visitLibraryDirective(LibraryDirective node) =>
166 _checkResolved(node, node.element, (node) => node is LibraryElement);
167
168 @override
169 Object visitNamedExpression(NamedExpression node) =>
170 node.expression.accept(this);
171
172 @override
173 Object visitPartDirective(PartDirective node) => _checkResolved(
174 node, node.element, (node) => node is CompilationUnitElement);
175
176 @override
177 Object visitPartOfDirective(PartOfDirective node) =>
178 _checkResolved(node, node.element, (node) => node is LibraryElement);
179
180 @override
181 Object visitPostfixExpression(PostfixExpression node) {
182 node.visitChildren(this);
183 if (!node.operator.isUserDefinableOperator) {
184 return null;
185 }
186 DartType operandType = node.operand.staticType;
187 if (operandType == null || operandType.isDynamic) {
188 return null;
189 }
190 return _checkResolved(
191 node, node.staticElement, (node) => node is MethodElement);
192 }
193
194 @override
195 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
196 SimpleIdentifier prefix = node.prefix;
197 prefix.accept(this);
198 DartType prefixType = prefix.staticType;
199 if (prefixType == null || prefixType.isDynamic) {
200 return null;
201 }
202 return _checkResolved(node, node.staticElement, null);
203 }
204
205 @override
206 Object visitPrefixExpression(PrefixExpression node) {
207 node.visitChildren(this);
208 if (!node.operator.isUserDefinableOperator) {
209 return null;
210 }
211 DartType operandType = node.operand.staticType;
212 if (operandType == null || operandType.isDynamic) {
213 return null;
214 }
215 return _checkResolved(
216 node, node.staticElement, (node) => node is MethodElement);
217 }
218
219 @override
220 Object visitPropertyAccess(PropertyAccess node) {
221 Expression target = node.realTarget;
222 target.accept(this);
223 DartType targetType = target.staticType;
224 if (targetType == null || targetType.isDynamic) {
225 return null;
226 }
227 return node.propertyName.accept(this);
228 }
229
230 @override
231 Object visitSimpleIdentifier(SimpleIdentifier node) {
232 if (node.name == "void") {
233 return null;
234 }
235 if (node.staticType != null &&
236 node.staticType.isDynamic &&
237 node.staticElement == null) {
238 return null;
239 }
240 AstNode parent = node.parent;
241 if (parent is MethodInvocation) {
242 MethodInvocation invocation = parent;
243 if (identical(invocation.methodName, node)) {
244 Expression target = invocation.realTarget;
245 DartType targetType = target == null ? null : target.staticType;
246 if (targetType == null || targetType.isDynamic) {
247 return null;
248 }
249 }
250 }
251 return _checkResolved(node, node.staticElement, null);
252 }
253
254 Object _checkResolved(
255 AstNode node, Element element, Predicate<Element> predicate) {
256 if (element == null) {
257 if (_knownExceptions == null || !_knownExceptions.contains(node)) {
258 _unresolvedNodes.add(node);
259 }
260 } else if (predicate != null) {
261 if (!predicate(element)) {
262 _wrongTypedNodes.add(node);
263 }
264 }
265 return null;
266 }
267
268 String _getFileName(AstNode node) {
269 // TODO (jwren) there are two copies of this method, one here and one in
270 // StaticTypeVerifier, they should be resolved into a single method
271 if (node != null) {
272 AstNode root = node.root;
273 if (root is CompilationUnit) {
274 CompilationUnit rootCU = root;
275 if (rootCU.element != null) {
276 return rootCU.element.source.fullName;
277 } else {
278 return "<unknown file- CompilationUnit.getElement() returned null>";
279 }
280 } else {
281 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni t>";
282 }
283 }
284 return "<unknown file- ASTNode is null>";
285 }
286
287 void _printNodes(StringBuffer buffer, List<AstNode> nodes) {
288 for (AstNode identifier in nodes) {
289 buffer.write(" ");
290 buffer.write(identifier.toString());
291 buffer.write(" (");
292 buffer.write(_getFileName(identifier));
293 buffer.write(" : ");
294 buffer.write(identifier.offset);
295 buffer.writeln(")");
296 }
297 }
298 }
299
300 class ResolverTestCase extends EngineTestCase {
301 /**
302 * The resource provider used by the test case.
303 */
304 MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
305
306 /**
307 * The analysis context used to parse the compilation units being resolved.
308 */
309 InternalAnalysisContext analysisContext2;
310
311 /**
312 * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and
313 * [HintCode.UNUSED_FIELD].
314 */
315 bool enableUnusedElement = false;
316
317 /**
318 * Specifies if [assertErrors] should check for [HintCode.UNUSED_LOCAL_VARIABL E].
319 */
320 bool enableUnusedLocalVariable = false;
321
322 AnalysisContext get analysisContext => analysisContext2;
323
324 /**
325 * Return a type provider that can be used to test the results of resolution.
326 *
327 * @return a type provider
328 * @throws AnalysisException if dart:core cannot be resolved
329 */
330 TypeProvider get typeProvider => analysisContext2.typeProvider;
331
332 /**
333 * Return a type system that can be used to test the results of resolution.
334 *
335 * @return a type system
336 */
337 TypeSystem get typeSystem => analysisContext2.typeSystem;
338
339 /**
340 * Add a source file with the given [filePath] in the root of the file system.
341 * The file path should be absolute. The file will have the given [contents]
342 * set in the content provider. Return the source representing the added file.
343 */
344 Source addNamedSource(String filePath, String contents) {
345 Source source =
346 cacheSource(resourceProvider.convertPath(filePath), contents);
347 ChangeSet changeSet = new ChangeSet();
348 changeSet.addedSource(source);
349 analysisContext2.applyChanges(changeSet);
350 return source;
351 }
352
353 /**
354 * Add a source file named 'test.dart' in the root of the file system. The
355 * file will have the given [contents] set in the content provider. Return the
356 * source representing the added file.
357 */
358 Source addSource(String contents) => addNamedSource("/test.dart", contents);
359
360 /**
361 * Assert that the number of errors reported against the given source matches the number of errors
362 * that are given and that they have the expected error codes. The order in wh ich the errors were
363 * gathered is ignored.
364 *
365 * @param source the source against which the errors should have been reported
366 * @param expectedErrorCodes the error codes of the errors that should have be en reported
367 * @throws AnalysisException if the reported errors could not be computed
368 * @throws AssertionFailedError if a different number of errors have been repo rted than were
369 * expected
370 */
371 void assertErrors(Source source,
372 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
373 GatheringErrorListener errorListener = new GatheringErrorListener();
374 for (AnalysisError error in analysisContext2.computeErrors(source)) {
375 expect(error.source, source);
376 ErrorCode errorCode = error.errorCode;
377 if (!enableUnusedElement &&
378 (errorCode == HintCode.UNUSED_ELEMENT ||
379 errorCode == HintCode.UNUSED_FIELD)) {
380 continue;
381 }
382 if (!enableUnusedLocalVariable &&
383 (errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
384 errorCode == HintCode.UNUSED_CATCH_STACK ||
385 errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) {
386 continue;
387 }
388 errorListener.onError(error);
389 }
390 errorListener.assertErrorsWithCodes(expectedErrorCodes);
391 }
392
393 /**
394 * Asserts that [code] verifies, but has errors with the given error codes.
395 *
396 * Like [assertErrors], but takes a string of source code.
397 */
398 // TODO(rnystrom): Use this in more tests that have the same structure.
399 void assertErrorsInCode(String code, List<ErrorCode> errors) {
400 Source source = addSource(code);
401 computeLibrarySourceErrors(source);
402 assertErrors(source, errors);
403 verify([source]);
404 }
405
406 /**
407 * Asserts that [code] has errors with the given error codes.
408 *
409 * Like [assertErrors], but takes a string of source code.
410 */
411 void assertErrorsInUnverifiedCode(String code, List<ErrorCode> errors) {
412 Source source = addSource(code);
413 computeLibrarySourceErrors(source);
414 assertErrors(source, errors);
415 }
416
417 /**
418 * Assert that no errors have been reported against the given source.
419 *
420 * @param source the source against which no errors should have been reported
421 * @throws AnalysisException if the reported errors could not be computed
422 * @throws AssertionFailedError if any errors have been reported
423 */
424 void assertNoErrors(Source source) {
425 assertErrors(source);
426 }
427
428 /**
429 * Asserts that [code] has no errors or warnings.
430 */
431 // TODO(rnystrom): Use this in more tests that have the same structure.
432 void assertNoErrorsInCode(String code) {
433 Source source = addSource(code);
434 computeLibrarySourceErrors(source);
435 assertNoErrors(source);
436 verify([source]);
437 }
438
439 /**
440 * @param code the code that assigns the value to the variable "v", no matter how. We check that
441 * "v" has expected static and propagated type.
442 */
443 void assertPropagatedAssignedType(String code, DartType expectedStaticType,
444 DartType expectedPropagatedType) {
445 SimpleIdentifier identifier = findMarkedIdentifier(code, "v = ");
446 expect(identifier.staticType, same(expectedStaticType));
447 expect(identifier.propagatedType, same(expectedPropagatedType));
448 }
449
450 /**
451 * @param code the code that iterates using variable "v". We check that
452 * "v" has expected static and propagated type.
453 */
454 void assertPropagatedIterationType(String code, DartType expectedStaticType,
455 DartType expectedPropagatedType) {
456 SimpleIdentifier identifier = findMarkedIdentifier(code, "v in ");
457 expect(identifier.staticType, same(expectedStaticType));
458 expect(identifier.propagatedType, same(expectedPropagatedType));
459 }
460
461 /**
462 * Check the static and propagated types of the expression marked with "; // m arker" comment.
463 *
464 * @param code source code to analyze, with the expression to check marked wit h "// marker".
465 * @param expectedStaticType if non-null, check actual static type is equal to this.
466 * @param expectedPropagatedType if non-null, check actual static type is equa l to this.
467 * @throws Exception
468 */
469 void assertTypeOfMarkedExpression(String code, DartType expectedStaticType,
470 DartType expectedPropagatedType) {
471 SimpleIdentifier identifier = findMarkedIdentifier(code, "; // marker");
472 if (expectedStaticType != null) {
473 expect(identifier.staticType, expectedStaticType);
474 }
475 expect(identifier.propagatedType, expectedPropagatedType);
476 }
477
478 /**
479 * Cache the [contents] for the file at the given [filePath] but don't add the
480 * source to the analysis context. The file path must be absolute.
481 */
482 Source cacheSource(String filePath, String contents) {
483 Source source = resourceProvider.getFile(filePath).createSource();
484 analysisContext2.setContents(source, contents);
485 return source;
486 }
487
488 /**
489 * Change the contents of the given [source] to the given [contents].
490 */
491 void changeSource(Source source, String contents) {
492 analysisContext2.setContents(source, contents);
493 ChangeSet changeSet = new ChangeSet();
494 changeSet.changedSource(source);
495 analysisContext2.applyChanges(changeSet);
496 }
497
498 /**
499 * Computes errors for the given [librarySource].
500 * This assumes that the given [librarySource] and its parts have already
501 * been added to the content provider using the method [addNamedSource].
502 */
503 void computeLibrarySourceErrors(Source librarySource) {
504 analysisContext.computeErrors(librarySource);
505 }
506
507 /**
508 * Create a library element that represents a library named `"test"` containin g a single
509 * empty compilation unit.
510 *
511 * @return the library element that was created
512 */
513 LibraryElementImpl createDefaultTestLibrary() =>
514 createTestLibrary(AnalysisContextFactory.contextWithCore(), "test");
515
516 /**
517 * Create a source object representing a file with the given [fileName] and
518 * give it an empty content. Return the source that was created.
519 */
520 Source createNamedSource(String fileName) {
521 Source source = resourceProvider.getFile(fileName).createSource();
522 analysisContext2.setContents(source, '');
523 return source;
524 }
525
526 /**
527 * Create a library element that represents a library with the given name cont aining a single
528 * empty compilation unit.
529 *
530 * @param libraryName the name of the library to be created
531 * @return the library element that was created
532 */
533 LibraryElementImpl createTestLibrary(
534 AnalysisContext context, String libraryName,
535 [List<String> typeNames]) {
536 String fileName = "/test/$libraryName.dart";
537 Source definingCompilationUnitSource = createNamedSource(fileName);
538 List<CompilationUnitElement> sourcedCompilationUnits;
539 if (typeNames == null) {
540 sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST;
541 } else {
542 int count = typeNames.length;
543 sourcedCompilationUnits = new List<CompilationUnitElement>(count);
544 for (int i = 0; i < count; i++) {
545 String typeName = typeNames[i];
546 ClassElementImpl type =
547 new ClassElementImpl.forNode(AstFactory.identifier3(typeName));
548 String fileName = "$typeName.dart";
549 CompilationUnitElementImpl compilationUnit =
550 new CompilationUnitElementImpl(fileName);
551 compilationUnit.source = createNamedSource(fileName);
552 compilationUnit.librarySource = definingCompilationUnitSource;
553 compilationUnit.types = <ClassElement>[type];
554 sourcedCompilationUnits[i] = compilationUnit;
555 }
556 }
557 CompilationUnitElementImpl compilationUnit =
558 new CompilationUnitElementImpl(fileName);
559 compilationUnit.librarySource =
560 compilationUnit.source = definingCompilationUnitSource;
561 LibraryElementImpl library = new LibraryElementImpl.forNode(
562 context, AstFactory.libraryIdentifier2([libraryName]));
563 library.definingCompilationUnit = compilationUnit;
564 library.parts = sourcedCompilationUnits;
565 return library;
566 }
567
568 /**
569 * Return the `SimpleIdentifier` marked by `marker`. The source code must have no
570 * errors and be verifiable.
571 *
572 * @param code source code to analyze.
573 * @param marker marker identifying sought after expression in source code.
574 * @return expression marked by the marker.
575 * @throws Exception
576 */
577 SimpleIdentifier findMarkedIdentifier(String code, String marker) {
578 try {
579 Source source = addSource(code);
580 LibraryElement library = resolve2(source);
581 assertNoErrors(source);
582 verify([source]);
583 CompilationUnit unit = resolveCompilationUnit(source, library);
584 // Could generalize this further by making [SimpleIdentifier.class] a
585 // parameter.
586 return EngineTestCase.findNode(
587 unit, code, marker, (node) => node is SimpleIdentifier);
588 } catch (exception) {
589 // Is there a better exception to throw here? The point is that an
590 // assertion failure here should be a failure, in both "test_*" and
591 // "fail_*" tests. However, an assertion failure is success for the
592 // purpose of "fail_*" tests, so without catching them here "fail_*" tests
593 // can succeed by failing for the wrong reason.
594 throw new StateError("Unexpected assertion failure: $exception");
595 }
596 }
597
598 Expression findTopLevelConstantExpression(
599 CompilationUnit compilationUnit, String name) =>
600 findTopLevelDeclaration(compilationUnit, name).initializer;
601
602 VariableDeclaration findTopLevelDeclaration(
603 CompilationUnit compilationUnit, String name) {
604 for (CompilationUnitMember member in compilationUnit.declarations) {
605 if (member is TopLevelVariableDeclaration) {
606 for (VariableDeclaration variable in member.variables.variables) {
607 if (variable.name.name == name) {
608 return variable;
609 }
610 }
611 }
612 }
613 return null;
614 // Not found
615 }
616
617 /**
618 * Re-create the analysis context being used by the test case.
619 */
620 void reset() {
621 analysisContext2 = AnalysisContextFactory.contextWithCore(
622 resourceProvider: resourceProvider);
623 }
624
625 /**
626 * Re-create the analysis context being used by the test case and set the
627 * [options] in the newly created context to the given [options].
628 */
629 void resetWithOptions(AnalysisOptions options) {
630 analysisContext2 = AnalysisContextFactory.contextWithCoreAndOptions(options,
631 resourceProvider: resourceProvider);
632 }
633
634 /**
635 * Given a library and all of its parts, resolve the contents of the library a nd the contents of
636 * the parts. This assumes that the sources for the library and its parts have already been added
637 * to the content provider using the method [addNamedSource].
638 *
639 * @param librarySource the source for the compilation unit that defines the l ibrary
640 * @return the element representing the resolved library
641 * @throws AnalysisException if the analysis could not be performed
642 */
643 LibraryElement resolve2(Source librarySource) =>
644 analysisContext2.computeLibraryElement(librarySource);
645
646 /**
647 * Return the resolved compilation unit corresponding to the given source in t he given library.
648 *
649 * @param source the source of the compilation unit to be returned
650 * @param library the library in which the compilation unit is to be resolved
651 * @return the resolved compilation unit
652 * @throws Exception if the compilation unit could not be resolved
653 */
654 CompilationUnit resolveCompilationUnit(
655 Source source, LibraryElement library) =>
656 analysisContext2.resolveCompilationUnit(source, library);
657
658 CompilationUnit resolveSource(String sourceText) =>
659 resolveSource2("/test.dart", sourceText);
660
661 CompilationUnit resolveSource2(String fileName, String sourceText) {
662 Source source = addNamedSource(fileName, sourceText);
663 LibraryElement library = analysisContext.computeLibraryElement(source);
664 return analysisContext.resolveCompilationUnit(source, library);
665 }
666
667 Source resolveSources(List<String> sourceTexts) {
668 for (int i = 0; i < sourceTexts.length; i++) {
669 CompilationUnit unit =
670 resolveSource2("/lib${i + 1}.dart", sourceTexts[i]);
671 // reference the source if this is the last source
672 if (i + 1 == sourceTexts.length) {
673 return unit.element.source;
674 }
675 }
676 return null;
677 }
678
679 void resolveWithAndWithoutExperimental(
680 List<String> strSources,
681 List<ErrorCode> codesWithoutExperimental,
682 List<ErrorCode> codesWithExperimental) {
683 // Setup analysis context as non-experimental
684 AnalysisOptionsImpl options = new AnalysisOptionsImpl();
685 // options.enableDeferredLoading = false;
686 resetWithOptions(options);
687 // Analysis and assertions
688 Source source = resolveSources(strSources);
689 assertErrors(source, codesWithoutExperimental);
690 verify([source]);
691 // Setup analysis context as experimental
692 reset();
693 // Analysis and assertions
694 source = resolveSources(strSources);
695 assertErrors(source, codesWithExperimental);
696 verify([source]);
697 }
698
699 void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) {
700 // Analysis and assertions
701 Source source = resolveSources(strSources);
702 assertErrors(source, codes);
703 verify([source]);
704 }
705
706 @override
707 void setUp() {
708 ElementFactory.flushStaticState();
709 super.setUp();
710 reset();
711 }
712
713 @override
714 void tearDown() {
715 analysisContext2 = null;
716 super.tearDown();
717 }
718
719 /**
720 * Verify that all of the identifiers in the compilation units associated with
721 * the given [sources] have been resolved.
722 */
723 void verify(List<Source> sources) {
724 ResolutionVerifier verifier = new ResolutionVerifier();
725 for (Source source in sources) {
726 List<Source> libraries = analysisContext2.getLibrariesContaining(source);
727 for (Source library in libraries) {
728 analysisContext2
729 .resolveCompilationUnit2(source, library)
730 .accept(verifier);
731 }
732 }
733 verifier.assertResolved();
734 }
735 }
736
737 /**
738 * Shared infrastructure for [StaticTypeAnalyzer2Test] and
739 * [StrongModeStaticTypeAnalyzer2Test].
740 */
741 class StaticTypeAnalyzer2TestShared extends ResolverTestCase {
742 String testCode;
743 Source testSource;
744 CompilationUnit testUnit;
745
746 /**
747 * Looks up the identifier with [name] and validates that its type type
748 * stringifies to [type] and that its generics match the given stringified
749 * output.
750 */
751 expectFunctionType(String name, String type,
752 {String elementTypeParams: '[]',
753 String typeParams: '[]',
754 String typeArgs: '[]',
755 String typeFormals: '[]'}) {
756 typeParameters(Element element) {
757 if (element is ExecutableElement) {
758 return element.typeParameters;
759 } else if (element is ParameterElement) {
760 return element.typeParameters;
761 }
762 fail('Wrong element type: ${element.runtimeType}');
763 }
764
765 SimpleIdentifier identifier = findIdentifier(name);
766 // Element is either ExecutableElement or ParameterElement.
767 Element element = identifier.staticElement;
768 FunctionTypeImpl functionType = identifier.staticType;
769 expect(functionType.toString(), type);
770 expect(typeParameters(element).toString(), elementTypeParams);
771 expect(functionType.typeParameters.toString(), typeParams);
772 expect(functionType.typeArguments.toString(), typeArgs);
773 expect(functionType.typeFormals.toString(), typeFormals);
774 }
775
776 /**
777 * Looks up the identifier with [name] and validates its static [type].
778 *
779 * If [type] is a string, validates that the identifier's static type
780 * stringifies to that text. Otherwise, [type] is used directly a [Matcher]
781 * to match the type.
782 *
783 * If [propagatedType] is given, also validate's the identifier's propagated
784 * type.
785 */
786 void expectIdentifierType(String name, type, [propagatedType]) {
787 SimpleIdentifier identifier = findIdentifier(name);
788 _expectType(identifier.staticType, type);
789 if (propagatedType != null) {
790 _expectType(identifier.propagatedType, propagatedType);
791 }
792 }
793
794 /**
795 * Looks up the initializer for the declaration containing [identifier] and
796 * validates its static [type].
797 *
798 * If [type] is a string, validates that the identifier's static type
799 * stringifies to that text. Otherwise, [type] is used directly a [Matcher]
800 * to match the type.
801 *
802 * If [propagatedType] is given, also validate's the identifier's propagated
803 * type.
804 */
805 void expectInitializerType(String name, type, [propagatedType]) {
806 SimpleIdentifier identifier = findIdentifier(name);
807 VariableDeclaration declaration =
808 identifier.getAncestor((node) => node is VariableDeclaration);
809 Expression initializer = declaration.initializer;
810 _expectType(initializer.staticType, type);
811 if (propagatedType != null) {
812 _expectType(initializer.propagatedType, propagatedType);
813 }
814 }
815
816 SimpleIdentifier findIdentifier(String search) {
817 SimpleIdentifier identifier = EngineTestCase.findNode(
818 testUnit, testCode, search, (node) => node is SimpleIdentifier);
819 return identifier;
820 }
821
822 void resolveTestUnit(String code) {
823 testCode = code;
824 testSource = addSource(testCode);
825 LibraryElement library = resolve2(testSource);
826 assertNoErrors(testSource);
827 verify([testSource]);
828 testUnit = resolveCompilationUnit(testSource, library);
829 }
830
831 /**
832 * Validates that [type] matches [expected].
833 *
834 * If [expected] is a string, validates that the type stringifies to that
835 * text. Otherwise, [expected] is used directly a [Matcher] to match the type.
836 */
837 _expectType(DartType type, expected) {
838 if (expected is String) {
839 expect(type.toString(), expected);
840 } else {
841 expect(type, expected);
842 }
843 }
844 }
OLDNEW
« no previous file with comments | « packages/analyzer/test/generated/resolver_test.dart ('k') | packages/analyzer/test/generated/scanner_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698