fish-lsp
Version:
LSP implementation for fish/fish-shell
127 lines (126 loc) • 4.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleHover = handleHover;
exports.getHoverForFlag = getHoverForFlag;
exports.collectCommandString = collectCommandString;
const vscode_languageserver_1 = require("vscode-languageserver");
const documentation_1 = require("./documentation");
const exec_1 = require("./utils/exec");
const node_types_1 = require("./utils/node-types");
const tree_sitter_1 = require("./utils/tree-sitter");
const translation_1 = require("./utils/translation");
async function handleHover(analyzer, document, position, current, cache, logger) {
if ((0, node_types_1.isOption)(current)) {
return await getHoverForFlag(current);
}
const local = analyzer.getDefinition(document, position);
if (local) {
return {
contents: {
kind: vscode_languageserver_1.MarkupKind.Markdown,
value: local.detail,
},
range: local.selectionRange,
};
}
const { kindType, kindString } = (0, translation_1.symbolKindsFromNode)(current);
const symbolType = ['function', 'class', 'variable'].includes(kindString) ? kindType : undefined;
logger?.log({ './src/hover.ts:37': kindType });
if (cache.find(current.text) !== undefined) {
await cache.resolve(current.text, document.uri, symbolType);
const item = symbolType ? cache.find(current.text, symbolType) : cache.getItem(current.text);
logger?.logAsJson('call: [./src/hover.ts:42]');
if (item && item?.docs) {
return {
contents: {
kind: vscode_languageserver_1.MarkupKind.Markdown,
value: item.docs.toString(),
},
};
}
}
const commandString = await collectCommandString(current);
const result = await (0, documentation_1.documentationHoverProvider)(commandString);
logger?.log({ commandString, result });
return result;
}
async function getHoverForFlag(current) {
const commandNode = (0, tree_sitter_1.findFirstParent)(current, n => (0, node_types_1.isCommand)(n) || (0, node_types_1.isFunctionDefinition)(n));
if (!commandNode) {
return null;
}
let commandStr = [commandNode.child(0)?.text || ''];
const flags = [];
let hasFlags = false;
for (const child of commandNode?.children || []) {
if (!hasFlags && !child.text.startsWith('-')) {
commandStr = await appendToCommand(commandStr, child.text);
}
else if (child.text.startsWith('-')) {
flags.push(child.text);
hasFlags = true;
}
}
const flagCompletions = await (0, exec_1.execCompletions)(...commandStr, '-');
const shouldSplitShortFlags = hasOldUnixStyleFlags(flagCompletions);
const fixedFlags = spiltShortFlags(flags, !shouldSplitShortFlags);
const found = flagCompletions
.map(line => line.split('\t'))
.filter(line => fixedFlags.includes(line[0]))
.map(line => line.join('\t'));
return {
contents: (0, documentation_1.enrichCommandWithFlags)(commandStr.join('-'), found),
};
}
function hasOldUnixStyleFlags(allFlags) {
for (const line of allFlags.map(line => line.split('\t'))) {
const flag = line[0];
if (flag.startsWith('-') && !flag.startsWith('--')) {
if (flag.length > 2) {
return true;
}
}
}
return false;
}
function spiltShortFlags(flags, shouldSplit) {
const newFlags = [];
for (let flag of flags) {
flag = flag.split('=')[0];
if (flag.startsWith('-') && !flag.startsWith('--')) {
if (flag.length > 2 && shouldSplit) {
newFlags.push(...flag.split('').map(f => '-' + f));
continue;
}
}
newFlags.push(flag);
}
return newFlags;
}
async function appendToCommand(commands, subCommand) {
const completions = await (0, exec_1.execSubCommandCompletions)(...commands, ' '); // HERE
if (completions.includes(subCommand)) {
commands.push(subCommand);
return commands;
}
else {
return commands;
}
}
async function collectCommandString(current) {
const commandNode = (0, tree_sitter_1.findFirstParent)(current, n => (0, node_types_1.isCommand)(n));
if (!commandNode) {
return '';
}
const commandNodeText = commandNode.child(0)?.text;
const subCommandName = commandNode.child(1)?.text;
if (subCommandName?.startsWith('-')) {
return commandNodeText || '';
}
const commandText = [commandNodeText, subCommandName].join('-');
const docs = await (0, exec_1.execCommandDocs)(commandText);
if (docs) {
return commandText;
}
return commandNodeText || '';
}