// source-scanner.ts — Scan source files for deprecated API patterns (SPEC-041)
import { readFile } from 'node:fs/promises';
import { glob } from 'glob';
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const DEFAULT_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'py'];
const EXCLUDE_PATTERNS = [
    '**/node_modules/**',
    '**/dist/**',
    '**/build/**',
    '**/.git/**',
    '**/coverage/**',
    '**/__pycache__/**',
];
// ---------------------------------------------------------------------------
// File scanner
// ---------------------------------------------------------------------------
/** Find all source files in the project, excluding build/vendor dirs. */
async function findSourceFiles(projectPath, scanPaths = []) {
    const basePaths = scanPaths.length > 0 ? scanPaths.map((p) => `${projectPath}/${p}`) : [projectPath];
    const allFiles = [];
    for (const base of basePaths) {
        for (const ext of DEFAULT_EXTENSIONS) {
            const found = await glob(`${base}/**/*.${ext}`, { ignore: EXCLUDE_PATTERNS });
            allFiles.push(...found);
        }
    }
    return [...new Set(allFiles)];
}
/** Scan a single file for all deprecation patterns. Returns findings. */
async function scanFile(filePath, patterns, projectPath) {
    let content;
    try {
        content = await readFile(filePath, 'utf-8');
    }
    catch {
        return [];
    }
    const lines = content.split('\n');
    const findings = [];
    const relativePath = filePath.replace(projectPath + '/', '');
    for (const pattern of patterns) {
        let regex;
        try {
            regex = new RegExp(pattern.pattern, 'g');
        }
        catch {
            continue; // skip invalid regex
        }
        lines.forEach((line, idx) => {
            if (regex.test(line)) {
                findings.push({
                    file: relativePath,
                    line: idx + 1,
                    apiName: pattern.apiName,
                    deprecatedSince: pattern.deprecatedSince,
                    removedIn: pattern.removedIn ?? undefined,
                    replacement: pattern.replacement,
                    example: pattern.example ?? undefined,
                    severity: pattern.severity,
                });
            }
            // Reset lastIndex for global regex
            regex.lastIndex = 0;
        });
    }
    return findings;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Scan all source files in the project for deprecated API patterns.
 */
export async function scanForDeprecations(projectPath, patterns, scanPaths = []) {
    if (patterns.length === 0) {
        return [];
    }
    const files = await findSourceFiles(projectPath, scanPaths);
    const allFindings = [];
    for (const file of files) {
        const fileFindings = await scanFile(file, patterns, projectPath);
        allFindings.push(...fileFindings);
    }
    return allFindings;
}
//# sourceMappingURL=source-scanner.js.map