/**
 * C and C++ language providers.
 *
 * Both languages use wildcard import semantics (headers expose all symbols
 * via #include). Neither language has named binding extraction.
 *
 * C uses 'first-wins' MRO (no inheritance). C++ uses 'leftmost-base' MRO
 * for its left-to-right multiple inheritance resolution order.
 */
import { SupportedLanguages } from '../../../_shared/index.js';
import { createClassExtractor } from '../class-extractors/generic.js';
import { cClassConfig, cppClassConfig } from '../class-extractors/configs/c-cpp.js';
import { defineLanguage } from '../language-provider.js';
import { typeConfig as cCppConfig } from '../type-extractors/c-cpp.js';
import { cCppExportChecker } from '../export-detection.js';
import { createImportResolver } from '../import-resolvers/resolver-factory.js';
import { cImportConfig, cppImportConfig } from '../import-resolvers/configs/c-cpp.js';
import { C_QUERIES, CPP_QUERIES } from '../tree-sitter-queries.js';
/**
 * Node types for standard function declarations that need C/C++ declarator handling.
 * Used by cCppExtractFunctionName to determine how to extract the function name.
 */
const FUNCTION_DECLARATION_TYPES = new Set([
    'function_declaration',
    'function_definition',
    'async_function_declaration',
    'generator_function_declaration',
    'function_item',
]);
import { createFieldExtractor } from '../field-extractors/generic.js';
import { cConfig as cFieldConfig, cppConfig as cppFieldConfig, } from '../field-extractors/configs/c-cpp.js';
import { createMethodExtractor } from '../method-extractors/generic.js';
import { cMethodConfig, cppMethodConfig } from '../method-extractors/configs/c-cpp.js';
import { createVariableExtractor } from '../variable-extractors/generic.js';
import { cVariableConfig, cppVariableConfig } from '../variable-extractors/configs/c-cpp.js';
import { createCallExtractor } from '../call-extractors/generic.js';
import { cCallConfig, cppCallConfig } from '../call-extractors/configs/c-cpp.js';
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
const C_BUILT_INS = new Set([
    'printf',
    'fprintf',
    'sprintf',
    'snprintf',
    'vprintf',
    'vfprintf',
    'vsprintf',
    'vsnprintf',
    'scanf',
    'fscanf',
    'sscanf',
    'malloc',
    'calloc',
    'realloc',
    'free',
    'memcpy',
    'memmove',
    'memset',
    'memcmp',
    'strlen',
    'strcpy',
    'strncpy',
    'strcat',
    'strncat',
    'strcmp',
    'strncmp',
    'strstr',
    'strchr',
    'strrchr',
    'atoi',
    'atol',
    'atof',
    'strtol',
    'strtoul',
    'strtoll',
    'strtoull',
    'strtod',
    'sizeof',
    'offsetof',
    'typeof',
    'assert',
    'abort',
    'exit',
    '_exit',
    'fopen',
    'fclose',
    'fread',
    'fwrite',
    'fseek',
    'ftell',
    'rewind',
    'fflush',
    'fgets',
    'fputs',
    'likely',
    'unlikely',
    'BUG',
    'BUG_ON',
    'WARN',
    'WARN_ON',
    'WARN_ONCE',
    'IS_ERR',
    'PTR_ERR',
    'ERR_PTR',
    'IS_ERR_OR_NULL',
    'ARRAY_SIZE',
    'container_of',
    'list_for_each_entry',
    'list_for_each_entry_safe',
    'min',
    'max',
    'clamp',
    'abs',
    'swap',
    'pr_info',
    'pr_warn',
    'pr_err',
    'pr_debug',
    'pr_notice',
    'pr_crit',
    'pr_emerg',
    'printk',
    'dev_info',
    'dev_warn',
    'dev_err',
    'dev_dbg',
    'GFP_KERNEL',
    'GFP_ATOMIC',
    'spin_lock',
    'spin_unlock',
    'spin_lock_irqsave',
    'spin_unlock_irqrestore',
    'mutex_lock',
    'mutex_unlock',
    'mutex_init',
    'kfree',
    'kmalloc',
    'kzalloc',
    'kcalloc',
    'krealloc',
    'kvmalloc',
    'kvfree',
    'get',
    'put',
]);
const cClassExtractor = createClassExtractor(cClassConfig);
const cppClassExtractor = createClassExtractor(cppClassConfig);
/**
 * C/C++ function name extraction — unwraps pointer_declarator / reference_declarator /
 * function_declarator / qualified_identifier chains to find the actual function name.
 * Handles field_identifier (method inside class body) and parenthesized_declarator.
 */
const cCppExtractFunctionName = (node) => {
    if (!FUNCTION_DECLARATION_TYPES.has(node.type))
        return null;
    let funcName = null;
    let label = 'Function';
    // C/C++: function_definition -> [pointer_declarator ->] function_declarator -> qualified_identifier/identifier
    // Unwrap pointer_declarator / reference_declarator wrappers to reach function_declarator
    let declarator = node.childForFieldName?.('declarator');
    if (!declarator) {
        for (let i = 0; i < node.childCount; i++) {
            const c = node.child(i);
            if (c?.type === 'function_declarator') {
                declarator = c;
                break;
            }
        }
    }
    while (declarator &&
        (declarator.type === 'pointer_declarator' || declarator.type === 'reference_declarator')) {
        let nextDeclarator = declarator.childForFieldName?.('declarator');
        if (!nextDeclarator) {
            for (let i = 0; i < declarator.childCount; i++) {
                const c = declarator.child(i);
                if (c?.type === 'function_declarator' ||
                    c?.type === 'pointer_declarator' ||
                    c?.type === 'reference_declarator') {
                    nextDeclarator = c;
                    break;
                }
            }
        }
        declarator = nextDeclarator;
    }
    if (declarator) {
        let innerDeclarator = declarator.childForFieldName?.('declarator');
        if (!innerDeclarator) {
            for (let i = 0; i < declarator.childCount; i++) {
                const c = declarator.child(i);
                if (c?.type === 'qualified_identifier' ||
                    c?.type === 'identifier' ||
                    c?.type === 'field_identifier' ||
                    c?.type === 'parenthesized_declarator') {
                    innerDeclarator = c;
                    break;
                }
            }
        }
        if (innerDeclarator?.type === 'qualified_identifier') {
            let nameNode = innerDeclarator.childForFieldName?.('name');
            if (!nameNode) {
                for (let i = 0; i < innerDeclarator.childCount; i++) {
                    const c = innerDeclarator.child(i);
                    if (c?.type === 'identifier') {
                        nameNode = c;
                        break;
                    }
                }
            }
            if (nameNode?.text) {
                funcName = nameNode.text;
                label = 'Method';
            }
        }
        else if (innerDeclarator?.type === 'identifier' ||
            innerDeclarator?.type === 'field_identifier') {
            // field_identifier is used for method names inside C++ class bodies
            funcName = innerDeclarator.text;
            if (innerDeclarator.type === 'field_identifier')
                label = 'Method';
        }
        else if (innerDeclarator?.type === 'parenthesized_declarator') {
            let nestedId = null;
            for (let i = 0; i < innerDeclarator.childCount; i++) {
                const c = innerDeclarator.child(i);
                if (c?.type === 'qualified_identifier' || c?.type === 'identifier') {
                    nestedId = c;
                    break;
                }
            }
            if (nestedId?.type === 'qualified_identifier') {
                let nameNode = nestedId.childForFieldName?.('name');
                if (!nameNode) {
                    for (let i = 0; i < nestedId.childCount; i++) {
                        const c = nestedId.child(i);
                        if (c?.type === 'identifier') {
                            nameNode = c;
                            break;
                        }
                    }
                }
                if (nameNode?.text) {
                    funcName = nameNode.text;
                    label = 'Method';
                }
            }
            else if (nestedId?.type === 'identifier') {
                funcName = nestedId.text;
            }
        }
    }
    // Fallback for other node types in FUNCTION_DECLARATION_TYPES (e.g. function_item for Rust in C++ tree)
    if (!funcName) {
        let nameNode = node.childForFieldName?.('name');
        if (!nameNode) {
            for (let i = 0; i < node.childCount; i++) {
                const c = node.child(i);
                if (c?.type === 'identifier' ||
                    c?.type === 'property_identifier' ||
                    c?.type === 'simple_identifier') {
                    nameNode = c;
                    break;
                }
            }
        }
        funcName = nameNode?.text ?? null;
    }
    return { funcName, label };
};
/** Check if a C/C++ function_definition is inside a class or struct body.
 *  Used by cppLabelOverride to skip duplicate function captures
 *  that are already covered by definition.method queries. */
function isCppInsideClassOrStruct(functionNode) {
    let ancestor = functionNode?.parent ?? null;
    while (ancestor) {
        if (ancestor.type === 'class_specifier' || ancestor.type === 'struct_specifier')
            return true;
        ancestor = ancestor.parent;
    }
    return false;
}
/** Label override shared by C and C++: skip function_definition captures inside class/struct
 *  bodies (they're duplicates of definition.method captures). */
const cppLabelOverride = (functionNode, defaultLabel) => {
    if (defaultLabel !== 'Function')
        return defaultLabel;
    return isCppInsideClassOrStruct(functionNode) ? null : defaultLabel;
};
export const cProvider = defineLanguage({
    id: SupportedLanguages.C,
    extensions: ['.c'],
    treeSitterQueries: C_QUERIES,
    typeConfig: cCppConfig,
    exportChecker: cCppExportChecker,
    importResolver: createImportResolver(cImportConfig),
    importSemantics: 'wildcard-transitive',
    callExtractor: createCallExtractor(cCallConfig),
    fieldExtractor: createFieldExtractor(cFieldConfig),
    methodExtractor: createMethodExtractor({
        ...cMethodConfig,
        extractFunctionName: cCppExtractFunctionName,
    }),
    variableExtractor: createVariableExtractor(cVariableConfig),
    classExtractor: cClassExtractor,
    heritageExtractor: createHeritageExtractor(SupportedLanguages.C),
    labelOverride: cppLabelOverride,
    builtInNames: C_BUILT_INS,
});
export const cppProvider = defineLanguage({
    id: SupportedLanguages.CPlusPlus,
    extensions: ['.cpp', '.cc', '.cxx', '.h', '.hpp', '.hxx', '.hh'],
    treeSitterQueries: CPP_QUERIES,
    typeConfig: cCppConfig,
    exportChecker: cCppExportChecker,
    importResolver: createImportResolver(cppImportConfig),
    importSemantics: 'wildcard-transitive',
    mroStrategy: 'leftmost-base',
    callExtractor: createCallExtractor(cppCallConfig),
    fieldExtractor: createFieldExtractor(cppFieldConfig),
    methodExtractor: createMethodExtractor({
        ...cppMethodConfig,
        extractFunctionName: cCppExtractFunctionName,
    }),
    variableExtractor: createVariableExtractor(cppVariableConfig),
    classExtractor: cppClassExtractor,
    heritageExtractor: createHeritageExtractor(SupportedLanguages.CPlusPlus),
    labelOverride: cppLabelOverride,
    builtInNames: C_BUILT_INS,
});
