UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

248 lines (247 loc) 9.38 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.VariableDefinitionFlag = exports.DefinitionScope = void 0; exports.getVariableScope = getVariableScope; exports.getScope = getScope; exports.expandEntireVariableLine = expandEntireVariableLine; exports.setQuery = setQuery; const NodeTypes = __importStar(require("./node-types")); const translation_1 = require("./translation"); const tree_sitter_1 = require("./tree-sitter"); class DefinitionScope { scopeNode; scopeTag; constructor(scopeNode, scopeTag) { this.scopeNode = scopeNode; this.scopeTag = scopeTag; } static create(scopeNode, scopeTag) { return new DefinitionScope(scopeNode, scopeTag); } containsPosition(position) { return (0, tree_sitter_1.isPositionWithinRange)(position, (0, tree_sitter_1.getRange)(this.scopeNode)); } isBeforePosition(position) { return this.scopeNode.startPosition.row < position.line || this.scopeNode.startPosition.row === position.line && this.scopeNode.startPosition.column < position.character; } isAfterPosition(position) { return this.scopeNode.endPosition.row > position.line || this.scopeNode.endPosition.row === position.line && this.scopeNode.endPosition.column > position.character; } isBeforeNode(node) { const range = (0, tree_sitter_1.getRange)(node); return this.scopeNode.startPosition.row < range.start.line || this.scopeNode.startPosition.row === range.start.line && this.scopeNode.startPosition.column < range.start.character; } isAfterNode(node) { const range = (0, tree_sitter_1.getRange)(node); return this.scopeNode.endPosition.row > range.end.line || this.scopeNode.endPosition.row === range.end.line && this.scopeNode.endPosition.column > range.end.character; } containsNode(node) { const range = (0, tree_sitter_1.getRange)(node); return this.containsPosition(range.start); } get tag() { const tag = this.scopeTag; return DefinitionScope.ScopeTags[tag] || 0; } static get ScopeTags() { return { universal: 5, global: 4, function: 3, local: 2, inherit: 1, '': 0, }; } } exports.DefinitionScope = DefinitionScope; class VariableDefinitionFlag { short; long; constructor(short, long) { this.short = short; this.long = long; } isMatch(node) { if (!NodeTypes.isOption(node)) { return false; } if (NodeTypes.isShortOption(node)) { return node.text.slice(1).split('').includes(this.short); } if (NodeTypes.isLongOption(node)) { return node.text.slice(2) === this.long; } return false; } get kind() { return this.long; } } exports.VariableDefinitionFlag = VariableDefinitionFlag; const variableDefinitionFlags = [ new VariableDefinitionFlag('g', 'global'), new VariableDefinitionFlag('l', 'local'), new VariableDefinitionFlag('', 'inherit'), new VariableDefinitionFlag('f', 'function'), new VariableDefinitionFlag('U', 'universal'), ]; const hasParentFunction = (node) => { return !!(0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isFunctionDefinition); }; function getMatchingFlags(focusedNode, nodes) { for (const node of nodes) { const match = variableDefinitionFlags.find(flag => flag.isMatch(node)); if (match) { return match; } } return hasParentFunction(focusedNode) ? new VariableDefinitionFlag('f', 'function') : new VariableDefinitionFlag('', 'inherit'); } function findScopeFromFlag(node, flag) { let scopeNode = node.parent; let scopeFlag = flag.kind; switch (flag.kind) { case 'global': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isProgram); scopeFlag = 'global'; break; case 'universal': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isProgram); scopeFlag = 'universal'; break; case 'local': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isScope); break; case 'function': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isFunctionDefinition); scopeFlag = 'function'; break; case 'for_scope': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isFunctionDefinition); scopeFlag = 'function'; if (!scopeNode) { scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isProgram); scopeFlag = 'global'; } break; case 'inherit': scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isScope); scopeFlag = 'inherit'; break; default: scopeNode = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isScope); break; } const finalScopeNode = scopeNode || node.parent; return DefinitionScope.create(finalScopeNode, scopeFlag); } function getVariableScope(node) { const definitionNodes = expandEntireVariableLine(node); const keywordNode = definitionNodes[0]; let matchingFlag = null; switch (keywordNode.text) { case 'for': matchingFlag = new VariableDefinitionFlag('', 'for_scope'); break; case 'set': case 'read': case 'function': default: matchingFlag = getMatchingFlags(node, definitionNodes); break; } const scope = findScopeFromFlag(node, matchingFlag); return scope; } function getScope(document, node) { if (NodeTypes.isEmittedEventDefinitionName(node)) { return DefinitionScope.create(node, 'global'); } if (NodeTypes.isAliasDefinitionName(node)) { const isAutoloadedName = (0, translation_1.isAutoloadedUriLoadsAliasName)(document); if (isAutoloadedName(node)) { return DefinitionScope.create(node, 'global'); } const parents = (0, tree_sitter_1.getParentNodes)(node.parent.parent) || (0, tree_sitter_1.getParentNodes)(node.parent); const firstParent = parents .filter(n => NodeTypes.isProgram(n) || NodeTypes.isFunctionDefinition(n)) .at(0); return DefinitionScope.create(firstParent, 'local'); } else if (NodeTypes.isFunctionDefinitionName(node)) { const isAutoloadedName = (0, translation_1.isAutoloadedUriLoadsFunctionName)(document); const parents = (0, tree_sitter_1.getParentNodes)(node.parent.parent) || (0, tree_sitter_1.getParentNodes)(node.parent); const firstParent = parents .filter(n => NodeTypes.isProgram(n) || NodeTypes.isFunctionDefinition(n)) .at(0); if (isAutoloadedName(node)) { const program = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isProgram); return DefinitionScope.create(program, 'global'); } return DefinitionScope.create(firstParent, 'local'); } else if (NodeTypes.isVariableDefinitionName(node)) { return getVariableScope(node); } const scope = (0, tree_sitter_1.firstAncestorMatch)(node, NodeTypes.isScope); return DefinitionScope.create(scope, 'local'); } function expandEntireVariableLine(node) { const results = [node]; let current = node.previousSibling; while (current !== null) { if (!current || NodeTypes.isNewline(current)) { break; } results.unshift(current); current = current.previousSibling; } current = node.nextSibling; while (current !== null) { if (!current || NodeTypes.isNewline(current)) { break; } results.push(current); current = current.nextSibling; } return results; } function setQuery(searchNodes) { const queryFlag = new VariableDefinitionFlag('q', 'query'); for (const flag of searchNodes) { if (queryFlag.isMatch(flag)) { return true; } } return false; }