/**
 * Function type conversion
 *
 * Phase 5 Step 4: Uses local parameter helper (no ProgramContext dependency).
 * Type conversion should NOT depend on statement conversion.
 */
import * as ts from "typescript";
import { convertBindingName } from "../../../syntax/binding-patterns.js";
/**
 * Convert TypeScript function type to IR function type
 */
export const convertFunctionType = (node, binding, convertType) => {
    const typeParameters = convertFunctionTypeParameters(node.typeParameters, binding, convertType);
    return {
        kind: "functionType",
        ...(typeParameters ? { typeParameters } : {}),
        parameters: convertTypeParameters(node.parameters, binding, convertType),
        returnType: convertType(node.type, binding),
    };
};
const convertFunctionTypeParameters = (typeParameters, binding, convertType) => {
    if (!typeParameters || typeParameters.length === 0) {
        return undefined;
    }
    return typeParameters.map((typeParameter) => ({
        kind: "typeParameter",
        name: typeParameter.name.text,
        constraint: typeParameter.constraint
            ? convertType(typeParameter.constraint, binding)
            : undefined,
        default: typeParameter.default
            ? convertType(typeParameter.default, binding)
            : undefined,
        variance: undefined,
        isStructuralConstraint: !!typeParameter.constraint &&
            ts.isTypeLiteralNode(typeParameter.constraint),
        structuralMembers: undefined,
    }));
};
/**
 * Convert parameters for type signatures (no initializers, no ProgramContext).
 *
 * This is used for FunctionTypeNode and MethodSignature in type contexts.
 * Unlike statement-converter's convertParameters, this:
 * - Does NOT convert initializers (type signatures don't have them)
 * - Does NOT require ProgramContext
 * - Takes a convertType function for type node conversion
 */
const convertTypeParameters = (parameters, binding, convertType) => {
    return parameters.map((param) => {
        let passing = "value";
        let actualType = param.type;
        // Detect ref<T>, out<T>, in<T>, inref<T> wrapper types
        if (param.type &&
            ts.isTypeReferenceNode(param.type) &&
            ts.isIdentifier(param.type.typeName)) {
            const typeName = param.type.typeName.text;
            if ((typeName === "ref" ||
                typeName === "out" ||
                typeName === "in" ||
                typeName === "inref") &&
                param.type.typeArguments &&
                param.type.typeArguments.length > 0) {
                // Set passing mode (both "in" and "inref" map to C# "in")
                passing =
                    typeName === "in" || typeName === "inref"
                        ? "in"
                        : typeName;
                // Extract wrapped type
                actualType = param.type.typeArguments[0];
            }
        }
        // Convert type if present
        const paramType = actualType ? convertType(actualType, binding) : undefined;
        return {
            kind: "parameter",
            pattern: convertBindingName(param.name),
            type: paramType,
            // Type signatures don't have initializers
            initializer: undefined,
            isOptional: !!param.questionToken,
            isRest: !!param.dotDotDotToken,
            passing,
        };
    });
};
//# sourceMappingURL=functions.js.map