UNPKG

coc.nvim

Version:

LSP based intellisense engine for neovim & vim8.

254 lines 9.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol"); const callSequence_1 = tslib_1.__importDefault(require("../util/callSequence")); const object_1 = require("../util/object"); const workspace_1 = tslib_1.__importDefault(require("../workspace")); const util_1 = require("./util"); const logger = require('../util/logger')('diagnostic-buffer'); const severityNames = ['CocError', 'CocWarning', 'CocInfo', 'CocHint']; // maintains sign and highlightId class DiagnosticBuffer { constructor(doc, config) { this.config = config; this.signIds = new Set(); this.sequence = null; this._onDidRefresh = new vscode_languageserver_protocol_1.Emitter(); this.matchIds = new Set(); this.diagnostics = []; this.onDidRefresh = this._onDidRefresh.event; this.bufnr = doc.bufnr; this.uri = doc.uri; this.srdId = workspace_1.default.createNameSpace('coc-diagnostic'); let timer = null; let time = Date.now(); this.refresh = (diagnostics) => { time = Date.now(); if (timer) clearTimeout(timer); timer = setTimeout(async () => { let current = time; if (this.sequence) { await this.sequence.cancel(); } // staled if (current != time) return; this._refresh(diagnostics); }, global.hasOwnProperty('__TEST__') ? 30 : 50); }; } get nvim() { return workspace_1.default.nvim; } _refresh(diagnostics) { if (object_1.equals(this.diagnostics, diagnostics)) return; let { nvim, bufnr } = this; let sequence = this.sequence = new callSequence_1.default(); let winid; sequence.addFunction(async () => { let [valid, id] = await nvim.eval(`[coc#util#valid_state(), bufwinid(${bufnr})]`); if (valid == 0) return false; winid = id; }); sequence.addFunction(async () => { nvim.pauseNotification(); this.setDiagnosticInfo(diagnostics); this.addSigns(diagnostics); this.setLocationlist(diagnostics, winid); this.addHighlight(diagnostics, winid); this.addDiagnosticVText(diagnostics); let [, err] = await this.nvim.resumeNotification(); if (err) logger.error('Diagnostic error:', err); }); sequence.start().then(async (canceled) => { if (!canceled) { this.diagnostics = diagnostics; this._onDidRefresh.fire(void 0); } }, e => { logger.error(e); }); } setLocationlist(diagnostics, winid) { if (!this.config.locationlist) return; let { nvim, bufnr } = this; // not shown if (winid == -1) return; let items = []; for (let diagnostic of diagnostics) { let item = util_1.getLocationListItem(diagnostic.source, bufnr, diagnostic); items.push(item); } nvim.call('setloclist', [winid, [], ' ', { title: 'Diagnostics of coc', items }], true); } clearSigns() { let { nvim, signIds, bufnr } = this; if (signIds.size > 0) { nvim.call('coc#util#unplace_signs', [bufnr, Array.from(signIds)], true); signIds.clear(); } } async checkSigns() { let { nvim, bufnr, signIds } = this; try { let content = await this.nvim.call('execute', [`sign place buffer=${bufnr}`]); let lines = content.split('\n'); let ids = []; for (let line of lines) { let ms = line.match(/^\s*line=\d+\s+id=(\d+)\s+name=(\w+)/); if (!ms) continue; let [, id, name] = ms; if (!signIds.has(Number(id)) && severityNames.indexOf(name) != -1) { ids.push(id); } } await nvim.call('coc#util#unplace_signs', [bufnr, ids]); } catch (e) { // noop } } addSigns(diagnostics) { if (!this.config.enableSign) return; this.clearSigns(); let { nvim, bufnr, signIds } = this; let signId = this.config.signOffset; signIds.clear(); let lines = new Set(); for (let diagnostic of diagnostics) { let { range, severity } = diagnostic; let line = range.start.line; if (lines.has(line)) continue; lines.add(line); let name = util_1.getNameFromSeverity(severity); nvim.command(`sign place ${signId} line=${line + 1} name=${name} buffer=${bufnr}`, true); signIds.add(signId); signId = signId + 1; } } setDiagnosticInfo(diagnostics) { let info = { error: 0, warning: 0, information: 0, hint: 0 }; for (let diagnostic of diagnostics) { switch (diagnostic.severity) { case vscode_languageserver_protocol_1.DiagnosticSeverity.Warning: info.warning = info.warning + 1; break; case vscode_languageserver_protocol_1.DiagnosticSeverity.Information: info.information = info.information + 1; break; case vscode_languageserver_protocol_1.DiagnosticSeverity.Hint: info.hint = info.hint + 1; break; default: info.error = info.error + 1; } } this.nvim.call('coc#util#set_buf_var', [this.bufnr, 'coc_diagnostic_info', info], true); if (!workspace_1.default.getDocument(this.bufnr)) return; if (workspace_1.default.bufnr == this.bufnr) this.nvim.command('redraws', true); this.nvim.call('coc#util#do_autocmd', ['CocDiagnosticChange'], true); } addDiagnosticVText(diagnostics) { let { bufnr, nvim } = this; if (!this.config.virtualText) return; if (!nvim.hasFunction('nvim_buf_set_virtual_text')) return; let buffer = this.nvim.createBuffer(bufnr); let lines = new Set(); let srcId = this.config.virtualTextSrcId; let prefix = this.config.virtualTextPrefix; buffer.clearNamespace(srcId); for (let diagnostic of diagnostics) { let { line } = diagnostic.range.start; if (lines.has(line)) continue; lines.add(line); let highlight = util_1.getNameFromSeverity(diagnostic.severity) + 'VirtualText'; let msg = diagnostic.message.split(/\n/) .map((l) => l.trim()) .filter((l) => l.length > 0) .slice(0, this.config.virtualTextLines) .join(this.config.virtualTextLineSeparator); buffer.setVirtualText(srcId, line, [[prefix + msg, highlight]], {}).logError(); } } clearHighlight() { let { bufnr, nvim, matchIds } = this; let doc = workspace_1.default.getDocument(bufnr); if (!doc) return; doc.clearMatchIds(matchIds); this.matchIds.clear(); } addHighlight(diagnostics, winid) { this.clearHighlight(); if (diagnostics.length == 0) return; if (winid == -1 && workspace_1.default.isVim && !workspace_1.default.env.textprop) return; let document = workspace_1.default.getDocument(this.bufnr); if (!document) return; const highlights = new Map(); for (let diagnostic of diagnostics) { let { range, severity } = diagnostic; let hlGroup = util_1.getNameFromSeverity(severity) + 'Highlight'; let ranges = highlights.get(hlGroup) || []; ranges.push(range); highlights.set(hlGroup, ranges); } for (let [hlGroup, ranges] of highlights.entries()) { let matchIds = document.highlightRanges(ranges, hlGroup, this.srdId); for (let id of matchIds) this.matchIds.add(id); } } /** * Used on buffer unload * * @public * @returns {Promise<void>} */ async clear() { if (this.sequence) await this.sequence.cancel(); let { nvim } = this; nvim.pauseNotification(); this.clearHighlight(); this.clearSigns(); if (this.config.virtualText && workspace_1.default.isNvim) { let buffer = this.nvim.createBuffer(this.bufnr); buffer.clearNamespace(this.config.virtualTextSrcId); } if (workspace_1.default.bufnr == this.bufnr) { nvim.command('unlet b:coc_diagnostic_info', true); } else { this.setDiagnosticInfo([]); } await nvim.resumeNotification(false, true); } dispose() { if (this.sequence) { this.sequence.cancel().catch(_e => { // noop }); } this._onDidRefresh.dispose(); } } exports.DiagnosticBuffer = DiagnosticBuffer; //# sourceMappingURL=buffer.js.map