UNPKG

sol2uml

Version:

Solidity contract visualisation tool.

247 lines 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertClass2Dot = void 0; // Returns a string of the UML Class in Graphviz's dot format const umlClass_1 = require("./umlClass"); const regEx_1 = require("./utils/regEx"); const convertClass2Dot = (umlClass, options = {}) => { // do not include library, interface, abstracts, struct or enum classes if hidden if (umlClass.stereotype === umlClass_1.ClassStereotype.Import || (options.hideLibraries && umlClass.stereotype === umlClass_1.ClassStereotype.Library) || (options.hideInterfaces && umlClass.stereotype === umlClass_1.ClassStereotype.Interface) || (options.hideAbstracts && umlClass.stereotype === umlClass_1.ClassStereotype.Abstract) || (options.hideStructs && umlClass.stereotype === umlClass_1.ClassStereotype.Struct) || (options.hideEnums && umlClass.stereotype === umlClass_1.ClassStereotype.Enum) || (options.hideConstants && umlClass.stereotype === umlClass_1.ClassStereotype.Constant)) { return ''; } let dotString = `\n${umlClass.id} [label="{${dotClassTitle(umlClass, options)}`; // Add attributes if (!options.hideVariables) { dotString += dotAttributeVisibilities(umlClass, options); } // Add operators if (!options.hideFunctions) { dotString += dotOperatorVisibilities(umlClass, options); } dotString += '}"]'; return dotString; }; exports.convertClass2Dot = convertClass2Dot; const dotClassTitle = (umlClass, options = {}) => { let stereoName = ''; const relativePath = options.hideFilename || (0, regEx_1.isAddress)(umlClass.relativePath) ? '' : `\\n${umlClass.relativePath}`; switch (umlClass.stereotype) { case umlClass_1.ClassStereotype.Abstract: stereoName = 'Abstract'; break; case umlClass_1.ClassStereotype.Interface: stereoName = 'Interface'; break; case umlClass_1.ClassStereotype.Library: stereoName = 'Library'; break; case umlClass_1.ClassStereotype.Struct: stereoName = 'Struct'; break; case umlClass_1.ClassStereotype.Enum: stereoName = 'Enum'; break; case umlClass_1.ClassStereotype.Constant: stereoName = 'Constant'; break; default: // Contract or undefined stereotype will just return the UmlClass name return `${umlClass.name}${relativePath}`; } return `\\<\\<${stereoName}\\>\\>\\n${umlClass.name}${relativePath}`; }; const dotAttributeVisibilities = (umlClass, options) => { if (umlClass.attributes.length === 0) return ''; let dotString = '| '; // if a struct, enum or constant then no visibility group if (umlClass.stereotype === umlClass_1.ClassStereotype.Struct || umlClass.stereotype === umlClass_1.ClassStereotype.Enum || umlClass.stereotype === umlClass_1.ClassStereotype.Constant) { return (dotString + dotAttributes(umlClass.attributes, options, undefined, false)); } // For each visibility group for (const vizGroup of ['Private', 'Internal', 'External', 'Public']) { const attributes = []; // For each attribute of te UML Class for (const attribute of umlClass.attributes) { if (!options.hidePrivates && vizGroup === 'Private' && attribute.visibility === umlClass_1.Visibility.Private) { attributes.push(attribute); } else if (!options.hidePrivates && vizGroup === 'Internal' && attribute.visibility === umlClass_1.Visibility.Internal) { attributes.push(attribute); } else if (vizGroup === 'External' && attribute.visibility === umlClass_1.Visibility.External) { attributes.push(attribute); } // Rest are Public, None or undefined visibilities else if (vizGroup === 'Public' && (attribute.visibility === umlClass_1.Visibility.Public || attribute.visibility === umlClass_1.Visibility.None || !attribute.visibility)) { attributes.push(attribute); } } dotString += dotAttributes(attributes, options, vizGroup); } return dotString; }; const dotAttributes = (attributes, options, vizGroup, indent = true) => { if (!attributes || attributes.length === 0) { return ''; } const indentString = indent ? '\\ \\ \\ ' : ''; let dotString = vizGroup ? vizGroup + ':\\l' : ''; // for each attribute attributes.forEach((attribute) => { const sourceContract = attribute.sourceContract && !options.hideSourceContract ? ` \\<\\<${attribute.sourceContract}\\>\\>` : ''; const type = options.hideTypes ? '' : `: ${attribute.type}`; dotString += `${indentString}${attribute.name}${type}${sourceContract}\\l`; }); return dotString; }; const dotOperatorVisibilities = (umlClass, options) => { if (umlClass.operators.length === 0) return ''; let dotString = '| '; // For each visibility group for (const vizGroup of ['Private', 'Internal', 'External', 'Public']) { const operators = []; // For each attribute of te UML Class for (const operator of umlClass.operators) { if (!options.hidePrivates && vizGroup === 'Private' && operator.visibility === umlClass_1.Visibility.Private) { operators.push(operator); } else if (!options.hidePrivates && vizGroup === 'Internal' && operator.visibility === umlClass_1.Visibility.Internal) { operators.push(operator); } else if (vizGroup === 'External' && operator.visibility === umlClass_1.Visibility.External) { operators.push(operator); } // Rest are Public, None or undefined visibilities else if (vizGroup === 'Public' && (operator.visibility === umlClass_1.Visibility.Public || operator.visibility === umlClass_1.Visibility.None || !operator.visibility)) { operators.push(operator); } } dotString += dotOperators(umlClass, vizGroup, operators, options); } return dotString; }; const dotOperators = (umlClass, vizGroup, operators, options) => { // Skip if there are no operators if (!operators || operators.length === 0) { return ''; } let dotString = vizGroup + ':\\l'; // Sort the operators by stereotypes const operatorsSortedByStereotype = operators.sort((a, b) => { return b.stereotype - a.stereotype; }); // Filter out any modifiers or events if options are flagged to hide them const operatorsFiltered = operatorsSortedByStereotype.filter((o) => !((options.hideModifiers === true && o.stereotype === umlClass_1.OperatorStereotype.Modifier) || (options.hideEvents === true && o.stereotype === umlClass_1.OperatorStereotype.Event))); for (const operator of operatorsFiltered) { dotString += '\\ \\ \\ \\ '; if (operator.stereotype > 0) { dotString += dotOperatorStereotype(umlClass, operator.stereotype); } dotString += operator.name; dotString += dotParameters(operator.parameters, false, options.hideTypes); if (operator.returnParameters?.length > 0 && !options.hideTypes) { dotString += ': ' + dotParameters(operator.returnParameters, true); } if (options.hideModifiers === false && operator.modifiers?.length > 0) { dotString += ` \\<\\<${operator.modifiers.join(', ')}\\>\\>`; } if (operator.sourceContract && !options.hideSourceContract) dotString += ` \\<\\<${operator.sourceContract}\\>\\>`; dotString += '\\l'; } return dotString; }; const dotOperatorStereotype = (umlClass, operatorStereotype) => { let dotString = ''; switch (operatorStereotype) { case umlClass_1.OperatorStereotype.Event: dotString += '\\<\\<event\\>\\>'; break; case umlClass_1.OperatorStereotype.Fallback: dotString += '\\<\\<fallback\\>\\>'; break; case umlClass_1.OperatorStereotype.Modifier: dotString += '\\<\\<modifier\\>\\>'; break; case umlClass_1.OperatorStereotype.Abstract: if (umlClass.stereotype === umlClass_1.ClassStereotype.Abstract) { dotString += '\\<\\<abstract\\>\\>'; } break; case umlClass_1.OperatorStereotype.Payable: dotString += '\\<\\<payable\\>\\>'; break; default: break; } return dotString + ' '; }; const dotParameters = (parameters, returnParams = false, hideTypes = false) => { if (hideTypes && !returnParams) { return '()'; } if (parameters.length == 1 && !parameters[0].name) { if (returnParams) { return parameters[0].type; } else { return `(${parameters[0].type})`; } } let dotString = '('; let paramCount = 0; for (const parameter of parameters) { // The parameter name can be null in return parameters if (parameter.name === null) { dotString += parameter.type; } else { dotString += parameter.name + ': ' + parameter.type; } // If not the last parameter if (++paramCount < parameters.length) { dotString += ', '; } } return dotString + ')'; }; //# sourceMappingURL=converterClass2Dot.js.map