UNPKG

plaxtony

Version:

Static code analysis of SC2 Galaxy Script

118 lines 4.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SignaturesProvider = void 0; const lsp = require("vscode-languageserver"); const utils_1 = require("../compiler/utils"); const printer_1 = require("../compiler/printer"); const checker_1 = require("../compiler/checker"); const provider_1 = require("./provider"); const utils_2 = require("./utils"); const s2meta_1 = require("./s2meta"); class SignaturesProvider extends provider_1.AbstractProvider { constructor() { super(...arguments); this.printer = new printer_1.Printer(); } evaluateActiveParameter(callExpr, position) { let activeParam = null; let prevArg; callExpr.arguments.some((argument, index, args) => { if (argument.pos <= position) { activeParam = index; prevArg = argument; // exit early when confirmed it is in bounds // in other case keep going to acomodate whitespaces if (argument.end >= position) { return true; } // offset is after last existing arg, it means the current argument wasn't yet parsed if (index === args.length - 1 && position > args[index].end) { activeParam++; } } // offset is before bounds of next param node, yet we got here - we must be in whitespace else if (prevArg) { activeParam = index; return true; } return; }); return activeParam; } getSignatureOfFunction(functionSymbol) { const functionDeclaration = functionSymbol.declarations[0]; let code = this.printer.printNode(Object.assign({}, functionDeclaration, { body: null })).trim(); // strip ; if (code.substr(code.length - 1, 1) === ';') { code = code.substr(0, code.length - 1); } const signatureInfo = { label: code, parameters: [], }; const docStr = s2meta_1.getDocumentationOfSymbol(this.store, functionSymbol, false); if (docStr) { signatureInfo.documentation = { kind: lsp.MarkupKind.Markdown, value: docStr, }; } const argsDoc = this.store.s2metadata ? this.store.s2metadata.getFunctionArgumentsDoc(functionSymbol.escapedName) : null; for (const [index, paramDeclaration] of functionDeclaration.parameters.entries()) { const paramInfo = { label: this.printer.printNode(paramDeclaration), }; if (argsDoc && argsDoc[index]) { paramInfo.documentation = { kind: lsp.MarkupKind.Markdown, value: argsDoc[index], }; } signatureInfo.parameters.push(paramInfo); } return signatureInfo; } getSignatureAt(uri, position) { const signatureHelp = { signatures: [], activeSignature: null, activeParameter: null, }; const sourceFile = this.store.documents.get(uri); if (!sourceFile) return; const currentToken = utils_2.getTokenAtPosition(position, sourceFile, true); if (!currentToken) { return null; } let node = currentToken.parent; const callNode = utils_1.findAncestor(node, (element) => { if (element.kind !== 121 /* CallExpression */) { return false; } // we don't want to provide signature for left side of CallExpression if (element.arguments.pos > position) { return false; } // skip if goes over range - we must've hit CloseParenToken if (element.end <= position) { return false; } return true; }); if (!callNode) { return null; } const checker = new checker_1.TypeChecker(this.store); const type = checker.getTypeOfNode(callNode.expression, true); if (type.flags & 16384 /* Function */) { const signatureInfo = this.getSignatureOfFunction(type.symbol); signatureHelp.activeSignature = 0; signatureHelp.activeParameter = this.evaluateActiveParameter(callNode, position); signatureHelp.signatures.push(signatureInfo); } return signatureHelp; } } exports.SignaturesProvider = SignaturesProvider; //# sourceMappingURL=signatures.js.map