UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

234 lines (233 loc) 10.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSymbolReference = void 0; const Locations = __importStar(require("../utils/locations")); const tree_sitter_1 = require("../utils/tree-sitter"); const emit_1 = require("./emit"); const node_types_1 = require("../utils/node-types"); const complete_1 = require("./complete"); const argparse_1 = require("./argparse"); const options_1 = require("./options"); const set_1 = require("./set"); const nested_strings_1 = require("./nested-strings"); const node_types_2 = require("../diagnostics/node-types"); const bind_1 = require("./bind"); const alias_1 = require("./alias"); const shouldSkipNode = ({ symbol, document, node, excludeEqualNode }) => { if (excludeEqualNode && symbol.equalsNode(node)) return true; if (excludeEqualNode && document.uri === symbol.uri) { if ((0, tree_sitter_1.equalRanges)((0, tree_sitter_1.getRange)(symbol.focusedNode), (0, tree_sitter_1.getRange)(node))) { return true; } } if (excludeEqualNode && symbol.isEvent() && symbol.focusedNode.equals(node)) { return true; } return false; }; const checkEventReference = ({ symbol, node }) => { if (symbol.isEventHook() && symbol.name === node.text && (0, emit_1.isEmittedEventDefinitionName)(node)) { return true; } if (symbol.isEmittedEvent() && symbol.name === node.text && !(0, emit_1.isEmittedEventDefinitionName)(node)) { return true; } return false; }; const isInValidScope = ({ symbol, document, node }) => { if (symbol.isLocal() && !symbol.isArgparse()) { return symbol.scopeContainsNode(node) && symbol.uri === document.uri; } return true; }; const matchesFunctionName = ({ symbol, node }) => { if (symbol.isFunction()) { if ((0, node_types_1.isArgumentThatCanContainCommandCalls)(node)) return true; if (symbol.name !== node.text && !(0, node_types_1.isString)(node)) { return false; } } return true; }; const checkCompleteCommandReference = ({ symbol, node }) => { const parentNode = node.parent ? (0, node_types_1.findParentCommand)(node) : null; if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'complete')) { return (0, complete_1.isMatchingCompletionFlagNodeWithFishSymbol)(symbol, node); } return false; }; const checkArgparseReference = ({ symbol, node }) => { if (!symbol.isArgparse()) return false; const parentName = symbol.parent?.name || symbol.scopeNode.firstNamedChild?.text || symbol.scopeNode.text; if ((0, argparse_1.isCompletionArgparseFlagWithCommandName)(node, parentName, symbol.argparseFlagName)) { return true; } if ((0, node_types_1.isOption)(node) && node.parent && (0, node_types_1.isCommandWithName)(node.parent, parentName)) { return (0, options_1.isMatchingOptionOrOptionValue)(node, options_1.Option.fromRaw(symbol.argparseFlag)); } if (symbol.name === node.text && symbol.parent?.scopeContainsNode(node)) { return true; } const parentFunction = (0, node_types_1.findParentFunction)(node); const parentNode = node.parent ? (0, node_types_1.findParentCommand)(node) : null; if ((0, node_types_1.isVariable)(node) || (0, node_types_1.isVariableDefinitionName)(node) || (0, set_1.isSetVariableDefinitionName)(node, false)) { return symbol.name === node.text && symbol.scopeContainsNode(node); } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'set', 'read', 'for', 'export', 'argparse')) { return !!(symbol.name === node.text && symbol.scopeContainsNode(node) && parentFunction?.equals(symbol.scopeNode)); } return false; }; const checkFunctionReference = ({ symbol, node }) => { if (!symbol.isFunction()) return false; const parentNode = node.parent ? (0, node_types_1.findParentCommand)(node) : null; const prevNode = node.previousNamedSibling; if ((0, node_types_1.isCommand)(node) && node.text === symbol.name) return true; if ((0, node_types_1.isFunctionDefinitionName)(node) && symbol.isGlobal()) { return symbol.equalsNode(node); } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, symbol.name) && parentNode.firstNamedChild?.equals(node)) { return true; } if ((0, node_types_1.isCommandWithName)(node, symbol.name)) return true; if ((0, node_types_1.isArgumentThatCanContainCommandCalls)(node)) { if ((0, node_types_1.isString)(node) || (0, node_types_1.isOption)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } return node.text === symbol.name; } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'type', 'functions')) { const firstChild = parentNode.namedChildren.find(n => !(0, node_types_1.isOption)(n)); return firstChild?.text === symbol.name; } if (prevNode && (0, options_1.isMatchingOption)(prevNode, options_1.Option.create('-w', '--wraps')) || node.parent && (0, node_types_1.isFunctionDefinition)(node.parent) && (0, options_1.isMatchingOptionOrOptionValue)(node, options_1.Option.create('-w', '--wraps'))) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'abbr')) { if (prevNode && (0, node_types_2.isMatchingAbbrFunction)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } const namedChild = (0, tree_sitter_1.getChildNodes)(parentNode).find(n => (0, node_types_2.isAbbrDefinitionName)(n)); if (namedChild && Locations.Range.isAfter((0, tree_sitter_1.getRange)(namedChild), symbol.selectionRange) && !(0, node_types_1.isOption)(node) && node.text === symbol.name) { return true; } } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'bind')) { if ((0, node_types_1.isOption)(node)) return false; if ((0, bind_1.isBindFunctionCall)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } if ((0, node_types_1.isString)(node) && (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name)) { return true; } const cmd = parentNode.childrenForFieldName('argument').slice(1) .filter(n => !(0, node_types_1.isOption)(n) && !(0, node_types_1.isEndStdinCharacter)(n)) .find(n => n.equals(node) && n.text === symbol.name); if (cmd) return true; } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'alias')) { if ((0, alias_1.isAliasDefinitionValue)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'argparse')) { if ((0, node_types_1.isOption)(node) || (0, node_types_1.isString)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'export', 'set', 'read', 'for', 'argparse')) { if ((0, node_types_1.isOption)(node) || (0, node_types_1.isString)(node)) { return (0, nested_strings_1.extractCommands)(node).some(cmd => cmd === symbol.name); } if ((0, node_types_1.isVariableDefinitionName)(node)) return false; return symbol.name === node.text; } return symbol.name === node.text && symbol.scopeContainsNode(node); }; const checkVariableReference = ({ symbol, node }) => { if (!symbol.isVariable() || node.text !== symbol.name) return false; if ((0, node_types_1.isVariable)(node) || (0, node_types_1.isVariableDefinitionName)(node)) return true; const parentNode = node.parent ? (0, node_types_1.findParentCommand)(node) : null; if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, symbol.name)) { return false; } if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'export', 'set', 'read', 'for', 'argparse')) { if ((0, node_types_1.isOption)(node)) return false; if ((0, node_types_1.isVariableDefinitionName)(node)) return symbol.name === node.text; } return symbol.name === node.text && symbol.scopeContainsNode(node); }; const referenceCheckers = [ checkEventReference, checkArgparseReference, checkFunctionReference, checkVariableReference, ]; const isSymbolReference = (symbol, document, node, excludeEqualNode = false) => { const ctx = { symbol, document, node, excludeEqualNode }; if (shouldSkipNode(ctx)) return false; if (symbol.isEvent()) { return checkEventReference(ctx); } if (!isInValidScope(ctx)) return false; if (!matchesFunctionName(ctx)) return false; const parentNode = node.parent ? (0, node_types_1.findParentCommand)(node) : null; if (parentNode && (0, node_types_1.isCommandWithName)(parentNode, 'complete')) { return checkCompleteCommandReference(ctx); } for (const checker of referenceCheckers) { if (checker(ctx)) return true; } return false; }; exports.isSymbolReference = isSymbolReference;