UNPKG

@abaplint/core

Version:
277 lines • 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Help = void 0; const nodes_1 = require("../abap/nodes"); const _lsp_utils_1 = require("./_lsp_utils"); const syntax_1 = require("../abap/5_syntax/syntax"); const _abap_object_1 = require("../objects/_abap_object"); const dump_scope_1 = require("./dump_scope"); const virtual_position_1 = require("../virtual_position"); const objects_1 = require("../objects"); const cds_lexer_1 = require("../cds/cds_lexer"); class Help { static find(reg, textDocument, position) { const abapFile = _lsp_utils_1.LSPUtils.getABAPFile(reg, textDocument.uri); if (abapFile !== undefined) { return this.dumpABAP(abapFile, reg, textDocument, position); } const file = reg.getFileByName(textDocument.uri); if (file === undefined) { return "File not found: " + textDocument.uri; } const obj = reg.findObjectForFile(file); if (obj instanceof objects_1.DataDefinition) { return this.dumpDDLS(obj, reg); } return "Unhandled object type: " + obj.getType(); } ///////////////////////////////////////////////// static dumpDDLS(obj, reg) { let content = ""; content += "<h1>" + obj.getType() + " " + obj.getName() + "</h1>\n"; content += obj.getDescription() + "\n"; content += obj.getParsingIssues().map(i => i.getMessage()).join("<br>\n"); content += `<hr>\n`; const parsed = obj.getParsedData(); parsed === null || parsed === void 0 ? true : delete parsed.tree; content += `<pre>` + JSON.stringify(parsed, null, 2) + "</pre>\n"; content += `<hr>\n`; content += `<pre>` + obj.parseType(reg).toText(0) + "</pre>\n"; content += `<hr>\n`; const file = obj.findSourceFile(); if (file) { const tokens = cds_lexer_1.CDSLexer.run(file); content += `<h3>Tokens</h3>\n<pre>\n`; for (const t of tokens) { content += JSON.stringify(t) + "\n"; } content += `</pre>\n`; } return content; } static dumpABAP(file, reg, textDocument, position) { let content = ""; content = ` <a href="#_tokens" rel="no-refresh">Tokens</a> | <a href="#_statements" rel="no-refresh">Statements</a> | <a href="#_structure" rel="no-refresh">Structure</a> | <a href="#_files" rel="no-refresh">Files</a> | <a href="#_info" rel="no-refresh">Info Dump</a> <hr> ` + "<tt>" + textDocument.uri + " (" + (position.line + 1) + ", " + (position.character + 1) + ")</tt>"; content = content + "<hr>"; content = content + this.cursorInformation(reg, textDocument, position, file); content = content + this.fileInformation(file); content = content + "<hr>"; content = content + this.dumpFiles(reg); content = content + "<hr>"; content = content + this.dumpInfo(file); return content; } static dumpInfo(file) { const info = file.getInfo(); const dump = { classDefinitions: info.listClassDefinitions(), classImplementations: info.listClassImplementations(), interfaceDefinitions: info.listInterfaceDefinitions(), forms: info.listFormDefinitions(), }; const text = JSON.stringify(dump, null, 2); return `<h3 id="_info">Info Dump</h3><pre>` + text + "</pre>"; } static cursorInformation(reg, textDocument, position, file) { let ret = ""; const found = _lsp_utils_1.LSPUtils.findCursor(reg, { textDocument, position }); if (found !== undefined) { ret = "Statement: " + this.linkToStatement(found.snode.get()) + "<br>\n" + "Token: " + found.token.constructor.name + "<br>\n" + this.fullPath(file, found.token).value; } else { ret = "No token found at cursor position"; } const obj = reg.getObject(file.getObjectType(), file.getObjectName()); if (obj instanceof _abap_object_1.ABAPObject) { const spaghetti = new syntax_1.SyntaxLogic(reg, obj).run().spaghetti; ret = ret + dump_scope_1.DumpScope.dump(spaghetti); if (found !== undefined) { ret = ret + "<hr>Spaghetti Scope by Cursor Position:<br><br>\n"; const lookup = spaghetti.lookupPosition(found.token.getStart(), textDocument.uri); if (lookup) { const identifier = lookup.getIdentifier(); ret = ret + "<u>" + identifier.stype + ", <tt>" + identifier.sname + "</tt>, " + identifier.filename; ret = ret + ", (" + identifier.start.getRow() + ", " + identifier.start.getCol() + ")</u><br>"; } else { ret = ret + "Not found"; } } } return ret; } static fullPath(file, token) { const structure = file.getStructure(); if (structure === undefined) { return { value: "", keyword: false }; } const found = this.traverse(structure, "", token); if (found === undefined) { return { value: "", keyword: false }; } return { value: "\n\n" + found.value, keyword: found.keyword }; } static traverse(node, parents, search) { let local = parents; if (local !== "") { local = local + " -> "; } if (node instanceof nodes_1.StructureNode) { local = local + "Structure: " + this.linkToStructure(node.get()); } else if (node instanceof nodes_1.StatementNode) { local = local + "Statement: " + this.linkToStatement(node.get()); } else if (node instanceof nodes_1.ExpressionNode) { local = local + "Expression: " + this.linkToExpression(node.get()); } else if (node instanceof nodes_1.TokenNode) { local = local + "Token: " + node.get().constructor.name; const token = node.get(); if (token.getStr() === search.getStr() && token.getCol() === search.getCol() && token.getRow() === search.getRow()) { const keyword = !(node instanceof nodes_1.TokenNodeRegex); return { value: local, keyword }; } } else { throw new Error("hover, traverse, unexpected node type"); } for (const child of node.getChildren()) { const ret = this.traverse(child, local, search); if (ret) { return ret; } } return undefined; } static fileInformation(file) { let content = ""; content = content + `<hr><h3 id="_tokens">Tokens</h3>\n`; content = content + this.tokens(file); content = content + `<hr><h3 id="_statements">Statements</h3>\n`; content = content + this.buildStatements(file); content = content + `<hr><h3 id="_structure">Structure</h3>\n`; const structure = file.getStructure(); if (structure !== undefined) { content = content + this.buildStructure([structure]); } else { content = content + "structure undefined"; } return content; } static escape(str) { str = str.replace(/&/g, "&amp;"); str = str.replace(/>/g, "&gt;"); str = str.replace(/</g, "&lt;"); str = str.replace(/"/g, "&quot;"); str = str.replace(/'/g, "&#039;"); return str; } static linkToStatement(statement) { return `<a href="https://syntax.abaplint.org/#/statement/${statement.constructor.name}" target="_blank">${statement.constructor.name}</a>\n`; } static linkToStructure(structure) { return `<a href="https://syntax.abaplint.org/#/structure/${structure.constructor.name}" target="_blank">${structure.constructor.name}</a>\n`; } static linkToExpression(expression) { return `<a href="https://syntax.abaplint.org/#/expression/${expression.constructor.name}" target="_blank">${expression.constructor.name}</a>\n`; } static outputNodes(nodes) { let ret = "<ul>"; for (const node of nodes) { let extra = ""; switch (node.constructor.name) { case "TokenNode": case "TokenNodeRegex": // @ts-ignore extra = node.get().constructor.name + ", \"" + node.get().getStr() + "\""; break; case "ExpressionNode": extra = this.linkToExpression(node.get()) + this.outputNodes(node.getChildren()); break; default: break; } ret = ret + "<li>" + node.constructor.name + ", " + extra + "</li>"; } return ret + "</ul>"; } static tokens(file) { let inner = `<table><tr><td><b>String</b></td><td><b>Type</b></td> <td><b>Row</b></td><td><b>Column</b></td> <td><b>vRow</b></td><td><b>vColumn</b></td> </tr>`; for (const token of file.getTokens()) { const tStart = token.getStart(); inner += "<tr><td><tt>" + this.escape(token.getStr()) + "</tt></td><td>" + token.constructor.name + "</td><td align=\"right\">" + tStart.getRow() + "</td><td align=\"right\">" + tStart.getCol() + "</td>"; if (tStart instanceof virtual_position_1.VirtualPosition) { inner += `<td>${tStart.vcol}</td><td>${tStart.vrow}</td>`; } else { inner += "<td></td><td></td>"; } inner += "</tr>"; } inner = inner + "</table>"; return inner; } static buildStatements(file) { let output = ""; for (const statement of file.getStatements()) { const row = statement.getStart().getRow(); // getting the class name only works if uglify does not mangle names output = output + row + ": " + this.linkToStatement(statement.get()) + "</div></b>\n" + this.outputNodes(statement.getChildren()); } return output; } static buildStructure(nodes) { let output = "<ul>"; for (const node of nodes) { if (node instanceof nodes_1.StructureNode) { output = output + "<li>" + this.linkToStructure(node.get()) + ", Structure " + this.buildStructure(node.getChildren()) + "</li>"; } else if (node instanceof nodes_1.StatementNode) { output = output + "<li>" + this.linkToStatement(node.get()) + ", Statement</li>"; } } return output + "</ul>"; } static dumpFiles(reg) { let output = `<h3 id="_files">Files</h3><table>\n`; for (const o of reg.getObjects()) { if (reg.isDependency(o) === true) { continue; } output = output + "<tr><td valign=\"top\">" + o.getType() + " " + o.getName() + "</td><td>"; for (const f of o.getFiles()) { output = output + f.getFilename() + "<br>"; } output = output + "</td></tr>\n"; } return output + "</table>\n"; } } exports.Help = Help; //# sourceMappingURL=help.js.map