| OLD | NEW |
| 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_common; |
| 6 | 6 |
| 7 import 'package:analyzer/analyzer.dart'; | 7 import 'package:analyzer/analyzer.dart'; |
| 8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/src/generated/engine.dart'; | 10 import 'package:analyzer/src/generated/engine.dart'; |
| 11 import 'package:analyzer/src/generated/error.dart'; | 11 import 'package:analyzer/src/generated/error.dart'; |
| 12 import 'package:analyzer/src/generated/java_engine_io.dart'; | 12 import 'package:analyzer/src/generated/java_engine_io.dart'; |
| 13 import 'package:analyzer/src/generated/parser.dart'; | 13 import 'package:analyzer/src/generated/parser.dart'; |
| 14 import 'package:analyzer/src/generated/scanner.dart'; | 14 import 'package:analyzer/src/generated/scanner.dart'; |
| 15 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
| 16 import 'package:analyzer/src/generated/source_io.dart'; | 16 import 'package:analyzer/src/generated/source_io.dart'; |
| 17 import 'package:analyzer/src/summary/base.dart'; | 17 import 'package:analyzer/src/summary/base.dart'; |
| 18 import 'package:analyzer/src/summary/format.dart'; | 18 import 'package:analyzer/src/summary/format.dart'; |
| 19 import 'package:analyzer/src/summary/prelink.dart'; | |
| 20 import 'package:analyzer/src/summary/public_namespace_computer.dart' | 19 import 'package:analyzer/src/summary/public_namespace_computer.dart' |
| 21 as public_namespace; | 20 as public_namespace; |
| 22 import 'package:analyzer/src/summary/summarize_ast.dart'; | |
| 23 import 'package:analyzer/src/summary/summarize_elements.dart' | 21 import 'package:analyzer/src/summary/summarize_elements.dart' |
| 24 as summarize_elements; | 22 as summarize_elements; |
| 25 import 'package:unittest/unittest.dart'; | 23 import 'package:unittest/unittest.dart'; |
| 26 | 24 |
| 27 import '../../generated/resolver_test.dart'; | 25 import '../../generated/resolver_test.dart'; |
| 28 import '../../reflective_tests.dart'; | |
| 29 | |
| 30 main() { | |
| 31 groupSep = ' | '; | |
| 32 runReflectiveTests(SummarizeElementsTest); | |
| 33 runReflectiveTests(PrelinkerTest); | |
| 34 runReflectiveTests(UnlinkedSummarizeAstTest); | |
| 35 } | |
| 36 | 26 |
| 37 /** | 27 /** |
| 38 * The public namespaces of the sdk are computed once so that we don't bog | 28 * 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 | 29 * down the test. Structured as a map from absolute URI to the corresponding |
| 40 * public namespace. | 30 * public namespace. |
| 41 * | 31 * |
| 42 * Note: should an exception occur during computation of this variable, it | 32 * Note: should an exception occur during computation of this variable, it |
| 43 * will silently be set to null to allow other tests to run. | 33 * will silently be set to null to allow other tests to run. |
| 44 */ | 34 */ |
| 45 final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () { | 35 final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 public_namespace.computePublicNamespace(unit).toBuffer()); | 107 public_namespace.computePublicNamespace(unit).toBuffer()); |
| 118 return namespace; | 108 return namespace; |
| 119 } | 109 } |
| 120 | 110 |
| 121 /** | 111 /** |
| 122 * Type of a function that validates an [TypeRef]. | 112 * Type of a function that validates an [TypeRef]. |
| 123 */ | 113 */ |
| 124 typedef void _TypeRefValidator(TypeRef unlinkedTypeRef); | 114 typedef void _TypeRefValidator(TypeRef unlinkedTypeRef); |
| 125 | 115 |
| 126 /** | 116 /** |
| 127 * Override of [SummaryTest] which verifies the correctness of the prelinker by | |
| 128 * creating summaries from the element model, discarding their prelinked | |
| 129 * information, and then recreating it using the prelinker. | |
| 130 */ | |
| 131 @reflectiveTest | |
| 132 class PrelinkerTest extends SummarizeElementsTest { | |
| 133 final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace = | |
| 134 <String, UnlinkedPublicNamespace>{}; | |
| 135 | |
| 136 @override | |
| 137 bool get expectAbsoluteUrisInDependencies => false; | |
| 138 | |
| 139 @override | |
| 140 bool get skipFullyLinkedData => true; | |
| 141 | |
| 142 @override | |
| 143 Source addNamedSource(String filePath, String contents) { | |
| 144 Source source = super.addNamedSource(filePath, contents); | |
| 145 uriToPublicNamespace[absUri(filePath)] = | |
| 146 computePublicNamespaceFromText(contents, source); | |
| 147 return source; | |
| 148 } | |
| 149 | |
| 150 String resolveToAbsoluteUri(LibraryElement library, String relativeUri) { | |
| 151 Source resolvedSource = | |
| 152 analysisContext.sourceFactory.resolveUri(library.source, relativeUri); | |
| 153 if (resolvedSource == null) { | |
| 154 fail('Failed to resolve relative uri "$relativeUri"'); | |
| 155 } | |
| 156 return resolvedSource.uri.toString(); | |
| 157 } | |
| 158 | |
| 159 @override | |
| 160 void serializeLibraryElement(LibraryElement library) { | |
| 161 super.serializeLibraryElement(library); | |
| 162 Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; | |
| 163 expect(unlinkedUnits.length, unitUris.length); | |
| 164 for (int i = 1; i < unlinkedUnits.length; i++) { | |
| 165 uriToUnit[unitUris[i]] = unlinkedUnits[i]; | |
| 166 } | |
| 167 UnlinkedUnit getPart(String relativeUri) { | |
| 168 String absoluteUri = resolveToAbsoluteUri(library, relativeUri); | |
| 169 UnlinkedUnit unit = uriToUnit[absoluteUri]; | |
| 170 if (unit == null) { | |
| 171 fail('Prelinker unexpectedly requested unit for "$relativeUri"' | |
| 172 ' (resolves to "$absoluteUri").'); | |
| 173 } | |
| 174 return unit; | |
| 175 } | |
| 176 UnlinkedPublicNamespace getImport(String relativeUri) { | |
| 177 String absoluteUri = resolveToAbsoluteUri(library, relativeUri); | |
| 178 UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri]; | |
| 179 if (namespace == null) { | |
| 180 namespace = uriToPublicNamespace[absoluteUri]; | |
| 181 } | |
| 182 if (namespace == null && !allowMissingFiles) { | |
| 183 fail('Prelinker unexpectedly requested namespace for "$relativeUri"' | |
| 184 ' (resolves to "$absoluteUri").' | |
| 185 ' Namespaces available: ${uriToPublicNamespace.keys}'); | |
| 186 } | |
| 187 return namespace; | |
| 188 } | |
| 189 linked = new LinkedLibrary.fromBuffer( | |
| 190 prelink(unlinkedUnits[0], getPart, getImport).toBuffer()); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 /** | |
| 195 * Override of [SummaryTest] which creates summaries from the element model. | |
| 196 */ | |
| 197 @reflectiveTest | |
| 198 class SummarizeElementsTest extends ResolverTestCase with SummaryTest { | |
| 199 /** | |
| 200 * The list of absolute unit URIs corresponding to the compilation units in | |
| 201 * [unlinkedUnits]. | |
| 202 */ | |
| 203 List<String> unitUris; | |
| 204 | |
| 205 /** | |
| 206 * Map containing all source files in this test, and their corresponding file | |
| 207 * contents. | |
| 208 */ | |
| 209 final Map<Source, String> _fileContents = <Source, String>{}; | |
| 210 | |
| 211 @override | |
| 212 LinkedLibrary linked; | |
| 213 | |
| 214 @override | |
| 215 List<UnlinkedUnit> unlinkedUnits; | |
| 216 | |
| 217 @override | |
| 218 bool get checkAstDerivedData => false; | |
| 219 | |
| 220 @override | |
| 221 bool get expectAbsoluteUrisInDependencies => true; | |
| 222 | |
| 223 @override | |
| 224 bool get skipFullyLinkedData => false; | |
| 225 | |
| 226 @override | |
| 227 Source addNamedSource(String filePath, String contents) { | |
| 228 Source source = super.addNamedSource(filePath, contents); | |
| 229 _fileContents[source] = contents; | |
| 230 return source; | |
| 231 } | |
| 232 | |
| 233 /** | |
| 234 * Serialize the library containing the given class [element], then | |
| 235 * deserialize it and return the summary of the class. | |
| 236 */ | |
| 237 UnlinkedClass serializeClassElement(ClassElement element) { | |
| 238 serializeLibraryElement(element.library); | |
| 239 return findClass(element.name, failIfAbsent: true); | |
| 240 } | |
| 241 | |
| 242 /** | |
| 243 * Serialize the given [library] element, then deserialize it and store the | |
| 244 * resulting summary in [linked] and [unlinkedUnits]. | |
| 245 */ | |
| 246 void serializeLibraryElement(LibraryElement library) { | |
| 247 summarize_elements.LibrarySerializationResult serializedLib = | |
| 248 summarize_elements.serializeLibrary(library, typeProvider); | |
| 249 { | |
| 250 List<int> buffer = serializedLib.linked.toBuffer(); | |
| 251 linked = new LinkedLibrary.fromBuffer(buffer); | |
| 252 } | |
| 253 unlinkedUnits = serializedLib.unlinkedUnits.map((UnlinkedUnitBuilder b) { | |
| 254 List<int> buffer = b.toBuffer(); | |
| 255 return new UnlinkedUnit.fromBuffer(buffer); | |
| 256 }).toList(); | |
| 257 unitUris = serializedLib.unitUris; | |
| 258 } | |
| 259 | |
| 260 @override | |
| 261 void serializeLibraryText(String text, {bool allowErrors: false}) { | |
| 262 Source source = addSource(text); | |
| 263 _fileContents[source] = text; | |
| 264 LibraryElement library = resolve2(source); | |
| 265 if (!allowErrors) { | |
| 266 assertNoErrors(source); | |
| 267 } | |
| 268 serializeLibraryElement(library); | |
| 269 expect(unlinkedUnits[0].imports.length, linked.importDependencies.length); | |
| 270 expect(linked.units.length, unlinkedUnits.length); | |
| 271 for (int i = 0; i < linked.units.length; i++) { | |
| 272 expect(unlinkedUnits[i].references.length, | |
| 273 lessThanOrEqualTo(linked.units[i].references.length)); | |
| 274 } | |
| 275 verifyPublicNamespace(); | |
| 276 } | |
| 277 | |
| 278 @override | |
| 279 void setUp() { | |
| 280 super.setUp(); | |
| 281 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
| 282 options.enableGenericMethods = true; | |
| 283 resetWithOptions(options); | |
| 284 } | |
| 285 | |
| 286 test_class_no_superclass() { | |
| 287 UnlinkedClass cls = serializeClassElement(typeProvider.objectType.element); | |
| 288 expect(cls.supertype, isNull); | |
| 289 expect(cls.hasNoSupertype, isTrue); | |
| 290 } | |
| 291 | |
| 292 /** | |
| 293 * Verify that [public_namespace.computePublicNamespace] produces data that's | |
| 294 * equivalent to that produced by [summarize_elements.serializeLibrary]. | |
| 295 */ | |
| 296 void verifyPublicNamespace() { | |
| 297 for (int i = 0; i < unlinkedUnits.length; i++) { | |
| 298 Source source = analysisContext.sourceFactory.forUri(unitUris[i]); | |
| 299 String text = _fileContents[source]; | |
| 300 if (text == null) { | |
| 301 if (!allowMissingFiles) { | |
| 302 fail('Could not find file while verifying public namespace: ' | |
| 303 '${unitUris[i]}'); | |
| 304 } | |
| 305 } else { | |
| 306 UnlinkedPublicNamespace namespace = | |
| 307 computePublicNamespaceFromText(text, source); | |
| 308 expect(canonicalize(namespace), | |
| 309 canonicalize(unlinkedUnits[i].publicNamespace), | |
| 310 reason: 'publicNamespace(${unitUris[i]})'); | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 /** | |
| 317 * Base class containing most summary tests. This allows summary tests to be | 117 * Base class containing most summary tests. This allows summary tests to be |
| 318 * re-used to exercise all the different ways in which summaries can be | 118 * re-used to exercise all the different ways in which summaries can be |
| 319 * generated (e.g. direct from the AST, from the element model, from a | 119 * generated (e.g. direct from the AST, from the element model, from a |
| 320 * "relinking" process, etc.) | 120 * "relinking" process, etc.) |
| 321 */ | 121 */ |
| 322 abstract class SummaryTest { | 122 abstract class SummaryTest { |
| 323 /** | 123 /** |
| 324 * A test will set this to `true` if it contains `import`, `export`, or | 124 * A test will set this to `true` if it contains `import`, `export`, or |
| 325 * `part` declarations that deliberately refer to non-existent files. | 125 * `part` declarations that deliberately refer to non-existent files. |
| 326 */ | 126 */ |
| (...skipping 4023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4350 expect(constExpr.operations, operators); | 4150 expect(constExpr.operations, operators); |
| 4351 expect(constExpr.ints, ints); | 4151 expect(constExpr.ints, ints); |
| 4352 expect(constExpr.doubles, doubles); | 4152 expect(constExpr.doubles, doubles); |
| 4353 expect(constExpr.strings, strings); | 4153 expect(constExpr.strings, strings); |
| 4354 expect(constExpr.references, hasLength(referenceValidators.length)); | 4154 expect(constExpr.references, hasLength(referenceValidators.length)); |
| 4355 for (int i = 0; i < referenceValidators.length; i++) { | 4155 for (int i = 0; i < referenceValidators.length; i++) { |
| 4356 referenceValidators[i](constExpr.references[i]); | 4156 referenceValidators[i](constExpr.references[i]); |
| 4357 } | 4157 } |
| 4358 } | 4158 } |
| 4359 } | 4159 } |
| 4360 | |
| 4361 /** | |
| 4362 * Override of [SummaryTest] which creates unlinked summaries directly from the | |
| 4363 * AST. | |
| 4364 */ | |
| 4365 @reflectiveTest | |
| 4366 class UnlinkedSummarizeAstTest extends Object with SummaryTest { | |
| 4367 @override | |
| 4368 LinkedLibrary linked; | |
| 4369 | |
| 4370 @override | |
| 4371 List<UnlinkedUnit> unlinkedUnits; | |
| 4372 | |
| 4373 /** | |
| 4374 * Map from absolute URI to the [UnlinkedUnit] for each compilation unit | |
| 4375 * passed to [addNamedSource]. | |
| 4376 */ | |
| 4377 Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; | |
| 4378 | |
| 4379 @override | |
| 4380 bool get checkAstDerivedData => true; | |
| 4381 | |
| 4382 @override | |
| 4383 bool get expectAbsoluteUrisInDependencies => false; | |
| 4384 | |
| 4385 @override | |
| 4386 bool get skipFullyLinkedData => true; | |
| 4387 | |
| 4388 @override | |
| 4389 addNamedSource(String filePath, String contents) { | |
| 4390 CompilationUnit unit = _parseText(contents); | |
| 4391 UnlinkedUnit unlinkedUnit = | |
| 4392 new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer()); | |
| 4393 uriToUnit[absUri(filePath)] = unlinkedUnit; | |
| 4394 } | |
| 4395 | |
| 4396 @override | |
| 4397 void serializeLibraryText(String text, {bool allowErrors: false}) { | |
| 4398 Uri testDartUri = Uri.parse(absUri('/test.dart')); | |
| 4399 String resolveToAbsoluteUri(String relativeUri) => | |
| 4400 testDartUri.resolve(relativeUri).toString(); | |
| 4401 CompilationUnit unit = _parseText(text); | |
| 4402 UnlinkedUnit definingUnit = | |
| 4403 new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer()); | |
| 4404 UnlinkedUnit getPart(String relativeUri) { | |
| 4405 String absoluteUri = resolveToAbsoluteUri(relativeUri); | |
| 4406 UnlinkedUnit unit = uriToUnit[absoluteUri]; | |
| 4407 if (unit == null && !allowMissingFiles) { | |
| 4408 fail('Prelinker unexpectedly requested unit for "$relativeUri"' | |
| 4409 ' (resolves to "$absoluteUri").'); | |
| 4410 } | |
| 4411 return unit; | |
| 4412 } | |
| 4413 UnlinkedPublicNamespace getImport(String relativeUri) { | |
| 4414 String absoluteUri = resolveToAbsoluteUri(relativeUri); | |
| 4415 UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri]; | |
| 4416 if (namespace == null) { | |
| 4417 namespace = uriToUnit[absoluteUri]?.publicNamespace; | |
| 4418 } | |
| 4419 if (namespace == null && !allowMissingFiles) { | |
| 4420 fail('Prelinker unexpectedly requested namespace for "$relativeUri"' | |
| 4421 ' (resolves to "$absoluteUri").' | |
| 4422 ' Namespaces available: ${uriToUnit.keys}'); | |
| 4423 } | |
| 4424 return namespace; | |
| 4425 } | |
| 4426 linked = new LinkedLibrary.fromBuffer( | |
| 4427 prelink(definingUnit, getPart, getImport).toBuffer()); | |
| 4428 unlinkedUnits = <UnlinkedUnit>[definingUnit]; | |
| 4429 for (String relativeUri in definingUnit.publicNamespace.parts) { | |
| 4430 UnlinkedUnit unit = uriToUnit[resolveToAbsoluteUri(relativeUri)]; | |
| 4431 if (unit == null) { | |
| 4432 if (!allowMissingFiles) { | |
| 4433 fail('Test referred to unknown unit $relativeUri'); | |
| 4434 } | |
| 4435 } else { | |
| 4436 unlinkedUnits.add(unit); | |
| 4437 } | |
| 4438 } | |
| 4439 } | |
| 4440 | |
| 4441 CompilationUnit _parseText(String text) { | |
| 4442 CharSequenceReader reader = new CharSequenceReader(text); | |
| 4443 Scanner scanner = | |
| 4444 new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER); | |
| 4445 Token token = scanner.tokenize(); | |
| 4446 Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER); | |
| 4447 parser.parseGenericMethods = true; | |
| 4448 return parser.parseCompilationUnit(token); | |
| 4449 } | |
| 4450 } | |
| OLD | NEW |