perlnavigator-server
Version:
Perl language server
85 lines • 3.35 kB
JavaScript
;
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