UNPKG

fish-lsp

Version:

LSP implementation for fish/fish-shell

178 lines (177 loc) 6.42 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.Workspace = void 0; exports.initializeDefaultFishWorkspaces = initializeDefaultFishWorkspaces; exports.getRelevantDocs = getRelevantDocs; const fastGlob = __importStar(require("fast-glob")); const fs_1 = require("fs"); const translation_1 = require("./translation"); const config_1 = require("../config"); const logger_1 = require("../logger"); async function getFileUriSet(path) { const stream = fastGlob.stream('**/*.fish', { cwd: path, absolute: true }); const result = new Set(); for await (const entry of stream) { const absPath = entry.toString(); const uri = (0, translation_1.pathToUri)(absPath); result.add(uri); } return result; } async function initializeDefaultFishWorkspaces() { const configWorkspaces = config_1.config.fish_lsp_all_indexed_paths; // Create an array of promises by mapping over workspacePaths const workspacePromises = configWorkspaces.map(path => Workspace.create(path)); // Wait for all promises to resolve const defaultSpaces = await Promise.all(workspacePromises); return defaultSpaces; } async function getRelevantDocs(workspaces) { const docs = []; for await (const ws of workspaces) { const workspaceDocs = await ws.asyncFilter((doc) => doc.shouldAnalyzeInBackground()); docs.push(...workspaceDocs); } return docs; } class Workspace { path; uris; symbols = new Map(); static async create(path) { const foundUris = await getFileUriSet(path); return new Workspace(path, foundUris); } constructor(path, fileUris) { this.path = path; this.uris = fileUris; } contains(...checkUris) { for (const uri of checkUris) { const uriAsPath = (0, translation_1.uriToPath)(uri); if (!uriAsPath.startsWith(this.path)) { return false; } //if (!this.uris.has(uri)) return false } return true; } add(...newUris) { for (const newUri of newUris) { this.uris.add(newUri); } } findMatchingFishIdentifiers(fishIdentifier) { const matches = []; const toMatch = `/${fishIdentifier}.fish`; for (const uri of this.uris) { if (uri.endsWith(toMatch)) { matches.push(uri); } } return matches; } /** * An immutable workspace would be '/usr/share/fish', since we don't want to * modify the system files. * * A mutable workspace would be '~/.config/fish' */ isMutable() { return config_1.config.fish_lsp_modifiable_paths.includes(this.path); } isLoadable() { return config_1.config.fish_lsp_all_indexed_paths.includes(this.path); } async updateFiles() { const newUris = await getFileUriSet(this.path); const diff = new Set([...this.uris].filter(x => !this.uris.has(x))); if (diff.size === 0) { return false; } newUris.forEach(uri => this.uris.add(uri)); return true; } hasCompletionUri(fishIdentifier) { const matchingUris = this.findMatchingFishIdentifiers(fishIdentifier); return matchingUris.some(uri => uri.endsWith(`/completions/${fishIdentifier}.fish`)); } hasFunctionUri(fishIdentifier) { const matchingUris = this.findMatchingFishIdentifiers(fishIdentifier); return matchingUris.some(uri => uri.endsWith(`/functions/${fishIdentifier}.fish`)); } hasCompletionAndFunction(fishIdentifier) { return this.hasFunctionUri(fishIdentifier) && this.hasCompletionUri(fishIdentifier); } async asyncUrisToLspDocuments() { const readPromises = Array.from(this.uris).map(async (uri) => { try { const path = (0, translation_1.uriToPath)(uri); const content = await fs_1.promises.readFile(path, 'utf8'); return (0, translation_1.toLspDocument)(path, content); } catch (err) { logger_1.logger.log(`Error reading file ${uri}: ${err}`); return null; } }); const docs = await Promise.all(readPromises); return docs.filter((doc) => doc !== null); } async asyncForEach(callback) { const docs = await this.asyncUrisToLspDocuments(); docs.forEach(callback); } async asyncFilter(callbackfn) { const docs = await this.asyncUrisToLspDocuments(); return docs.filter(callbackfn); } urisToLspDocuments() { const docs = []; for (const uri of this.uris) { const path = (0, translation_1.uriToPath)(uri); const content = (0, fs_1.readFileSync)(path); const doc = (0, translation_1.toLspDocument)(path, content.toString()); docs.push(doc); } return docs; } forEach(callback) { for (const doc of this.urisToLspDocuments()) { callback(doc); } } filter(callbackfn) { const result = []; for (const doc of this.urisToLspDocuments()) { if (callbackfn(doc)) { result.push(doc); } } return result; } } exports.Workspace = Workspace;