Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // (c) 2015, the Dart Team. All rights reserved. Use of this | 1 // (c) 2015, the Dart Team. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in | 2 // source code is governed by a BSD-style license that can be found in |
| 3 // the LICENSE file. | 3 // the LICENSE file. |
| 4 | 4 |
| 5 library reflectable.src.transformer_implementation; | 5 library reflectable.src.transformer_implementation; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:developer' as developer; | 9 import 'dart:developer' as developer; |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| 11 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/constant.dart'; | 12 import 'package:analyzer/src/generated/constant.dart'; |
| 13 import 'package:analyzer/src/generated/element.dart'; | 13 import 'package:analyzer/src/generated/element.dart'; |
| 14 import 'package:analyzer/src/generated/utilities_dart.dart'; | 14 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 15 import 'package:barback/barback.dart'; | 15 import 'package:barback/barback.dart'; |
| 16 import 'package:code_transformers/resolver.dart'; | 16 import 'package:code_transformers/resolver.dart'; |
| 17 import 'package:dart_style/dart_style.dart'; | 17 import 'package:dart_style/dart_style.dart'; |
| 18 import 'package:path/path.dart' as path; | 18 import 'package:path/path.dart' as path; |
| 19 import 'element_capability.dart' as ec; | 19 import 'element_capability.dart' as ec; |
| 20 import 'encoding_constants.dart' as constants; | 20 import 'encoding_constants.dart' as constants; |
| 21 import 'fixed_point.dart'; | 21 import 'fixed_point.dart'; |
| 22 import 'reflectable_class_constants.dart' as reflectable_class_constants; | 22 import 'reflectable_class_constants.dart' as reflectable_class_constants; |
| 23 import 'transformer_errors.dart' as errors; | 23 import 'transformer_errors.dart' as errors; |
| 24 | 24 |
| 25 /// Specifiers for warnings that may be suppressed; `allWarnings` disables all | |
| 26 /// warnings, and the remaining values are concerned with individual warnings. | |
| 27 /// Remember to update the explanatory text in [_findSuppressWarnings] whenever | |
| 28 /// this list is updated. | |
| 29 enum WarningKind { | |
| 30 missingEntryPoint, | |
| 31 badSuperclass, | |
| 32 badNamePattern, | |
| 33 badMetadata | |
| 34 } | |
| 35 | |
| 25 // Single source of instances of [Resolver], shared across multiple | 36 // Single source of instances of [Resolver], shared across multiple |
| 26 // invocations of `apply` to save memory. | 37 // invocations of `apply` to save memory. |
| 27 Resolvers _resolvers = new Resolvers(dartSdkDirectory); | 38 Resolvers _resolvers = new Resolvers(dartSdkDirectory); |
| 28 | 39 |
| 29 class ReflectionWorld { | 40 class ReflectionWorld { |
| 30 final Resolver resolver; | 41 final Resolver resolver; |
| 31 final AssetId generatedLibraryId; | 42 final AssetId generatedLibraryId; |
| 32 final List<_ReflectorDomain> reflectors; | 43 final List<_ReflectorDomain> reflectors; |
| 33 final LibraryElement reflectableLibrary; | 44 final LibraryElement reflectableLibrary; |
| 34 final LibraryElement entryPointLibrary; | 45 final LibraryElement entryPointLibrary; |
| (...skipping 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2250 // because we will then simply work on a normal Dart program that uses | 2261 // because we will then simply work on a normal Dart program that uses |
| 2251 // dart:mirrors, which should have the same behavior as the translated | 2262 // dart:mirrors, which should have the same behavior as the translated |
| 2252 // program, and this could work quite well in practice, except for | 2263 // program, and this could work quite well in practice, except for |
| 2253 // debugging which is concerned with the generated code (but that would | 2264 // debugging which is concerned with the generated code (but that would |
| 2254 // ideally be an infrequent occurrence). | 2265 // ideally be an infrequent occurrence). |
| 2255 | 2266 |
| 2256 class TransformerImplementation { | 2267 class TransformerImplementation { |
| 2257 TransformLogger _logger; | 2268 TransformLogger _logger; |
| 2258 Resolver _resolver; | 2269 Resolver _resolver; |
| 2259 bool _formatted; | 2270 bool _formatted; |
| 2271 List<WarningKind> _suppressedWarnings; | |
| 2272 | |
| 2273 bool _warningEnabled(WarningKind kind) { | |
| 2274 return !_suppressedWarnings.contains(kind); | |
| 2275 } | |
| 2260 | 2276 |
| 2261 /// Checks whether the given [type] from the target program is "our" | 2277 /// Checks whether the given [type] from the target program is "our" |
| 2262 /// class [Reflectable] by looking up the static field | 2278 /// class [Reflectable] by looking up the static field |
| 2263 /// [Reflectable.thisClassId] and checking its value (which is a 40 | 2279 /// [Reflectable.thisClassId] and checking its value (which is a 40 |
| 2264 /// character string computed by sha1sum on an old version of | 2280 /// character string computed by sha1sum on an old version of |
| 2265 /// reflectable.dart). | 2281 /// reflectable.dart). |
| 2266 /// | 2282 /// |
| 2267 /// Discussion of approach: Checking that we have found the correct | 2283 /// Discussion of approach: Checking that we have found the correct |
| 2268 /// [Reflectable] class is crucial for correctness, and the "obvious" | 2284 /// [Reflectable] class is crucial for correctness, and the "obvious" |
| 2269 /// approach of just looking up the library and then the class with the | 2285 /// approach of just looking up the library and then the class with the |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2284 if (idField is ConstFieldElementImpl) { | 2300 if (idField is ConstFieldElementImpl) { |
| 2285 EvaluationResultImpl idResult = idField.evaluationResult; | 2301 EvaluationResultImpl idResult = idField.evaluationResult; |
| 2286 if (idResult != null) { | 2302 if (idResult != null) { |
| 2287 return idField.constantValue.toStringValue() == | 2303 return idField.constantValue.toStringValue() == |
| 2288 reflectable_class_constants.id; | 2304 reflectable_class_constants.id; |
| 2289 } | 2305 } |
| 2290 // idResult == null: analyzer/.../element.dart does not specify | 2306 // idResult == null: analyzer/.../element.dart does not specify |
| 2291 // whether this could happen, but it is surely not the right | 2307 // whether this could happen, but it is surely not the right |
| 2292 // class, so we fall through. | 2308 // class, so we fall through. |
| 2293 } | 2309 } |
| 2294 // Not a const field, cannot be the right class. | 2310 // Not a const field, or failed the test, cannot be the right class. |
| 2295 return false; | 2311 return false; |
| 2296 } | 2312 } |
| 2297 | 2313 |
| 2298 /// Returns the ClassElement in the target program which corresponds to class | 2314 /// Returns the ClassElement in the target program which corresponds to class |
| 2299 /// [Reflectable]. | 2315 /// [Reflectable]. |
| 2300 ClassElement _findReflectableClassElement(LibraryElement reflectableLibrary) { | 2316 ClassElement _findReflectableClassElement(LibraryElement reflectableLibrary) { |
| 2301 for (CompilationUnitElement unit in reflectableLibrary.units) { | 2317 for (CompilationUnitElement unit in reflectableLibrary.units) { |
| 2302 for (ClassElement type in unit.types) { | 2318 for (ClassElement type in unit.types) { |
| 2303 if (type.name == reflectable_class_constants.name && | 2319 if (type.name == reflectable_class_constants.name && |
| 2304 _equalsClassReflectable(type)) { | 2320 _equalsClassReflectable(type)) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2395 // have no effect; it might be better to emit a diagnostic message (a | 2411 // have no effect; it might be better to emit a diagnostic message (a |
| 2396 // hint?) in order to notify the programmer that "it does not work". | 2412 // hint?) in order to notify the programmer that "it does not work". |
| 2397 // The trade-off is that such constructs may have been written by | 2413 // The trade-off is that such constructs may have been written by |
| 2398 // programmers who are doing something else, intentionally. To emit a | 2414 // programmers who are doing something else, intentionally. To emit a |
| 2399 // diagnostic message, we must check whether there is a Reflectable | 2415 // diagnostic message, we must check whether there is a Reflectable |
| 2400 // somewhere inside this syntactic construct, and then emit the message | 2416 // somewhere inside this syntactic construct, and then emit the message |
| 2401 // in cases that we "consider likely to be misunderstood". | 2417 // in cases that we "consider likely to be misunderstood". |
| 2402 return null; | 2418 return null; |
| 2403 } | 2419 } |
| 2404 | 2420 |
| 2405 _warn(String message, Element element) { | 2421 _warn(WarningKind kind, String message, [Element element]) { |
| 2406 _logger.warning(message, | 2422 if (_warningEnabled(kind)) { |
| 2407 asset: _resolver.getSourceAssetId(element), | 2423 if (element != null) { |
| 2408 span: _resolver.getSourceSpan(element)); | 2424 _logger.warning(message, |
| 2425 asset: _resolver.getSourceAssetId(element), | |
| 2426 span: _resolver.getSourceSpan(element)); | |
| 2427 } else { | |
| 2428 _logger.warning(message); | |
| 2429 } | |
| 2430 } | |
| 2409 } | 2431 } |
| 2410 | 2432 |
| 2411 /// Finds all GlobalQuantifyCapability and GlobalQuantifyMetaCapability | 2433 /// Finds all GlobalQuantifyCapability and GlobalQuantifyMetaCapability |
| 2412 /// annotations on imports of [reflectableLibrary], and record the arguments | 2434 /// annotations on imports of [reflectableLibrary], and record the arguments |
| 2413 /// of these annotations by modifying [globalPatterns] and [globalMetadata]. | 2435 /// of these annotations by modifying [globalPatterns] and [globalMetadata]. |
| 2414 void _findGlobalQuantifyAnnotations( | 2436 void _findGlobalQuantifyAnnotations( |
| 2415 Map<RegExp, List<ClassElement>> globalPatterns, | 2437 Map<RegExp, List<ClassElement>> globalPatterns, |
| 2416 Map<ClassElement, List<ClassElement>> globalMetadata) { | 2438 Map<ClassElement, List<ClassElement>> globalMetadata) { |
| 2417 LibraryElement reflectableLibrary = | 2439 LibraryElement reflectableLibrary = |
| 2418 _resolver.getLibraryByName("reflectable.reflectable"); | 2440 _resolver.getLibraryByName("reflectable.reflectable"); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2434 for (ImportElement import in library.imports) { | 2456 for (ImportElement import in library.imports) { |
| 2435 for (ElementAnnotationImpl metadatum in import.metadata) { | 2457 for (ElementAnnotationImpl metadatum in import.metadata) { |
| 2436 if (metadatum.element == globalQuantifyCapabilityConstructor) { | 2458 if (metadatum.element == globalQuantifyCapabilityConstructor) { |
| 2437 EvaluationResultImpl evaluation = metadatum.evaluationResult; | 2459 EvaluationResultImpl evaluation = metadatum.evaluationResult; |
| 2438 if (evaluation != null && evaluation.value != null) { | 2460 if (evaluation != null && evaluation.value != null) { |
| 2439 DartObjectImpl value = evaluation.value; | 2461 DartObjectImpl value = evaluation.value; |
| 2440 String pattern = value.fields["classNamePattern"].toStringValue(); | 2462 String pattern = value.fields["classNamePattern"].toStringValue(); |
| 2441 if (pattern == null) { | 2463 if (pattern == null) { |
| 2442 // TODO(sigurdm) implement: Create a span for the annotation | 2464 // TODO(sigurdm) implement: Create a span for the annotation |
| 2443 // rather than the import. | 2465 // rather than the import. |
| 2444 _warn("The classNamePattern must be a string", import); | 2466 _warn(WarningKind.badNamePattern, |
| 2467 "The classNamePattern must be a string", import); | |
| 2445 continue; | 2468 continue; |
| 2446 } | 2469 } |
| 2447 ClassElement reflector = | 2470 ClassElement reflector = |
| 2448 value.fields["(super)"].fields["reflector"].type.element; | 2471 value.fields["(super)"].fields["reflector"].type.element; |
| 2449 if (reflector == null || | 2472 if (reflector == null || |
| 2450 reflector.type.element.supertype.element != | 2473 reflector.type.element.supertype.element != |
| 2451 reflectableClass) { | 2474 reflectableClass) { |
| 2452 String found = | 2475 String found = |
| 2453 reflector == null ? "" : " Found ${reflector.name}"; | 2476 reflector == null ? "" : " Found ${reflector.name}"; |
| 2454 _warn( | 2477 _warn( |
| 2478 WarningKind.badSuperclass, | |
| 2455 "The reflector must be a direct subclass of Reflectable." + | 2479 "The reflector must be a direct subclass of Reflectable." + |
| 2456 found, | 2480 found, |
| 2457 import); | 2481 import); |
| 2458 continue; | 2482 continue; |
| 2459 } | 2483 } |
| 2460 globalPatterns | 2484 globalPatterns |
| 2461 .putIfAbsent(new RegExp(pattern), () => <ClassElement>[]) | 2485 .putIfAbsent(new RegExp(pattern), () => <ClassElement>[]) |
| 2462 .add(reflector); | 2486 .add(reflector); |
| 2463 } | 2487 } |
| 2464 } else if (metadatum.element == | 2488 } else if (metadatum.element == |
| 2465 globalQuantifyMetaCapabilityConstructor) { | 2489 globalQuantifyMetaCapabilityConstructor) { |
| 2466 EvaluationResultImpl evaluation = metadatum.evaluationResult; | 2490 EvaluationResultImpl evaluation = metadatum.evaluationResult; |
| 2467 if (evaluation?.value != null) { | 2491 if (evaluation?.value != null) { |
| 2468 DartObjectImpl value = evaluation.value; | 2492 DartObjectImpl value = evaluation.value; |
| 2469 Object metadataFieldValue = | 2493 Object metadataFieldValue = |
| 2470 value.fields["metadataType"].toTypeValue().element; | 2494 value.fields["metadataType"].toTypeValue().element; |
| 2471 if (metadataFieldValue == null || | 2495 if (metadataFieldValue == null || |
| 2472 value.fields["metadataType"].type.element != typeClass) { | 2496 value.fields["metadataType"].type.element != typeClass) { |
| 2473 // TODO(sigurdm) implement: Create a span for the annotation. | 2497 // TODO(sigurdm) implement: Create a span for the annotation. |
| 2474 _warn( | 2498 _warn( |
| 2499 WarningKind.badMetadata, | |
| 2475 "The metadata must be a Type. " | 2500 "The metadata must be a Type. " |
| 2476 "Found ${value.fields["metadataType"].type.element.name}", | 2501 "Found ${value.fields["metadataType"].type.element.name}", |
| 2477 import); | 2502 import); |
| 2478 continue; | 2503 continue; |
| 2479 } | 2504 } |
| 2480 ClassElement reflector = | 2505 ClassElement reflector = |
| 2481 value.fields["(super)"].fields["reflector"].type.element; | 2506 value.fields["(super)"].fields["reflector"].type.element; |
| 2482 if (reflector == null || | 2507 if (reflector == null || |
| 2483 reflector.type.element.supertype.element != | 2508 reflector.type.element.supertype.element != |
| 2484 reflectableClass) { | 2509 reflectableClass) { |
| 2485 String found = | 2510 String found = |
| 2486 reflector == null ? "" : " Found ${reflector.name}"; | 2511 reflector == null ? "" : " Found ${reflector.name}"; |
| 2487 _warn( | 2512 _warn( |
| 2513 WarningKind.badSuperclass, | |
| 2488 "The reflector must be a direct subclass of Reflectable." + | 2514 "The reflector must be a direct subclass of Reflectable." + |
| 2489 found, | 2515 found, |
| 2490 import); | 2516 import); |
| 2491 continue; | 2517 continue; |
| 2492 } | 2518 } |
| 2493 globalMetadata | 2519 globalMetadata |
| 2494 .putIfAbsent(metadataFieldValue, () => <ClassElement>[]) | 2520 .putIfAbsent(metadataFieldValue, () => <ClassElement>[]) |
| 2495 .add(reflector); | 2521 .add(reflector); |
| 2496 } | 2522 } |
| 2497 } | 2523 } |
| 2498 } | 2524 } |
| 2499 } | 2525 } |
| 2500 } | 2526 } |
| 2501 } | 2527 } |
| 2502 | 2528 |
| 2503 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by | 2529 /// Returns a [ReflectionWorld] instantiated with all the reflectors seen by |
| 2504 /// [_resolver] and all classes annotated by them. The [reflectableLibrary] | 2530 /// [_resolver] and all classes annotated by them. The [reflectableLibrary] |
| 2505 /// must be the element representing 'package:reflectable/reflectable.dart', | 2531 /// must be the element representing 'package:reflectable/reflectable.dart', |
| 2506 /// the [entryPoint] must be the element representing the entry point under | 2532 /// the [entryPoint] must be the element representing the entry point under |
| 2507 /// transformation, and [dataId] must represent the entry point as well, | 2533 /// transformation, and [dataId] must represent the entry point as well, |
| 2508 /// and it is used to decide whether it is possible to import other libraries | 2534 /// and it is used to decide whether it is possible to import other libraries |
| 2509 /// from the entry point. If the transformation is guaranteed to have no | 2535 /// from the entry point. If the transformation is guaranteed to have no |
| 2510 /// effect the return value is [null]. | 2536 /// effect the return value is [null]. |
| 2511 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary, | 2537 ReflectionWorld _computeWorld(LibraryElement reflectableLibrary, |
| 2512 LibraryElement entryPoint, AssetId dataId) { | 2538 LibraryElement entryPoint, AssetId dataId) { |
| 2513 final ClassElement classReflectable = | 2539 final ClassElement classReflectable = |
| 2514 _findReflectableClassElement(reflectableLibrary); | 2540 _findReflectableClassElement(reflectableLibrary); |
| 2515 // If class `Reflectable` is absent the transformation must be a no-op. | 2541 // If class `Reflectable` is absent the transformation must be a no-op. |
| 2516 if (classReflectable == null) return null; | 2542 if (classReflectable == null) { |
| 2543 _logger.info("Ignoring entry point $entryPoint that does not " | |
| 2544 "include the class `Reflectable`."); | |
| 2545 return null; | |
| 2546 } | |
| 2517 | 2547 |
| 2518 // The world will be built from the library arguments plus these two. | 2548 // The world will be built from the library arguments plus these two. |
| 2519 final Map<ClassElement, _ReflectorDomain> domains = | 2549 final Map<ClassElement, _ReflectorDomain> domains = |
| 2520 <ClassElement, _ReflectorDomain>{}; | 2550 <ClassElement, _ReflectorDomain>{}; |
| 2521 final _ImportCollector importCollector = new _ImportCollector(); | 2551 final _ImportCollector importCollector = new _ImportCollector(); |
| 2522 | 2552 |
| 2523 // Maps each pattern to the list of reflectors associated with it via | 2553 // Maps each pattern to the list of reflectors associated with it via |
| 2524 // a [GlobalQuantifyCapability]. | 2554 // a [GlobalQuantifyCapability]. |
| 2525 Map<RegExp, List<ClassElement>> globalPatterns = | 2555 Map<RegExp, List<ClassElement>> globalPatterns = |
| 2526 <RegExp, List<ClassElement>>{}; | 2556 <RegExp, List<ClassElement>>{}; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2733 } | 2763 } |
| 2734 | 2764 |
| 2735 /// Extracts the namePattern String from an instance of a subclass of | 2765 /// Extracts the namePattern String from an instance of a subclass of |
| 2736 /// NamePatternCapability. | 2766 /// NamePatternCapability. |
| 2737 String extractNamePattern(DartObjectImpl constant) { | 2767 String extractNamePattern(DartObjectImpl constant) { |
| 2738 if (constant.fields == null || | 2768 if (constant.fields == null || |
| 2739 constant.fields["(super)"] == null || | 2769 constant.fields["(super)"] == null || |
| 2740 constant.fields["(super)"].fields["namePattern"] == null || | 2770 constant.fields["(super)"].fields["namePattern"] == null || |
| 2741 constant.fields["(super)"].fields["namePattern"].toStringValue() == | 2771 constant.fields["(super)"].fields["namePattern"].toStringValue() == |
| 2742 null) { | 2772 null) { |
| 2743 // TODO(sigurdm) diagnostic: Better error-message. | 2773 // TODO(eernst) implement: Add location info to message. |
| 2744 _logger.warning("Could not extract namePattern."); | 2774 _warn(WarningKind.badNamePattern, |
| 2775 "Could not extract namePattern from capability."); | |
| 2776 return ""; | |
| 2745 } | 2777 } |
| 2746 return constant.fields["(super)"].fields["namePattern"].toStringValue(); | 2778 return constant.fields["(super)"].fields["namePattern"].toStringValue(); |
| 2747 } | 2779 } |
| 2748 | 2780 |
| 2749 /// Extracts the metadata property from an instance of a subclass of | 2781 /// Extracts the metadata property from an instance of a subclass of |
| 2750 /// MetadataCapability. | 2782 /// MetadataCapability. |
| 2751 ClassElement extractMetaData(DartObjectImpl constant) { | 2783 ClassElement extractMetaData(DartObjectImpl constant) { |
| 2752 if (constant.fields == null || | 2784 if (constant.fields == null || |
| 2753 constant.fields["(super)"] == null || | 2785 constant.fields["(super)"] == null || |
| 2754 constant.fields["(super)"].fields["metadataType"] == null) { | 2786 constant.fields["(super)"].fields["metadataType"] == null) { |
| 2755 // TODO(sigurdm) diagnostic: Better error-message. We need a way | 2787 // TODO(eernst) implement: Add location info to message. |
| 2756 // to get a source location from a constant. | 2788 _warn(WarningKind.badMetadata, |
| 2757 _logger.warning("Could not extract the metadata field."); | 2789 "Could not extract metadata type from capability."); |
| 2758 return null; | 2790 return null; |
| 2759 } | 2791 } |
| 2760 Object metadataFieldValue = constant.fields["(super)"].fields[ | 2792 Object metadataFieldValue = constant.fields["(super)"].fields[ |
| 2761 "metadataType"].toTypeValue().element; | 2793 "metadataType"].toTypeValue().element; |
| 2762 if (metadataFieldValue is! ClassElement) { | 2794 if (metadataFieldValue is! ClassElement) { |
| 2763 _logger.warning("The metadataType field must be a Type object."); | 2795 // TODO(eernst) implement: Add location info to message. |
| 2796 _warn(WarningKind.badMetadata, | |
| 2797 "Metadata specification in capability must be a `Type`."); | |
| 2764 return null; | 2798 return null; |
| 2765 } | 2799 } |
| 2766 return metadataFieldValue; | 2800 return metadataFieldValue; |
| 2767 } | 2801 } |
| 2768 | 2802 |
| 2769 switch (classElement.name) { | 2803 switch (classElement.name) { |
| 2770 case "_NameCapability": | 2804 case "_NameCapability": |
| 2771 return ec.nameCapability; | 2805 return ec.nameCapability; |
| 2772 case "_ClassifyCapability": | 2806 case "_ClassifyCapability": |
| 2773 return ec.classifyCapability; | 2807 return ec.classifyCapability; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2951 DartFormatter formatter = new DartFormatter(); | 2985 DartFormatter formatter = new DartFormatter(); |
| 2952 result = formatter.format(result); | 2986 result = formatter.format(result); |
| 2953 } | 2987 } |
| 2954 return result; | 2988 return result; |
| 2955 } | 2989 } |
| 2956 | 2990 |
| 2957 /// Performs the transformation which eliminates all imports of | 2991 /// Performs the transformation which eliminates all imports of |
| 2958 /// `package:reflectable/reflectable.dart` and instead provides a set of | 2992 /// `package:reflectable/reflectable.dart` and instead provides a set of |
| 2959 /// statically generated mirror classes. | 2993 /// statically generated mirror classes. |
| 2960 Future apply(AggregateTransform aggregateTransform, List<String> entryPoints, | 2994 Future apply(AggregateTransform aggregateTransform, List<String> entryPoints, |
| 2961 bool formatted) async { | 2995 bool formatted, List<WarningKind> suppressedWarnings) async { |
| 2962 _logger = aggregateTransform.logger; | 2996 _logger = aggregateTransform.logger; |
| 2963 _formatted = formatted; | 2997 _formatted = formatted; |
| 2998 _suppressedWarnings = suppressedWarnings; | |
| 2964 // The type argument in the return type is omitted because the | 2999 // The type argument in the return type is omitted because the |
| 2965 // documentation on barback and on transformers do not specify it. | 3000 // documentation on barback and on transformers do not specify it. |
| 2966 | 3001 |
| 2967 List<Asset> assets = await aggregateTransform.primaryInputs.toList(); | 3002 List<Asset> assets = await aggregateTransform.primaryInputs.toList(); |
| 2968 | 3003 |
| 2969 if (assets.isEmpty) { | 3004 if (assets.isEmpty) { |
| 2970 // It is not an error to have nothing to transform. | 3005 // It is not an error to have nothing to transform. |
| 2971 _logger.info("Nothing to transform"); | 3006 _logger.info("Nothing to transform"); |
| 2972 // Terminate with a non-failing status code to the OS. | 3007 // Terminate with a non-failing status code to the OS. |
| 2973 exit(0); | 3008 exit(0); |
| 2974 } | 3009 } |
| 2975 | 3010 |
| 2976 // TODO(eernst) algorithm: Build a mapping from entry points to assets by | 3011 // TODO(eernst) algorithm: Build a mapping from entry points to assets by |
| 2977 // iterating over `assets` and doing a binary search on a sorted | 3012 // iterating over `assets` and doing a binary search on a sorted |
| 2978 // list of entry points: if A is the number of assets and E is the | 3013 // list of entry points: if A is the number of assets and E is the |
| 2979 // number of entry points (note: E < A, and E == 1 could be quite | 3014 // number of entry points (note: E < A, and E == 1 could be quite |
| 2980 // common), this would cost O(A*log(E)), whereas the current | 3015 // common), this would cost O(A*log(E)), whereas the current |
| 2981 // approach costs O(A*E). OK, it's log(E)+epsilon, not 0 when E == 1. | 3016 // approach costs O(A*E). OK, it's log(E)+epsilon, not 0 when E == 1. |
| 2982 for (String entryPoint in entryPoints) { | 3017 for (String entryPoint in entryPoints) { |
| 2983 // Find the asset corresponding to [entryPoint] | 3018 // Find the asset corresponding to [entryPoint] |
| 2984 Asset entryPointAsset = assets.firstWhere( | 3019 Asset entryPointAsset = assets.firstWhere( |
| 2985 (Asset asset) => asset.id.path.endsWith(entryPoint), | 3020 (Asset asset) => asset.id.path.endsWith(entryPoint), |
| 2986 orElse: () => null); | 3021 orElse: () => null); |
| 2987 if (entryPointAsset == null) { | 3022 if (entryPointAsset == null) { |
| 2988 aggregateTransform.logger.info("Missing entry point: $entryPoint"); | 3023 if (_warningEnabled(WarningKind.missingEntryPoint)) { |
| 3024 String entryPointPath = | |
| 3025 entryPoint.split('/').join(Platform.pathSeparator); | |
| 3026 bool entryPointFileExists = await new File(entryPointPath).exists(); | |
|
jakemac
2015/11/17 14:58:07
This is definitely an anti-pattern for transformer
| |
| 3027 if (!entryPointFileExists) { | |
| 3028 // We did not receive an asset for [entryPoint], and there is no | |
| 3029 // corresponding file (so it is not just because we were invoked | |
| 3030 // from `pub build test` and [entryPoint] is in `web`, or something | |
| 3031 // similar). Announce the problem. | |
| 3032 aggregateTransform.logger | |
| 3033 .warning("Missing entry point: $entryPoint"); | |
| 3034 } | |
| 3035 } | |
| 2989 continue; | 3036 continue; |
| 2990 } | 3037 } |
| 2991 Transform wrappedTransform = | 3038 Transform wrappedTransform = |
| 2992 new _AggregateTransformWrapper(aggregateTransform, entryPointAsset); | 3039 new _AggregateTransformWrapper(aggregateTransform, entryPointAsset); |
| 2993 | 3040 |
| 2994 _resolver = await _resolvers.get(wrappedTransform); | 3041 _resolver = await _resolvers.get(wrappedTransform); |
| 2995 LibraryElement reflectableLibrary = | 3042 LibraryElement reflectableLibrary = |
| 2996 _resolver.getLibraryByName("reflectable.reflectable"); | 3043 _resolver.getLibraryByName("reflectable.reflectable"); |
| 2997 if (reflectableLibrary == null) { | 3044 if (reflectableLibrary == null) { |
| 2998 // Stop and do not consumePrimary, i.e., let the original source | 3045 // Stop and do not consumePrimary, i.e., let the original source |
| (...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4058 return functionElement == null | 4105 return functionElement == null |
| 4059 ? "null" | 4106 ? "null" |
| 4060 : "${functionElement.library.name}.${functionElement.name}"; | 4107 : "${functionElement.library.name}.${functionElement.name}"; |
| 4061 } | 4108 } |
| 4062 | 4109 |
| 4063 String _qualifiedTypeParameterName(TypeParameterElement typeParameterElement) { | 4110 String _qualifiedTypeParameterName(TypeParameterElement typeParameterElement) { |
| 4064 if (typeParameterElement == null) return "null"; | 4111 if (typeParameterElement == null) return "null"; |
| 4065 return "${_qualifiedName(typeParameterElement.enclosingElement)}." | 4112 return "${_qualifiedName(typeParameterElement.enclosingElement)}." |
| 4066 "${typeParameterElement.name}"; | 4113 "${typeParameterElement.name}"; |
| 4067 } | 4114 } |
| OLD | NEW |