fish-lsp
Version:
LSP implementation for fish/fish-shell
125 lines (124 loc) • 5.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleDisableSingleLine = handleDisableSingleLine;
exports.handleDisableBlock = handleDisableBlock;
exports.groupDiagnostics = groupDiagnostics;
exports.handleDisableEntireFile = handleDisableEntireFile;
exports.getDisableDiagnosticActions = getDisableDiagnosticActions;
const vscode_languageserver_1 = require("vscode-languageserver");
const error_codes_1 = require("../diagnostics/error-codes");
const action_kinds_1 = require("./action-kinds");
const logger_1 = require("../logger");
function createDisableAction(title, document, edits, diagnostics, isPreferred = false) {
return {
title,
kind: action_kinds_1.SupportedCodeActionKinds.Disable,
edit: {
changes: {
[document.uri]: edits,
},
},
diagnostics,
isPreferred,
};
}
function handleDisableSingleLine(document, diagnostic) {
const indent = document.getIndentAtLine(diagnostic.range.start.line);
const edit = vscode_languageserver_1.TextEdit.insert({ line: diagnostic.range.start.line, character: 0 }, `${indent}# @fish-lsp-disable-next-line ${diagnostic.code}\n`);
const severity = error_codes_1.ErrorCodes.getSeverityString(diagnostic.severity);
return createDisableAction(`Disable ${severity} diagnostic ${diagnostic.code} for line ${diagnostic.range.start.line + 1}`, document, [edit], [diagnostic]);
}
function handleDisableBlock(document, group) {
const numbers = Array.from(new Set(group.diagnostics.map(diagnostic => diagnostic.code)).values()).join(' ');
const startIndent = document.getIndentAtLine(group.startLine);
const endIndent = document.getIndentAtLine(group.endLine);
const edits = [
vscode_languageserver_1.TextEdit.insert({ line: group.startLine, character: 0 }, `${startIndent}# @fish-lsp-disable ${numbers}\n`),
vscode_languageserver_1.TextEdit.insert({ line: group.endLine + 1, character: 0 }, `${endIndent}# @fish-lsp-enable ${numbers}\n`),
];
return {
...createDisableAction(`Disable diagnostics ${numbers} in block (lines ${group.startLine + 1}-${group.endLine + 1})`, document, edits, group.diagnostics),
};
}
function groupDiagnostics(diagnostics, maxGap = 1) {
if (diagnostics.length === 0)
return [];
const sorted = [...diagnostics].sort((a, b) => a.range.start.line - b.range.start.line);
const groups = [];
let currentGroup = {
startLine: sorted[0].range.start.line,
endLine: sorted[0].range.end.line,
diagnostics: [sorted[0]],
};
for (let i = 1; i < sorted.length; i++) {
const current = sorted[i];
const gap = current.range.start.line - currentGroup.endLine;
if (gap <= maxGap) {
currentGroup.endLine = Math.max(currentGroup.endLine, current.range.end.line);
currentGroup.diagnostics.push(current);
}
else {
groups.push(currentGroup);
currentGroup = {
startLine: current.range.start.line,
endLine: current.range.end.line,
diagnostics: [current],
};
}
}
groups.push(currentGroup);
return groups;
}
function handleDisableEntireFile(document, diagnostics) {
const results = [];
const diagnosticsCounts = new Map();
diagnostics.forEach(diagnostic => {
const code = diagnostic.code;
diagnosticsCounts.set(code, (diagnosticsCounts.get(code) || 0) + 1);
});
const matchingDiagnostics = [];
diagnosticsCounts.forEach((count, code) => {
if (count >= 5) {
logger_1.logger.log(`CODEACTION: Disabling ${count} ${code.toString()} diagnostics in file`);
}
matchingDiagnostics.push(code);
});
if (matchingDiagnostics.length === 0)
return results;
let tokenLine = 0;
let firstLine = document.getLine(tokenLine);
if (firstLine.startsWith('#!/')) {
tokenLine++;
}
firstLine = document.getLine(tokenLine);
const allNumbersStr = matchingDiagnostics.join(' ').trim();
if (!firstLine.startsWith('# @fish-lsp-disable')) {
const edits = [
vscode_languageserver_1.TextEdit.insert({ line: tokenLine, character: 0 }, `# @fish-lsp-disable ${allNumbersStr}\n`),
];
results.push(createDisableAction(`Disable all diagnostics in file (${allNumbersStr.split(' ').join(', ')})`, document, edits, diagnostics));
matchingDiagnostics.forEach(match => {
const severity = error_codes_1.ErrorCodes.getSeverityString(error_codes_1.ErrorCodes.getDiagnostic(match).severity);
results.push(createDisableAction(`Disable ${severity} ${match.toString()} diagnostics for entire file`, document, [
vscode_languageserver_1.TextEdit.insert({ line: tokenLine, character: 0 }, `# @fish-lsp-disable ${match.toString()}\n`),
], diagnostics));
});
}
return results;
}
function getDisableDiagnosticActions(document, diagnostics) {
const actions = [];
diagnostics
.filter(diagnostic => diagnostic.severity === vscode_languageserver_1.DiagnosticSeverity.Warning
|| diagnostic.code === error_codes_1.ErrorCodes.sourceFileDoesNotExist).forEach(diagnostic => {
actions.push(handleDisableSingleLine(document, diagnostic));
});
const groups = groupDiagnostics(diagnostics);
groups.forEach(group => {
if (group.diagnostics.length > 1) {
actions.push(handleDisableBlock(document, group));
}
});
actions.push(...handleDisableEntireFile(document, diagnostics));
return actions;
}