"use strict";
/**
 * Shared Code Analysis Utilities
 *
 * ParsedFile-aware versions of control flow analysis and context extraction.
 * Consolidates duplicated logic from control-flow.ts and various detectors.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.isInsideTryCatch = isInsideTryCatch;
exports.hasTryCatchNearby = hasTryCatchNearby;
exports.extractFunctionContext = extractFunctionContext;
exports.searchSurroundingLines = searchSurroundingLines;
const context_helpers_1 = require("./context-helpers");
/**
 * Check if a line is inside a try-catch block.
 * Tracks brace depth from the start of the file to the target line.
 */
function isInsideTryCatch(file, lineNumber) {
    const lines = file.lines;
    let tryDepth = 0;
    let inTryBlock = false;
    const braceStack = [];
    for (let i = 0; i < lineNumber && i < lines.length; i++) {
        const line = lines[i];
        if (/\btry\s*\{/.test(line) && !(0, context_helpers_1.isComment)(line)) {
            inTryBlock = true;
            tryDepth++;
            const openBraces = (line.match(/\{/g) || []).length;
            const closeBraces = (line.match(/\}/g) || []).length;
            for (let j = 0; j < openBraces - closeBraces; j++) {
                braceStack.push('try');
            }
        }
        else if (/\bcatch\s*\(/.test(line) && !(0, context_helpers_1.isComment)(line)) {
            // Entering catch block - still protected
        }
        else if (/\bfinally\s*\{/.test(line) && !(0, context_helpers_1.isComment)(line)) {
            // Entering finally block - still protected
        }
        else {
            const openBraces = (line.match(/\{/g) || []).length;
            const closeBraces = (line.match(/\}/g) || []).length;
            for (let j = 0; j < openBraces; j++) {
                braceStack.push(inTryBlock && tryDepth > 0 ? 'try' : 'other');
            }
            for (let j = 0; j < closeBraces; j++) {
                const popped = braceStack.pop();
                if (popped === 'try') {
                    tryDepth--;
                    if (tryDepth === 0) {
                        inTryBlock = false;
                    }
                }
            }
        }
    }
    return tryDepth > 0;
}
/**
 * Simpler heuristic: check if there's a try-catch in the same function scope.
 * Looks for try { before the line and } catch after, within reasonable bounds.
 */
function hasTryCatchNearby(file, lineNumber, windowSize = 20) {
    const lines = file.lines;
    const startLine = Math.max(0, lineNumber - windowSize);
    const endLine = Math.min(lines.length, lineNumber + windowSize);
    // Look backward for 'try {'
    let foundTry = false;
    for (let i = lineNumber - 1; i >= startLine; i--) {
        const line = lines[i];
        if (/\btry\s*\{/.test(line) && !(0, context_helpers_1.isComment)(line)) {
            foundTry = true;
            break;
        }
        if (/\b(function|async function|=>|class)\b/.test(line) && /\{/.test(line)) {
            break;
        }
    }
    if (!foundTry)
        return false;
    // Look forward for '} catch'
    for (let i = lineNumber; i < endLine; i++) {
        const line = lines[i];
        if (/\}\s*catch\s*\(/.test(line) && !(0, context_helpers_1.isComment)(line)) {
            return true;
        }
        if (i > lineNumber && /\b(function|async function|class)\b/.test(line) && /\{/.test(line)) {
            break;
        }
    }
    return false;
}
/**
 * Extract function context where a call is being made.
 * Looks backwards from the current line to find enclosing function name.
 * Returns lowercase function name or null if not found.
 */
function extractFunctionContext(file, lineNumber) {
    const lines = file.lines;
    const start = Math.max(0, lineNumber - 20);
    for (let i = lineNumber; i >= start; i--) {
        const line = lines[i];
        // Skip anonymous arrow functions in callbacks
        const hasMethodCallWithArrowCallback = /\.\w+\(.*\([^)]*\)\s*=>/.test(line);
        if (hasMethodCallWithArrowCallback && !/^(const|let|var|function|async|export)/.test(line.trim())) {
            continue;
        }
        // Named function declaration
        const funcMatch = line.match(/function\s+(\w+)\s*\(/);
        if (funcMatch) {
            return funcMatch[1].toLowerCase();
        }
        // Arrow function with const/let/var
        const arrowMatch = line.match(/(const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)(?:\s*:\s*\w+)?\s*=>/);
        if (arrowMatch) {
            return arrowMatch[2].toLowerCase();
        }
        // Method declaration
        const methodMatch = line.match(/^\s*(?:async\s+)?(\w+)\s*\([^)]*\)\s*\{/);
        if (methodMatch) {
            return methodMatch[1].toLowerCase();
        }
        // Export function
        const exportFuncMatch = line.match(/export\s+(?:async\s+)?function\s+(\w+)\s*\(/);
        if (exportFuncMatch) {
            return exportFuncMatch[1].toLowerCase();
        }
        // Export const arrow
        const exportConstMatch = line.match(/export\s+const\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)(?:\s*:\s*\w+)?\s*=>/);
        if (exportConstMatch) {
            return exportConstMatch[1].toLowerCase();
        }
    }
    return null;
}
/**
 * Search surrounding lines for any of the given patterns.
 * Consolidates the ±N line search pattern used across 55+ occurrences.
 *
 * @param file ParsedFile to search in
 * @param lineIndex 0-based center line
 * @param patterns RegExp patterns to search for
 * @param windowSize number of lines before and after to search
 * @returns found: true if any pattern matched, with matched line and pattern
 */
function searchSurroundingLines(file, lineIndex, patterns, windowSize) {
    const startIndex = Math.max(0, lineIndex - windowSize);
    const endIndex = Math.min(file.lineCount - 1, lineIndex + windowSize);
    for (let i = startIndex; i <= endIndex; i++) {
        const line = file.lines[i];
        for (const pattern of patterns) {
            if (pattern.test(line)) {
                return { found: true, matchedLine: i, matchedPattern: pattern };
            }
        }
    }
    return { found: false };
}
//# sourceMappingURL=code-analysis.js.map