@abaplint/core
Version:
abaplint - Core API
277 lines • 11.6 kB
JavaScript
;
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, "&");
str = str.replace(/>/g, ">");
str = str.replace(/</g, "<");
str = str.replace(/"/g, """);
str = str.replace(/'/g, "'");
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