"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getEmitDeclarations = exports.register = void 0;
const vscode = __importStar(require("vscode-languageserver-protocol"));
const shared_1 = require("../shared");
function register(ctx) {
    const ts = ctx.typescript.module;
    return (uri, options) => {
        const document = ctx.getTextDocument(uri);
        if (!document)
            return [];
        const fileName = ctx.uriToFileName(document.uri);
        const program = ctx.typescript.languageService.getProgram();
        const sourceFile = program?.getSourceFile(fileName);
        if (!program || !sourceFile)
            return [];
        const token = {
            isCancellationRequested() {
                return ctx.typescript?.languageServiceHost.getCancellationToken?.().isCancellationRequested() ?? false;
            },
            throwIfCancellationRequested() { },
        };
        let errors = (0, shared_1.safeCall)(() => [
            ...options.semantic ? program.getSemanticDiagnostics(sourceFile, token) : [],
            ...options.syntactic ? program.getSyntacticDiagnostics(sourceFile, token) : [],
            ...options.suggestion ? ctx.typescript.languageService.getSuggestionDiagnostics(fileName) : [],
        ]) ?? [];
        if (options.declaration && getEmitDeclarations(program.getCompilerOptions())) {
            errors = errors.concat(program.getDeclarationDiagnostics(sourceFile, token));
        }
        return translateDiagnostics(document, errors);
        function translateDiagnostics(document, input) {
            return input.map(diag => translateDiagnostic(diag, document)).filter((v) => !!v);
        }
        function translateDiagnostic(diag, document) {
            if (diag.start === undefined)
                return;
            if (diag.length === undefined)
                return;
            const diagnostic = {
                range: {
                    start: document.positionAt(diag.start),
                    end: document.positionAt(diag.start + diag.length),
                },
                severity: translateErrorType(diag.category),
                source: 'ts',
                code: diag.code,
                message: getMessageText(diag),
            };
            if (diag.relatedInformation) {
                diagnostic.relatedInformation = diag.relatedInformation
                    .map(rErr => translateDiagnosticRelated(rErr))
                    .filter((v) => !!v);
            }
            if (diag.reportsUnnecessary) {
                if (diagnostic.tags === undefined)
                    diagnostic.tags = [];
                diagnostic.tags.push(vscode.DiagnosticTag.Unnecessary);
            }
            if (diag.reportsDeprecated) {
                if (diagnostic.tags === undefined)
                    diagnostic.tags = [];
                diagnostic.tags.push(vscode.DiagnosticTag.Deprecated);
            }
            return diagnostic;
        }
        function translateDiagnosticRelated(diag) {
            if (diag.start === undefined)
                return;
            if (diag.length === undefined)
                return;
            let document;
            if (diag.file) {
                document = ctx.getTextDocument(ctx.fileNameToUri(diag.file.fileName));
            }
            if (!document)
                return;
            const diagnostic = {
                location: {
                    uri: document.uri,
                    range: {
                        start: document.positionAt(diag.start),
                        end: document.positionAt(diag.start + diag.length),
                    },
                },
                message: getMessageText(diag),
            };
            return diagnostic;
        }
        function translateErrorType(input) {
            switch (input) {
                case ts.DiagnosticCategory.Warning: return vscode.DiagnosticSeverity.Warning;
                case ts.DiagnosticCategory.Error: return vscode.DiagnosticSeverity.Error;
                case ts.DiagnosticCategory.Suggestion: return vscode.DiagnosticSeverity.Hint;
                case ts.DiagnosticCategory.Message: return vscode.DiagnosticSeverity.Information;
            }
            return vscode.DiagnosticSeverity.Error;
        }
    };
}
exports.register = register;
function getMessageText(diag, level = 0) {
    let messageText = '  '.repeat(level);
    if (typeof diag.messageText === 'string') {
        messageText += diag.messageText;
    }
    else {
        messageText += diag.messageText.messageText;
        if (diag.messageText.next) {
            for (const info of diag.messageText.next) {
                messageText += '\n' + getMessageText(info, level + 1);
            }
        }
    }
    return messageText;
}
function getEmitDeclarations(compilerOptions) {
    return !!(compilerOptions.declaration || compilerOptions.composite);
}
exports.getEmitDeclarations = getEmitDeclarations;
//# sourceMappingURL=diagnostics.js.map