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 |