typeTestType method

Parser<TypeNode> typeTestType()
inherited

A type used in type tests and type casts (is, is!, as), where the outermost type can have a trailing ? if not followed by an expression (disambiguating against ternary conditional ? :).

Implementation

Parser<TypeNode> typeTestType() => [
  // Standalone Function type with optional guarded trailing nullability: Function(...)
  seq4(
    ref0(functionToken),
    ref0(typeParameters).optionalWith(const <TypeParameterNode>[]),
    ref0(formalParameters),
    ref0(typeTestNullableSuffix).optional(),
  ).map4(
    (_, typeParams, params, q) => FunctionTypeNode(
      typeParameters: typeParams,
      parameters: params,
      isNullable: q != null,
    ),
  ),
  // Non-function base type with function suffixes and optional guarded trailing nullability
  seq3(
    ref0(nonFunctionTypeWithoutNullable),
    seq3(
      ref0(functionToken),
      ref0(typeParameters).optionalWith(const <TypeParameterNode>[]),
      ref0(formalParameters),
    ).star(),
    ref0(typeTestNullableSuffix).optional(),
  ).map3((base, functionSuffixes, q) {
    var current = base;
    for (var i = 0; i < functionSuffixes.length; i++) {
      final suffix = functionSuffixes[i];
      final isLast = i == functionSuffixes.length - 1;
      current = FunctionTypeNode(
        returnType: current,
        typeParameters: suffix.$2,
        parameters: suffix.$3,
        isNullable: isLast && q != null,
      );
    }
    if (functionSuffixes.isEmpty && q != null) {
      current = current is NamedTypeNode
          ? NamedTypeNode(
              name: current.name,
              typeArguments: current.typeArguments,
              isNullable: true,
            )
          : (current is RecordTypeNode
                ? RecordTypeNode(
                    positionalFields: current.positionalFields,
                    namedFields: current.namedFields,
                    isNullable: true,
                  )
                : current);
    }
    return current;
  }),
].toChoiceParser();