generateGenericInterceptor function

String generateGenericInterceptor(
  1. GenericInterceptorConfig config
)

Emits the full D4.registerBridged{,Static}MethodInterceptor(...) call for config, including the re-dispatch switch (typeName) over its type-arg allow-list.

Returns the empty string when GenericInterceptorConfig.typeArgVariants is empty (nothing to re-dispatch). The output is a single statement (trailing newline included) suitable for emission inside the generated interceptor registration function.

Implementation

String generateGenericInterceptor(GenericInterceptorConfig config) {
  if (config.typeArgVariants.isEmpty) return '';

  final className = config.className;
  final methodName = config.methodName;
  final ctxIndex = config.contextArgIndex;
  final ctxType = config.contextArgType;
  // Static re-dispatch targets the class itself; instance re-dispatch targets
  // the validated receiver.
  final receiver = config.isStatic ? className : 't';

  final registerFn = config.isStatic
      ? 'registerBridgedStaticMethodInterceptor'
      : 'registerBridgedMethodInterceptor';
  final lambdaParams = config.isStatic
      ? '(visitor, positional, named, typeArgs)'
      : '(visitor, target, positional, named, typeArgs)';

  final b = StringBuffer();
  b.writeln('  // Re-dispatch $className.$methodName<T> over the declared');
  b.writeln("  // type-arg allow-list so the type-erased bridge boundary doesn't");
  b.writeln('  // collapse <T> to <dynamic>. Generated by the d4rtgen generic-');
  b.writeln('  // interceptor generator.');
  b.writeln("  D4.$registerFn('$className', '$methodName',");
  b.writeln('      $lambdaParams {');
  if (!config.isStatic) {
    b.writeln('    final t = target is $className ? target : null;');
    b.writeln('    if (t == null) return null;');
  }
  b.writeln('    if (positional.length <= $ctxIndex) return null;');
  b.writeln('    final ctx = positional[$ctxIndex];');
  b.writeln('    if (ctx is! $ctxType) return null;');
  b.writeln('    final typeName = (typeArgs != null && typeArgs.isNotEmpty)');
  b.writeln('        ? typeArgs[0].name');
  b.writeln('        : null;');
  b.writeln('    final byType = switch (typeName) {');
  for (final t in config.typeArgVariants) {
    b.writeln("      '$t' => $receiver.$methodName<$t>(ctx),");
  }
  b.writeln('      _ => null,');
  b.writeln('    };');
  final fallback = config.fallbackExpr;
  if (fallback != null) {
    b.writeln('    if (byType != null) return byType;');
    b.writeln('    return $fallback;');
  } else {
    b.writeln('    return byType;');
  }
  b.writeln('  });');
  return b.toString();
}