UNPKG

sol2uml

Version:

Solidity contract visualisation tool.

122 lines 6.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.topologicalSortClasses = exports.classesConnectedToBaseContract = exports.classesConnectedToBaseContracts = exports.filterHiddenClasses = void 0; const js_graph_algorithms_1 = require("js-graph-algorithms"); const umlClass_1 = require("./umlClass"); const associations_1 = require("./associations"); const debug = require('debug')('sol2uml'); /** * Filter out any UML Class types that are to be hidden. * @param umlClasses array of UML classes of type `UMLClass` * @param options sol2uml class options * @return umlClasses filtered list of UML classes of type `UMLClass` */ const filterHiddenClasses = (umlClasses, options) => { return umlClasses.filter((u) => (u.stereotype === umlClass_1.ClassStereotype.Enum && !options.hideEnums) || (u.stereotype === umlClass_1.ClassStereotype.Struct && !options.hideStructs) || (u.stereotype === umlClass_1.ClassStereotype.Abstract && !options.hideAbstracts) || (u.stereotype === umlClass_1.ClassStereotype.Interface && !options.hideInterfaces) || (u.stereotype === umlClass_1.ClassStereotype.Constant && !options.hideConstants) || (u.stereotype === umlClass_1.ClassStereotype.Library && !options.hideLibraries) || ((u.stereotype === umlClass_1.ClassStereotype.None || u.stereotype === umlClass_1.ClassStereotype.Contract) && !options.hideContracts)); }; exports.filterHiddenClasses = filterHiddenClasses; /** * Finds all the UML classes that have an association with a list of base contract names. * The associated classes can be contracts, abstract contracts, interfaces, libraries, enums, structs or constants. * @param umlClasses array of UML classes of type `UMLClass` * @param baseContractNames array of base contract names * @param depth limit the number of associations from the base contract. * @return filteredUmlClasses list of UML classes of type `UMLClass` */ const classesConnectedToBaseContracts = (umlClasses, baseContractNames, depth) => { let filteredUmlClasses = {}; const weightedDirectedGraph = loadWeightedDirectedGraph(umlClasses); for (const baseContractName of baseContractNames) { filteredUmlClasses = { ...filteredUmlClasses, ...(0, exports.classesConnectedToBaseContract)(umlClasses, baseContractName, weightedDirectedGraph, depth), }; } return Object.values(filteredUmlClasses); }; exports.classesConnectedToBaseContracts = classesConnectedToBaseContracts; /** * Finds all the UML classes that have an association with a base contract name. * The associated classes can be contracts, abstract contracts, interfaces, libraries, enums, structs or constants. * @param umlClasses array of UML classes of type `UMLClass` * @param baseContractName base contract name * @param weightedDirectedGraph graph of type WeightedDiGraph from the `js-graph-algorithms` package * @param depth limit the number of associations from the base contract. * @return filteredUmlClasses list of UML classes of type `UMLClass` */ const classesConnectedToBaseContract = (umlClasses, baseContractName, weightedDirectedGraph, depth = 1000) => { // Find the base UML Class from the base contract name const baseUmlClass = umlClasses.find(({ name }) => { return name === baseContractName; }); if (!baseUmlClass) { throw Error(`Failed to find base contract with name "${baseContractName}"`); } const dfs = new js_graph_algorithms_1.Dijkstra(weightedDirectedGraph, baseUmlClass.id); // Get all the UML Classes that are connected to the base contract const filteredUmlClasses = {}; for (const umlClass of umlClasses) { if (dfs.distanceTo(umlClass.id) <= depth) { filteredUmlClasses[umlClass.name] = umlClass; } } return filteredUmlClasses; }; exports.classesConnectedToBaseContract = classesConnectedToBaseContract; function loadWeightedDirectedGraph(umlClasses) { const weightedDirectedGraph = new js_graph_algorithms_1.WeightedDiGraph( // the number vertices in the graph umlClass_1.UmlClass.idCounter + 1); for (const sourceUmlClass of umlClasses) { for (const association of Object.values(sourceUmlClass.associations)) { // Find the first UML Class that matches the target class name const targetUmlClass = (0, associations_1.findAssociatedClass)(association, sourceUmlClass, umlClasses); if (!targetUmlClass) { continue; } const isTarget = umlClasses.find((u) => u.id === targetUmlClass.id); debug(`isTarget ${!!isTarget}: Adding edge from ${sourceUmlClass.name} with id ${sourceUmlClass.id} to ${targetUmlClass.name} with id ${targetUmlClass.id} and type ${targetUmlClass.stereotype}`); weightedDirectedGraph.addEdge(new js_graph_algorithms_1.Edge(sourceUmlClass.id, targetUmlClass.id, 1)); } } return weightedDirectedGraph; } const topologicalSortClasses = (umlClasses) => { const directedAcyclicGraph = loadDirectedAcyclicGraph(umlClasses); const topologicalSort = new js_graph_algorithms_1.TopologicalSort(directedAcyclicGraph); // Topological sort the class ids const sortedUmlClassIds = topologicalSort.order().reverse(); const sortedUmlClasses = sortedUmlClassIds.map((umlClassId) => // Lookup the UmlClass for each class id umlClasses.find((umlClass) => umlClass.id === umlClassId)); // Filter out any unfound classes. This happens when diff sources the second contract. return sortedUmlClasses.filter((umlClass) => umlClass !== undefined); }; exports.topologicalSortClasses = topologicalSortClasses; const loadDirectedAcyclicGraph = (umlClasses) => { const directedAcyclicGraph = new js_graph_algorithms_1.DiGraph(umlClass_1.UmlClass.idCounter); // the number vertices in the graph for (const sourceUmlClass of umlClasses) { for (const association of Object.values(sourceUmlClass.associations)) { // Find the first UML Class that matches the target class name const targetUmlClass = (0, associations_1.findAssociatedClass)(association, sourceUmlClass, umlClasses); if (!targetUmlClass) { continue; } directedAcyclicGraph.addEdge(sourceUmlClass.id, targetUmlClass.id); } } return directedAcyclicGraph; }; //# sourceMappingURL=filterClasses.js.map