fish-lsp
Version:
LSP implementation for fish/fish-shell
173 lines (172 loc) • 8.42 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCodeActionHandler = createCodeActionHandler;
exports.equalDiagnostics = equalDiagnostics;
exports.createOnCodeActionResolveHandler = createOnCodeActionResolveHandler;
exports.codeActionHandlers = codeActionHandlers;
const disable_actions_1 = require("./disable-actions");
const quick_fixes_1 = require("./quick-fixes");
const translation_1 = require("../utils/translation");
const logger_1 = require("../logger");
const tree_sitter_1 = require("../utils/tree-sitter");
const refactors_1 = require("./refactors");
const argparse_completions_1 = require("./argparse-completions");
const node_types_1 = require("../utils/node-types");
const alias_wrapper_1 = require("./alias-wrapper");
function createCodeActionHandler(docs, analyzer) {
async function getSelectionCodeActions(document, range) {
const rootNode = analyzer.getRootNode(document.uri);
if (!rootNode)
return [];
const selectedNode = (0, tree_sitter_1.getNodeAtRange)(rootNode, range);
if (!selectedNode)
return [];
const results = [];
if ((0, node_types_1.isProgram)(selectedNode)) {
analyzer.getNodes(document.uri).forEach(n => {
if ((0, node_types_1.isCommandWithName)(n, 'argparse')) {
const argparseAction = (0, argparse_completions_1.createArgparseCompletionsCodeAction)(n, document);
if (argparseAction)
results.push(argparseAction);
}
});
}
if (!(0, node_types_1.isProgram)(selectedNode)) {
const commandToFunctionAction = (0, refactors_1.extractCommandToFunction)(document, selectedNode);
if (commandToFunctionAction)
results.push(commandToFunctionAction);
}
if ((0, node_types_1.isCommandWithName)(selectedNode, 'alias')) {
const aliasInlineFunction = await (0, alias_wrapper_1.createAliasInlineAction)(document, selectedNode);
const aliasNewFile = await (0, alias_wrapper_1.createAliasSaveActionNewFile)(document, selectedNode);
if (aliasInlineFunction)
results.push(aliasInlineFunction);
if (aliasNewFile)
results.push(aliasNewFile);
}
return results;
}
async function processQuickFixes(document, diagnostics, analyzer) {
const results = [];
for (const diagnostic of diagnostics) {
logger_1.logger.log('Processing diagnostic', diagnostic.code, diagnostic.message);
const quickFixs = await (0, quick_fixes_1.getQuickFixes)(document, diagnostic, analyzer);
for (const fix of quickFixs) {
logger_1.logger.log('QuickFix', fix?.title);
}
if (quickFixs)
results.push(...quickFixs);
}
return results;
}
async function processRefactors(document, range) {
const results = [];
const rootNode = analyzer.getRootNode(document.uri);
if (!rootNode)
return results;
const selectedNode = (0, tree_sitter_1.getNodeAtRange)(rootNode, range);
if (!selectedNode)
return results;
let aliasCommand = selectedNode;
if (selectedNode.text === 'alias')
aliasCommand = selectedNode.parent;
if (aliasCommand && (0, node_types_1.isCommandWithName)(aliasCommand, 'alias')) {
logger_1.logger.log('isCommandWithName(alias)', aliasCommand.text);
const aliasInlineFunction = await (0, alias_wrapper_1.createAliasInlineAction)(document, aliasCommand);
const aliasNewFile = await (0, alias_wrapper_1.createAliasSaveActionNewFile)(document, aliasCommand);
if (aliasInlineFunction)
results.push(aliasInlineFunction);
if (aliasNewFile)
results.push(aliasNewFile);
return results;
}
const extractFunction = (0, refactors_1.extractToFunction)(document, range);
if (extractFunction)
results.push(extractFunction);
const extractCommandFunction = (0, refactors_1.extractCommandToFunction)(document, selectedNode);
if (extractCommandFunction)
results.push(extractCommandFunction);
const extractVar = (0, refactors_1.extractToVariable)(document, range, selectedNode);
if (extractVar)
results.push(extractVar);
const extractFuncToFile = (0, refactors_1.extractFunctionToFile)(document, range, selectedNode);
if (extractFuncToFile)
results.push(extractFuncToFile);
const extractCompletionToFile = (0, refactors_1.extractFunctionWithArgparseToCompletionsFile)(document, range, selectedNode);
if (extractCompletionToFile)
results.push(extractCompletionToFile);
const convertIf = (0, refactors_1.convertIfToCombiners)(document, selectedNode);
if (convertIf)
results.push(convertIf);
return results;
}
return async function handleCodeAction(params) {
logger_1.logger.log('onCodeAction', params);
const uri = (0, translation_1.uriToPath)(params.textDocument.uri);
const document = docs.get(uri);
if (!document || !uri)
return [];
logger_1.logger.log('onCodeAction', { uri });
const results = [];
const diagnostics = params.context.diagnostics.filter(d => d.source === 'fish-lsp');
const onlyRefactoring = params.context.only?.some(kind => kind.startsWith('refactor'));
const onlyQuickFix = params.context.only?.some(kind => kind.startsWith('quickfix'));
logger_1.logger.log('Requested actions', { onlyRefactoring, onlyQuickFix });
logger_1.logger.log('Diagnostics', diagnostics.map(d => d.message));
if (diagnostics.length > 0 && !onlyRefactoring) {
results.push(...(0, disable_actions_1.getDisableDiagnosticActions)(document, diagnostics));
}
if (onlyQuickFix) {
logger_1.logger.log('Processing onlyQuickFixes');
results.push(...await processQuickFixes(document, diagnostics, analyzer));
results.push(...await getSelectionCodeActions(document, params.range));
const allAction = (0, quick_fixes_1.createFixAllAction)(document, results);
if (allAction)
results.push(allAction);
logger_1.logger.log('CodeAction results', results.map(r => r.title));
return results;
}
if (onlyRefactoring) {
logger_1.logger.log('Processing onlyRefactors');
results.push(...await processRefactors(document, params.range));
logger_1.logger.log('CodeAction results', results.map(r => r.title));
return results;
}
logger_1.logger.log('Processing all actions');
results.push(...await processQuickFixes(document, diagnostics, analyzer));
results.push(...await getSelectionCodeActions(document, params.range));
const allAction = (0, quick_fixes_1.createFixAllAction)(document, results);
if (allAction) {
logger_1.logger.log({
name: 'allAction',
title: allAction.title,
kind: allAction.kind,
diagnostics: diagnostics?.map(d => d.message),
edit: allAction.edit,
});
results.push(allAction);
}
logger_1.logger.log('CodeAction results', results.map(r => r.title));
return results;
};
}
function equalDiagnostics(d1, d2) {
return d1.code === d2.code &&
d1.message === d2.message &&
d1.range.start.line === d2.range.start.line &&
d1.range.start.character === d2.range.start.character &&
d1.range.end.line === d2.range.end.line &&
d1.range.end.character === d2.range.end.character &&
d1.data.node?.text === d2.data.node?.text;
}
function createOnCodeActionResolveHandler(_docs, _analyzer) {
return async function codeActionResolover(codeAction) {
return codeAction;
};
}
function codeActionHandlers(docs, analyzer) {
return {
onCodeAction: createCodeActionHandler(docs, analyzer),
onCodeActionResolve: createOnCodeActionResolveHandler(docs, analyzer),
};
}