LCOV - code coverage report
Current view: top level - src - build_controller.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 65 65 100.0 %
Date: 2021-09-23 09:58:53 Functions: 0 0 -

          Line data    Source code
       1             : part of rx_bloc_generator;
       2             : 
       3             : /// Validates the main bloc file and provides the generator the needed data
       4             : class _BuildController {
       5           1 :   _BuildController({
       6             :     required this.rxBlocClass,
       7             :     required this.eventClass,
       8             :     required this.stateClass,
       9             :   });
      10             : 
      11             :   final ClassElement rxBlocClass;
      12             :   final ClassElement? eventClass;
      13             :   final ClassElement? stateClass;
      14             : 
      15           1 :   String generate() {
      16             :     // Check for any broken rules
      17           1 :     _validate();
      18             : 
      19           3 :     final blocTypeClassName = '${rxBlocClass.displayName}Type';
      20           3 :     final blocClassName = '\$${rxBlocClass.displayName}';
      21           2 :     final eventClassName = eventClass!.displayName;
      22           2 :     final stateClassName = stateClass!.displayName;
      23           4 :     final blocFilePath = rxBlocClass.location?.components.first ?? '';
      24             :     final mainBlocFileName =
      25           3 :         Uri.tryParse(blocFilePath, (blocFilePath.lastIndexOf('/') + 1))
      26           1 :                 ?.toString() ??
      27             :             '';
      28             : 
      29             :     /// The output buffer containing all the generated code
      30           1 :     final _output = StringBuffer();
      31             : 
      32           1 :     <String>[
      33             :       /// .. part of '[rx_bloc_name]_bloc.dart'
      34             :       // TODO(Diev): Use [Directive.partOf] instead once `part of` is supported
      35           1 :       "part of '$mainBlocFileName';",
      36             : 
      37             :       // abstract class [RxBlocName]BlocType
      38           1 :       _BlocTypeClass(
      39             :         blocTypeClassName,
      40             :         eventClassName,
      41             :         stateClassName,
      42           2 :       ).build().toDartCodeString(),
      43             : 
      44             :       // abstract class $[RxBlocName]Bloc
      45           1 :       _BlocClass(
      46             :         blocClassName,
      47             :         blocTypeClassName,
      48             :         eventClassName,
      49             :         stateClassName,
      50           2 :         eventClass!.methods,
      51           2 :         stateClass!.fields
      52             :             // Skip @RxBlocIgnoreState() ignored states
      53           2 :             .where((FieldElement field) =>
      54           2 :                 field.getter is PropertyAccessorElement &&
      55           1 :                 field.getter != null &&
      56           3 :                 (field.getter!.metadata.isEmpty ||
      57             :                     !const TypeChecker.fromRuntime(RxBlocIgnoreState)
      58           2 :                         .hasAnnotationOf(field.getter!)))
      59           1 :             .toList(),
      60           2 :       ).build().toDartCodeString(),
      61             : 
      62             :       // class _[EventMethodName]EventArgs
      63             :       // ..._eventMethodsArgsClasses(),
      64           2 :       ...eventClass!.methods
      65           3 :           .where((MethodElement method) => method.isUsingArgumentClass)
      66           2 :           .map((MethodElement method) {
      67           3 :         return _EventArgumentsClass(method).build().toDartCodeString();
      68           1 :       }).toList()
      69           2 :     ].forEach(_output.writeln);
      70             : 
      71           1 :     return _output.toString();
      72             :   }
      73             : 
      74             :   /// Checks and logs if there is anything missed
      75           1 :   void _validate() {
      76           1 :     _validateEvents();
      77           1 :     _validateStates();
      78             :   }
      79             : 
      80           1 :   void _validateEvents() {
      81             :     // Events class required
      82           1 :     if (eventClass == null) {
      83           1 :       throw _RxBlocGeneratorException(
      84           1 :         _generateMissingClassError(
      85           1 :           eventClass?.displayName ?? '',
      86           2 :           rxBlocClass.name,
      87             :         ),
      88             :       );
      89             :     }
      90             : 
      91             :     // Methods only - No fields should exist
      92           4 :     eventClass!.fields.forEach((field) {
      93           2 :       throw _RxBlocGeneratorException(
      94           2 :           '${eventClass!.name} should contain methods only,'
      95           1 :           ' while ${field.name} seems to be a field.');
      96             :     });
      97             :   }
      98             : 
      99           1 :   void _validateStates() {
     100             :     // States class required
     101           1 :     if (stateClass == null) {
     102           1 :       throw _RxBlocGeneratorException(
     103           1 :         _generateMissingClassError(
     104           2 :           eventClass?.displayName ?? '',
     105           2 :           rxBlocClass.name,
     106             :         ),
     107             :       );
     108             :     }
     109             : 
     110             :     // Fields only - No methods should exist
     111           4 :     stateClass!.methods.forEach((method) {
     112           1 :       throw _RxBlocGeneratorException(
     113           2 :           'State ${method.name}should be defined using the get keyword.');
     114             :     });
     115             : 
     116           4 :     stateClass!.accessors.forEach((fieldElement) {
     117           1 :       if (!fieldElement.isAbstract) {
     118           2 :         final name = fieldElement.name.replaceAll('=', '');
     119           1 :         throw _RxBlocGeneratorException(
     120           1 :             'State $name should not contain a body definition.');
     121             :       }
     122             :     });
     123             :   }
     124             : 
     125             :   /// Generate string that represents error when a missing class is detected.
     126             :   ///
     127             :   /// The function takes a [className] which represents the missing class that
     128             :   /// is tied closely to the [blocName] bloc. The [className] represents either
     129             :   /// the user-defined or the default value for the events/states class that
     130             :   /// is vital for proper bloc generation.
     131           1 :   String _generateMissingClassError(String className, String blocName) =>
     132           1 :       (StringBuffer()
     133           2 :             ..writeAll(<String>[
     134           1 :               '$blocName$className class missing.',
     135             :               'Please make sure you have properly named and specified',
     136             :               'your class in the same file where the $blocName resides.'
     137           1 :             ], '\n\t'))
     138           1 :           .toString();
     139             : }

Generated by: LCOV version 1.15