import { DiagnosticSeverity, DiagnosticTag } from "vscode-languageserver/node";
import { Visitor } from "@herb-tools/core";
import { isHTMLTextNode } from "@herb-tools/core";
export class Diagnostics {
    constructor(connection, documentService, parserService, linterService, configService) {
        this.diagnostics = new Map();
        this.connection = connection;
        this.documentService = documentService;
        this.parserService = parserService;
        this.linterService = linterService;
        this.configService = configService;
    }
    async validate(textDocument) {
        let allDiagnostics = [];
        if (textDocument.uri.endsWith('.herb.yml')) {
            allDiagnostics = await this.configService.validateDocument(textDocument);
        }
        else {
            const parseResult = this.parserService.parseDocument(textDocument);
            const lintResult = await this.linterService.lintDocument(textDocument);
            const unreachableCodeDiagnostics = this.getUnreachableCodeDiagnostics(parseResult.document);
            allDiagnostics = [
                ...parseResult.diagnostics,
                ...lintResult.diagnostics,
                ...unreachableCodeDiagnostics,
            ];
        }
        this.diagnostics.set(textDocument, allDiagnostics);
        this.sendDiagnosticsFor(textDocument);
    }
    getUnreachableCodeDiagnostics(document) {
        const collector = new UnreachableCodeCollector();
        collector.visit(document);
        return collector.diagnostics;
    }
    async refreshDocument(document) {
        await this.validate(document);
    }
    async refreshAllDocuments() {
        const documents = this.documentService.getAll();
        await Promise.all(documents.map(document => this.refreshDocument(document)));
    }
    sendDiagnosticsFor(textDocument) {
        const diagnostics = this.diagnostics.get(textDocument) || [];
        this.connection.sendDiagnostics({
            uri: textDocument.uri,
            diagnostics,
        });
        this.diagnostics.delete(textDocument);
    }
}
export class UnreachableCodeCollector extends Visitor {
    constructor() {
        super(...arguments);
        this.diagnostics = [];
    }
    visitERBCaseNode(node) {
        this.checkUnreachableChildren(node.children);
        this.visitChildNodes(node);
    }
    visitERBCaseMatchNode(node) {
        this.checkUnreachableChildren(node.children);
        this.visitChildNodes(node);
    }
    checkUnreachableChildren(children) {
        for (const child of children) {
            if (isHTMLTextNode(child) && child.content.trim() === "") {
                continue;
            }
            const diagnostic = {
                range: {
                    start: {
                        line: this.toZeroBased(child.location.start.line),
                        character: child.location.start.column
                    },
                    end: {
                        line: this.toZeroBased(child.location.end.line),
                        character: child.location.end.column
                    }
                },
                message: "Unreachable code: content between case and when/in is never executed",
                severity: DiagnosticSeverity.Hint,
                tags: [DiagnosticTag.Unnecessary],
                source: "Herb Language Server"
            };
            this.diagnostics.push(diagnostic);
        }
    }
    toZeroBased(line) {
        return line - 1;
    }
}
//# sourceMappingURL=diagnostics.js.map