fish-lsp
Version:
LSP implementation for fish/fish-shell
158 lines (157 loc) • 7.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCodeActionHandler = createCodeActionHandler;
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) {
/**
* small helper for now, used to add code actions that are not `preferred`
* quickfixes to the list of results, when a quickfix is requested.
*/
async function getSelectionCodeActions(document, range) {
const rootNode = analyzer.getRootNode(document);
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).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.isIfStatement)(n)) {
const convertIfAction = (0, refactors_1.convertIfToCombiners)(document, n, false);
if (convertIfAction)
results.push(convertIfAction);
}
});
}
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;
}
/**
* Helper to add quick fixes to the list that are mostly of the type `preferred`
*
* These quick fixes include things like `disable` actions, and general fixes to silence diagnostics
*/
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;
}
/**
* Process refactors for the given document and range
*/
async function processRefactors(document, range) {
const results = [];
const rootNode = analyzer.getRootNode(document);
if (!rootNode)
return results;
// Get node at the selected range
const selectedNode = (0, tree_sitter_1.getNodeAtRange)(rootNode, range);
if (!selectedNode)
return results;
// try refactoring aliases first
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;
}
// Try each refactoring action
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 [];
const results = [];
// Check what kinds of actions are requested
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', params.context.diagnostics.map(d => d.message));
// Add disable actions
if (params.context.diagnostics.length > 0 && !onlyRefactoring) {
results.push(...(0, disable_actions_1.getDisableDiagnosticActions)(document, params.context.diagnostics));
}
// Add quick fixes if requested
if (onlyQuickFix) {
logger_1.logger.log('Processing onlyQuickFixes');
results.push(...await processQuickFixes(document, params.context.diagnostics, analyzer));
results.push(...await getSelectionCodeActions(document, params.range));
logger_1.logger.log('CodeAction results', results.map(r => r.title));
return results;
}
// add the refactors
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, params.context.diagnostics, analyzer));
results.push(...await getSelectionCodeActions(document, params.range));
logger_1.logger.log('CodeAction results', results.map(r => r.title));
return results;
};
}