/**
 * Dart Language Provider
 *
 * Dart traits:
 *   - importSemantics: 'wildcard-leaf' (Dart imports bring everything public into scope)
 *   - exportChecker: public if no leading underscore
 *   - Dart SDK imports (dart:*) and external packages are skipped
 *   - enclosingFunctionFinder: Dart's tree-sitter grammar places function_body
 *     as a sibling of function_signature/method_signature (not as a child).
 *     The hook resolves the enclosing function by inspecting the previous sibling.
 */
import { FUNCTION_NODE_TYPES } from '../utils/ast-helpers.js';
import { SupportedLanguages } from '../../../_shared/index.js';
import { createClassExtractor } from '../class-extractors/generic.js';
import { dartClassConfig } from '../class-extractors/configs/dart.js';
import { defineLanguage } from '../language-provider.js';
import { typeConfig as dartConfig } from '../type-extractors/dart.js';
import { dartExportChecker } from '../export-detection.js';
import { createImportResolver } from '../import-resolvers/resolver-factory.js';
import { dartImportConfig } from '../import-resolvers/configs/dart.js';
import { DART_QUERIES } from '../tree-sitter-queries.js';
import { createFieldExtractor } from '../field-extractors/generic.js';
import { dartConfig as dartFieldConfig } from '../field-extractors/configs/dart.js';
import { createMethodExtractor } from '../method-extractors/generic.js';
import { dartMethodConfig } from '../method-extractors/configs/dart.js';
import { createVariableExtractor } from '../variable-extractors/generic.js';
import { dartVariableConfig } from '../variable-extractors/configs/dart.js';
import { createCallExtractor } from '../call-extractors/generic.js';
import { dartCallConfig } from '../call-extractors/configs/dart.js';
import { createHeritageExtractor } from '../heritage-extractors/generic.js';
/**
 * Resolve the enclosing function from a `function_body` node by looking at its
 * previous sibling.  In Dart's tree-sitter grammar, function_signature and
 * function_body are siblings under program or class_body, unlike most languages
 * where the function declaration wraps both.
 *
 * Extracts the function name inline — Dart uses function_signature and
 * method_signature (which wraps function_signature) as its FUNCTION_NODE_TYPES.
 */
const dartEnclosingFunctionFinder = (node) => {
    if (node.type !== 'function_body')
        return null;
    const prev = node.previousSibling;
    if (!prev || !FUNCTION_NODE_TYPES.has(prev.type))
        return null;
    // method_signature wraps function_signature — unwrap to reach the name
    let target = prev;
    let label = 'Function';
    if (prev.type === 'method_signature') {
        label = 'Method';
        for (let i = 0; i < prev.childCount; i++) {
            const c = prev.child(i);
            if (c?.type === 'function_signature') {
                target = c;
                break;
            }
        }
    }
    const funcName = target.childForFieldName?.('name')?.text ?? null;
    return funcName ? { funcName, label } : null;
};
const BUILT_INS = new Set([
    'setState',
    'mounted',
    'debugPrint',
    'runApp',
    'showDialog',
    'showModalBottomSheet',
    'Navigator',
    'push',
    'pushNamed',
    'pushReplacement',
    'pop',
    'maybePop',
    'ScaffoldMessenger',
    'showSnackBar',
    'deactivate',
    'reassemble',
    'debugDumpApp',
    'debugDumpRenderTree',
    'then',
    'catchError',
    'whenComplete',
    'listen',
]);
export const dartProvider = defineLanguage({
    id: SupportedLanguages.Dart,
    extensions: ['.dart'],
    treeSitterQueries: DART_QUERIES,
    typeConfig: dartConfig,
    exportChecker: dartExportChecker,
    importResolver: createImportResolver(dartImportConfig),
    importSemantics: 'wildcard-leaf',
    callExtractor: createCallExtractor(dartCallConfig),
    fieldExtractor: createFieldExtractor(dartFieldConfig),
    methodExtractor: createMethodExtractor(dartMethodConfig),
    variableExtractor: createVariableExtractor(dartVariableConfig),
    classExtractor: createClassExtractor(dartClassConfig),
    heritageExtractor: createHeritageExtractor(SupportedLanguages.Dart),
    enclosingFunctionFinder: dartEnclosingFunctionFinder,
    builtInNames: BUILT_INS,
});
