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

Side by Side Diff: pkg/analyzer/test/src/summary/summary_test.dart

Issue 1602883003: Introduce code for computing an unlinked summary directly from an AST. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library analyzer.test.src.summary.summary_test; 5 library analyzer.test.src.summary.summary_test;
6 6
7 import 'package:analyzer/analyzer.dart';
7 import 'package:analyzer/dart/ast/ast.dart'; 8 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart'; 9 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/src/generated/engine.dart'; 10 import 'package:analyzer/src/generated/engine.dart';
10 import 'package:analyzer/src/generated/error.dart'; 11 import 'package:analyzer/src/generated/error.dart';
11 import 'package:analyzer/src/generated/java_engine_io.dart'; 12 import 'package:analyzer/src/generated/java_engine_io.dart';
12 import 'package:analyzer/src/generated/parser.dart'; 13 import 'package:analyzer/src/generated/parser.dart';
13 import 'package:analyzer/src/generated/scanner.dart'; 14 import 'package:analyzer/src/generated/scanner.dart';
14 import 'package:analyzer/src/generated/source.dart'; 15 import 'package:analyzer/src/generated/source.dart';
15 import 'package:analyzer/src/generated/source_io.dart'; 16 import 'package:analyzer/src/generated/source_io.dart';
16 import 'package:analyzer/src/summary/base.dart'; 17 import 'package:analyzer/src/summary/base.dart';
17 import 'package:analyzer/src/summary/format.dart'; 18 import 'package:analyzer/src/summary/format.dart';
18 import 'package:analyzer/src/summary/prelink.dart'; 19 import 'package:analyzer/src/summary/prelink.dart';
19 import 'package:analyzer/src/summary/public_namespace_computer.dart' 20 import 'package:analyzer/src/summary/public_namespace_computer.dart'
20 as public_namespace; 21 as public_namespace;
22 import 'package:analyzer/src/summary/summarize_ast.dart';
21 import 'package:analyzer/src/summary/summarize_elements.dart' 23 import 'package:analyzer/src/summary/summarize_elements.dart'
22 as summarize_elements; 24 as summarize_elements;
23 import 'package:unittest/unittest.dart'; 25 import 'package:unittest/unittest.dart';
24 26
25 import '../../generated/resolver_test.dart'; 27 import '../../generated/resolver_test.dart';
26 import '../../reflective_tests.dart'; 28 import '../../reflective_tests.dart';
27 29
28 main() { 30 main() {
29 groupSep = ' | '; 31 groupSep = ' | ';
30 runReflectiveTests(SummarizeElementsTest); 32 runReflectiveTests(SummarizeElementsTest);
31 runReflectiveTests(PrelinkerTest); 33 runReflectiveTests(PrelinkerTest);
34 runReflectiveTests(UnlinkedSummarizeAstTest);
32 } 35 }
33 36
34 /** 37 /**
38 * The public namespaces of the sdk are computed once so that we don't bog
39 * down the test. Structured as a map from absolute URI to the corresponding
40 * public namespace.
41 *
42 * Note: should an exception occur during computation of this variable, it
43 * will silently be set to null to allow other tests to run.
44 */
45 final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () {
46 try {
47 AnalysisContext analysisContext = AnalysisContextFactory.contextWithCore();
48 Map<String, UnlinkedPublicNamespace> uriToNamespace =
49 <String, UnlinkedPublicNamespace>{};
50 List<LibraryElement> libraries = [
51 analysisContext.typeProvider.objectType.element.library,
52 analysisContext.typeProvider.futureType.element.library
53 ];
54 for (LibraryElement library in libraries) {
55 summarize_elements.LibrarySerializationResult serializedLibrary =
56 summarize_elements.serializeLibrary(
57 library, analysisContext.typeProvider);
58 for (int i = 0; i < serializedLibrary.unlinkedUnits.length; i++) {
59 uriToNamespace[serializedLibrary.unitUris[i]] =
60 new UnlinkedUnit.fromBuffer(
61 serializedLibrary.unlinkedUnits[i].toBuffer()).publicNamespace;
62 }
63 }
64 return uriToNamespace;
65 } catch (_) {
66 return null;
67 }
68 }();
69
70 /**
35 * Convert a summary object (or a portion of one) into a canonical form that 71 * Convert a summary object (or a portion of one) into a canonical form that
36 * can be easily compared using [expect]. If [orderByName] is true, and the 72 * can be easily compared using [expect]. If [orderByName] is true, and the
37 * object is a [List], it is sorted by the `name` field of its elements. 73 * object is a [List], it is sorted by the `name` field of its elements.
38 */ 74 */
39 Object canonicalize(Object obj, {bool orderByName: false}) { 75 Object canonicalize(Object obj, {bool orderByName: false}) {
40 if (obj is SummaryClass) { 76 if (obj is SummaryClass) {
41 Map<String, Object> result = <String, Object>{}; 77 Map<String, Object> result = <String, Object>{};
42 obj.toMap().forEach((String key, Object value) { 78 obj.toMap().forEach((String key, Object value) {
43 bool orderByName = false; 79 bool orderByName = false;
44 if (obj is UnlinkedPublicNamespace && key == 'names') { 80 if (obj is UnlinkedPublicNamespace && key == 'names') {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 return namespace; 118 return namespace;
83 } 119 }
84 120
85 /** 121 /**
86 * Override of [SummaryTest] which verifies the correctness of the prelinker by 122 * Override of [SummaryTest] which verifies the correctness of the prelinker by
87 * creating summaries from the element model, discarding their prelinked 123 * creating summaries from the element model, discarding their prelinked
88 * information, and then recreating it using the prelinker. 124 * information, and then recreating it using the prelinker.
89 */ 125 */
90 @reflectiveTest 126 @reflectiveTest
91 class PrelinkerTest extends SummarizeElementsTest { 127 class PrelinkerTest extends SummarizeElementsTest {
92 /**
93 * The public namespaces of the sdk are computed once so that we don't bog
94 * down the test. Structured as a map from absolute URI to the corresponding
95 * public namespace.
96 *
97 * Note: should an exception occur during computation of this variable, it
98 * will silently be set to null to allow other tests to run.
99 */
100 static final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () {
101 try {
102 AnalysisContext analysisContext =
103 AnalysisContextFactory.contextWithCore();
104 Map<String, UnlinkedPublicNamespace> uriToNamespace =
105 <String, UnlinkedPublicNamespace>{};
106 List<LibraryElement> libraries = [
107 analysisContext.typeProvider.objectType.element.library,
108 analysisContext.typeProvider.futureType.element.library
109 ];
110 for (LibraryElement library in libraries) {
111 summarize_elements.LibrarySerializationResult serializedLibrary =
112 summarize_elements.serializeLibrary(
113 library, analysisContext.typeProvider);
114 for (int i = 0; i < serializedLibrary.unlinkedUnits.length; i++) {
115 uriToNamespace[serializedLibrary.unitUris[i]] =
116 new UnlinkedUnit.fromBuffer(
117 serializedLibrary.unlinkedUnits[i].toBuffer())
118 .publicNamespace;
119 }
120 }
121 return uriToNamespace;
122 } catch (_) {
123 return null;
124 }
125 }();
126
127 final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace = 128 final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace =
128 <String, UnlinkedPublicNamespace>{}; 129 <String, UnlinkedPublicNamespace>{};
129 130
130 @override 131 @override
131 bool get expectAbsoluteUrisInDependencies => false; 132 bool get expectAbsoluteUrisInDependencies => false;
132 133
133 @override 134 @override
134 Source addNamedSource(String filePath, String contents) { 135 Source addNamedSource(String filePath, String contents) {
135 Source source = super.addNamedSource(filePath, contents); 136 Source source = super.addNamedSource(filePath, contents);
136 uriToPublicNamespace[absUri(filePath)] = 137 uriToPublicNamespace[absUri(filePath)] =
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 */ 194 */
194 List<String> unitUris; 195 List<String> unitUris;
195 196
196 /** 197 /**
197 * Map containing all source files in this test, and their corresponding file 198 * Map containing all source files in this test, and their corresponding file
198 * contents. 199 * contents.
199 */ 200 */
200 final Map<Source, String> _fileContents = <Source, String>{}; 201 final Map<Source, String> _fileContents = <Source, String>{};
201 202
202 @override 203 @override
204 LinkedLibrary linked;
205
206 @override
207 List<UnlinkedUnit> unlinkedUnits;
208
209 @override
203 bool get checkAstDerivedData => false; 210 bool get checkAstDerivedData => false;
204 211
205 @override 212 @override
206 bool get expectAbsoluteUrisInDependencies => true; 213 bool get expectAbsoluteUrisInDependencies => true;
207 214
208 @override 215 @override
209 Source addNamedSource(String filePath, String contents) { 216 Source addNamedSource(String filePath, String contents) {
210 Source source = super.addNamedSource(filePath, contents); 217 Source source = super.addNamedSource(filePath, contents);
211 _fileContents[source] = contents; 218 _fileContents[source] = contents;
212 return source; 219 return source;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 303 }
297 304
298 /** 305 /**
299 * Base class containing most summary tests. This allows summary tests to be 306 * Base class containing most summary tests. This allows summary tests to be
300 * re-used to exercise all the different ways in which summaries can be 307 * re-used to exercise all the different ways in which summaries can be
301 * generated (e.g. direct from the AST, from the element model, from a 308 * generated (e.g. direct from the AST, from the element model, from a
302 * "relinking" process, etc.) 309 * "relinking" process, etc.)
303 */ 310 */
304 abstract class SummaryTest { 311 abstract class SummaryTest {
305 /** 312 /**
306 * Linked summary that results from serializing and then deserializing the
307 * library under test.
308 */
309 LinkedLibrary linked;
310
311 /**
312 * Unlinked compilation unit summaries that result from serializing and
313 * deserializing the library under test.
314 */
315 List<UnlinkedUnit> unlinkedUnits;
316
317 /**
318 * A test will set this to `true` if it contains `import`, `export`, or 313 * A test will set this to `true` if it contains `import`, `export`, or
319 * `part` declarations that deliberately refer to non-existent files. 314 * `part` declarations that deliberately refer to non-existent files.
320 */ 315 */
321 bool allowMissingFiles = false; 316 bool allowMissingFiles = false;
322 317
323 /** 318 /**
324 * `true` if the summary was created directly from the AST (and hence 319 * `true` if the summary was created directly from the AST (and hence
325 * contains information that is not obtainable from the element model alone). 320 * contains information that is not obtainable from the element model alone).
326 * TODO(paulberry): modify the element model so that it contains all the data 321 * TODO(paulberry): modify the element model so that it contains all the data
327 * that summaries need, so that this flag is no longer needed. 322 * that summaries need, so that this flag is no longer needed.
328 */ 323 */
329 bool get checkAstDerivedData; 324 bool get checkAstDerivedData;
330 325
331 /** 326 /**
332 * Get access to the linked defining compilation unit. 327 * Get access to the linked defining compilation unit.
333 */ 328 */
334 LinkedUnit get definingUnit => linked.units[0]; 329 LinkedUnit get definingUnit => linked.units[0];
335 330
336 /** 331 /**
337 * `true` if the linked portion of the summary is expected to contain 332 * `true` if the linked portion of the summary is expected to contain
338 * absolute URIs. This happens because the element model doesn't (yet) store 333 * absolute URIs. This happens because the element model doesn't (yet) store
339 * enough information to recover relative URIs, TODO(paulberry): fix this. 334 * enough information to recover relative URIs, TODO(paulberry): fix this.
340 */ 335 */
341 bool get expectAbsoluteUrisInDependencies; 336 bool get expectAbsoluteUrisInDependencies;
342 337
343 /** 338 /**
339 * Get access to the linked summary that results from serializing and
340 * then deserializing the library under test.
341 */
342 LinkedLibrary get linked;
343
344 /**
345 * Get access to the unlinked compilation unit summaries that result from
346 * serializing and deserializing the library under test.
347 */
348 List<UnlinkedUnit> get unlinkedUnits;
349
350 /**
344 * Convert [path] to a suitably formatted absolute path URI for the current 351 * Convert [path] to a suitably formatted absolute path URI for the current
345 * platform. 352 * platform.
346 */ 353 */
347 String absUri(String path) { 354 String absUri(String path) {
348 return FileUtilities2.createFile(path).toURI().toString(); 355 return FileUtilities2.createFile(path).toURI().toString();
349 } 356 }
350 357
351 /** 358 /**
352 * Add the given source file so that it may be referenced by the file under 359 * Add the given source file so that it may be referenced by the file under
353 * test. 360 * test.
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 expect(reference.prefixReference, 0); 543 expect(reference.prefixReference, 0);
537 } 544 }
538 if (absoluteUri == null) { 545 if (absoluteUri == null) {
539 expect(referenceResolution.dependency, 0); 546 expect(referenceResolution.dependency, 0);
540 } else { 547 } else {
541 checkDependency(referenceResolution.dependency, absoluteUri, relativeUri); 548 checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
542 } 549 }
543 if (!allowTypeParameters) { 550 if (!allowTypeParameters) {
544 expect(typeRef.typeArguments, isEmpty); 551 expect(typeRef.typeArguments, isEmpty);
545 } 552 }
546 if (expectedKind == ReferenceKind.unresolved) { 553 if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
547 // summarize_elements.dart isn't yet able to record the name of 554 // summarize_elements.dart isn't yet able to record the name or prefix of
548 // unresolved references. TODO(paulberry): fix this. 555 // unresolved references. TODO(paulberry): fix this.
549 expect(reference.name, '*unresolved*'); 556 expect(reference.name, '*unresolved*');
550 } else if (expectedName == null) {
551 expect(reference.name, isEmpty);
552 } else {
553 expect(reference.name, expectedName);
554 }
555 if (expectedPrefix == null) {
556 expect(reference.prefixReference, 0); 557 expect(reference.prefixReference, 0);
557 } else { 558 } else {
558 checkPrefix(reference.prefixReference, expectedPrefix); 559 if (expectedName == null) {
560 expect(reference.name, isEmpty);
561 } else {
562 expect(reference.name, expectedName);
563 }
564 if (expectedPrefix == null) {
565 expect(reference.prefixReference, 0);
566 } else {
567 checkPrefix(reference.prefixReference, expectedPrefix);
568 }
559 } 569 }
560 expect(referenceResolution.kind, expectedKind); 570 expect(referenceResolution.kind, expectedKind);
561 expect(referenceResolution.unit, expectedTargetUnit); 571 expect(referenceResolution.unit, expectedTargetUnit);
562 expect(referenceResolution.numTypeParameters, numTypeParameters); 572 expect(referenceResolution.numTypeParameters, numTypeParameters);
563 } 573 }
564 574
565 /** 575 /**
566 * Verify that the given [typeRef] represents a reference to an unresolved 576 * Verify that the given [typeRef] represents a reference to an unresolved
567 * type. 577 * type.
568 */ 578 */
(...skipping 12 matching lines...) Expand all
581 /** 591 /**
582 * Docs 592 * Docs
583 */ 593 */
584 v 594 v
585 }'''; 595 }''';
586 UnlinkedEnumValue value = serializeEnumText(text).values[0]; 596 UnlinkedEnumValue value = serializeEnumText(text).values[0];
587 expect(value.documentationComment, isNotNull); 597 expect(value.documentationComment, isNotNull);
588 checkDocumentationComment(value.documentationComment, text); 598 checkDocumentationComment(value.documentationComment, text);
589 } 599 }
590 600
591 fail_test_import_missing() {
592 // TODO(paulberry): At the moment unresolved imports are not included in
593 // the element model, so we can't pass this test.
594 // Unresolved imports are included since this is necessary for proper
595 // dependency tracking.
596 allowMissingFiles = true;
597 serializeLibraryText('import "foo.dart";', allowErrors: true);
598 // Second import is the implicit import of dart:core
599 expect(unlinkedUnits[0].imports, hasLength(2));
600 checkDependency(
601 linked.importDependencies[0], absUri('/foo.dart'), 'foo.dart');
602 }
603
604 fail_type_reference_to_nonexistent_file_via_prefix() {
605 // TODO(paulberry): this test currently fails because there is not enough
606 // information in the element model to figure out that the unresolved
607 // reference `p.C` uses the prefix `p`.
608 allowMissingFiles = true;
609 UnlinkedTypeRef typeRef = serializeTypeText('p.C',
610 otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
611 checkUnresolvedTypeRef(typeRef, 'p', 'C');
612 }
613
614 fail_type_reference_to_type_visible_via_multiple_import_prefixes() {
615 // TODO(paulberry): this test currently fails because the element model
616 // doesn't record enough information to track which prefix is used to refer
617 // to a type.
618 addNamedSource('/lib1.dart', 'class C');
619 addNamedSource('/lib2.dart', 'export "lib1.dart";');
620 addNamedSource('/lib3.dart', 'export "lib1.dart";');
621 addNamedSource('/lib4.dart', 'export "lib1.dart";');
622 serializeLibraryText('''
623 import 'lib2.dart';
624 import 'lib3.dart' as a;
625 import 'lib4.dart' as b;
626 C c2;
627 a.C c3;
628 b.C c4;''');
629 // Note: it is important that each reference to class C records the prefix
630 // used to find it; otherwise it's possible that relinking might produce an
631 // incorrect result after a change to lib2.dart, lib3.dart, or lib4.dart.
632 checkTypeRef(
633 findVariable('c2').type, absUri('/lib1.dart'), 'lib1.dart', 'C');
634 checkTypeRef(
635 findVariable('c3').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
636 expectedPrefix: 'a');
637 checkTypeRef(
638 findVariable('c4').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
639 expectedPrefix: 'b');
640 }
641
642 /** 601 /**
643 * Find the class with the given [className] in the summary, and return its 602 * Find the class with the given [className] in the summary, and return its
644 * [UnlinkedClass] data structure. If [unit] is not given, the class is 603 * [UnlinkedClass] data structure. If [unit] is not given, the class is
645 * looked for in the defining compilation unit. 604 * looked for in the defining compilation unit.
646 */ 605 */
647 UnlinkedClass findClass(String className, 606 UnlinkedClass findClass(String className,
648 {bool failIfAbsent: false, UnlinkedUnit unit}) { 607 {bool failIfAbsent: false, UnlinkedUnit unit}) {
649 unit ??= unlinkedUnits[0]; 608 unit ??= unlinkedUnits[0];
650 UnlinkedClass result; 609 UnlinkedClass result;
651 for (UnlinkedClass cls in unit.classes) { 610 for (UnlinkedClass cls in unit.classes) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 if (result == null && failIfAbsent) { 711 if (result == null && failIfAbsent) {
753 fail('Variable $variableName not found in serialized output'); 712 fail('Variable $variableName not found in serialized output');
754 } 713 }
755 return result; 714 return result;
756 } 715 }
757 716
758 /** 717 /**
759 * Serialize the given library [text] and return the summary of the class 718 * Serialize the given library [text] and return the summary of the class
760 * with the given [className]. 719 * with the given [className].
761 */ 720 */
762 UnlinkedClass serializeClassText(String text, [String className = 'C']) { 721 UnlinkedClass serializeClassText(String text,
763 serializeLibraryText(text); 722 {String className: 'C', bool allowErrors: false}) {
723 serializeLibraryText(text, allowErrors: allowErrors);
764 return findClass(className, failIfAbsent: true); 724 return findClass(className, failIfAbsent: true);
765 } 725 }
766 726
767 /** 727 /**
768 * Serialize the given library [text] and return the summary of the enum with 728 * Serialize the given library [text] and return the summary of the enum with
769 * the given [enumName]. 729 * the given [enumName].
770 */ 730 */
771 UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) { 731 UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) {
772 serializeLibraryText(text); 732 serializeLibraryText(text);
773 return findEnum(enumName, failIfAbsent: true); 733 return findEnum(enumName, failIfAbsent: true);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 773
814 /** 774 /**
815 * Serialize a type declaration using the given [text] as a type name, and 775 * Serialize a type declaration using the given [text] as a type name, and
816 * return a summary of the corresponding [UnlinkedTypeRef]. If the type 776 * return a summary of the corresponding [UnlinkedTypeRef]. If the type
817 * declaration needs to refer to types that are not available in core, those 777 * declaration needs to refer to types that are not available in core, those
818 * types may be declared in [otherDeclarations]. 778 * types may be declared in [otherDeclarations].
819 */ 779 */
820 UnlinkedTypeRef serializeTypeText(String text, 780 UnlinkedTypeRef serializeTypeText(String text,
821 {String otherDeclarations: '', bool allowErrors: false}) { 781 {String otherDeclarations: '', bool allowErrors: false}) {
822 return serializeVariableText('$otherDeclarations\n$text v;', 782 return serializeVariableText('$otherDeclarations\n$text v;',
823 allowErrors: allowErrors) 783 allowErrors: allowErrors).type;
824 .type;
825 } 784 }
826 785
827 /** 786 /**
828 * Serialize the given library [text] and return the summary of the variable 787 * Serialize the given library [text] and return the summary of the variable
829 * with the given [variableName]. 788 * with the given [variableName].
830 */ 789 */
831 UnlinkedVariable serializeVariableText(String text, 790 UnlinkedVariable serializeVariableText(String text,
832 {String variableName: 'v', bool allowErrors: false}) { 791 {String variableName: 'v', bool allowErrors: false}) {
833 serializeLibraryText(text, allowErrors: allowErrors); 792 serializeLibraryText(text, allowErrors: allowErrors);
834 return findVariable(variableName, failIfAbsent: true); 793 return findVariable(variableName, failIfAbsent: true);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 class D { 987 class D {
1029 D.foo(); 988 D.foo();
1030 D.bar(); 989 D.bar();
1031 } 990 }
1032 class E {} 991 class E {}
1033 '''); 992 ''');
1034 expect(cls.executables, isEmpty); 993 expect(cls.executables, isEmpty);
1035 } 994 }
1036 995
1037 test_class_alias_private() { 996 test_class_alias_private() {
1038 serializeClassText('class _C = _D with _E; class _D {} class _E {}', '_C'); 997 serializeClassText('class _C = _D with _E; class _D {} class _E {}',
998 className: '_C');
1039 expect(unlinkedUnits[0].publicNamespace.names, isEmpty); 999 expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
1040 } 1000 }
1041 1001
1042 test_class_alias_reference_generic() { 1002 test_class_alias_reference_generic() {
1043 UnlinkedTypeRef typeRef = serializeTypeText('C', 1003 UnlinkedTypeRef typeRef = serializeTypeText('C',
1044 otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}'); 1004 otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
1045 checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2); 1005 checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
1046 } 1006 }
1047 1007
1048 test_class_alias_reference_generic_imported() { 1008 test_class_alias_reference_generic_imported() {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 UnlinkedClass cls = serializeClassText('class C {}'); 1132 UnlinkedClass cls = serializeClassText('class C {}');
1173 expect(cls.typeParameters, isEmpty); 1133 expect(cls.typeParameters, isEmpty);
1174 } 1134 }
1175 1135
1176 test_class_non_alias_flag() { 1136 test_class_non_alias_flag() {
1177 UnlinkedClass cls = serializeClassText('class C {}'); 1137 UnlinkedClass cls = serializeClassText('class C {}');
1178 expect(cls.isMixinApplication, false); 1138 expect(cls.isMixinApplication, false);
1179 } 1139 }
1180 1140
1181 test_class_private() { 1141 test_class_private() {
1182 serializeClassText('class _C {}', '_C'); 1142 serializeClassText('class _C {}', className: '_C');
1183 expect(unlinkedUnits[0].publicNamespace.names, isEmpty); 1143 expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
1184 } 1144 }
1185 1145
1186 test_class_reference_generic() { 1146 test_class_reference_generic() {
1187 UnlinkedTypeRef typeRef = 1147 UnlinkedTypeRef typeRef =
1188 serializeTypeText('C', otherDeclarations: 'class C<D, E> {}'); 1148 serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
1189 checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2); 1149 checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
1190 } 1150 }
1191 1151
1192 test_class_reference_generic_imported() { 1152 test_class_reference_generic_imported() {
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 expect(executable.isConst, false); 1858 expect(executable.isConst, false);
1899 expect(executable.isFactory, false); 1859 expect(executable.isFactory, false);
1900 expect(executable.isStatic, false); 1860 expect(executable.isStatic, false);
1901 expect(executable.parameters, hasLength(1)); 1861 expect(executable.parameters, hasLength(1));
1902 checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool'); 1862 checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool');
1903 expect(executable.typeParameters, isEmpty); 1863 expect(executable.typeParameters, isEmpty);
1904 } 1864 }
1905 1865
1906 test_executable_operator_index_set() { 1866 test_executable_operator_index_set() {
1907 UnlinkedExecutable executable = serializeClassText( 1867 UnlinkedExecutable executable = serializeClassText(
1908 'class C { void operator[]=(int i, bool v) => null; }') 1868 'class C { void operator[]=(int i, bool v) => null; }').executables[0];
1909 .executables[0];
1910 expect(executable.kind, UnlinkedExecutableKind.functionOrMethod); 1869 expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
1911 expect(executable.name, '[]='); 1870 expect(executable.name, '[]=');
1912 expect(executable.hasImplicitReturnType, false); 1871 expect(executable.hasImplicitReturnType, false);
1913 expect(executable.isAbstract, false); 1872 expect(executable.isAbstract, false);
1914 expect(executable.isConst, false); 1873 expect(executable.isConst, false);
1915 expect(executable.isFactory, false); 1874 expect(executable.isFactory, false);
1916 expect(executable.isStatic, false); 1875 expect(executable.isStatic, false);
1917 expect(executable.parameters, hasLength(2)); 1876 expect(executable.parameters, hasLength(2));
1918 expect(executable.returnType, isNull); 1877 expect(executable.returnType, isNull);
1919 expect(executable.typeParameters, isEmpty); 1878 expect(executable.typeParameters, isEmpty);
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
2471 expect(unlinkedUnits[0].imports, hasLength(1)); 2430 expect(unlinkedUnits[0].imports, hasLength(1));
2472 checkDependency(linked.importDependencies[0], 'dart:core', 'dart:core'); 2431 checkDependency(linked.importDependencies[0], 'dart:core', 'dart:core');
2473 expect(unlinkedUnits[0].imports[0].uri, isEmpty); 2432 expect(unlinkedUnits[0].imports[0].uri, isEmpty);
2474 expect(unlinkedUnits[0].imports[0].uriOffset, 0); 2433 expect(unlinkedUnits[0].imports[0].uriOffset, 0);
2475 expect(unlinkedUnits[0].imports[0].uriEnd, 0); 2434 expect(unlinkedUnits[0].imports[0].uriEnd, 0);
2476 expect(unlinkedUnits[0].imports[0].prefixReference, 0); 2435 expect(unlinkedUnits[0].imports[0].prefixReference, 0);
2477 expect(unlinkedUnits[0].imports[0].combinators, isEmpty); 2436 expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
2478 expect(unlinkedUnits[0].imports[0].isImplicit, isTrue); 2437 expect(unlinkedUnits[0].imports[0].isImplicit, isTrue);
2479 } 2438 }
2480 2439
2440 test_import_missing() {
2441 if (!checkAstDerivedData) {
2442 // TODO(paulberry): At the moment unresolved imports are not included in
2443 // the element model, so we can't pass this test.
2444 return;
2445 }
2446 // Unresolved imports are included since this is necessary for proper
2447 // dependency tracking.
2448 allowMissingFiles = true;
2449 serializeLibraryText('import "foo.dart";', allowErrors: true);
2450 // Second import is the implicit import of dart:core
2451 expect(unlinkedUnits[0].imports, hasLength(2));
2452 checkDependency(
2453 linked.importDependencies[0], absUri('/foo.dart'), 'foo.dart');
2454 }
2455
2481 test_import_no_combinators() { 2456 test_import_no_combinators() {
2482 serializeLibraryText('import "dart:async"; Future x;'); 2457 serializeLibraryText('import "dart:async"; Future x;');
2483 // Second import is the implicit import of dart:core 2458 // Second import is the implicit import of dart:core
2484 expect(unlinkedUnits[0].imports, hasLength(2)); 2459 expect(unlinkedUnits[0].imports, hasLength(2));
2485 expect(unlinkedUnits[0].imports[0].combinators, isEmpty); 2460 expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
2486 } 2461 }
2487 2462
2488 test_import_no_flags() { 2463 test_import_no_flags() {
2489 serializeLibraryText('import "dart:async"; Future x;'); 2464 serializeLibraryText('import "dart:async"; Future x;');
2490 expect(unlinkedUnits[0].imports[0].isImplicit, isFalse); 2465 expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 2618
2644 test_import_uri() { 2619 test_import_uri() {
2645 String uriString = '"dart:async"'; 2620 String uriString = '"dart:async"';
2646 String libraryText = 'import $uriString; Future x;'; 2621 String libraryText = 'import $uriString; Future x;';
2647 serializeLibraryText(libraryText); 2622 serializeLibraryText(libraryText);
2648 // Second import is the implicit import of dart:core 2623 // Second import is the implicit import of dart:core
2649 expect(unlinkedUnits[0].imports, hasLength(2)); 2624 expect(unlinkedUnits[0].imports, hasLength(2));
2650 expect(unlinkedUnits[0].imports[0].uri, 'dart:async'); 2625 expect(unlinkedUnits[0].imports[0].uri, 'dart:async');
2651 } 2626 }
2652 2627
2628 test_invalid_prefix_dynamic() {
2629 if (checkAstDerivedData) {
2630 // TODO(paulberry): get this to work properly.
2631 return;
2632 }
2633 checkUnresolvedTypeRef(
2634 serializeTypeText('dynamic.T', allowErrors: true), 'dynamic', 'T');
2635 }
2636
2637 test_invalid_prefix_type_parameter() {
2638 if (checkAstDerivedData) {
2639 // TODO(paulberry): get this to work properly.
2640 return;
2641 }
2642 checkUnresolvedTypeRef(
2643 serializeClassText('class C<T> { T.U x; }', allowErrors: true).fields[0]
2644 .type,
2645 'T',
2646 'U');
2647 }
2648
2649 test_invalid_prefix_void() {
2650 if (checkAstDerivedData) {
2651 // TODO(paulberry): get this to work properly.
2652 return;
2653 }
2654 checkUnresolvedTypeRef(
2655 serializeTypeText('void.T', allowErrors: true), 'void', 'T');
2656 }
2657
2653 test_library_documented() { 2658 test_library_documented() {
2654 String text = ''' 2659 String text = '''
2655 // Extra comment so doc comment offset != 0 2660 // Extra comment so doc comment offset != 0
2656 /** 2661 /**
2657 * Docs 2662 * Docs
2658 */ 2663 */
2659 library foo;'''; 2664 library foo;''';
2660 serializeLibraryText(text); 2665 serializeLibraryText(text);
2661 expect(unlinkedUnits[0].libraryDocumentationComment, isNotNull); 2666 expect(unlinkedUnits[0].libraryDocumentationComment, isNotNull);
2662 checkDocumentationComment( 2667 checkDocumentationComment(
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2827 allowTypeParameters: true, numTypeParameters: 2); 2832 allowTypeParameters: true, numTypeParameters: 2);
2828 expect(typeRef.typeArguments, hasLength(2)); 2833 expect(typeRef.typeArguments, hasLength(2));
2829 checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int'); 2834 checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
2830 checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object'); 2835 checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object');
2831 } 2836 }
2832 2837
2833 test_type_dynamic() { 2838 test_type_dynamic() {
2834 checkDynamicTypeRef(serializeTypeText('dynamic')); 2839 checkDynamicTypeRef(serializeTypeText('dynamic'));
2835 } 2840 }
2836 2841
2842 test_type_param_not_shadowed_by_constructor() {
2843 UnlinkedClass cls =
2844 serializeClassText('class C<D> { D x; C.D(); } class D {}');
2845 checkParamTypeRef(cls.fields[0].type, 1);
2846 }
2847
2848 test_type_param_not_shadowed_by_field_in_extends() {
2849 UnlinkedClass cls =
2850 serializeClassText('class C<T> extends D<T> { T x; } class D<T> {}');
2851 checkParamTypeRef(cls.supertype.typeArguments[0], 1);
2852 }
2853
2854 test_type_param_not_shadowed_by_field_in_implements() {
2855 UnlinkedClass cls =
2856 serializeClassText('class C<T> implements D<T> { T x; } class D<T> {}');
2857 checkParamTypeRef(cls.interfaces[0].typeArguments[0], 1);
2858 }
2859
2860 test_type_param_not_shadowed_by_field_in_with() {
2861 UnlinkedClass cls = serializeClassText(
2862 'class C<T> extends Object with D<T> { T x; } class D<T> {}');
2863 checkParamTypeRef(cls.mixins[0].typeArguments[0], 1);
2864 }
2865
2866 test_type_param_not_shadowed_by_method_parameter() {
2867 UnlinkedClass cls = serializeClassText('class C<T> { f(int T, T x) {} }');
2868 checkParamTypeRef(cls.executables[0].parameters[1].type, 1);
2869 }
2870
2871 test_type_param_not_shadowed_by_setter() {
2872 // The code under test should not produce a compile-time error, but it
2873 // does.
2874 bool workAroundBug25525 = true;
2875 UnlinkedClass cls = serializeClassText(
2876 'class C<D> { D x; void set D(value) {} } class D {}',
2877 allowErrors: workAroundBug25525);
2878 checkParamTypeRef(cls.fields[0].type, 1);
2879 }
2880
2881 test_type_param_not_shadowed_by_typedef_parameter() {
2882 UnlinkedTypedef typedef =
2883 serializeTypedefText('typedef void F<T>(int T, T x);');
2884 checkParamTypeRef(typedef.parameters[1].type, 1);
2885 }
2886
2887 test_type_param_shadowed_by_field() {
2888 UnlinkedClass cls = serializeClassText(
2889 'class C<D> { D x; int D; } class D {}',
2890 allowErrors: true);
2891 checkDynamicTypeRef(cls.fields[0].type);
2892 }
2893
2894 test_type_param_shadowed_by_getter() {
2895 UnlinkedClass cls = serializeClassText(
2896 'class C<D> { D x; int get D => null; } class D {}',
2897 allowErrors: true);
2898 checkDynamicTypeRef(cls.fields[0].type);
2899 }
2900
2901 test_type_param_shadowed_by_method() {
2902 UnlinkedClass cls = serializeClassText(
2903 'class C<D> { D x; void D() {} } class D {}',
2904 allowErrors: true);
2905 checkDynamicTypeRef(cls.fields[0].type);
2906 }
2907
2908 test_type_param_shadowed_by_type_param() {
2909 UnlinkedClass cls =
2910 serializeClassText('class C<T> { T f<T>(T x) => null; }');
2911 checkParamTypeRef(cls.executables[0].returnType, 1);
2912 checkParamTypeRef(cls.executables[0].parameters[0].type, 1);
2913 }
2914
2837 test_type_reference_from_part() { 2915 test_type_reference_from_part() {
2838 addNamedSource('/a.dart', 'part of foo; C v;'); 2916 addNamedSource('/a.dart', 'part of foo; C v;');
2839 serializeLibraryText('library foo; part "a.dart"; class C {}'); 2917 serializeLibraryText('library foo; part "a.dart"; class C {}');
2840 checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type, 2918 checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
2841 null, null, 'C', 2919 null, null, 'C',
2842 expectedKind: ReferenceKind.classOrEnum, 2920 expectedKind: ReferenceKind.classOrEnum,
2843 linkedSourceUnit: linked.units[1], 2921 linkedSourceUnit: linked.units[1],
2844 unlinkedSourceUnit: unlinkedUnits[1]); 2922 unlinkedSourceUnit: unlinkedUnits[1]);
2845 } 2923 }
2846 2924
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2937 addNamedSource('/a.dart', 'part of my.lib; class C {}'); 3015 addNamedSource('/a.dart', 'part of my.lib; class C {}');
2938 checkTypeRef( 3016 checkTypeRef(
2939 serializeTypeText('C', 3017 serializeTypeText('C',
2940 otherDeclarations: 'library my.lib; part "a.dart";'), 3018 otherDeclarations: 'library my.lib; part "a.dart";'),
2941 null, 3019 null,
2942 null, 3020 null,
2943 'C', 3021 'C',
2944 expectedTargetUnit: 1); 3022 expectedTargetUnit: 1);
2945 } 3023 }
2946 3024
3025 test_type_reference_to_nonexistent_file_via_prefix() {
3026 if (!checkAstDerivedData) {
3027 // TODO(paulberry): this test currently fails because there is not enough
3028 // information in the element model to figure out that the unresolved
3029 // reference `p.C` uses the prefix `p`.
3030 return;
3031 }
3032 allowMissingFiles = true;
3033 UnlinkedTypeRef typeRef = serializeTypeText('p.C',
3034 otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
3035 checkUnresolvedTypeRef(typeRef, 'p', 'C');
3036 }
3037
2947 test_type_reference_to_part() { 3038 test_type_reference_to_part() {
2948 addNamedSource('/a.dart', 'part of foo; class C { C(); }'); 3039 addNamedSource('/a.dart', 'part of foo; class C { C(); }');
2949 serializeLibraryText('library foo; part "a.dart"; C c;'); 3040 serializeLibraryText('library foo; part "a.dart"; C c;');
2950 checkTypeRef(unlinkedUnits[0].variables.single.type, null, null, 'C', 3041 checkTypeRef(unlinkedUnits[0].variables.single.type, null, null, 'C',
2951 expectedKind: ReferenceKind.classOrEnum, expectedTargetUnit: 1); 3042 expectedKind: ReferenceKind.classOrEnum, expectedTargetUnit: 1);
2952 } 3043 }
2953 3044
3045 test_type_reference_to_type_visible_via_multiple_import_prefixes() {
3046 if (!checkAstDerivedData) {
3047 // TODO(paulberry): this test currently fails because the element model
3048 // doesn't record enough information to track which prefix is used to
3049 // refer to a type.
3050 return;
3051 }
3052 addNamedSource('/lib1.dart', 'class C');
3053 addNamedSource('/lib2.dart', 'export "lib1.dart";');
3054 addNamedSource('/lib3.dart', 'export "lib1.dart";');
3055 addNamedSource('/lib4.dart', 'export "lib1.dart";');
3056 serializeLibraryText('''
3057 import 'lib2.dart';
3058 import 'lib3.dart' as a;
3059 import 'lib4.dart' as b;
3060 C c2;
3061 a.C c3;
3062 b.C c4;''');
3063 // Note: it is important that each reference to class C records the prefix
3064 // used to find it; otherwise it's possible that relinking might produce an
3065 // incorrect result after a change to lib2.dart, lib3.dart, or lib4.dart.
3066 checkTypeRef(
3067 findVariable('c2').type, absUri('/lib1.dart'), 'lib1.dart', 'C');
3068 checkTypeRef(
3069 findVariable('c3').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
3070 expectedPrefix: 'a');
3071 checkTypeRef(
3072 findVariable('c4').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
3073 expectedPrefix: 'b');
3074 }
3075
2954 test_type_reference_to_typedef() { 3076 test_type_reference_to_typedef() {
2955 checkTypeRef(serializeTypeText('F', otherDeclarations: 'typedef void F();'), 3077 checkTypeRef(serializeTypeText('F', otherDeclarations: 'typedef void F();'),
2956 null, null, 'F', 3078 null, null, 'F',
2957 expectedKind: ReferenceKind.typedef); 3079 expectedKind: ReferenceKind.typedef);
2958 } 3080 }
2959 3081
2960 test_type_unit_counts_unreferenced_units() { 3082 test_type_unit_counts_unreferenced_units() {
2961 addNamedSource('/a.dart', 'library a; part "b.dart"; part "c.dart";'); 3083 addNamedSource('/a.dart', 'library a; part "b.dart"; part "c.dart";');
2962 addNamedSource('/b.dart', 'part of a;'); 3084 addNamedSource('/b.dart', 'part of a;');
2963 addNamedSource('/c.dart', 'part of a; class C {}'); 3085 addNamedSource('/c.dart', 'part of a; class C {}');
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
3161 UnlinkedVariable variable = 3283 UnlinkedVariable variable =
3162 serializeVariableText('int i;', variableName: 'i'); 3284 serializeVariableText('int i;', variableName: 'i');
3163 checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int'); 3285 checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
3164 } 3286 }
3165 3287
3166 test_varible_private() { 3288 test_varible_private() {
3167 serializeVariableText('int _i;', variableName: '_i'); 3289 serializeVariableText('int _i;', variableName: '_i');
3168 expect(unlinkedUnits[0].publicNamespace.names, isEmpty); 3290 expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
3169 } 3291 }
3170 } 3292 }
3293
3294 /**
3295 * Override of [SummaryTest] which creates unlinked summaries directly from the
3296 * AST.
3297 */
3298 @reflectiveTest
3299 class UnlinkedSummarizeAstTest extends Object with SummaryTest {
3300 @override
3301 LinkedLibrary linked;
3302
3303 @override
3304 List<UnlinkedUnit> unlinkedUnits;
3305
3306 /**
3307 * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
3308 * passed to [addNamedSource].
3309 */
3310 Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
3311
3312 @override
3313 bool get checkAstDerivedData => true;
3314
3315 @override
3316 bool get expectAbsoluteUrisInDependencies => false;
3317
3318 @override
3319 addNamedSource(String filePath, String contents) {
3320 CompilationUnit unit = _parseText(contents);
3321 UnlinkedUnit unlinkedUnit =
3322 new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer());
3323 uriToUnit[absUri(filePath)] = unlinkedUnit;
3324 }
3325
3326 @override
3327 void serializeLibraryText(String text, {bool allowErrors: false}) {
3328 Uri testDartUri = Uri.parse(absUri('/test.dart'));
3329 String resolveToAbsoluteUri(String relativeUri) =>
3330 testDartUri.resolve(relativeUri).toString();
3331 CompilationUnit unit = _parseText(text);
3332 UnlinkedUnit definingUnit =
3333 new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer());
3334 UnlinkedUnit getPart(String relativeUri) {
3335 String absoluteUri = resolveToAbsoluteUri(relativeUri);
3336 UnlinkedUnit unit = uriToUnit[absoluteUri];
3337 if (unit == null && !allowMissingFiles) {
3338 fail('Prelinker unexpectedly requested unit for "$relativeUri"'
3339 ' (resolves to "$absoluteUri").');
3340 }
3341 return unit;
3342 }
3343 UnlinkedPublicNamespace getImport(String relativeUri) {
3344 String absoluteUri = resolveToAbsoluteUri(relativeUri);
3345 UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri];
3346 if (namespace == null) {
3347 namespace = uriToUnit[absoluteUri]?.publicNamespace;
3348 }
3349 if (namespace == null && !allowMissingFiles) {
3350 fail('Prelinker unexpectedly requested namespace for "$relativeUri"'
3351 ' (resolves to "$absoluteUri").'
3352 ' Namespaces available: ${uriToUnit.keys}');
3353 }
3354 return namespace;
3355 }
3356 linked = new LinkedLibrary.fromBuffer(
3357 prelink(definingUnit, getPart, getImport).toBuffer());
3358 unlinkedUnits = <UnlinkedUnit>[definingUnit];
3359 for (String relativeUri in definingUnit.publicNamespace.parts) {
3360 UnlinkedUnit unit = uriToUnit[resolveToAbsoluteUri(relativeUri)];
3361 if (unit == null) {
3362 if (!allowMissingFiles) {
3363 fail('Test referred to unknown unit $relativeUri');
3364 }
3365 } else {
3366 unlinkedUnits.add(unit);
3367 }
3368 }
3369 }
3370
3371 CompilationUnit _parseText(String text) {
3372 CharSequenceReader reader = new CharSequenceReader(text);
3373 Scanner scanner =
3374 new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
3375 Token token = scanner.tokenize();
3376 Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
3377 parser.parseGenericMethods = true;
3378 return parser.parseCompilationUnit(token);
3379 }
3380 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698