UNPKG

@syntest/cfg

Version:
142 lines 5.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ControlFlowGraph = void 0; /* * Copyright 2020-2023 Delft University of Technology and SynTest contributors * * This file is part of SynTest Framework - SynTest Core. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const cloneDeep = require("lodash.clonedeep"); /** * Represents a control flow graph. */ class ControlFlowGraph { constructor(entry, successExit, errorExit, nodes, edges) { this._entry = entry; this._successExit = successExit; this._errorExit = errorExit; this._nodes = cloneDeep(nodes); this._edges = cloneDeep(edges); this._incomingEdges = this.getIncomingEdgesMap(); this._outgoingEdges = this.getOutgoingEdgesMap(); } get entry() { return this._entry; } get successExit() { return this._successExit; } get errorExit() { return this._errorExit; } get nodes() { return this._nodes; } get edges() { return this._edges; } // Returns list of nodes that have an outgoing edge to the target node getParents(targetNodeId) { const parentEdges = this.getIncomingEdges(targetNodeId); return parentEdges.map((edge) => this.getNodeById(edge.source)); } // Returns list of nodes that have an outgoing edge from the target node getChildren(targetNodeId) { const childEdges = this.getOutgoingEdges(targetNodeId); return childEdges.map((edge) => this.getNodeById(edge.target)); } getIncomingEdges(nodeId) { if (!this._incomingEdges.has(nodeId)) { return []; } return [...this._incomingEdges.get(nodeId)]; } getOutgoingEdges(nodeId) { if (!this._outgoingEdges.has(nodeId)) { return []; } return [...this._outgoingEdges.get(nodeId)]; } /** * Builds the incoming edges map of the graph * @returns */ getIncomingEdgesMap() { const map = new Map(); for (const edge of this._edges) { if (!map.has(edge.target)) { map.set(edge.target, []); } map.get(edge.target).push(edge); } return map; } /** * Builds the outgoing edges map of the graph * @returns */ getOutgoingEdgesMap() { const map = new Map(); for (const edge of this._edges) { if (!map.has(edge.source)) { map.set(edge.source, []); } map.get(edge.source).push(edge); } return map; } // Successively applies a filter method on initial list of nodes with specified predicates getNodesByPredicates(...predicates) { let filteredList = [...this._nodes.values()]; for (const predicate of predicates) { filteredList = filteredList.filter((element) => predicate(element)); } return filteredList; } // Applies a find method on list of nodes with a given predicate getNodeByPredicate(predicate) { return [...this._nodes.values()].find((element) => predicate(element)); } // Retrieves Node object based on its id getNodeById(nodeId) { return this._nodes.get(nodeId); } getNodesByIds(nodeIds) { return nodeIds.map((id) => this.getNodeById(id)); } // Filters list of nodes, returning only nodes of a given type getNodesByType(type) { return [...this._nodes.values()].filter((n) => n.type === type); } // Filters list of nodes by specified line numbers, // returning only nodes that contain AT LEAST ONE OF the given line numbers getNodesByLineNumbers(lineNumbers) { return [...this._nodes.values()].filter((node) => // maybe should check in between node.statements.some((statement) => lineNumbers.has(statement.location.start.line) || lineNumbers.has(statement.location.end.line))); } // Returns Node that contains specified line number and is of a given type getNodeOfTypeByLine(lineNumber, type) { return [...this._nodes.values()].find((n) => { // TODO maybe should check in between? return (n.type === type && n.statements.some((statement) => statement.location.start.line === lineNumber || statement.location.end.line === lineNumber)); }); } } exports.ControlFlowGraph = ControlFlowGraph; //# sourceMappingURL=ControlFlowGraph.js.map