ServerLifecycleComponent.fromClassElement constructor

ServerLifecycleComponent.fromClassElement(
  1. ClassElement element,
  2. AnnotationArguments arguments, {
  3. ConstructorElement? constructor,
  4. DartObject? instanceFields,
  5. List<DartType> typeArguments = const [],
})

Implementation

factory ServerLifecycleComponent.fromClassElement(
  ClassElement element,
  AnnotationArguments arguments, {
  ConstructorElement? constructor,
  DartObject? instanceFields,
  List<DartType> typeArguments = const [],
}) {
  final genericTypes = element.typeParameters
      .map(ServerGenericType.fromElement)
      .toList();
  final typeSubstitutions = buildTypeSubstitutionMap(element, typeArguments);

  Iterable<ServerLifecycleComponentMethod> methodsFromElement() sync* {
    for (final method in element.methods) {
      if (ServerLifecycleComponentMethod.fromElement(
            method,
            typeSubstitutions: typeSubstitutions,
          )
          case final componentMethod?) {
        yield componentMethod;
      }
    }
  }

  final methods = methodsFromElement().toList();

  final guards = <ServerLifecycleComponentMethod>[];
  final middlewares = <ServerLifecycleComponentMethod>[];
  final interceptors = (
    pre: <ServerLifecycleComponentMethod>[],
    post: <ServerLifecycleComponentMethod>[],
  );
  final exceptionCatchers = <ServerLifecycleComponentMethod>[];
  final requestWrappers = <ServerLifecycleComponentMethod>[];

  for (final method in methods) {
    final _ = switch (true) {
      _ when method.isGuard => guards.add(method),
      _ when method.isMiddleware => middlewares.add(method),
      _ when method.isInterceptorPre => interceptors.pre.add(method),
      _ when method.isInterceptorPost => interceptors.post.add(method),
      _ when method.isExceptionCatcher => exceptionCatchers.add(method),
      _ when method.isRequestWrapper => requestWrappers.add(method),
      _ => null,
    };
  }

  final ctor =
      constructor ?? element.constructors.firstWhereOrNull((e) => e.isPublic);

  if (ctor == null) {
    throw ArgumentError.value(
      LifecycleComponent,
      'type',
      'Expected a class element with a public constructor',
    );
  }

  final paramNamesFromConstructor = {
    for (final p in ctor.formalParameters) p.name ?? '',
  };

  final params = <ServerParam>[
    ...ctor.formalParameters.map((FormalParameterElement e) {
      final param = ServerParam.fromElement(
        e,
        typeSubstitutions: typeSubstitutions,
      );

      if (arguments.all[param.name] case final arg?) {
        param.argument = arg;
      }

      return param;
    }),
    if (instanceFields != null)
      for (final field in element.fields) ...[
        if (_getInitializerListFieldValue(
              field,
              paramNamesFromConstructor,
              instanceFields,
            )
            case final value?)
          ServerParam(
            name:
                field.name ??
                (throw ArgumentError(
                  'Expected a named field on ${element.name}, '
                  'got an unnamed field',
                )),
            type: ServerType.fromType(
              typeSubstitutions.isEmpty
                  ? field.type
                  : substituteType(field.type, typeSubstitutions),
            ),
            isRequired: true,
            isNamed: true,
            argument: AnnotationArgument.fromFieldValue(
              field.name ??
                  (throw ArgumentError(
                    'Expected a named field on ${element.name}, '
                    'got an unnamed field',
                  )),
              value,
              field,
            ),
          ),
      ],
  ];

  final name = element.name;

  if (name == null) {
    throw Exception('Class name is null');
  }

  return ServerLifecycleComponent(
    name: name,
    guards: guards,
    middlewares: middlewares,
    interceptors: interceptors,
    exceptionCatchers: exceptionCatchers,
    requestWrappers: requestWrappers,
    params: params,
    import: ServerImports.fromElement(ctor.returnType.element),
    arguments: arguments,
    genericTypes: genericTypes,
    instantiatedTypeArguments: typeSubstitutions.isNotEmpty
        ? typeArguments.map(ServerType.fromType).toList()
        : const [],
  );
}