UNPKG

@abaplint/core

Version:
297 lines • 9.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpaghettiScope = exports.SpaghettiScopeNode = void 0; const _typed_identifier_1 = require("../types/_typed_identifier"); const _identifier_1 = require("../4_file_information/_identifier"); const _reference_1 = require("./_reference"); const assert_error_1 = require("./assert_error"); class ScopeData { constructor() { this.data = { vars: {}, cdefs: {}, idefs: {}, forms: [], // todo, refactor to object types: {}, extraLikeTypes: {}, deferred: {}, references: [], sqlConversion: [], }; } getData() { return this.data; } } class SpaghettiScopeNode extends ScopeData { [Symbol.for("debug.description")]() { return `SpaghettiSN ${this.identifier.sname} ${this.identifier.stype}`; } constructor(identifier, parent) { super(); this.identifier = identifier; this.parent = parent; this.children = []; } getParent() { return this.parent; } addChild(node) { this.children.push(node); } getChildren() { return this.children; } getFirstChild() { return this.children[0]; } getIdentifier() { return this.identifier; } calcCoverage() { if (this.identifier.end === undefined) { throw new assert_error_1.AssertError("internal error, caclCoverage"); } return { start: this.identifier.start, end: this.identifier.end }; } setEnd(end) { this.identifier.end = end; } findDeferred(name) { let search = this; while (search !== undefined) { const found = search.getData().deferred[name.toUpperCase()]; if (found) { return { id: new _identifier_1.Identifier(found.token, search.identifier.filename), ooType: found.ooType, }; } search = search.getParent(); } return undefined; } findClassDefinition(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { const c = search.getData().cdefs[upper]; if (c !== undefined) { return c; } search = search.getParent(); } return undefined; } listClassDefinitions() { let search = this; const ret = []; while (search !== undefined) { ret.push(...Object.values(search.getData().cdefs)); search = search.getParent(); } return ret; } listInterfaceDefinitions() { let search = this; const ret = []; while (search !== undefined) { ret.push(...Object.values(search.getData().idefs)); search = search.getParent(); } return ret; } findFormDefinition(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { for (const form of search.getData().forms) { if (form.getName().toUpperCase() === upper) { return form; } } search = search.getParent(); } return undefined; } findInterfaceDefinition(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { const idef = search.getData().idefs[upper]; if (idef) { return idef; } search = search.getParent(); } return undefined; } findType(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { const found = search.getData().types[upper]; if (found) { return found; } search = search.getParent(); } return undefined; } findExtraLikeType(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { const data = search.getData(); if (data.extraLikeTypes[upper]) { return data.extraLikeTypes[upper]; } search = search.getParent(); } return undefined; } findVariable(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { const data = search.getData(); if (data.vars[upper]) { return data.vars[upper]; } search = search.getParent(); } return undefined; } findWriteReference(pos) { for (const r of this.getData().references) { if (r.referenceType === _reference_1.ReferenceType.DataWriteReference && r.position.getStart().equals(pos)) { if (r.resolved instanceof _typed_identifier_1.TypedIdentifier) { return r.resolved; } } } return undefined; } findTableReference(pos) { for (const r of this.getData().references) { if (r.referenceType === _reference_1.ReferenceType.TableReference && r.position.getStart().equals(pos) && r.resolved) { return r.resolved.getName(); } } return undefined; } findTableVoidReference(pos) { for (const r of this.getData().references) { if (r.referenceType === _reference_1.ReferenceType.TableVoidReference && r.position.getStart().equals(pos)) { return true; } } return false; } // this method is used in the transpiler findScopeForVariable(name) { let search = this; const upper = name.toUpperCase(); while (search !== undefined) { if (search.getData().vars[upper] !== undefined) { return search.getIdentifier(); } search = search.getParent(); } return undefined; } } exports.SpaghettiScopeNode = SpaghettiScopeNode; class SpaghettiScope { constructor(top) { this.node = top; } // list variable definitions across all nodes listDefinitions(filename) { const ret = []; for (const n of this.allNodes()) { if (n.getIdentifier().filename === filename) { const vars = n.getData().vars; for (const v in vars) { if (vars[v].getFilename() === filename) { ret.push({ name: v, identifier: vars[v] }); } } } } return ret; } listReadPositions(filename) { const ret = []; for (const n of this.allNodes()) { if (n.getIdentifier().filename === filename) { for (const v of n.getData().references) { if (v.referenceType === _reference_1.ReferenceType.DataReadReference && v.position.getFilename() === filename) { ret.push(v.position); } } } } return ret; } listWritePositions(filename) { const ret = []; for (const n of this.allNodes()) { if (n.getIdentifier().filename === filename) { for (const v of n.getData().references) { if (v.referenceType === _reference_1.ReferenceType.DataWriteReference && v.position.getFilename() === filename) { ret.push(v.position); } } } } return ret; } lookupPosition(p, filename) { if (p === undefined || filename === undefined) { return undefined; } return this.lookupPositionTraverse(p, filename, this.node); } getFirstChild() { return this.node.getFirstChild(); } getTop() { return this.node; } ///////////////////////////// allNodes() { const ret = []; const stack = [this.node]; while (stack.length > 0) { const current = stack.pop(); ret.push(current); stack.push(...current.getChildren()); } return ret; } lookupPositionTraverse(p, filename, node) { const coverage = node.calcCoverage(); if (node.getIdentifier().filename === filename && p.isBetween(coverage.start, coverage.end) === false) { return undefined; } // possible optimization: binary search the nodes for (const c of node.getChildren()) { const result = this.lookupPositionTraverse(p, filename, c); if (result !== undefined) { return result; } } if (node.getIdentifier().filename === filename && p.isBetween(coverage.start, coverage.end)) { return node; } return undefined; } } exports.SpaghettiScope = SpaghettiScope; //# sourceMappingURL=spaghetti_scope.js.map