// P1: Error ignored with _ — CRITICAL
// Matches: result, _ := something.Func() or n, _ = fmt.Println()
const ERROR_IGNORED = /,\s*_\s*:?=\s*[\w.]+\s*\(/;
// P2: Type assertion without ok — HIGH
// Matches: .(SomeType) but not , ok :=
const TYPE_ASSERT_NO_OK = /\.\([A-Z]\w*\)/;
const TYPE_ASSERT_WITH_OK = /,\s*ok\s*:?=.*\.\([A-Z]\w*\)/;
// P3: nil dereference — HIGH
// Detects: calling a method on a value returned by a function without nil check
// Simple heuristic: func() result immediately accessed with .
const NIL_DEREF_PATTERN = /\w+\s*:?=\s*\w+\s*\([^)]*\)\s*\n\s*\w+\.\w+/;
function splitLines(content) {
    return content.split('\n');
}
function detectP1(filePath, content) {
    const risks = [];
    const lines = splitLines(content);
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i] ?? '';
        if (ERROR_IGNORED.test(line)) {
            risks.push({
                file: filePath,
                line: i + 1,
                pattern: 'GO_ERROR_IGNORED',
                severity: 'CRITICAL',
                description: 'Error return value ignored with _. Ignoring errors leads to silent failures and unexpected state.',
                suggestedFix: 'Handle the error: if err != nil { return err } or log and handle appropriately.',
                autoFixable: false,
            });
        }
    }
    return risks;
}
function detectP2(filePath, content) {
    const risks = [];
    const lines = splitLines(content);
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i] ?? '';
        // Skip lines that use the safe two-value form
        if (TYPE_ASSERT_WITH_OK.test(line)) {
            continue;
        }
        if (TYPE_ASSERT_NO_OK.test(line)) {
            risks.push({
                file: filePath,
                line: i + 1,
                pattern: 'GO_TYPE_ASSERT_NO_OK',
                severity: 'HIGH',
                description: 'Type assertion .(Type) without ok check panics if the interface value has a different underlying type.',
                suggestedFix: 'Use the two-value form: value, ok := x.(Type); if !ok { ... }',
                autoFixable: false,
            });
        }
    }
    return risks;
}
function detectP3(filePath, content) {
    const risks = [];
    if (!NIL_DEREF_PATTERN.test(content)) {
        return risks;
    }
    // Find lines with immediate method calls after assignments from functions
    const lines = splitLines(content);
    for (let i = 0; i < lines.length - 1; i++) {
        const current = lines[i] ?? '';
        const next = lines[i + 1] ?? '';
        const isAssignment = /\w+\s*:?=\s*\w+\s*\([^)]*\)/.test(current);
        const isImmediateAccess = /^\s*\w+\.\w+/.test(next);
        const hasNilCheck = /if\s+\w+\s*==\s*nil/.test(current) || /if\s+\w+\s*!=\s*nil/.test(next);
        if (isAssignment && isImmediateAccess && !hasNilCheck) {
            risks.push({
                file: filePath,
                line: i + 2,
                pattern: 'GO_POTENTIAL_NIL_DEREF',
                severity: 'HIGH',
                description: 'Potential nil pointer dereference: function return value used immediately without nil check.',
                suggestedFix: 'Check for nil before accessing fields: if result != nil { ... }',
                autoFixable: false,
            });
        }
    }
    return risks;
}
export const goDetector = {
    language: 'Go',
    fileExtensions: ['.go'],
    detect(filePath, content) {
        return [
            ...detectP1(filePath, content),
            ...detectP2(filePath, content),
            ...detectP3(filePath, content),
        ];
    },
};
//# sourceMappingURL=go-detector.js.map