UNPKG

@abaplint/core

Version:
473 lines • 17.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CurrentScope = void 0; const _builtin_1 = require("./_builtin"); const ddic_1 = require("../../ddic"); const position_1 = require("../../position"); const spaghetti_scope_1 = require("./spaghetti_scope"); const _identifier_1 = require("../4_file_information/_identifier"); const _scope_type_1 = require("./_scope_type"); const syntax_1 = require("./syntax"); class CurrentScope { static buildDefault(reg, obj) { const s = new CurrentScope(reg, obj); s.push(_scope_type_1.ScopeType.BuiltIn, _scope_type_1.ScopeType.BuiltIn, new position_1.Position(1, 1), _builtin_1.BuiltIn.filename); this.addBuiltIn(s, reg.getConfig().getSyntaxSetttings().globalConstants); let name = _scope_type_1.ScopeType.Global; if (obj) { name = name + "_" + obj.getName(); } s.push(_scope_type_1.ScopeType.Global, name, new position_1.Position(1, 1), name); return s; } static addBuiltIn(s, extras) { const b = new _builtin_1.BuiltIn(); const builtin = b.get(extras); s.addList(builtin); for (const t of b.getTypes()) { s.addType(t); } } constructor(reg, obj) { this.current = undefined; this.parentObj = obj; this.reg = reg; } /////////////////////////// getVersion() { return this.reg.getConfig().getVersion(); } getRegistry() { return this.reg; } addType(type) { if (type === undefined) { return; } this.addTypeNamed(type.getName(), type); } addTypeNamed(name, type) { if (type === undefined) { return; } if (this.current === undefined) { return; } const upper = name.toUpperCase(); if (this.current.getData().types[upper] !== undefined) { throw new Error(`Type name "${name}" already defined`); } else if (this.isOO() && this.current.getData().vars[upper] !== undefined) { throw new Error(`"${name}" already defined`); } this.current.getData().types[upper] = type; } addExtraLikeType(type) { if (type === undefined) { return; } this.addExtraLikeTypeNamed(type.getName(), type); } addExtraLikeTypeNamed(name, type) { if (type === undefined) { return; } if (this.current === undefined) { return; } const upper = name.toUpperCase(); if (this.current.getData().extraLikeTypes[upper] !== undefined) { throw new Error(`Type name "${name}" already defined`); } this.current.getData().extraLikeTypes[upper] = type; } addClassDefinition(c) { if (this.current === undefined) { return; } const name = c.getName().toUpperCase(); if (this.current.getData().cdefs[name] !== undefined) { throw new Error(`Class "${name}" already defined`); } this.current.getData().cdefs[name] = c; } addFormDefinitions(f) { if (this.current === undefined) { return; } this.current.getData().forms.push(...f); } addInterfaceDefinition(i) { if (this.current === undefined) { return; } const name = i.getName().toUpperCase(); if (this.current.getData().cdefs[name] !== undefined) { throw new Error(`Interface "${name}" already defined`); } this.current.getData().idefs[name] = i; } addNamedIdentifier(name, identifier) { if (this.current === undefined) { return; } const upper = name.toUpperCase(); if (this.current.getData().vars[upper] !== undefined) { // console.dir(new Error().stack); throw new Error(`Variable name "${name}" already defined`); } else if (this.isOO() && this.current.getData().types[upper] !== undefined) { throw new Error(`"${name}" already defined`); } this.current.getData().vars[upper] = identifier; } addNamedIdentifierToParent(name, identifier) { if (this.current === undefined) { return; } const parent = this.current.getParent(); if (parent === undefined) { return; } const upper = name.toUpperCase(); if (parent.getData().vars[upper] !== undefined) { // console.dir(new Error().stack); throw new Error(`Variable name "${name}" already defined`); } else if (this.isOO() && parent.getData().types[upper] !== undefined) { throw new Error(`"${name}" already defined`); } parent.getData().vars[upper] = identifier; } addIdentifier(identifier) { if (identifier === undefined) { return; } this.addNamedIdentifier(identifier.getName(), identifier); } addDeferred(token, type) { if (token === undefined) { return; } this.current.getData().deferred[token.getStr().toUpperCase()] = { token, ooType: type }; } addListPrefix(identifiers, prefix) { for (const id of identifiers) { this.addNamedIdentifier(prefix + id.getName(), id); } } addList(identifiers) { for (const id of identifiers) { this.addIdentifier(id); } } addReference(usage, referencing, type, filename, extra) { var _a, _b; if (usage === undefined || type === undefined) { return; } const position = new _identifier_1.Identifier(usage, filename); if (Array.isArray(type)) { for (const t of type) { (_a = this.current) === null || _a === void 0 ? void 0 : _a.getData().references.push({ position, resolved: referencing, referenceType: t, extra }); } } else { (_b = this.current) === null || _b === void 0 ? void 0 : _b.getData().references.push({ position, resolved: referencing, referenceType: type, extra }); } } addSQLConversion(fieldName, message, token) { var _a; (_a = this.current) === null || _a === void 0 ? void 0 : _a.getData().sqlConversion.push({ fieldName, message, token }); } /////////////////////////// findFunctionModule(name) { if (name === undefined) { return undefined; } for (const fugr of this.reg.getObjectsByType("FUGR")) { const func = fugr.getModule(name); if (func !== undefined) { return func; } } return undefined; } findObjectDefinition(name) { if (name === undefined) { return undefined; } const clas = this.findClassDefinition(name); if (clas) { return clas; } const intf = this.findInterfaceDefinition(name); if (intf) { return intf; } return undefined; } isBadiDef(name) { const upper = name.toUpperCase(); for (const enhs of this.reg.getObjectsByType("ENHS")) { for (const def of enhs.listBadiDefinitions()) { if (def.name.toUpperCase() === upper) { return true; } } } return false; } existsObject(name) { var _a, _b, _c; if (name === undefined) { return undefined; } let prefixRTTI = ""; if (this.parentObj.getType() === "PROG") { prefixRTTI = "\\PROGRAM=" + this.parentObj.getName(); } else if (this.parentObj.getType() === "CLAS") { prefixRTTI = "\\CLASS-POOL=" + this.parentObj.getName(); } const findLocalClass = (_a = this.current) === null || _a === void 0 ? void 0 : _a.findClassDefinition(name); if (findLocalClass) { if (findLocalClass.isGlobal() === true) { prefixRTTI = ""; } return { id: findLocalClass, ooType: "CLAS", RTTIName: prefixRTTI + "\\CLASS=" + findLocalClass.getName() }; } const globalClas = this.reg.getObject("CLAS", name); if (globalClas) { return { id: globalClas.getIdentifier(), ooType: "CLAS", RTTIName: "\\CLASS=" + globalClas.getName() }; } const findLocalInterface = (_b = this.current) === null || _b === void 0 ? void 0 : _b.findInterfaceDefinition(name); if (findLocalInterface) { if (findLocalInterface.isGlobal() === true) { prefixRTTI = ""; } return { id: findLocalInterface, ooType: "INTF", RTTIName: prefixRTTI + "\\INTERFACE=" + findLocalInterface.getName() }; } const globalIntf = this.reg.getObject("INTF", name); if (globalIntf) { return { id: globalIntf.getIdentifier(), ooType: "INTF", RTTIName: "\\INTERFACE=" + globalIntf.getName() }; } const def = (_c = this.current) === null || _c === void 0 ? void 0 : _c.findDeferred(name); if (def !== undefined) { let rttiName = prefixRTTI; switch (def.ooType) { case "INTF": rttiName = rttiName + "\\INTERFACE=" + name; break; default: rttiName = rttiName + "\\CLASS=" + name; break; } return { id: def.id, ooType: def.ooType, RTTIName: rttiName }; } return undefined; } /////////////////////////// /** Lookup class in local and global scope */ findClassDefinition(name) { var _a; if (name === undefined) { return undefined; } const clocal = (_a = this.current) === null || _a === void 0 ? void 0 : _a.findClassDefinition(name); if (clocal) { return clocal; } const cglobal = this.reg.getObject("CLAS", name); if (cglobal) { return cglobal.getDefinition(); } return undefined; } findTypePoolConstant(name) { var _a; if (name === undefined || name.includes("_") === undefined) { return undefined; } const typePoolName = name.split("_")[0]; if (typePoolName.length <= 1 || typePoolName.length > 5) { return undefined; } if (this.parentObj.getType() === "TYPE" && this.parentObj.getName().toUpperCase() === typePoolName.toUpperCase()) { // dont recurse into itself return undefined; } const typePool = this.reg.getObject("TYPE", typePoolName); if (typePool === undefined) { return undefined; } const spag = (_a = new syntax_1.SyntaxLogic(this.reg, typePool).run().spaghetti.getFirstChild()) === null || _a === void 0 ? void 0 : _a.getFirstChild(); const found = spag === null || spag === void 0 ? void 0 : spag.findVariable(name); return found; } findTypePoolType(name) { var _a; if (name.includes("_") === undefined) { return undefined; } const typePoolName = name.split("_")[0]; if (typePoolName.length <= 2 || typePoolName.length > 5) { return undefined; } if (this.parentObj.getType() === "TYPE" && this.parentObj.getName().toUpperCase() === typePoolName.toUpperCase()) { // dont recurse into itself return undefined; } if (new ddic_1.DDIC(this.reg).lookupNoVoid(name) !== undefined) { // this is tricky, it should not do recursion when parsing the type pool itself, // think about DTEL ABAP_ENCOD vs TYPE ABAP return undefined; } const typePool = this.reg.getObject("TYPE", typePoolName); if (typePool === undefined) { return undefined; } const spag = (_a = new syntax_1.SyntaxLogic(this.reg, typePool).run().spaghetti.getFirstChild()) === null || _a === void 0 ? void 0 : _a.getFirstChild(); const found = spag === null || spag === void 0 ? void 0 : spag.findType(name); return found; } /** Lookup interface in local and global scope */ findInterfaceDefinition(name) { var _a; if (name === undefined) { return undefined; } const ilocal = (_a = this.current) === null || _a === void 0 ? void 0 : _a.findInterfaceDefinition(name); if (ilocal) { return ilocal; } const iglobal = this.reg.getObject("INTF", name); if (iglobal) { return iglobal.getDefinition(); } return undefined; } findFormDefinition(name) { var _a; return (_a = this.current) === null || _a === void 0 ? void 0 : _a.findFormDefinition(name); } findType(name) { var _a; if (name === undefined) { return undefined; } return (_a = this.current) === null || _a === void 0 ? void 0 : _a.findType(name); } findExtraLikeType(name) { var _a; if (name === undefined) { return undefined; } return (_a = this.current) === null || _a === void 0 ? void 0 : _a.findExtraLikeType(name); } findVariable(name) { var _a; if (name === undefined) { return undefined; } const found = (_a = this.current) === null || _a === void 0 ? void 0 : _a.findVariable(name); if (found) { return found; } return this.findTypePoolConstant(name); } /////////////////////////// getDDIC() { return new ddic_1.DDIC(this.reg); } getDDICReferences() { return this.reg.getDDICReferences(); } getMSAGReferences() { return this.reg.getMSAGReferences(); } getParentObj() { return this.parentObj; } getName() { if (this.current === undefined) { throw new Error("error, getName"); } return this.current.getIdentifier().sname; } getType() { if (this.current === undefined) { throw new Error("error, getType"); } return this.current.getIdentifier().stype; } push(stype, sname, start, filename) { const identifier = { stype, sname, start, filename, end: undefined }; // console.dir("push scope, " + stype); if (this.current === undefined) { // the top node this.current = new spaghetti_scope_1.SpaghettiScopeNode(identifier, undefined); } else { const parent = this.current; this.current = new spaghetti_scope_1.SpaghettiScopeNode(identifier, parent); parent.addChild(this.current); } } isOO() { let curr = this.current; while (curr !== undefined) { const stype = curr.getIdentifier().stype; if (stype === _scope_type_1.ScopeType.ClassDefinition // || stype === ScopeType.ClassImplementation || stype === _scope_type_1.ScopeType.Interface) { return true; } curr = curr.getParent(); } return false; } isAnyOO() { let curr = this.current; while (curr !== undefined) { const stype = curr.getIdentifier().stype; if (stype === _scope_type_1.ScopeType.ClassDefinition || stype === _scope_type_1.ScopeType.ClassImplementation || stype === _scope_type_1.ScopeType.Interface) { return true; } curr = curr.getParent(); } return false; } isGlobalOO() { return this.parentObj.getType() === "INTF" || this.parentObj.getType() === "CLAS"; } isTypePool() { var _a; return ((_a = this.current) === null || _a === void 0 ? void 0 : _a.getIdentifier().filename.endsWith(".type.abap")) === true || false; } setAllowHeaderUse(name) { // workaround for SELECT FOR ALL ENTRIES this.allowHeaderUse = name; } isAllowHeaderUse(name) { var _a; return name.toUpperCase() === ((_a = this.allowHeaderUse) === null || _a === void 0 ? void 0 : _a.toUpperCase()); } pop(end) { // console.dir("pop scope, " + this.current?.getIdentifier().stype); this.allowHeaderUse = undefined; if (this.current === undefined) { throw new Error("something wrong, top scope popped"); } this.current.setEnd(end); const current = this.current; this.current = this.current.getParent(); return new spaghetti_scope_1.SpaghettiScope(current); } } exports.CurrentScope = CurrentScope; //# sourceMappingURL=_current_scope.js.map