LCOV - code coverage report
Current view: top level - code_builder - on_generate_route_builder.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.0 % 102 100
Test Date: 2024-07-24 10:28:19 Functions: - 0 0

            Line data    Source code
       1              : import 'package:code_builder/code_builder.dart';
       2              : import 'package:collection/collection.dart';
       3              : import 'package:flutter_navigation_generator/src/models/importable_type.dart';
       4              : import 'package:flutter_navigation_generator/src/models/route_config.dart';
       5              : import 'package:flutter_navigation_generator/src/utils/case_utils.dart';
       6              : import 'package:flutter_navigation_generator/src/utils/importable_type_to_string.dart';
       7              : import 'package:flutter_navigation_generator/src/utils/route_config_extension.dart';
       8              : import 'package:flutter_navigation_generator/src/utils/utils.dart';
       9              : import 'package:flutter_navigation_generator_annotations/flutter_navigation_generator_annotations.dart';
      10              : 
      11              : class OnGenerateRouteBuilder {
      12              :   final Set<RouteConfig> routes;
      13              :   final ImportableType? pageType;
      14              :   final ImportableType? unknownRoute;
      15              :   final List<ImportableType> defaultGuards;
      16              :   final Uri? targetFile;
      17              : 
      18            1 :   OnGenerateRouteBuilder({
      19              :     required this.routes,
      20              :     this.pageType,
      21              :     this.unknownRoute,
      22              :     this.targetFile,
      23              :     this.defaultGuards = const [],
      24              :   });
      25              : 
      26            1 :   String _withPageType(RouteConfig? route, String screen) {
      27            1 :     final pageClass = route?.pageType != null
      28            3 :         ? typeRefer(route!.pageType).symbol
      29            1 :         : pageType != null
      30            3 :             ? typeRefer(pageType).symbol
      31              :             : 'MaterialPageRoute';
      32            6 :     return '$pageClass<${typeRefer(route?.returnType).symbol}>(builder: (_) => $screen, settings: settings, fullscreenDialog: ${route?.isFullscreenDialog == true},)';
      33              :   }
      34              : 
      35            1 :   String _generateRoute(RouteConfig route) {
      36            4 :     final constructor = route.constructorName == route.routeWidget.className ||
      37            2 :             route.constructorName.isEmpty
      38            2 :         ? route.routeWidget.className
      39            4 :         : '${route.routeWidget.className}.${route.constructorName}';
      40              :     final constructorCall =
      41            4 :         '$constructor(${route.parameters.asMap().map((_, p) {
      42            1 :               final nullableSuffix = p.isNullable ? '?' : '';
      43              :               final convertFromString =
      44            1 :                   ImportableTypeStringConverter.convertFromString(
      45            2 :                       p, 'arguments[\'${p.argumentName}\']');
      46            1 :               return MapEntry(
      47            1 :                 p.argumentName,
      48            4 :                 (p.className == 'Key' || p.className == 'String')
      49            0 :                     ? "arguments['${p.argumentName}'] as ${p.className}$nullableSuffix"
      50            6 :                     : "arguments['${p.argumentName}'] is String ? $convertFromString : arguments['${p.argumentName}'] as ${p.className}${p.typeArguments.isNotEmpty ? '<${p.typeArguments.map((e) => e.className).join(',')}>' : ''}$nullableSuffix",
      51              :               );
      52            8 :             }).entries.map((e) => '${e.key}: ${e.value},').join('')})';
      53              : 
      54              :     var guardsCode = '';
      55            3 :     if ((route.guards ?? defaultGuards).isNotEmpty) {
      56            4 :       for (final guard in route.guards ?? defaultGuards) {
      57            3 :         final insanceName = CaseUtil(guard.className).camelCase;
      58            1 :         guardsCode +=
      59            3 :             'final $insanceName = guards.whereType<${typeRefer(guard).symbol}>().first;\n';
      60            2 :         guardsCode += 'if (!$insanceName.value) {\n';
      61            1 :         guardsCode += '  guardedRouteSettings = settings;\n';
      62            1 :         guardsCode += '  return onGenerateRoute(RouteSettings(\n';
      63            1 :         guardsCode += '    arguments: settings.arguments,\n';
      64            2 :         guardsCode += '    name: $insanceName.alternativeRoute,\n';
      65            1 :         guardsCode += '  ));\n';
      66            1 :         guardsCode += '}\n';
      67              :       }
      68              :     }
      69            2 :     return '${guardsCode}return ${_withPageType(route, constructorCall)};';
      70              :   }
      71              : 
      72            1 :   Method generate() {
      73            1 :     final pageRoutes = routes
      74            2 :         .where((r) =>
      75            1 :             r.generatePageRoute &&
      76            2 :             r.navigationType != NavigationType.bottomSheet &&
      77            2 :             r.navigationType != NavigationType.dialog)
      78            1 :         .toList();
      79            2 :     for (final pageRoute in pageRoutes.toList()) {
      80              :       final pageRoute2 = pageRoutes
      81            5 :           .firstWhere((element) => element.routeName == pageRoute.routeName);
      82            1 :       if (pageRoute != pageRoute2) {
      83            0 :         pageRoutes.remove(pageRoute);
      84              :       }
      85              :     }
      86            1 :     return Method(
      87            1 :       (m) => m
      88            1 :         ..name = 'onGenerateRoute'
      89            1 :         ..returns = const Reference('Route<dynamic>?')
      90            2 :         ..requiredParameters.add(
      91            1 :           Parameter(
      92            1 :             (p) => p
      93            1 :               ..name = 'settings'
      94            1 :               ..type = const Reference('RouteSettings'),
      95              :           ),
      96              :         )
      97            3 :         ..body = Block.of([
      98            2 :           if (pageRoutes.isNotEmpty) ...[
      99              :             const Code(
     100              :                 '''final arguments = settings.arguments is Map ? (settings.arguments as Map).cast<String, dynamic>() : <String, dynamic>{};
     101              :     final settingsUri = Uri.parse(settings.name ?? '');
     102              :     settingsUri.queryParameters.forEach((key, value) {
     103              :       arguments[key] ??= value;
     104              :     });'''),
     105            1 :             Code(
     106           10 :                 'switch (settingsUri.path) {${pageRoutes.where((route) => !route.routeNameContainsParameters).map((route) => 'case RouteNames.${route.asRouteName}: ${_generateRoute(route)}').join('')}}'),
     107              :           ],
     108              :           if (pageRoutes
     109            4 :               .any((element) => element.routeNameContainsParameters)) ...[
     110              :             const Code('final pathSegments = settingsUri.pathSegments;'),
     111              :             ...pageRoutes
     112            3 :                 .where((pageRoute) => pageRoute.routeNameContainsParameters)
     113            1 :                 .groupListsBy(
     114            4 :                     (pageRoute) => pageRoute.routeName.pathSegments.length)
     115            1 :                 .entries
     116            1 :                 .sorted((a, b) => -a.key.compareTo(b.key))
     117            2 :                 .map((group) {
     118            1 :               final pathSegments = group.key;
     119            1 :               var code = 'if (pathSegments.length == $pathSegments) {';
     120            4 :               final pageRoutesMap = group.value.asMap().map((key, value) =>
     121            1 :                   MapEntry(
     122            3 :                       value, value.routeName.parametersFromRouteName.length));
     123            1 :               final pageRoutes = pageRoutesMap.entries
     124            1 :                   .sorted((a, b) => a.value.compareTo(b.value))
     125            3 :                   .map((e) => e.key)
     126            1 :                   .toList();
     127            2 :               for (final pageRoute in pageRoutes) {
     128            2 :                 final pathSegments = pageRoute.routeName.pathSegments;
     129              :                 final hasRigidSegments =
     130            3 :                     pathSegments.any((element) => !element.startsWith(':'));
     131              :                 if (hasRigidSegments) {
     132            1 :                   code += 'if (';
     133            1 :                   code += pathSegments
     134            1 :                       .asMap()
     135            1 :                       .entries
     136            1 :                       .where(
     137            3 :                           (pathSegment) => !pathSegment.value.startsWith(':'))
     138            2 :                       .map((pathSegment) =>
     139            3 :                           'pathSegments[${pathSegment.key}] == \'${pathSegment.value}\'')
     140            1 :                       .join(' && ');
     141            1 :                   code += ') {';
     142              :                 }
     143            1 :                 code += pathSegments
     144            1 :                     .asMap()
     145            1 :                     .entries
     146            4 :                     .where((pathSegment) => pathSegment.value.startsWith(':'))
     147            2 :                     .map((pathSegment) =>
     148            5 :                         'arguments[\'${pathSegments[pathSegment.key].substring(1)}\'] = pathSegments[${pathSegment.key}];')
     149            1 :                     .join('\n');
     150            2 :                 code += _generateRoute(pageRoute);
     151            1 :                 if (hasRigidSegments) code += '}';
     152              :               }
     153              : 
     154            2 :               return Code('$code}');
     155              :             }),
     156              :           ],
     157            2 :           if (unknownRoute != null) ...[
     158            1 :             Code(
     159            6 :                 'return ${_withPageType(null, '${typeRefer(unknownRoute!).symbol!}()')};'),
     160            1 :           ] else ...[
     161              :             const Code('return null;'),
     162              :           ],
     163              :         ]),
     164              :     );
     165              :   }
     166              : }
        

Generated by: LCOV version 2.0-1