UNPKG

perlnavigator-server

Version:

Perl language server

85 lines 3.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSignature = void 0; const types_1 = require("./types"); const utils_1 = require("./utils"); const refinement_1 = require("./refinement"); async function getSignature(params, perlDoc, txtDoc, modMap) { let position = params.position; const [symbol, currentSig] = getFunction(position, txtDoc); if (!symbol) return; const elems = (0, utils_1.lookupSymbol)(perlDoc, modMap, symbol, position.line); // Nothing or too many things. if (elems.length != 1) return; let elem = elems[0]; const refined = await (0, refinement_1.refineElementIfSub)(elem, params, perlDoc); if (!refined) return; // const elem_count = perlDoc.elems.size; // Currently unused. return buildSignature(refined, currentSig, symbol); } exports.getSignature = getSignature; function getFunction(position, txtDoc) { const start = { line: position.line, character: 0 }; const end = { line: position.line + 1, character: 0 }; const text = txtDoc.getText({ start, end }); const index = txtDoc.offsetAt(position) - txtDoc.offsetAt(start); let r = index; // right // Find signature. for (; r > 1 && text[r] != "("; --r) { if (r > 0 && text[r - 1] == ")") return []; // Sig closes } if (r <= 1) return []; let l = r - 1; // left const canShift = (c) => /[\w\:\>\-]/.exec(c); for (; l >= 0 && canShift(text[l]); --l) // Allow for ->, but not => or > (e.g. $foo->bar, but not $foo=>bar or $foo>bar). if (text[l] == ">") if (l - 1 >= 0 && text[l - 1] != "-") break; if (l < 0 || text[l] != "$" && text[l] != "@" && text[l] != "%") ++l; let symbol = text.substring(l, r); const currSig = text.substring(r, index); const prefix = text.substring(0, l); if (symbol.match(/^->\w+$/)) { // If you have Foo::Bar->new(...)->func, the extracted symbol will be ->func // We can special case this to Foo::Bar->func. The regex allows arguments to new(), including params with matched () let match = prefix.match(/(\w(?:\w|::\w)*)->new\((?:\([^()]*\)|[^()])*\)$/); if (match) symbol = match[1] + symbol; } return [symbol, currSig]; } function buildSignature(elem, currentSig, symbol) { let params = elem.signature; if (!params) return; params = [...params]; // Clone to ensure we don't modify the original let activeParameter = (currentSig.match(/,/g) || []).length; if (symbol.indexOf("->") != -1 && elem.type != types_1.PerlSymbolKind.LocalMethod) { // Subroutine vs method is not relevant, only matters if you called it as a method (except Corinna, for which $self is implicit) params.shift(); // function_name = function_name.replace(/::(\w+)$/, '->$1'); } if (params.length == 0) return; let paramLabels = []; for (const param of params) paramLabels.push({ label: param }); let mainSig = { parameters: paramLabels, label: "(" + params.join(", ") + ")", }; let sig = { signatures: [mainSig], activeSignature: 0, activeParameter: activeParameter, }; return sig; } //# sourceMappingURL=signatures.js.map