"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runServer = void 0;
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
const lsp = require("vscode-languageserver");
const rpc = require("vscode-jsonrpc");
const dot_language_support_1 = require("dot-language-support");
const vscode_languageserver_1 = require("vscode-languageserver");
const defaultSettings = { maxNumberOfProblems: 100 };
function runServer(connection) {
    if (!connection)
        throw "connection is missing";
    const languageService = (0, dot_language_support_1.createService)();
    let documents = new lsp.TextDocuments(vscode_languageserver_textdocument_1.TextDocument);
    const astOfFile = new Map();
    documents.listen(connection);
    let shouldSendDiagnosticRelatedInformation = false;
    connection.onInitialize((_params) => {
        let a = _params.capabilities && _params.capabilities.textDocument && _params.capabilities.textDocument.publishDiagnostics && _params.capabilities.textDocument.publishDiagnostics.relatedInformation;
        shouldSendDiagnosticRelatedInformation = !!a;
        return {
            capabilities: {
                textDocumentSync: vscode_languageserver_1.TextDocumentSyncKind.Full,
                completionProvider: {
                    triggerCharacters: ["="],
                    resolveProvider: false,
                },
                hoverProvider: true,
                referencesProvider: true,
                definitionProvider: true,
                renameProvider: true,
                codeActionProvider: true,
                executeCommandProvider: {
                    commands: languageService.getAvailableCommands(),
                },
                colorProvider: true,
            }
        };
    });
    function rebuildAll() {
        for (const uri of astOfFile.keys())
            updateAst(uri);
    }
    function updateAst(uri, doc) {
        if (doc === undefined)
            doc = documents.get(uri);
        if (doc) {
            const ast = languageService.parseDocument(doc);
            astOfFile.set(uri, ast);
            return ast;
        }
        return undefined;
    }
    function ensureAst(uri, doc) {
        let ast = astOfFile.get(uri);
        if (ast === undefined)
            ast = updateAst(uri, doc);
        return ast;
    }
    connection.onHover(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.hover(doc, ast, req.position)
            : invalidRequest();
    });
    connection.onReferences(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.findReferences(doc, ast, req.position, req.context)
            : invalidRequest();
    });
    connection.onDefinition(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.findDefinition(doc, ast, req.position)
            : invalidRequest();
    });
    connection.onDocumentColor(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.getDocumentColors(doc, ast)
            : invalidRequest();
    });
    connection.onColorPresentation(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.getColorRepresentations(doc, ast, req.color, req.range)
            : invalidRequest();
    });
    connection.onCodeAction(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        if (doc && ast) {
            const r = languageService.getCodeActions(doc, ast, req.range, req.context);
            if (r) {
                r.forEach(command => {
                    if (command.arguments)
                        command.arguments.push(uri);
                    else
                        command.arguments = [uri];
                });
            }
            return r;
        }
        return invalidRequest();
    });
    connection.onExecuteCommand(req => {
        const args = req.arguments;
        if (!args || args.length < 1)
            return;
        const uri = args.pop();
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        if (doc && ast) {
            req.arguments = args.length === 0 ? undefined : args;
            const edit = languageService.executeCommand(doc, ast, req);
            if (edit)
                connection.workspace.applyEdit(edit);
        }
    });
    connection.onRenameRequest(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        if (doc && ast) {
            const r = languageService.renameSymbol(doc, ast, req.position, req.newName);
            return r ? r : invalidRequest();
        }
        return invalidRequest();
    });
    documents.onDidChangeContent(change => {
        const doc = change.document;
        const ast = updateAst(doc.uri, doc);
        if (ast === undefined)
            throw "This cannot happen";
        return validateDocument(doc, ast);
    });
    let currentSettings = Object.assign({}, defaultSettings);
    connection.onDidChangeConfiguration(change => {
        const newSettings = change.settings.dotLanguageServer;
        if (newSettings)
            currentSettings = newSettings;
        rebuildAll();
        validateAll();
    });
    function validateAll() {
        for (const uri of astOfFile.keys()) {
            const doc = documents.get(uri);
            if (doc) {
                const ast = ensureAst(uri, doc);
                if (ast)
                    validateDocument(doc, ast);
            }
        }
    }
    function validateDocument(doc, sf) {
        const diagnostics = languageService.validateDocument(doc, sf);
        connection.sendDiagnostics({ uri: doc.uri, diagnostics });
    }
    connection.onDidChangeWatchedFiles(_change => {
        connection.console.log("We received an file change event");
    });
    connection.onCompletion(req => {
        const uri = req.textDocument.uri;
        const doc = documents.get(uri);
        const ast = ensureAst(uri, doc);
        return doc && ast
            ? languageService.getCompletions(doc, ast, req.position)
            : invalidRequest();
    });
    documents.onDidOpen(params => updateAst(params.document.uri, params.document));
    const invalidRequest = () => new rpc.ResponseError(rpc.ErrorCodes.InvalidRequest, "Invalid request");
    connection.listen();
}
exports.runServer = runServer;
//# sourceMappingURL=server.js.map