UNPKG

@abaplint/core

Version:
358 lines • 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Registry = void 0; const config_1 = require("./config"); const artifacts_objects_1 = require("./artifacts_objects"); const find_global_definitions_1 = require("./abap/5_syntax/global_definitions/find_global_definitions"); const excludeHelper_1 = require("./utils/excludeHelper"); const ddic_references_1 = require("./ddic_references"); const rules_runner_1 = require("./rules_runner"); const msag_references_1 = require("./msag_references"); const macro_references_1 = require("./macro_references"); // todo, this should really be an instance in case there are multiple Registry'ies class ParsingPerformance { static clear() { this.results = []; this.lexing = 0; this.statements = 0; this.structure = 0; } static push(obj, result) { if (result.runtimeExtra) { this.lexing += result.runtimeExtra.lexing; this.statements += result.runtimeExtra.statements; this.structure += result.runtimeExtra.structure; } if (result.runtime < 100) { return; } if (this.results === undefined) { this.results = []; } let extra = ""; if (result.runtimeExtra) { extra = `\t(lexing: ${result.runtimeExtra.lexing}ms, statements: ${result.runtimeExtra.statements}ms, structure: ${result.runtimeExtra.structure}ms)`; } this.results.push({ runtime: result.runtime, extra, name: obj.getType() + " " + obj.getName(), }); } static output() { const MAX = 10; this.results.sort((a, b) => { return b.runtime - a.runtime; }); for (let i = 0; i < MAX; i++) { const row = this.results[i]; if (row === undefined) { break; } process.stderr.write(`\t${row.runtime}ms\t${row.name} ${row.extra}\n`); } process.stderr.write(`\tTotal lexing: ${this.lexing}ms\n`); process.stderr.write(`\tTotal statements: ${this.statements}ms\n`); process.stderr.write(`\tTotal structure: ${this.structure}ms\n`); } } /////////////////////////////////////////////////////////////////////////////////////////////// class Registry { constructor(conf) { this.objects = {}; this.objectsByType = {}; this.dependencies = {}; this.setConfig(conf ? conf : config_1.Config.getDefault()); this.ddicReferences = new ddic_references_1.DDICReferences(); this.msagReferences = new msag_references_1.MSAGReferences(); this.macroReferences = new macro_references_1.MacroReferences(); } static abaplintVersion() { // magic, see build script "version.sh" return "2.113.186"; } getDDICReferences() { return this.ddicReferences; } getMSAGReferences() { return this.msagReferences; } getMacroReferences() { return this.macroReferences; } *getObjects() { for (const name in this.objects) { for (const type in this.objects[name]) { yield this.objects[name][type]; } } } *getObjectsByType(type) { for (const name in this.objectsByType[type] || []) { yield this.objectsByType[type][name]; } } *getFiles() { for (const obj of this.getObjects()) { for (const file of obj.getFiles()) { yield file; } } } getFirstObject() { for (const name in this.objects) { for (const type in this.objects[name]) { return this.objects[name][type]; } } return undefined; } getObjectCount(skipDependencies = true) { let res = 0; for (const o of this.getObjects()) { if (skipDependencies === true && this.isDependency(o)) { continue; } res = res + 1; } return res; } getFileByName(filename) { const upper = filename.toUpperCase(); for (const o of this.getObjects()) { for (const f of o.getFiles()) { if (f.getFilename().toUpperCase() === upper) { return f; } } } return undefined; } getObject(type, name) { if (type === undefined || name === undefined) { return undefined; } const searchName = name.toUpperCase(); if (this.objects[searchName]) { return this.objects[searchName][type]; } return undefined; } getConfig() { return this.conf; } // assumption: Config is immutable, and can only be changed via this method setConfig(conf) { for (const obj of this.getObjects()) { obj.setDirty(); } this.conf = conf; this.errorNamespace = new RegExp(this.getConfig().getSyntaxSetttings().errorNamespace, "i"); return this; } inErrorNamespace(name) { return this.errorNamespace.test(name); } addFile(file) { return this.addFiles([file]); } updateFile(file) { const obj = this.find(file.getObjectName(), file.getObjectType()); obj.updateFile(file); return this; } removeFile(file) { const obj = this.find(file.getObjectName(), file.getObjectType()); obj.removeFile(file); if (obj.getFiles().length === 0) { this.ddicReferences.clear(obj); this.msagReferences.clear(obj); this.removeObject(obj); } return this; } _addFiles(files, dependency) { var _a; const globalExclude = ((_a = this.conf.getGlobal().exclude) !== null && _a !== void 0 ? _a : []) .map(pattern => new RegExp(pattern, "i")); for (const f of files) { const filename = f.getFilename(); const isNotAbapgitFile = filename.split(".").length <= 2; if (isNotAbapgitFile || excludeHelper_1.ExcludeHelper.isExcluded(filename, globalExclude)) { continue; } let found = this.findOrCreate(f.getObjectName(), f.getObjectType()); if (dependency === false && found && this.isDependency(found)) { this.removeDependency(found); found = this.findOrCreate(f.getObjectName(), f.getObjectType()); } found.addFile(f); } return this; } addFiles(files) { this._addFiles(files, false); return this; } addDependencies(files) { for (const f of files) { this.addDependency(f); } return this; } addDependency(file) { var _a; const type = (_a = file.getObjectType()) === null || _a === void 0 ? void 0 : _a.toUpperCase(); if (type === undefined) { return this; } const name = file.getObjectName().toUpperCase(); if (this.dependencies[type] === undefined) { this.dependencies[type] = {}; } this.dependencies[type][name] = true; this._addFiles([file], true); return this; } removeDependency(obj) { var _a; (_a = this.dependencies[obj.getType()]) === null || _a === void 0 ? true : delete _a[obj.getName()]; this.removeObject(obj); } isDependency(obj) { var _a; return ((_a = this.dependencies[obj.getType()]) === null || _a === void 0 ? void 0 : _a[obj.getName()]) === true; } isFileDependency(filename) { var _a, _b; const f = this.getFileByName(filename); if (f === undefined) { return false; } const type = (_a = f.getObjectType()) === null || _a === void 0 ? void 0 : _a.toUpperCase(); if (type === undefined) { return false; } const name = f.getObjectName().toUpperCase(); return ((_b = this.dependencies[type]) === null || _b === void 0 ? void 0 : _b[name]) === true; } // assumption: the file is already in the registry findObjectForFile(file) { const filename = file.getFilename(); for (const obj of this.getObjects()) { for (const ofile of obj.getFiles()) { if (ofile.getFilename() === filename) { return obj; } } } return undefined; } // todo, this will be changed to async sometime findIssues(input) { if (this.isDirty() === true) { this.parse(); } return new rules_runner_1.RulesRunner(this).runRules(this.getObjects(), input); } // todo, this will be changed to async sometime findIssuesObject(iobj) { if (this.isDirty() === true) { this.parse(); } return new rules_runner_1.RulesRunner(this).runRules([iobj]); } // todo, this will be changed to async sometime parse() { if (this.isDirty() === false) { return this; } ParsingPerformance.clear(); for (const o of this.getObjects()) { this.parsePrivate(o); } new find_global_definitions_1.FindGlobalDefinitions(this).run(); return this; } async parseAsync(input) { var _a, _b; if (this.isDirty() === false) { return this; } ParsingPerformance.clear(); (_a = input === null || input === void 0 ? void 0 : input.progress) === null || _a === void 0 ? void 0 : _a.set(this.getObjectCount(false), "Lexing and parsing"); for (const o of this.getObjects()) { await ((_b = input === null || input === void 0 ? void 0 : input.progress) === null || _b === void 0 ? void 0 : _b.tick("Lexing and parsing(" + this.conf.getVersion() + ") - " + o.getType() + " " + o.getName())); this.parsePrivate(o); } if ((input === null || input === void 0 ? void 0 : input.outputPerformance) === true) { ParsingPerformance.output(); } new find_global_definitions_1.FindGlobalDefinitions(this).run(input === null || input === void 0 ? void 0 : input.progress); return this; } ////////////////////////////////////////// // todo, refactor, this is a mess, see where-used, a lot of the code should be in this method instead parsePrivate(input) { const config = this.getConfig(); const result = input.parse(config.getVersion(), config.getSyntaxSetttings().globalMacros, this); ParsingPerformance.push(input, result); } isDirty() { for (const o of this.getObjects()) { const dirty = o.isDirty(); if (dirty === true) { return true; } } return false; } findOrCreate(name, type) { try { return this.find(name, type); } catch (_a) { const newName = name.toUpperCase(); const newType = type ? type : "UNKNOWN"; const add = artifacts_objects_1.ArtifactsObjects.newObject(newName, newType); if (this.objects[newName] === undefined) { this.objects[newName] = {}; } this.objects[newName][newType] = add; if (this.objectsByType[newType] === undefined) { this.objectsByType[newType] = {}; } this.objectsByType[newType][newName] = add; return add; } } removeObject(remove) { if (remove === undefined) { return; } if (this.objects[remove.getName()][remove.getType()] === undefined) { throw new Error("removeObject: object not found"); } if (Object.keys(this.objects[remove.getName()]).length === 1) { delete this.objects[remove.getName()]; } else { delete this.objects[remove.getName()][remove.getType()]; } if (Object.keys(this.objectsByType[remove.getType()]).length === 1) { delete this.objectsByType[remove.getType()]; } else { delete this.objectsByType[remove.getType()][remove.getName()]; } } find(name, type) { const searchType = type ? type : "UNKNOWN"; const searchName = name.toUpperCase(); if (this.objects[searchName] !== undefined && this.objects[searchName][searchType]) { return this.objects[searchName][searchType]; } throw new Error("find: object not found, " + type + " " + name); } } exports.Registry = Registry; //# sourceMappingURL=registry.js.map