UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

135 lines (134 loc) 5.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceResource = void 0; exports.isSourceCommandName = isSourceCommandName; exports.isSourceCommandWithArgument = isSourceCommandWithArgument; exports.isSourceCommandArgumentName = isSourceCommandArgumentName; exports.isSourcedFilename = isSourcedFilename; exports.isExistingSourceFilenameNode = isExistingSourceFilenameNode; exports.getExpandedSourcedFilenameNode = getExpandedSourcedFilenameNode; exports.createSourceResources = createSourceResources; exports.reachableSources = reachableSources; exports.symbolsFromResource = symbolsFromResource; const node_types_1 = require("../utils/node-types"); const file_operations_1 = require("../utils/file-operations"); const tree_sitter_1 = require("../utils/tree-sitter"); const definition_scope_1 = require("../utils/definition-scope"); function isSourceCommandName(node) { return (0, node_types_1.isCommandWithName)(node, 'source') || (0, node_types_1.isCommandWithName)(node, '.'); } function isSourceCommandWithArgument(node) { return isSourceCommandName(node) && node.childCount > 1 && node.child(1)?.text !== '-'; } function isSourceCommandArgumentName(node) { if (node.parent && isSourceCommandWithArgument(node.parent)) { return node.parent?.child(1)?.equals(node) && node.isNamed && node.text !== '-'; } return false; } function isSourcedFilename(node) { if (node.parent && isSourceCommandName(node.parent)) { return node.parent?.child(1)?.equals(node) && node.isNamed && node.text !== '-'; } return false; } function isExistingSourceFilenameNode(node) { if (!isSourcedFilename(node)) return false; return file_operations_1.SyncFileHelper.exists(node.text) && !file_operations_1.SyncFileHelper.isDirectory(node.text) && file_operations_1.SyncFileHelper.isFile(node.text); } function getExpandedSourcedFilenameNode(node) { if (isExistingSourceFilenameNode(node)) { return file_operations_1.SyncFileHelper.expandEnvVars(node.text); } return undefined; } class SourceResource { from; to; range; node; definitionScope; sources; constructor(from, to, range, node, definitionScope, sources) { this.from = from; this.to = to; this.range = range; this.node = node; this.definitionScope = definitionScope; this.sources = sources; } static create(from, to, range, node, sources) { let scopeParent = node.parent; for (const parent of (0, tree_sitter_1.getParentNodesGen)(node)) { if ((0, node_types_1.isFunctionDefinition)(parent) || (0, node_types_1.isProgram)(parent)) { scopeParent = parent; break; } } const definitionScope = definition_scope_1.DefinitionScope.create(scopeParent, 'local'); return new SourceResource(from, to, range, node, definitionScope, sources); } scopeReachableFromNode(node) { const parent = (0, node_types_1.findParentFunction)(node); const isTopLevel = (0, node_types_1.isTopLevelDefinition)(this.node); if (parent && !isTopLevel) return this.definitionScope.containsNode(node); return this.definitionScope.containsNode(node) && node.startIndex >= this.definitionScope.scopeNode.startIndex; } } exports.SourceResource = SourceResource; function createSourceResources(analyzer, from) { const result = []; const nodes = analyzer.getNodes(from.uri).filter(n => { return isSourceCommandArgumentName(n) && !!isExistingSourceFilenameNode(n); }); if (nodes.length === 0) return result; for (const node of nodes) { const sourcedFile = getExpandedSourcedFilenameNode(node); if (!sourcedFile) continue; const to = analyzer.getDocumentFromPath(sourcedFile) || file_operations_1.SyncFileHelper.toLspDocument(sourcedFile); const range = (0, tree_sitter_1.getRange)(node); analyzer.analyze(to); const sources = createSourceResources(analyzer, to); result.push(SourceResource.create(from, to, range, node, sources)); } return result; } function reachableSources(resources, uniqueUris = new Set()) { const result = []; const sourceShouldInclude = (child, parent) => { return child.definitionScope.containsNode(parent.node) && (0, tree_sitter_1.precedesRange)(parent.range, child.range) && !uniqueUris.has(child.to.uri); }; for (const resource of resources) { const children = reachableSources(resource.sources); if (!uniqueUris.has(resource.to.uri)) { uniqueUris.add(resource.to.uri); result.push(resource); } for (const child of children) { if (sourceShouldInclude(child, resource)) { uniqueUris.add(child.to.uri); result.push(child); } } } return result; } function symbolsFromResource(analyzer, resources, uniqueNames = new Set()) { const result = []; const symbols = analyzer.getFlatDocumentSymbols(resources.to.uri); for (const symbol of symbols) { if (uniqueNames.has(symbol.name)) continue; if (symbol.isGlobal() || symbol.isRootLevel()) { result.push(symbol); } } return result; }