UNPKG

@oaklean/profiler-core

Version:

Part of the @oaklean suite. It provides all basic functions to work with the `.oak` file format. It allows parsing the `.oak` file format as well as tools for analyzing the measurement values. It also provides all necessary capabilities required for prec

711 lines 82.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceFileMetaDataTree = void 0; const fs = __importStar(require("fs")); const glob_to_regexp_1 = __importDefault(require("glob-to-regexp")); const BaseModel_1 = require("./BaseModel"); const ModelMap_1 = require("./ModelMap"); const SourceFileMetaData_1 = require("./SourceFileMetaData"); const SourceNodeMetaData_1 = require("./SourceNodeMetaData"); const NodeModule_1 = require("./NodeModule"); const SensorValues_1 = require("./SensorValues"); const PathIndex_1 = require("./index/PathIndex"); const GlobalIndex_1 = require("./index/GlobalIndex"); const UnifiedPath_1 = require("../system/UnifiedPath"); const PermissionHelper_1 = require("../helper/PermissionHelper"); // Types const types_1 = require("../types"); const LoggerHelper_1 = require("../helper/LoggerHelper"); const SetHelper_1 = require("../helper/SetHelper"); const UnitHelper_1 = require("../helper/UnitHelper"); function areNumbersClose(a, b, epsilon = 1e-10) { return Math.abs(a - b) < epsilon; } class SourceFileMetaDataTree extends BaseModel_1.BaseModel { constructor(type, filePath, index, compiledSourceFilePath, originalSourceFilePath) { super(); this.type = type; this.filePath = filePath; this.index = index; this.compiledSourceFilePath = compiledSourceFilePath; this.originalSourceFilePath = originalSourceFilePath; } globalIndex() { switch (this.type) { case types_1.SourceFileMetaDataTreeType.Root: return this.index; case types_1.SourceFileMetaDataTreeType.File: return this.index.moduleIndex.globalIndex; case types_1.SourceFileMetaDataTreeType.Directory: case types_1.SourceFileMetaDataTreeType.Module: return this.index.globalIndex; } throw new Error('SourceFileMetaDataTree.globalIndex: unexpected type'); } static isRootNode(data) { return data.type === types_1.SourceFileMetaDataTreeType.Root; } static isFileNode(data) { return data.type === types_1.SourceFileMetaDataTreeType.File; } static isDirectoryNode(data) { return data.type === types_1.SourceFileMetaDataTreeType.Directory; } static isModuleNode(data) { return data.type === types_1.SourceFileMetaDataTreeType.Module; } isRoot() { return SourceFileMetaDataTree.isRootNode(this); } isFile() { return SourceFileMetaDataTree.isFileNode(this); } isDirectory() { return SourceFileMetaDataTree.isDirectoryNode(this); } isModule() { return SourceFileMetaDataTree.isModuleNode(this); } get lang_internalHeadlessSensorValues() { if (this._lang_internalHeadlessSensorValues === undefined) { this._lang_internalHeadlessSensorValues = new SensorValues_1.SensorValues({}); } return this._lang_internalHeadlessSensorValues; } set lang_internalHeadlessSensorValues(value) { this._lang_internalHeadlessSensorValues = value; } get aggregatedLangInternalSourceNodeMetaData() { if (!this._aggregatedLangInternalSourceNodeMetaData) { this._aggregatedLangInternalSourceNodeMetaData = new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined), new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined)); } return this._aggregatedLangInternalSourceNodeMetaData; } get aggregatedInternSourceMetaData() { if (!this._aggregatedInternSourceMetaData) { this._aggregatedInternSourceMetaData = new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined), new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined)); } return this._aggregatedInternSourceMetaData; } get aggregatedExternSourceMetaData() { if (!this._aggregatedExternSourceMetaData) { this._aggregatedExternSourceMetaData = new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined), new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, new SensorValues_1.SensorValues({}), undefined)); } return this._aggregatedExternSourceMetaData; } get totalAggregatedSourceMetaData() { return SourceFileMetaData_1.AggregatedSourceNodeMetaData.join(this.aggregatedLangInternalSourceNodeMetaData, this.aggregatedInternSourceMetaData, this.aggregatedExternSourceMetaData); } get langInternalChildren() { if (!this._langInternalChildren) { this._langInternalChildren = new ModelMap_1.ModelMap('string'); } return this._langInternalChildren; } get internChildren() { if (!this._internChildren) { this._internChildren = new ModelMap_1.ModelMap('string'); } return this._internChildren; } get externChildren() { if (!this._externChildren) { this._externChildren = new ModelMap_1.ModelMap('string'); } return this._externChildren; } storeToFile(filePath, kind) { if (!fs.existsSync(filePath.dirName().toPlatformString())) { PermissionHelper_1.PermissionHelper.mkdirRecursivelyWithUserPermission(filePath.dirName().toPlatformString()); } switch (kind !== undefined ? kind : 'json') { case 'pretty-json': PermissionHelper_1.PermissionHelper.writeFileWithUserPermission(filePath.toPlatformString(), JSON.stringify(this, null, 2)); break; case 'json': PermissionHelper_1.PermissionHelper.writeFileWithUserPermission(filePath.toPlatformString(), JSON.stringify(this)); break; default: break; } } validate() { var _a, _b, _c, _d; if (this.type === types_1.SourceFileMetaDataTreeType.File) { (_a = this.sourceFileMetaData) === null || _a === void 0 ? void 0 : _a.validate(); return; } const totals = []; const maxs = []; for (const sourceFileMetaData of this.internChildren.values()) { totals.push(sourceFileMetaData.aggregatedInternSourceMetaData.total); maxs.push(sourceFileMetaData.aggregatedInternSourceMetaData.max); } const total = SourceNodeMetaData_1.SourceNodeMetaData.sum(...totals); const max = SourceNodeMetaData_1.SourceNodeMetaData.max(...maxs); // IMPORTANT to change when new measurement type gets added if (this.type === types_1.SourceFileMetaDataTreeType.Root) { total.sensorValues.aggregatedCPUTime = UnitHelper_1.UnitHelper.sumMicroSeconds(total.sensorValues.aggregatedCPUTime, this.lang_internalHeadlessSensorValues.aggregatedCPUTime, 1); total.sensorValues.aggregatedCPUEnergyConsumption = UnitHelper_1.UnitHelper.sumMilliJoule(total.sensorValues.aggregatedCPUEnergyConsumption, this.lang_internalHeadlessSensorValues.aggregatedCPUEnergyConsumption, 1); total.sensorValues.aggregatedRAMEnergyConsumption = UnitHelper_1.UnitHelper.sumMilliJoule(total.sensorValues.aggregatedRAMEnergyConsumption, this.lang_internalHeadlessSensorValues.aggregatedRAMEnergyConsumption, 1); } if (total.sensorValues.aggregatedCPUTime !== total.sensorValues.selfCPUTime + total.sensorValues.internCPUTime + total.sensorValues.externCPUTime + total.sensorValues.langInternalCPUTime || !areNumbersClose(total.sensorValues.aggregatedCPUEnergyConsumption, total.sensorValues.selfCPUEnergyConsumption + total.sensorValues.internCPUEnergyConsumption + total.sensorValues.externCPUEnergyConsumption + total.sensorValues.langInternalCPUEnergyConsumption) || !areNumbersClose(total.sensorValues.aggregatedRAMEnergyConsumption, total.sensorValues.selfRAMEnergyConsumption + total.sensorValues.internRAMEnergyConsumption + total.sensorValues.externRAMEnergyConsumption + total.sensorValues.langInternalRAMEnergyConsumption)) { LoggerHelper_1.LoggerHelper.error(total.sensorValues, (_b = this.filePath) === null || _b === void 0 ? void 0 : _b.toString()); throw new Error('SourceFileMetaDataTree.validate: Assertion error aggregatedCPUTime is not correct'); } if (!SourceNodeMetaData_1.SourceNodeMetaData.equals(this.aggregatedInternSourceMetaData.max, max)) { LoggerHelper_1.LoggerHelper.error(max, this.aggregatedInternSourceMetaData.max, (_c = this.filePath) === null || _c === void 0 ? void 0 : _c.toString()); throw new Error('SourceFileMetaDataTree.validate: Assertion error max is not correct ' + ((_d = this.filePath) === null || _d === void 0 ? void 0 : _d.toString())); } } toJSON() { var _a, _b, _c, _d, _e, _f; if (process.env.NODE_ENV === 'test') { this.validate(); } return { lang_internalHeadlessSensorValues: (_a = this._lang_internalHeadlessSensorValues) === null || _a === void 0 ? void 0 : _a.toJSON(), aggregatedLangInternalSourceNodeMetaData: (_b = this._aggregatedLangInternalSourceNodeMetaData) === null || _b === void 0 ? void 0 : _b.toJSON(), aggregatedInternSourceMetaData: (_c = this._aggregatedInternSourceMetaData) === null || _c === void 0 ? void 0 : _c.toJSON(), aggregatedExternSourceMetaData: (_d = this._aggregatedExternSourceMetaData) === null || _d === void 0 ? void 0 : _d.toJSON(), type: this.type, filePath: (_e = this.filePath) === null || _e === void 0 ? void 0 : _e.toJSON(), compiledSourceFilePath: this.compiledSourceFilePath, originalSourceFilePath: this.originalSourceFilePath, langInternalChildren: this.langInternalChildren.toJSON(), internChildren: this.internChildren.toJSON() || {}, externChildren: this.externChildren.toJSON(), sourceFileMetaData: (_f = this.sourceFileMetaData) === null || _f === void 0 ? void 0 : _f.toJSON(), globalIndex: (this.isRoot() ? this.index.toJSON() : undefined), engineModule: (this.isRoot() ? this.index.engineModule.toJSON() : undefined), }; } static fromJSON(json, type, indexFromParent) { var _a, _b, _c, _d; let data; if (typeof json === 'string') { data = JSON.parse(json); } else { data = json; } let index; if (type !== data.type) { throw new Error('SourceFileMetaDataTree.fromJSON: given type and type of input data is not the same'); } if (SourceFileMetaDataTree.isRootNode(data)) { if (data.globalIndex === undefined) { throw new Error('SourceFileMetaDataTree.fromJSON: input does not contain a globalIndex'); } index = GlobalIndex_1.GlobalIndex.fromJSON(data.globalIndex, NodeModule_1.NodeModule.fromJSON(data.engineModule)); } else { if (indexFromParent === undefined) { throw new Error('SourceFileMetaDataTree.fromJSON: indexFromParent must be given for non root nodes'); } index = indexFromParent; } const result = new SourceFileMetaDataTree(data.type, ((data.type === types_1.SourceFileMetaDataTreeType.File || data.type === types_1.SourceFileMetaDataTreeType.Directory || data.type === types_1.SourceFileMetaDataTreeType.Module) ? new UnifiedPath_1.UnifiedPath(data.filePath) : undefined), index); if (data.lang_internalHeadlessSensorValues) { result._lang_internalHeadlessSensorValues = SensorValues_1.SensorValues.fromJSON(data.lang_internalHeadlessSensorValues); } if (data.aggregatedLangInternalSourceNodeMetaData) { result._aggregatedLangInternalSourceNodeMetaData = SourceFileMetaData_1.AggregatedSourceNodeMetaData.fromJSON(data.aggregatedLangInternalSourceNodeMetaData); } if (data.aggregatedInternSourceMetaData) { result._aggregatedInternSourceMetaData = SourceFileMetaData_1.AggregatedSourceNodeMetaData.fromJSON(data.aggregatedInternSourceMetaData); } if (data.aggregatedExternSourceMetaData) { result._aggregatedExternSourceMetaData = SourceFileMetaData_1.AggregatedSourceNodeMetaData.fromJSON(data.aggregatedExternSourceMetaData); } result.originalSourceFilePath = data.originalSourceFilePath; result.compiledSourceFilePath = data.compiledSourceFilePath; if (data.sourceFileMetaData) { if (index === undefined) { throw new Error('SourceFileMetaDataTree.fromJSON: pathIndex is missing'); } result.sourceFileMetaData = SourceFileMetaData_1.SourceFileMetaData.fromJSON(data.sourceFileMetaData, index); } if (data.langInternalChildren) { for (const [langInternalPath, subTree] of Object.entries(data.langInternalChildren)) { const indexToPass = type === types_1.SourceFileMetaDataTreeType.Root ? (_a = index.getLangInternalIndex('get')) === null || _a === void 0 ? void 0 : _a.getFilePathIndex('get', subTree.filePath) : (_c = (_b = index === null || index === void 0 ? void 0 : index.globalIndex) === null || _b === void 0 ? void 0 : _b.getLangInternalIndex('get')) === null || _c === void 0 ? void 0 : _c.getFilePathIndex('get', subTree.filePath); if (indexToPass === undefined) { LoggerHelper_1.LoggerHelper.error(index.getModuleIndex('get')); throw new Error('SourceFileMetaDataTree.fromJSON: (langInternal children) could not resolve index for subTree'); } result.langInternalChildren.set(langInternalPath, SourceFileMetaDataTree.fromJSON(subTree, subTree.type, indexToPass)); } } if (data.internChildren) { for (const [filePart, subTree] of Object.entries(data.internChildren)) { let indexToPass; switch (subTree.type) { case types_1.SourceFileMetaDataTreeType.Directory: indexToPass = type === types_1.SourceFileMetaDataTreeType.Root ? index.getModuleIndex('get') : index; break; case types_1.SourceFileMetaDataTreeType.File: indexToPass = type === types_1.SourceFileMetaDataTreeType.Root ? (_d = index.getModuleIndex('get')) === null || _d === void 0 ? void 0 : _d.getFilePathIndex('get', subTree.filePath) : index.getFilePathIndex('get', subTree.filePath); break; default: throw new Error('SourceFileMetaDataTree.fromJSON: unexpected subTree type'); } if (indexToPass === undefined) { LoggerHelper_1.LoggerHelper.error(index.getModuleIndex('get')); throw new Error('SourceFileMetaDataTree.fromJSON: (intern children) could not resolve index for subTree'); } result.internChildren.set(filePart, SourceFileMetaDataTree.fromJSON(subTree, subTree.type, indexToPass)); } } if (data.externChildren) { for (const [moduleIdentifier, subTree] of Object.entries(data.externChildren)) { let indexToPass; switch (type) { case types_1.SourceFileMetaDataTreeType.Root: indexToPass = index.getModuleIndex('get', moduleIdentifier); break; case types_1.SourceFileMetaDataTreeType.Module: indexToPass = index.globalIndex.getModuleIndex('get', moduleIdentifier); break; default: throw new Error('SourceFileMetaDataTree.fromJSON: unexpected subTree type'); } if (indexToPass === undefined) { throw new Error('SourceFileMetaDataTree.fromJSON: (extern children) could not resolve index for subTree'); } result.externChildren.set(moduleIdentifier, SourceFileMetaDataTree.fromJSON(subTree, subTree.type, indexToPass)); } } return result; } static loadFromFile(filePath) { if (!fs.existsSync(filePath.toPlatformString())) { return undefined; } return SourceFileMetaDataTree.fromJSON(fs.readFileSync(filePath.toPlatformString()).toString(), types_1.SourceFileMetaDataTreeType.Root, undefined); } addToAggregatedLangInternalSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData) { this.aggregatedLangInternalSourceNodeMetaData.total = SourceNodeMetaData_1.SourceNodeMetaData.sum(this.aggregatedLangInternalSourceNodeMetaData.total, aggregatedSourceNodeMetaData.total); this.aggregatedLangInternalSourceNodeMetaData.max = SourceNodeMetaData_1.SourceNodeMetaData.max(this.aggregatedLangInternalSourceNodeMetaData.max, aggregatedSourceNodeMetaData.max); } addToAggregatedInternSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData) { this.aggregatedInternSourceMetaData.total = SourceNodeMetaData_1.SourceNodeMetaData.sum(this.aggregatedInternSourceMetaData.total, aggregatedSourceNodeMetaData.total); this.aggregatedInternSourceMetaData.max = SourceNodeMetaData_1.SourceNodeMetaData.max(this.aggregatedInternSourceMetaData.max, aggregatedSourceNodeMetaData.max); } addToAggregatedExternSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData) { this.aggregatedExternSourceMetaData.total = SourceNodeMetaData_1.SourceNodeMetaData.sum(this.aggregatedExternSourceMetaData.total, aggregatedSourceNodeMetaData.total); this.aggregatedExternSourceMetaData.max = SourceNodeMetaData_1.SourceNodeMetaData.max(this.aggregatedExternSourceMetaData.max, aggregatedSourceNodeMetaData.max); } static fromProjectReport(projectReport, mode = 'original') { const tree = new SourceFileMetaDataTree(types_1.SourceFileMetaDataTreeType.Root, undefined, projectReport.globalIndex); tree.addProjectReport(projectReport, mode); tree.lang_internalHeadlessSensorValues = SensorValues_1.SensorValues.fromJSON(projectReport.lang_internalHeadlessSensorValues.toJSON()); return tree; } insertLangInternalPath(langInternalPath, aggregatedSourceNodeMetaData, sourceFileMetaData) { var _a; this.addToAggregatedLangInternalSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData); let child = this.langInternalChildren.get(langInternalPath); if (!child) { const moduleIndex = (_a = (this.isRoot() ? this.index.getModuleIndex('get') : this.index)) === null || _a === void 0 ? void 0 : _a.globalIndex.getLangInternalIndex('get'); const pathIndex = moduleIndex === null || moduleIndex === void 0 ? void 0 : moduleIndex.getFilePathIndex('get', langInternalPath); if (pathIndex === undefined) { throw new Error('SourceFileMetaDataTree.insertLangInternalPath: could not resolve path index'); } child = new SourceFileMetaDataTree(types_1.SourceFileMetaDataTreeType.File, new UnifiedPath_1.UnifiedPath(langInternalPath), pathIndex); child.sourceFileMetaData = sourceFileMetaData; child.addToAggregatedInternSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData); this.langInternalChildren.set(langInternalPath, child); return child; } else { throw new Error('SourceFileMetaDataTree.insertLangInternalPath: path was already inserted ' + `${langInternalPath}`); } } insertPath(filePathParts, compiledSourceFilePath, originalSourceFilePath, aggregatedSourceNodeMetaData, sourceFileMetaData) { this.addToAggregatedInternSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData); let child = this.internChildren.get(filePathParts[0]); const filePath = this.type === types_1.SourceFileMetaDataTreeType.Module ? new UnifiedPath_1.UnifiedPath('./') : (this.filePath === undefined ? new UnifiedPath_1.UnifiedPath('./') : this.filePath); if (filePathParts.length === 1) { if (!child) { const moduleIndex = (this.isRoot() ? this.index.getModuleIndex('get') : this.index); const pathIndex = moduleIndex === null || moduleIndex === void 0 ? void 0 : moduleIndex.getFilePathIndex('get', filePath.join(...filePathParts).toString()); if (pathIndex === undefined) { throw new Error('SourceFileMetaDataTree.insertPath: could not resolve path index'); } child = new SourceFileMetaDataTree(types_1.SourceFileMetaDataTreeType.File, filePath.join(filePathParts[0]), pathIndex, compiledSourceFilePath, originalSourceFilePath); child.sourceFileMetaData = sourceFileMetaData; child.addToAggregatedInternSourceNodeMetaDataOfTree(aggregatedSourceNodeMetaData); this.internChildren.set(filePathParts[0], child); return child; } else { throw new Error('SourceFileMetaDataTree.insertPath: path was already inserted ' + `${filePath.toString()}/${filePathParts[0]}`); } } if (!child) { const moduleIndex = (this.isRoot() ? this.index.getModuleIndex('get') : this.index); if (moduleIndex === undefined) { throw new Error('SourceFileMetaDataTree.insertPath: could not resolve module index'); } child = new SourceFileMetaDataTree(types_1.SourceFileMetaDataTreeType.Directory, filePath.toString() === '' ? new UnifiedPath_1.UnifiedPath(filePathParts[0]) : filePath.join(filePathParts[0]), moduleIndex); this.internChildren.set(filePathParts[0], child); } return child.insertPath(filePathParts.slice(1), compiledSourceFilePath, originalSourceFilePath, aggregatedSourceNodeMetaData, sourceFileMetaData); } addExternReport(moduleReport, index, mode) { const child = new SourceFileMetaDataTree(types_1.SourceFileMetaDataTreeType.Module, new UnifiedPath_1.UnifiedPath('node_modules/' + moduleReport.nodeModule.identifier), index); child.addInternReport(moduleReport, mode); for (const [moduleID, externModuleReport] of moduleReport.extern.entries()) { const childIndex = index.globalIndex.getModuleIndexByID(moduleID); if (childIndex === undefined) { throw new Error('SourceFileMetaDataTree.addExternReport: could not resolve module index'); } child.addExternReport(externModuleReport, childIndex, mode); } this.addToAggregatedExternSourceNodeMetaDataOfTree(child.totalAggregatedSourceMetaData); this.externChildren.set(moduleReport.nodeModule.identifier, child); } addInternReport(projectReport, mode) { const reversedInternMapping = projectReport.reversedInternMapping; for (const [filePathID, sourceFileMetaData] of projectReport.lang_internal.entries()) { const filePathIndex = projectReport.getPathIndexByID(filePathID); if (filePathIndex === undefined) { throw new Error(`SourceFileMetaDataTree.addInternReport: could not resolve path from pathID: ${filePathID}`); } const aggregatedSourceNodeMetaData = new SourceFileMetaData_1.AggregatedSourceNodeMetaData(sourceFileMetaData.totalSourceNodeMetaData().sum, sourceFileMetaData.maxSourceNodeMetaData()); const fileNode = this.insertLangInternalPath(filePathIndex.identifier, aggregatedSourceNodeMetaData, sourceFileMetaData); fileNode.sourceFileMetaData = sourceFileMetaData; } for (const [filePathID, sourceFileMetaData] of projectReport.intern.entries()) { const filePathIndex = projectReport.getPathIndexByID(filePathID); const reversedFilePathID = reversedInternMapping.get(filePathID); const reversedFilePathIndex = reversedFilePathID !== undefined ? projectReport.getPathIndexByID(reversedFilePathID) : undefined; if (filePathIndex === undefined) { throw new Error(`SourceFileMetaDataTree.addInternReport: could not resolve path from pathID: ${filePathID}`); } const reversedFilePath = reversedFilePathIndex !== undefined ? reversedFilePathIndex.identifier : undefined; const filePathParts = (mode === 'compiled' || reversedFilePath === undefined) ? new UnifiedPath_1.UnifiedPath(filePathIndex.identifier).split() : new UnifiedPath_1.UnifiedPath(reversedFilePath).split(); const aggregatedSourceNodeMetaData = new SourceFileMetaData_1.AggregatedSourceNodeMetaData(sourceFileMetaData.totalSourceNodeMetaData().sum, sourceFileMetaData.maxSourceNodeMetaData()); const fileNode = this.insertPath(filePathParts, filePathIndex.identifier, reversedFilePath, aggregatedSourceNodeMetaData, sourceFileMetaData); fileNode.sourceFileMetaData = sourceFileMetaData; } } addProjectReport(projectReport, mode) { if (!this.isRoot()) { throw new Error('SourceFileMetaDataTree.addProjectReport: can only be executed on root nodes'); } this.addInternReport(projectReport, mode); for (const [moduleID, externModuleReport] of projectReport.extern.entries()) { const childIndex = this.index.getModuleIndexByID(moduleID); if (childIndex === undefined) { throw new Error('SourceFileMetaDataTree.addExternReport: could not resolve module index'); } this.addExternReport(externModuleReport, childIndex, mode); } } _mergeReferences(...references) { const result = new ModelMap_1.ModelMap('number'); for (const reference of references) { for (const [pathID, sensorValues] of reference.entries()) { const accumulatedSensorValues = result.get(pathID); if (accumulatedSensorValues !== undefined) { result.set(pathID, SensorValues_1.SensorValues.sum(accumulatedSensorValues, sensorValues)); } else { result.set(pathID, sensorValues); } } } return result; } filter(includedFilterPath, excludedFilterPath) { const self = this; // eslint-disable-line @typescript-eslint/no-this-alias const includeCache = new Map(); const excludeCache = new Map(); const pathIndexCache = new Map(); // Normalize filter paths if (includedFilterPath && !(includedFilterPath.endsWith('/*') || includedFilterPath.endsWith('/'))) { includedFilterPath = includedFilterPath + '/*'; } else if (includedFilterPath && includedFilterPath.endsWith('/')) { includedFilterPath = includedFilterPath + '*'; } // check if the path is included/excluded in the filter function checkGlob(filePath, filterPath) { if (filePath === undefined) { throw new Error('SourceFileMetaDataTree.checkGlob: filePath is undefined'); } const normalizedDirectory = filePath.startsWith('./') ? filePath.substring(2) : filePath; const normalizedFilterPath = filterPath.startsWith('./') ? filterPath.substring(2) : filterPath; const includeRe = (0, glob_to_regexp_1.default)(normalizedFilterPath, { extended: true }); return includeRe.test(normalizedDirectory) || includeRe.test(normalizedDirectory + '/'); } function pathIndexByID(pathID) { let pathIndex = pathIndexCache.get(pathID); if (pathIndex === undefined) { pathIndex = self.globalIndex().getPathIndexByID(pathID); if (pathIndex === undefined) { throw new Error('SourceFileMetaDataTree.filter: pathIndex is undefined'); } pathIndexCache.set(pathID, pathIndex); } return pathIndex; } // Filter function on pathIndex function filterPaths(pathIndexObj) { const pathIndex = pathIndexObj instanceof PathIndex_1.PathIndex ? pathIndexObj : pathIndexByID(pathIndexObj); if (pathIndex.id === undefined) { throw new Error('SourceFileMetaDataTree.filter: pathIndex.id is undefined'); } let isIncludedNode = includeCache.get(pathIndex.id); let isExcludedNode = excludeCache.get(pathIndex.id); if (isIncludedNode === undefined) { isIncludedNode = includedFilterPath ? checkGlob(pathIndex.identifier, includedFilterPath) : true; includeCache.set(pathIndex.id, isIncludedNode); } if (isExcludedNode === undefined) { isExcludedNode = excludedFilterPath ? checkGlob(pathIndex.identifier, excludedFilterPath) : false; excludeCache.set(pathIndex.id, isExcludedNode); } return isIncludedNode && !isExcludedNode; } function filterReferences(references) { for (const pathID of references.keys()) { if (!filterPaths(pathID)) { references.delete(pathID); } } } // call the filter function return this._filter(filterPaths, filterReferences); } _filter(filterPaths, filterReferences) { const allSensorValuesToSum = []; const allInternReferencesToMerge = []; const allExternReferencesToMerge = []; const allLangInternalReferencesToMerge = []; const allContainsFilesToMerge = []; const node = new SourceFileMetaDataTree(this.type, this.filePath, this.index, this.compiledSourceFilePath, this.originalSourceFilePath); node.lang_internalHeadlessSensorValues = SensorValues_1.SensorValues.fromJSON(this.lang_internalHeadlessSensorValues.toJSON()); node.sourceFileMetaData = this.sourceFileMetaData; if (SourceFileMetaDataTree.isFileNode(this)) { if (this.sourceFileMetaData === undefined) { throw new Error('SourceFileMetaDataTree.filter: sourceFileMetaData is undefined'); } const pathID = this.sourceFileMetaData.pathIndex.id; if (pathID === undefined) { throw new Error('SourceFileMetaDataTree.filter: pathID is undefined'); } const max = this.sourceFileMetaData.maxSourceNodeMetaData(); const total = this.sourceFileMetaData.totalSourceNodeMetaData(); filterReferences(total.intern); filterReferences(total.extern); filterReferences(total.langInternal); allInternReferencesToMerge.push(total.intern); allExternReferencesToMerge.push(total.extern); allLangInternalReferencesToMerge.push(total.langInternal); allContainsFilesToMerge.push(new Set([pathID])); const internSum = SensorValues_1.SensorValues.sum(...total.intern.values()); const externSum = SensorValues_1.SensorValues.sum(...total.extern.values()); const langInternalSum = SensorValues_1.SensorValues.sum(...total.langInternal.values()); // clones the total sensor values but removes the references const ownSensorValues = total.sum.sensorValues.cloneAsIsolated(); allSensorValuesToSum.push(ownSensorValues); node.addToAggregatedInternSourceNodeMetaDataOfTree(new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, ownSensorValues.add({ internSensorValues: internSum, externSensorValues: externSum, langInternalSensorValues: langInternalSum }), undefined), max)); } if (this.langInternalChildren.size > 0) { const sensorValuesToSum = []; const maxSourceNodeMetaDataToMax = []; const internReferencesToMerge = []; const externReferencesToMerge = []; const langInternalReferencesToMerge = []; const containsFilesToMerge = []; for (const [langInternalPath, child] of this.langInternalChildren.entries()) { const { node: filteredChild, sensorValues: filteredChildSensorValues, internReferences: filteredIntern, externReferences: filteredExtern, langInternalReferences: filteredLangInternal, containsFiles: filteredContainsFiles } = child._filter(filterPaths, filterReferences); if (filteredChild) { node.langInternalChildren.set(langInternalPath, filteredChild); if (filteredChildSensorValues) { sensorValuesToSum.push(filteredChildSensorValues); } internReferencesToMerge.push(filteredIntern); externReferencesToMerge.push(filteredExtern); langInternalReferencesToMerge.push(filteredLangInternal); containsFilesToMerge.push(filteredContainsFiles); maxSourceNodeMetaDataToMax.push(filteredChild.totalAggregatedSourceMetaData.max); } } const internReferences = this._mergeReferences(...internReferencesToMerge); const externReferences = this._mergeReferences(...externReferencesToMerge); const langInternalReferences = this._mergeReferences(...langInternalReferencesToMerge); const containsFilesInChildren = SetHelper_1.SetHelper.union(...containsFilesToMerge); for (const pathID of containsFilesInChildren) { internReferences.delete(pathID); externReferences.delete(pathID); langInternalReferences.delete(pathID); } allInternReferencesToMerge.push(internReferences); allExternReferencesToMerge.push(externReferences); allLangInternalReferencesToMerge.push(langInternalReferences); node.addToAggregatedLangInternalSourceNodeMetaDataOfTree(new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, SensorValues_1.SensorValues.sum(...sensorValuesToSum, ...internReferences.values()), undefined), SourceNodeMetaData_1.SourceNodeMetaData.max(...maxSourceNodeMetaDataToMax))); } if (this.internChildren.size > 0) { const sensorValuesToSum = []; const maxSourceNodeMetaDataToMax = []; const internReferencesToMerge = []; const externReferencesToMerge = []; const langInternalReferencesToMerge = []; const containsFilesToMerge = []; for (const [internPath, child] of this.internChildren.entries()) { const { node: filteredChild, sensorValues: filteredChildSensorValues, internReferences: filteredIntern, externReferences: filteredExtern, langInternalReferences: filteredLangInternal, containsFiles: filteredContainsFiles } = child._filter(filterPaths, filterReferences); if (filteredChild) { node.internChildren.set(internPath, filteredChild); if (filteredChildSensorValues) { sensorValuesToSum.push(filteredChildSensorValues); } internReferencesToMerge.push(filteredIntern); externReferencesToMerge.push(filteredExtern); langInternalReferencesToMerge.push(filteredLangInternal); containsFilesToMerge.push(filteredContainsFiles); maxSourceNodeMetaDataToMax.push(filteredChild.totalAggregatedSourceMetaData.max); } } const internReferences = this._mergeReferences(...internReferencesToMerge); const externReferences = this._mergeReferences(...externReferencesToMerge); const langInternalReferences = this._mergeReferences(...langInternalReferencesToMerge); const containsFilesInChildren = SetHelper_1.SetHelper.union(...containsFilesToMerge); for (const pathID of containsFilesInChildren) { internReferences.delete(pathID); externReferences.delete(pathID); langInternalReferences.delete(pathID); } const sensorValuesSum = SensorValues_1.SensorValues.sum(...sensorValuesToSum); const internReferencesSum = SensorValues_1.SensorValues.sum(...internReferences.values()); const externReferencesSum = SensorValues_1.SensorValues.sum(...externReferences.values()); const langInternalReferencesSum = SensorValues_1.SensorValues.sum(...langInternalReferences.values()); allInternReferencesToMerge.push(internReferences); allExternReferencesToMerge.push(externReferences); allLangInternalReferencesToMerge.push(langInternalReferences); allContainsFilesToMerge.push(containsFilesInChildren); allSensorValuesToSum.push(sensorValuesSum); node.addToAggregatedInternSourceNodeMetaDataOfTree(new SourceFileMetaData_1.AggregatedSourceNodeMetaData(new SourceNodeMetaData_1.SourceNodeMetaData(types_1.SourceNodeMetaDataType.Aggregate, undefined, sensorValuesSum.add({ internSensorValues: internReferencesSum, externSensorValues: externReferencesSum, langInternalSensorValues: langInternalReferencesSum }), undefined), SourceNodeMetaData_1.SourceNodeMetaData.max(...maxSourceNodeMetaDataToMax))); } if (this.externChildren.size > 0) { const totalSourceNodeMetaDataToMerge = []; for (const [moduleIdentifier, child] of this.externChildren.entries()) { const { node: filteredChild } = child._filter(filterPaths, filterReferences); if (filteredChild) { node.externChildren.set(moduleIdentifier, filteredChild); totalSourceNodeMetaDataToMerge.push(filteredChild.aggregatedInternSourceMetaData); } } node.addToAggregatedExternSourceNodeMetaDataOfTree(SourceFileMetaData_1.AggregatedSourceNodeMetaData.join(...totalSourceNodeMetaDataToMerge)); } const internReferences = this._mergeReferences(...allInternReferencesToMerge); const externReferences = this._mergeReferences(...allExternReferencesToMerge); const langInternalReferences = this._mergeReferences(...allLangInternalReferencesToMerge); if (SourceFileMetaDataTree.isFileNode(this)) { const survivesFilter = filterPaths(this.index); if (!survivesFilter) { return { node: null, sensorValues: undefined, internReferences, externReferences, langInternalReferences, containsFiles: SetHelper_1.SetHelper.union(...allContainsFilesToMerge) }; } } if (!SourceFileMetaDataTree.isFileNode(this) && node.internChildren.size === 0 && node.langInternalChildren.size === 0 && node.externChildren.size === 0) { return { node: null, sensorValues: undefined, internReferences, externReferences, langInternalReferences, containsFiles: SetHelper_1.SetHelper.union(...allContainsFilesToMerge) }; } return { node, sensorValues: SensorValues_1.SensorValues.sum(...allSensorValuesToSum), internReferences, externReferences, langInternalReferences, containsFiles: SetHelper_1.SetHelper.union(...allContainsFilesToMerge) }; } } exports.SourceFileMetaDataTree = SourceFileMetaDataTree; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU291cmNlRmlsZU1ldGFEYXRhVHJlZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tb2RlbC9Tb3VyY2VGaWxlTWV0YURhdGFUcmVlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdUNBQXdCO0FBRXhCLG9FQUF5QztBQUV6QywyQ0FBdUM7QUFDdkMseUNBQXFDO0FBQ3JDLDZEQUc2QjtBQUM3Qiw2REFBeUQ7QUFJekQsNkNBQXlDO0FBQ3pDLGlEQUE2QztBQUM3QyxpREFBNkM7QUFDN0MscURBQWlEO0FBR2pELHVEQUFtRDtBQUNuRCxpRUFBNkQ7QUFDN0QsUUFBUTtBQUNSLG9DQWFpQjtBQUNqQix5REFBcUQ7QUFDckQsbURBQStDO0FBQy9DLHFEQUFpRDtBQWdCakQsU0FBUyxlQUFlLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFBRSxPQUFPLEdBQUcsS0FBSztJQUM3RCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQTtBQUNqQyxDQUFDO0FBRUQsTUFBYSxzQkFBNkQsU0FBUSxxQkFBUztJQXFCMUYsWUFDQyxJQUFPLEVBQ1AsUUFBdUMsRUFDdkMsS0FBc0IsRUFDdEIsc0JBQTJDLEVBQzNDLHNCQUEyQztRQUUzQyxLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQ3hCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1FBQ2xCLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxzQkFBc0IsQ0FBQTtRQUNwRCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsc0JBQXNCLENBQUE7SUFDckQsQ0FBQztJQUVELFdBQVc7UUFDVixRQUFRLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuQixLQUFLLGtDQUEw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