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

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

Issue 1576743002: Create a prelinker for summaries. (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/dart/element/element.dart'; 7 import 'package:analyzer/dart/element/element.dart';
8 import 'package:analyzer/src/generated/ast.dart'; 8 import 'package:analyzer/src/generated/ast.dart';
9 import 'package:analyzer/src/generated/engine.dart'; 9 import 'package:analyzer/src/generated/engine.dart';
10 import 'package:analyzer/src/generated/error.dart'; 10 import 'package:analyzer/src/generated/error.dart';
11 import 'package:analyzer/src/generated/java_engine_io.dart'; 11 import 'package:analyzer/src/generated/java_engine_io.dart';
12 import 'package:analyzer/src/generated/parser.dart'; 12 import 'package:analyzer/src/generated/parser.dart';
13 import 'package:analyzer/src/generated/scanner.dart'; 13 import 'package:analyzer/src/generated/scanner.dart';
14 import 'package:analyzer/src/generated/source.dart'; 14 import 'package:analyzer/src/generated/source.dart';
15 import 'package:analyzer/src/generated/source_io.dart'; 15 import 'package:analyzer/src/generated/source_io.dart';
16 import 'package:analyzer/src/summary/base.dart'; 16 import 'package:analyzer/src/summary/base.dart';
17 import 'package:analyzer/src/summary/format.dart'; 17 import 'package:analyzer/src/summary/format.dart';
18 import 'package:analyzer/src/summary/prelink.dart';
18 import 'package:analyzer/src/summary/public_namespace_computer.dart' 19 import 'package:analyzer/src/summary/public_namespace_computer.dart'
19 as public_namespace; 20 as public_namespace;
20 import 'package:analyzer/src/summary/summarize_elements.dart' 21 import 'package:analyzer/src/summary/summarize_elements.dart'
21 as summarize_elements; 22 as summarize_elements;
22 import 'package:unittest/unittest.dart'; 23 import 'package:unittest/unittest.dart';
23 24
24 import '../../generated/resolver_test.dart'; 25 import '../../generated/resolver_test.dart';
25 import '../../reflective_tests.dart'; 26 import '../../reflective_tests.dart';
26 27
27 main() { 28 main() {
28 groupSep = ' | '; 29 groupSep = ' | ';
29 runReflectiveTests(SummarizeElementsTest); 30 runReflectiveTests(SummarizeElementsTest);
31 runReflectiveTests(PrelinkerTest);
30 } 32 }
31 33
32 /** 34 /**
35 * 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
37 * object is a [List], it is sorted by the `name` field of its elements.
38 */
39 Object canonicalize(Object obj, {bool orderByName: false}) {
40 if (obj is SummaryClass) {
41 Map<String, Object> result = <String, Object>{};
42 obj.toMap().forEach((String key, Object value) {
43 bool orderByName = false;
44 if (obj is UnlinkedPublicNamespace && key == 'names') {
45 orderByName = true;
46 }
47 result[key] = canonicalize(value, orderByName: orderByName);
48 });
49 return result;
50 } else if (obj is List) {
51 List<Object> result = <Object>[];
52 for (Object item in obj) {
53 result.add(canonicalize(item));
54 }
55 if (orderByName) {
56 result.sort((Object a, Object b) {
57 if (a is Map && b is Map) {
58 return Comparable.compare(a['name'], b['name']);
59 } else {
60 return 0;
61 }
62 });
63 }
64 return result;
65 } else if (obj is String || obj is num || obj is bool) {
66 return obj;
67 } else {
68 return obj.toString();
69 }
70 }
71
72 UnlinkedPublicNamespace computePublicNamespaceFromText(
73 String text, Source source) {
74 CharacterReader reader = new CharSequenceReader(text);
75 Scanner scanner =
76 new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
77 Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
78 parser.parseGenericMethods = true;
79 CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
80 UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
81 public_namespace
82 .computePublicNamespace(new BuilderContext(), unit)
83 .toBuffer());
84 return namespace;
85 }
86
87 /**
88 * Override of [SummaryTest] which verifies the correctness of the prelinker by
89 * creating summaries from the element model, discarding their prelinked
90 * information, and then recreating it using the prelinker.
91 */
92 @reflectiveTest
93 class PrelinkerTest extends SummarizeElementsTest {
94 /**
95 * The public namespaces of the sdk are computed once so that we don't bog
96 * down the test. Structured as a map from absolute URI to the corresponding
97 * public namespace.
98 *
99 * Note: should an exception occur during computation of this variable, it
100 * will silently be set to null to allow other tests to run.
101 */
102 static final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () {
103 try {
104 AnalysisContext analysisContext =
105 AnalysisContextFactory.contextWithCore();
106 Map<String, UnlinkedPublicNamespace> uriToNamespace =
107 <String, UnlinkedPublicNamespace>{};
108 List<LibraryElement> libraries = [
109 analysisContext.typeProvider.objectType.element.library,
110 analysisContext.typeProvider.futureType.element.library
111 ];
112 for (LibraryElement library in libraries) {
113 summarize_elements.LibrarySerializationResult serializedLibrary =
114 summarize_elements.serializeLibrary(
115 new BuilderContext(), library, analysisContext.typeProvider);
116 for (int i = 0; i < serializedLibrary.unlinkedUnits.length; i++) {
117 uriToNamespace[
118 serializedLibrary.unitUris[i]] = new UnlinkedUnit.fromBuffer(
119 serializedLibrary.unlinkedUnits[i].toBuffer()).publicNamespace;
120 }
121 }
122 return uriToNamespace;
123 } catch (_) {
124 return null;
125 }
126 }();
127
128 final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace =
129 <String, UnlinkedPublicNamespace>{};
130
131 @override
132 bool get expectAbsoluteUrisInDependencies => false;
133
134 @override
135 Source addNamedSource(String filePath, String contents) {
136 Source source = super.addNamedSource(filePath, contents);
137 uriToPublicNamespace[absUri(filePath)] =
138 computePublicNamespaceFromText(contents, source);
139 return source;
140 }
141
142 String resolveAbsoluteUri(LibraryElement library, String relativeUri) {
scheglov 2016/01/10 05:15:12 resolveToAbsoluteUri would be better maybe?
Paul Berry 2016/01/10 22:15:17 Done.
143 Source resolvedSource =
144 analysisContext.sourceFactory.resolveUri(library.source, relativeUri);
145 if (resolvedSource == null) {
146 fail('Failed to resolve relative uri "$relativeUri"');
147 }
148 String absoluteUri = resolvedSource.uri.toString();
149 return absoluteUri;
scheglov 2016/01/10 05:15:12 Could be inlined.
Paul Berry 2016/01/10 22:15:17 Done.
150 }
151
152 @override
153 void serializeLibraryElement(LibraryElement library) {
154 super.serializeLibraryElement(library);
155 Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
156 expect(unlinkedUnits.length, unitUris.length);
157 for (int i = 1; i < unlinkedUnits.length; i++) {
158 uriToUnit[unitUris[i]] = unlinkedUnits[i];
159 }
160 UnlinkedUnit getPart(String relativeUri) {
161 String absoluteUri = resolveAbsoluteUri(library, relativeUri);
162 UnlinkedUnit unit = uriToUnit[absoluteUri];
163 if (unit == null) {
164 fail('Prelinker unexpectedly requested unit for "$relativeUri"'
165 ' (resolves to "$absoluteUri").');
166 }
167 return unit;
168 }
169 UnlinkedPublicNamespace getImport(String relativeUri) {
170 String absoluteUri = resolveAbsoluteUri(library, relativeUri);
171 UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri];
172 if (namespace == null) {
173 namespace = uriToPublicNamespace[absoluteUri];
174 }
175 if (namespace == null && !allowMissingFiles) {
176 fail('Prelinker unexpectedly requested namespace for "$relativeUri"'
177 ' (resolves to "$absoluteUri").'
178 ' Namespaces available: ${uriToPublicNamespace.keys}');
179 }
180 return namespace;
181 }
182 prelinked = new PrelinkedLibrary.fromBuffer(
183 prelink(builderContext, unlinkedUnits[0], getPart, getImport)
184 .toBuffer());
185 }
186 }
187
188 /**
33 * Override of [SummaryTest] which creates summaries from the element model. 189 * Override of [SummaryTest] which creates summaries from the element model.
34 */ 190 */
35 @reflectiveTest 191 @reflectiveTest
36 class SummarizeElementsTest extends ResolverTestCase with SummaryTest { 192 class SummarizeElementsTest extends ResolverTestCase with SummaryTest {
37 final BuilderContext builderContext = new BuilderContext(); 193 final BuilderContext builderContext = new BuilderContext();
38 194
39 /** 195 /**
40 * The list of absolute unit URIs corresponding to the compilation units in 196 * The list of absolute unit URIs corresponding to the compilation units in
41 * [unlinkedUnits]. 197 * [unlinkedUnits].
42 */ 198 */
43 List<String> unitUris; 199 List<String> unitUris;
44 200
45 @override 201 @override
46 bool get checkAstDerivedData => false; 202 bool get checkAstDerivedData => false;
47 203
48 /** 204 @override
49 * Convert a summary object (or a portion of one) into a canonical form that 205 bool get expectAbsoluteUrisInDependencies => true;
50 * can be easily compared using [expect]. If [orderByName] is true, and the
51 * object is a [List], it is sorted by the `name` field of its elements.
52 */
53 Object canonicalize(Object obj, {bool orderByName: false}) {
54 if (obj is SummaryClass) {
55 Map<String, Object> result = <String, Object>{};
56 obj.toMap().forEach((String key, Object value) {
57 bool orderByName = false;
58 if (obj is UnlinkedPublicNamespace && key == 'names') {
59 orderByName = true;
60 }
61 result[key] = canonicalize(value, orderByName: orderByName);
62 });
63 return result;
64 } else if (obj is List) {
65 List<Object> result = <Object>[];
66 for (Object item in obj) {
67 result.add(canonicalize(item));
68 }
69 if (orderByName) {
70 result.sort((Object a, Object b) {
71 if (a is Map && b is Map) {
72 return Comparable.compare(a['name'], b['name']);
73 } else {
74 return 0;
75 }
76 });
77 }
78 return result;
79 } else {
80 return obj;
81 }
82 }
83 206
84 /** 207 /**
85 * Serialize the library containing the given class [element], then 208 * Serialize the library containing the given class [element], then
86 * deserialize it and return the summary of the class. 209 * deserialize it and return the summary of the class.
87 */ 210 */
88 UnlinkedClass serializeClassElement(ClassElement element) { 211 UnlinkedClass serializeClassElement(ClassElement element) {
89 serializeLibraryElement(element.library); 212 serializeLibraryElement(element.library);
90 return findClass(element.name, failIfAbsent: true); 213 return findClass(element.name, failIfAbsent: true);
91 } 214 }
92 215
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } 265 }
143 266
144 /** 267 /**
145 * Verify that [public_namespace.computePublicNamespace] produces data that's 268 * Verify that [public_namespace.computePublicNamespace] produces data that's
146 * equivalent to that produced by [summarize_elements.serializeLibrary]. 269 * equivalent to that produced by [summarize_elements.serializeLibrary].
147 */ 270 */
148 void verifyPublicNamespace() { 271 void verifyPublicNamespace() {
149 for (int i = 0; i < unlinkedUnits.length; i++) { 272 for (int i = 0; i < unlinkedUnits.length; i++) {
150 Source source = analysisContext.sourceFactory.forUri(unitUris[i]); 273 Source source = analysisContext.sourceFactory.forUri(unitUris[i]);
151 String text = analysisContext.getContents(source).data; 274 String text = analysisContext.getContents(source).data;
152 CharacterReader reader = new CharSequenceReader(text);
153 Scanner scanner =
154 new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
155 Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
156 parser.parseGenericMethods = true;
157 CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
158 UnlinkedPublicNamespace namespace = 275 UnlinkedPublicNamespace namespace =
159 new UnlinkedPublicNamespace.fromBuffer(public_namespace 276 computePublicNamespaceFromText(text, source);
160 .computePublicNamespace(builderContext, unit)
161 .toBuffer());
162 expect(canonicalize(namespace), 277 expect(canonicalize(namespace),
163 canonicalize(unlinkedUnits[i].publicNamespace), 278 canonicalize(unlinkedUnits[i].publicNamespace),
164 reason: 'publicNamespace(${unitUris[i]})'); 279 reason: 'publicNamespace(${unitUris[i]})');
165 } 280 }
166 } 281 }
167 } 282 }
168 283
169 /** 284 /**
170 * Base class containing most summary tests. This allows summary tests to be 285 * Base class containing most summary tests. This allows summary tests to be
171 * re-used to exercise all the different ways in which summaries can be 286 * re-used to exercise all the different ways in which summaries can be
172 * generated (e.g. direct from the AST, from the element model, from a 287 * generated (e.g. direct from the AST, from the element model, from a
173 * "relinking" process, etc.) 288 * "relinking" process, etc.)
174 */ 289 */
175 abstract class SummaryTest { 290 abstract class SummaryTest {
176 /** 291 /**
177 * Prelinked summary that results from serializing and then deserializing the 292 * Prelinked summary that results from serializing and then deserializing the
178 * library under test. 293 * library under test.
179 */ 294 */
180 PrelinkedLibrary prelinked; 295 PrelinkedLibrary prelinked;
181 296
182 /** 297 /**
183 * Unlinked compilation unit summaries that result from serializing and 298 * Unlinked compilation unit summaries that result from serializing and
184 * deserializing the library under test. 299 * deserializing the library under test.
185 */ 300 */
186 List<UnlinkedUnit> unlinkedUnits; 301 List<UnlinkedUnit> unlinkedUnits;
187 302
188 /** 303 /**
304 * A test will set this to `true` if it contains `import`, `export`, or
305 * `part` declarations that deliberately refer to non-existent files.
306 */
307 bool allowMissingFiles = false;
308
309 /**
189 * `true` if the summary was created directly from the AST (and hence 310 * `true` if the summary was created directly from the AST (and hence
190 * contains information that is not obtainable from the element model alone). 311 * contains information that is not obtainable from the element model alone).
191 * TODO(paulberry): modify the element model so that it contains all the data 312 * TODO(paulberry): modify the element model so that it contains all the data
192 * that summaries need, so that this flag is no longer needed. 313 * that summaries need, so that this flag is no longer needed.
193 */ 314 */
194 bool get checkAstDerivedData; 315 bool get checkAstDerivedData;
195 316
196 /** 317 /**
197 * Get access to the prelinked defining compilation unit. 318 * Get access to the prelinked defining compilation unit.
198 */ 319 */
199 PrelinkedUnit get definingUnit => prelinked.units[0]; 320 PrelinkedUnit get definingUnit => prelinked.units[0];
200 321
201 /** 322 /**
323 * `true` if the prelinked portion of the summary is expected to contain
324 * absolute URIs. This happens because the element model doesn't (yet) store
325 * enough information to recover relative URIs, TODO(paulberry): fix this.
326 */
327 bool get expectAbsoluteUrisInDependencies;
328
329 /**
202 * Convert [path] to a suitably formatted absolute path URI for the current 330 * Convert [path] to a suitably formatted absolute path URI for the current
203 * platform. 331 * platform.
204 */ 332 */
205 String absUri(String path) { 333 String absUri(String path) {
206 return FileUtilities2.createFile(path).toURI().toString(); 334 return FileUtilities2.createFile(path).toURI().toString();
207 } 335 }
208 336
209 /** 337 /**
210 * Add the given source file so that it may be referenced by the file under 338 * Add the given source file so that it may be referenced by the file under
211 * test. 339 * test.
212 */ 340 */
213 addNamedSource(String filePath, String contents); 341 Source addNamedSource(String filePath, String contents);
214 342
215 /** 343 /**
216 * Verify that the [dependency]th element of the dependency table represents 344 * Verify that the [dependency]th element of the dependency table represents
217 * a file reachable via the given [absoluteUri] and [relativeUri]. 345 * a file reachable via the given [absoluteUri] and [relativeUri].
218 */ 346 */
219 void checkDependency(int dependency, String absoluteUri, String relativeUri) { 347 void checkDependency(int dependency, String absoluteUri, String relativeUri) {
220 if (!checkAstDerivedData) { 348 if (expectAbsoluteUrisInDependencies) {
221 // The element model doesn't (yet) store enough information to recover 349 // The element model doesn't (yet) store enough information to recover
222 // relative URIs, so we have to use the absolute URI. 350 // relative URIs, so we have to use the absolute URI.
223 // TODO(paulberry): fix this. 351 // TODO(paulberry): fix this.
224 relativeUri = absoluteUri; 352 relativeUri = absoluteUri;
225 } 353 }
226 expect(dependency, new isInstanceOf<int>()); 354 expect(dependency, new isInstanceOf<int>());
227 expect(prelinked.dependencies[dependency].uri, relativeUri); 355 expect(prelinked.dependencies[dependency].uri, relativeUri);
228 } 356 }
229 357
230 /** 358 /**
(...skipping 24 matching lines...) Expand all
255 */ 383 */
256 void checkDynamicTypeRef(UnlinkedTypeRef typeRef) { 384 void checkDynamicTypeRef(UnlinkedTypeRef typeRef) {
257 checkTypeRef(typeRef, null, null, null); 385 checkTypeRef(typeRef, null, null, null);
258 } 386 }
259 387
260 /** 388 /**
261 * Verify that the dependency table contains an entry for a file reachable 389 * Verify that the dependency table contains an entry for a file reachable
262 * via the given [absoluteUri] and [relativeUri]. 390 * via the given [absoluteUri] and [relativeUri].
263 */ 391 */
264 void checkHasDependency(String absoluteUri, String relativeUri) { 392 void checkHasDependency(String absoluteUri, String relativeUri) {
265 if (!checkAstDerivedData) { 393 if (expectAbsoluteUrisInDependencies) {
266 // The element model doesn't (yet) store enough information to recover 394 // The element model doesn't (yet) store enough information to recover
267 // relative URIs, so we have to use the absolute URI. 395 // relative URIs, so we have to use the absolute URI.
268 // TODO(paulberry): fix this. 396 // TODO(paulberry): fix this.
269 relativeUri = absoluteUri; 397 relativeUri = absoluteUri;
270 } 398 }
399 List<String> found = <String>[];
271 for (PrelinkedDependency dep in prelinked.dependencies) { 400 for (PrelinkedDependency dep in prelinked.dependencies) {
272 if (dep.uri == relativeUri) { 401 if (dep.uri == relativeUri) {
273 return; 402 return;
274 } 403 }
404 found.add(dep.uri);
275 } 405 }
276 fail('Did not find dependency $absoluteUri'); 406 fail('Did not find dependency $relativeUri. Found: $found');
277 } 407 }
278 408
279 /** 409 /**
280 * Verify that the dependency table *does not* contain any entries for a file 410 * Verify that the dependency table *does not* contain any entries for a file
281 * reachable via the given [absoluteUri] and [relativeUri]. 411 * reachable via the given [absoluteUri] and [relativeUri].
282 */ 412 */
283 void checkLacksDependency(String absoluteUri, String relativeUri) { 413 void checkLacksDependency(String absoluteUri, String relativeUri) {
284 if (!checkAstDerivedData) { 414 if (expectAbsoluteUrisInDependencies) {
285 // The element model doesn't (yet) store enough information to recover 415 // The element model doesn't (yet) store enough information to recover
286 // relative URIs, so we have to use the absolute URI. 416 // relative URIs, so we have to use the absolute URI.
287 // TODO(paulberry): fix this. 417 // TODO(paulberry): fix this.
288 relativeUri = absoluteUri; 418 relativeUri = absoluteUri;
289 } 419 }
290 for (PrelinkedDependency dep in prelinked.dependencies) { 420 for (PrelinkedDependency dep in prelinked.dependencies) {
291 if (dep.uri == relativeUri) { 421 if (dep.uri == relativeUri) {
292 fail('Unexpected dependency found: $relativeUri'); 422 fail('Unexpected dependency found: $relativeUri');
293 } 423 }
294 } 424 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 expect(reference.prefixReference, 0); 486 expect(reference.prefixReference, 0);
357 } 487 }
358 if (absoluteUri == null) { 488 if (absoluteUri == null) {
359 expect(referenceResolution.dependency, 0); 489 expect(referenceResolution.dependency, 0);
360 } else { 490 } else {
361 checkDependency(referenceResolution.dependency, absoluteUri, relativeUri); 491 checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
362 } 492 }
363 if (!allowTypeParameters) { 493 if (!allowTypeParameters) {
364 expect(typeRef.typeArguments, isEmpty); 494 expect(typeRef.typeArguments, isEmpty);
365 } 495 }
366 if (expectedName == null) { 496 if (expectedKind == PrelinkedReferenceKind.unresolved) {
497 // summarize_elements.dart isn't yet able to record the name of
498 // unresolved references. TODO(paulberry): fix this.
499 expect(reference.name, '*unresolved*');
500 } else if (expectedName == null) {
367 expect(reference.name, isEmpty); 501 expect(reference.name, isEmpty);
368 } else { 502 } else {
369 expect(reference.name, expectedName); 503 expect(reference.name, expectedName);
370 } 504 }
371 if (expectedPrefix == null) { 505 if (expectedPrefix == null) {
372 expect(reference.prefixReference, 0); 506 expect(reference.prefixReference, 0);
373 } else { 507 } else {
374 checkPrefix(reference.prefixReference, expectedPrefix); 508 checkPrefix(reference.prefixReference, expectedPrefix);
375 } 509 }
376 expect(referenceResolution.kind, expectedKind); 510 expect(referenceResolution.kind, expectedKind);
(...skipping 26 matching lines...) Expand all
403 UnlinkedEnumValue value = serializeEnumText(text).values[0]; 537 UnlinkedEnumValue value = serializeEnumText(text).values[0];
404 expect(value.documentationComment, isNotNull); 538 expect(value.documentationComment, isNotNull);
405 checkDocumentationComment(value.documentationComment, text); 539 checkDocumentationComment(value.documentationComment, text);
406 } 540 }
407 541
408 fail_test_import_missing() { 542 fail_test_import_missing() {
409 // TODO(paulberry): At the moment unresolved imports are not included in 543 // TODO(paulberry): At the moment unresolved imports are not included in
410 // the element model, so we can't pass this test. 544 // the element model, so we can't pass this test.
411 // Unresolved imports are included since this is necessary for proper 545 // Unresolved imports are included since this is necessary for proper
412 // dependency tracking. 546 // dependency tracking.
547 allowMissingFiles = true;
413 serializeLibraryText('import "foo.dart";', allowErrors: true); 548 serializeLibraryText('import "foo.dart";', allowErrors: true);
414 // Second import is the implicit import of dart:core 549 // Second import is the implicit import of dart:core
415 expect(unlinkedUnits[0].imports, hasLength(2)); 550 expect(unlinkedUnits[0].imports, hasLength(2));
416 checkDependency( 551 checkDependency(
417 prelinked.importDependencies[0], absUri('/foo.dart'), 'foo.dart'); 552 prelinked.importDependencies[0], absUri('/foo.dart'), 'foo.dart');
418 } 553 }
419 554
420 fail_type_reference_to_nonexistent_file_via_prefix() { 555 fail_type_reference_to_nonexistent_file_via_prefix() {
421 // TODO(paulberry): this test currently fails because there is not enough 556 // TODO(paulberry): this test currently fails because there is not enough
422 // information in the element model to figure out that the unresolved 557 // information in the element model to figure out that the unresolved
423 // reference `p.C` uses the prefix `p`. 558 // reference `p.C` uses the prefix `p`.
559 allowMissingFiles = true;
424 UnlinkedTypeRef typeRef = serializeTypeText('p.C', 560 UnlinkedTypeRef typeRef = serializeTypeText('p.C',
425 otherDeclarations: 'import "foo.dart" as p;', allowErrors: true); 561 otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
426 checkUnresolvedTypeRef(typeRef, 'p', 'C'); 562 checkUnresolvedTypeRef(typeRef, 'p', 'C');
427 } 563 }
428 564
429 fail_type_reference_to_type_visible_via_multiple_import_prefixes() { 565 fail_type_reference_to_type_visible_via_multiple_import_prefixes() {
430 // TODO(paulberry): this test currently fails because the element model 566 // TODO(paulberry): this test currently fails because the element model
431 // doesn't record enough information to track which prefix is used to refer 567 // doesn't record enough information to track which prefix is used to refer
432 // to a type. 568 // to a type.
433 addNamedSource('/lib1.dart', 'class C'); 569 addNamedSource('/lib1.dart', 'class C');
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 764
629 /** 765 /**
630 * Serialize a type declaration using the given [text] as a type name, and 766 * Serialize a type declaration using the given [text] as a type name, and
631 * return a summary of the corresponding [UnlinkedTypeRef]. If the type 767 * return a summary of the corresponding [UnlinkedTypeRef]. If the type
632 * declaration needs to refer to types that are not available in core, those 768 * declaration needs to refer to types that are not available in core, those
633 * types may be declared in [otherDeclarations]. 769 * types may be declared in [otherDeclarations].
634 */ 770 */
635 UnlinkedTypeRef serializeTypeText(String text, 771 UnlinkedTypeRef serializeTypeText(String text,
636 {String otherDeclarations: '', bool allowErrors: false}) { 772 {String otherDeclarations: '', bool allowErrors: false}) {
637 return serializeVariableText('$otherDeclarations\n$text v;', 773 return serializeVariableText('$otherDeclarations\n$text v;',
638 allowErrors: allowErrors) 774 allowErrors: allowErrors).type;
639 .type;
640 } 775 }
641 776
642 /** 777 /**
643 * Serialize the given library [text] and return the summary of the variable 778 * Serialize the given library [text] and return the summary of the variable
644 * with the given [variableName]. 779 * with the given [variableName].
645 */ 780 */
646 UnlinkedVariable serializeVariableText(String text, 781 UnlinkedVariable serializeVariableText(String text,
647 {String variableName: 'v', bool allowErrors: false}) { 782 {String variableName: 'v', bool allowErrors: false}) {
648 serializeLibraryText(text, allowErrors: allowErrors); 783 serializeLibraryText(text, allowErrors: allowErrors);
649 return findVariable(variableName, failIfAbsent: true); 784 return findVariable(variableName, failIfAbsent: true);
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 } 1443 }
1309 1444
1310 test_dependencies_import_to_export_in_subdirs_absolute_export() { 1445 test_dependencies_import_to_export_in_subdirs_absolute_export() {
1311 addNamedSource('/a/a.dart', 1446 addNamedSource('/a/a.dart',
1312 'library a; export "${absUri('/a/b/b.dart')}"; class A {}'); 1447 'library a; export "${absUri('/a/b/b.dart')}"; class A {}');
1313 addNamedSource('/a/b/b.dart', 'library b;'); 1448 addNamedSource('/a/b/b.dart', 'library b;');
1314 serializeLibraryText('import "a/a.dart"; A a;'); 1449 serializeLibraryText('import "a/a.dart"; A a;');
1315 checkHasDependency(absUri('/a/a.dart'), 'a/a.dart'); 1450 checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
1316 // The main test library depends on b.dart, because names defined in 1451 // The main test library depends on b.dart, because names defined in
1317 // b.dart are exported by a.dart. 1452 // b.dart are exported by a.dart.
1318 checkHasDependency(absUri('/a/b/b.dart'), '/a/b/b.dart'); 1453 checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
1319 } 1454 }
1320 1455
1321 test_dependencies_import_to_export_in_subdirs_absolute_import() { 1456 test_dependencies_import_to_export_in_subdirs_absolute_import() {
1322 addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}'); 1457 addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
1323 addNamedSource('/a/b/b.dart', 'library b;'); 1458 addNamedSource('/a/b/b.dart', 'library b;');
1324 serializeLibraryText('import "${absUri('/a/a.dart')}"; A a;'); 1459 serializeLibraryText('import "${absUri('/a/a.dart')}"; A a;');
1325 checkHasDependency(absUri('/a/a.dart'), '/a/a.dart'); 1460 checkHasDependency(absUri('/a/a.dart'), absUri('/a/a.dart'));
1326 // The main test library depends on b.dart, because names defined in 1461 // The main test library depends on b.dart, because names defined in
1327 // b.dart are exported by a.dart. 1462 // b.dart are exported by a.dart.
1328 checkHasDependency(absUri('/a/b/b.dart'), '/a/b/b.dart'); 1463 checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
1329 } 1464 }
1330 1465
1331 test_dependencies_import_to_export_in_subdirs_relative() { 1466 test_dependencies_import_to_export_in_subdirs_relative() {
1332 addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}'); 1467 addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
1333 addNamedSource('/a/b/b.dart', 'library b;'); 1468 addNamedSource('/a/b/b.dart', 'library b;');
1334 serializeLibraryText('import "a/a.dart"; A a;'); 1469 serializeLibraryText('import "a/a.dart"; A a;');
1335 checkHasDependency(absUri('/a/a.dart'), 'a/a.dart'); 1470 checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
1336 // The main test library depends on b.dart, because names defined in 1471 // The main test library depends on b.dart, because names defined in
1337 // b.dart are exported by a.dart. 1472 // b.dart are exported by a.dart.
1338 checkHasDependency(absUri('/a/b/b.dart'), 'a/b/b.dart'); 1473 checkHasDependency(absUri('/a/b/b.dart'), 'a/b/b.dart');
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 expect(executable.isConst, false); 1790 expect(executable.isConst, false);
1656 expect(executable.isFactory, false); 1791 expect(executable.isFactory, false);
1657 expect(executable.isStatic, false); 1792 expect(executable.isStatic, false);
1658 expect(executable.parameters, hasLength(1)); 1793 expect(executable.parameters, hasLength(1));
1659 checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool'); 1794 checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool');
1660 expect(executable.typeParameters, isEmpty); 1795 expect(executable.typeParameters, isEmpty);
1661 } 1796 }
1662 1797
1663 test_executable_operator_index_set() { 1798 test_executable_operator_index_set() {
1664 UnlinkedExecutable executable = serializeClassText( 1799 UnlinkedExecutable executable = serializeClassText(
1665 'class C { void operator[]=(int i, bool v) => null; }') 1800 'class C { void operator[]=(int i, bool v) => null; }').executables[0];
1666 .executables[0];
1667 expect(executable.kind, UnlinkedExecutableKind.functionOrMethod); 1801 expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
1668 expect(executable.name, '[]='); 1802 expect(executable.name, '[]=');
1669 expect(executable.hasImplicitReturnType, false); 1803 expect(executable.hasImplicitReturnType, false);
1670 expect(executable.isAbstract, false); 1804 expect(executable.isAbstract, false);
1671 expect(executable.isConst, false); 1805 expect(executable.isConst, false);
1672 expect(executable.isFactory, false); 1806 expect(executable.isFactory, false);
1673 expect(executable.isStatic, false); 1807 expect(executable.isStatic, false);
1674 expect(executable.parameters, hasLength(2)); 1808 expect(executable.parameters, hasLength(2));
1675 expect(executable.returnType, isNull); 1809 expect(executable.returnType, isNull);
1676 expect(executable.typeParameters, isEmpty); 1810 expect(executable.typeParameters, isEmpty);
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 2229
2096 test_import_non_deferred() { 2230 test_import_non_deferred() {
2097 serializeLibraryText( 2231 serializeLibraryText(
2098 'import "dart:async" as a; main() { print(a.Future); }'); 2232 'import "dart:async" as a; main() { print(a.Future); }');
2099 expect(unlinkedUnits[0].imports[0].isDeferred, isFalse); 2233 expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
2100 } 2234 }
2101 2235
2102 test_import_of_file_with_missing_part() { 2236 test_import_of_file_with_missing_part() {
2103 // Other references in foo.dart should be resolved even though foo.dart's 2237 // Other references in foo.dart should be resolved even though foo.dart's
2104 // part declaration for bar.dart refers to a non-existent file. 2238 // part declaration for bar.dart refers to a non-existent file.
2239 allowMissingFiles = true;
2105 addNamedSource('/foo.dart', 'part "bar.dart"; class C {}'); 2240 addNamedSource('/foo.dart', 'part "bar.dart"; class C {}');
2106 serializeLibraryText('import "foo.dart"; C x;'); 2241 serializeLibraryText('import "foo.dart"; C x;');
2107 checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C'); 2242 checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
2108 } 2243 }
2109 2244
2110 test_import_of_missing_export() { 2245 test_import_of_missing_export() {
2111 // Other references in foo.dart should be resolved even though foo.dart's 2246 // Other references in foo.dart should be resolved even though foo.dart's
2112 // re-export of bar.dart refers to a non-existent file. 2247 // re-export of bar.dart refers to a non-existent file.
2248 allowMissingFiles = true;
2113 addNamedSource('/foo.dart', 'export "bar.dart"; class C {}'); 2249 addNamedSource('/foo.dart', 'export "bar.dart"; class C {}');
2114 serializeLibraryText('import "foo.dart"; C x;'); 2250 serializeLibraryText('import "foo.dart"; C x;');
2115 checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C'); 2251 checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
2116 } 2252 }
2117 2253
2118 test_import_offset() { 2254 test_import_offset() {
2119 String libraryText = ' import "dart:async"; Future x;'; 2255 String libraryText = ' import "dart:async"; Future x;';
2120 serializeLibraryText(libraryText); 2256 serializeLibraryText(libraryText);
2121 expect(unlinkedUnits[0].imports[0].offset, libraryText.indexOf('import')); 2257 expect(unlinkedUnits[0].imports[0].offset, libraryText.indexOf('import'));
2122 expect(unlinkedUnits[0].imports[0].uriOffset, 2258 expect(unlinkedUnits[0].imports[0].uriOffset,
(...skipping 24 matching lines...) Expand all
2147 expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v='); 2283 expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
2148 } 2284 }
2149 2285
2150 test_import_prefix_reference() { 2286 test_import_prefix_reference() {
2151 UnlinkedVariable variable = 2287 UnlinkedVariable variable =
2152 serializeVariableText('import "dart:async" as a; a.Future v;'); 2288 serializeVariableText('import "dart:async" as a; a.Future v;');
2153 checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future', 2289 checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
2154 expectedPrefix: 'a', numTypeParameters: 1); 2290 expectedPrefix: 'a', numTypeParameters: 1);
2155 } 2291 }
2156 2292
2293 test_import_prefixes_take_precedence_over_imported_names() {
2294 addNamedSource('/a.dart', 'class b {} class A');
2295 addNamedSource('/b.dart', 'class Cls {}');
2296 addNamedSource('/c.dart', 'class Cls {}');
2297 addNamedSource('/d.dart', 'class c {} class D');
2298 serializeLibraryText('''
2299 import 'a.dart';
2300 import 'b.dart' as b;
2301 import 'c.dart' as c;
2302 import 'd.dart';
2303 A aCls;
2304 b.Cls bCls;
2305 c.Cls cCls;
2306 D dCls;
2307 ''');
2308 checkTypeRef(findVariable('aCls').type, absUri('/a.dart'), 'a.dart', 'A');
2309 checkTypeRef(findVariable('bCls').type, absUri('/b.dart'), 'b.dart', 'Cls',
2310 expectedPrefix: 'b');
2311 checkTypeRef(findVariable('cCls').type, absUri('/c.dart'), 'c.dart', 'Cls',
2312 expectedPrefix: 'c');
2313 checkTypeRef(findVariable('dCls').type, absUri('/d.dart'), 'd.dart', 'D');
2314 }
2315
2157 test_import_reference() { 2316 test_import_reference() {
2158 UnlinkedVariable variable = 2317 UnlinkedVariable variable =
2159 serializeVariableText('import "dart:async"; Future v;'); 2318 serializeVariableText('import "dart:async"; Future v;');
2160 checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future', 2319 checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
2161 numTypeParameters: 1); 2320 numTypeParameters: 1);
2162 } 2321 }
2163 2322
2164 test_import_reference_merged_no_prefix() { 2323 test_import_reference_merged_no_prefix() {
2165 serializeLibraryText(''' 2324 serializeLibraryText('''
2166 import "dart:async" show Future; 2325 import "dart:async" show Future;
(...skipping 15 matching lines...) Expand all
2182 2341
2183 a.Future f; 2342 a.Future f;
2184 a.Stream s; 2343 a.Stream s;
2185 '''); 2344 ''');
2186 checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future', 2345 checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
2187 expectedPrefix: 'a', numTypeParameters: 1); 2346 expectedPrefix: 'a', numTypeParameters: 1);
2188 checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream', 2347 checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
2189 expectedPrefix: 'a', numTypeParameters: 1); 2348 expectedPrefix: 'a', numTypeParameters: 1);
2190 } 2349 }
2191 2350
2351 test_import_reference_merged_prefixed_separate_libraries() {
2352 addNamedSource('/a.dart', 'class A {}');
2353 addNamedSource('/b.dart', 'class B {}');
2354 serializeLibraryText('''
2355 import 'a.dart' as p;
2356 import 'b.dart' as p;
2357
2358 p.A a;
2359 p.B b;
2360 ''');
2361 checkTypeRef(findVariable('a').type, absUri('/a.dart'), 'a.dart', 'A',
2362 expectedPrefix: 'p');
2363 checkTypeRef(findVariable('b').type, absUri('/b.dart'), 'b.dart', 'B',
2364 expectedPrefix: 'p');
2365 }
2366
2192 test_import_show_order() { 2367 test_import_show_order() {
2193 String libraryText = 2368 String libraryText =
2194 'import "dart:async" show Future, Stream; Future x; Stream y;'; 2369 'import "dart:async" show Future, Stream; Future x; Stream y;';
2195 serializeLibraryText(libraryText); 2370 serializeLibraryText(libraryText);
2196 // Second import is the implicit import of dart:core 2371 // Second import is the implicit import of dart:core
2197 expect(unlinkedUnits[0].imports, hasLength(2)); 2372 expect(unlinkedUnits[0].imports, hasLength(2));
2198 expect(unlinkedUnits[0].imports[0].combinators, hasLength(1)); 2373 expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
2199 expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2)); 2374 expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
2200 expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty); 2375 expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty);
2201 expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future'); 2376 expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 expect(unlinkedUnits[0].libraryNameLength, 'foo.bar'.length); 2415 expect(unlinkedUnits[0].libraryNameLength, 'foo.bar'.length);
2241 } 2416 }
2242 2417
2243 test_library_unnamed() { 2418 test_library_unnamed() {
2244 serializeLibraryText(''); 2419 serializeLibraryText('');
2245 expect(unlinkedUnits[0].libraryName, isEmpty); 2420 expect(unlinkedUnits[0].libraryName, isEmpty);
2246 expect(unlinkedUnits[0].libraryNameOffset, 0); 2421 expect(unlinkedUnits[0].libraryNameOffset, 0);
2247 expect(unlinkedUnits[0].libraryNameLength, 0); 2422 expect(unlinkedUnits[0].libraryNameLength, 0);
2248 } 2423 }
2249 2424
2425 test_local_names_take_precedence_over_imported_names() {
2426 addNamedSource('/a.dart', 'class C {} class D {}');
2427 serializeLibraryText('''
2428 import 'a.dart';
2429 class C {}
2430 C c;
2431 D d;''');
2432 checkTypeRef(findVariable('c').type, null, null, 'C');
2433 checkTypeRef(findVariable('d').type, absUri('/a.dart'), 'a.dart', 'D');
2434 }
2435
2250 test_method_documented() { 2436 test_method_documented() {
2251 String text = ''' 2437 String text = '''
2252 class C { 2438 class C {
2253 /** 2439 /**
2254 * Docs 2440 * Docs
2255 */ 2441 */
2256 f() {} 2442 f() {}
2257 }'''; 2443 }''';
2258 UnlinkedExecutable executable = serializeClassText(text).executables[0]; 2444 UnlinkedExecutable executable = serializeClassText(text).executables[0];
2259 expect(executable.documentationComment, isNotNull); 2445 expect(executable.documentationComment, isNotNull);
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2688 UnlinkedVariable variable = 2874 UnlinkedVariable variable =
2689 serializeVariableText('int i;', variableName: 'i'); 2875 serializeVariableText('int i;', variableName: 'i');
2690 checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int'); 2876 checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
2691 } 2877 }
2692 2878
2693 test_varible_private() { 2879 test_varible_private() {
2694 serializeVariableText('int _i;', variableName: '_i'); 2880 serializeVariableText('int _i;', variableName: '_i');
2695 expect(unlinkedUnits[0].publicNamespace.names, isEmpty); 2881 expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
2696 } 2882 }
2697 } 2883 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698