forked from naddison36/sol2uml
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconverterStorage2Dot.js
130 lines (130 loc) · 5.54 KB
/
converterStorage2Dot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertStorage2Dot = exports.convertStorages2Dot = void 0;
const converterClasses2Storage_1 = require("./converterClasses2Storage");
const umlClass_1 = require("./umlClass");
const formatters_1 = require("./utils/formatters");
const debug = require('debug')('sol2uml');
const convertStorages2Dot = (storageSections, options) => {
let dotString = `
digraph StorageDiagram {
rankdir=LR
arrowhead=open
bgcolor="${options.backColor}"
edge [color="${options.shapeColor}"]
node [shape=record, style=filled, color="${options.shapeColor}", fillcolor="${options.fillColor}", fontcolor="${options.textColor}", fontname="Courier New"]`;
// process contract and the struct storages
storageSections.forEach((storage) => {
dotString = convertStorage2Dot(storage, dotString, options);
});
// link contract and structs to structs
storageSections.forEach((slot) => {
slot.variables.forEach((storage) => {
if (storage.referenceSectionId) {
dotString += `\n ${slot.id}:${storage.id} -> ${storage.referenceSectionId}`;
}
});
});
// Need to close off the last digraph
dotString += '\n}';
debug(dotString);
return dotString;
};
exports.convertStorages2Dot = convertStorages2Dot;
function convertStorage2Dot(storageSection, dotString, options) {
// write storage header with name and optional address
dotString += `\n${storageSection.id} [label="${storageSection.name} \\<\\<${storageSection.type}\\>\\>\\n${storageSection.address || storageSection.offset || ''}`;
dotString += ' | {';
const startingVariables = storageSection.variables.filter((s) => s.byteOffset === 0);
// for each slot displayed, does is have any variables with parsed data?
const displayData = startingVariables.map((startVar) => storageSection.variables.some((variable) => variable.fromSlot === startVar.fromSlot && variable.parsedValue));
const linePad = '\\n\\ ';
// write slot numbers
const dataLine = options.data ? linePad : '';
dotString +=
storageSection.offset || storageSection.mapping
? `{ offset${dataLine}`
: `{ slot${dataLine}`;
startingVariables.forEach((variable, i) => {
const dataLine = options.data && displayData[i] ? linePad : '';
if (variable.offset) {
dotString += ` | ${(0, formatters_1.shortBytes32)(variable.offset)}${dataLine}`;
}
else if (variable.fromSlot === variable.toSlot) {
dotString += ` | ${variable.fromSlot}${dataLine}`;
}
else {
dotString += ` | ${variable.fromSlot}-${variable.toSlot}${dataLine}`;
}
});
// write slot values if available
if (options.data && !options.hideValues) {
dotString += `} | {value${dataLine}`;
startingVariables.forEach((variable, i) => {
if (displayData[i]) {
dotString += ` | ${variable.slotValue || ''}${linePad}`;
}
else {
dotString += ` | `;
}
});
}
const contractVariablePrefix = storageSection.type === converterClasses2Storage_1.StorageSectionType.Contract
? '\\<inherited contract\\>.'
: '';
const dataLine2 = options.data ? `\\ndecoded data` : '';
dotString += `} | { type: ${contractVariablePrefix}variable (bytes)${dataLine2}`;
// For each slot
startingVariables.forEach((variable) => {
// Get all the storage variables in this slot
const slotVariables = storageSection.variables.filter((s) => (!s.offset && s.fromSlot === variable.fromSlot) ||
(s.offset && s.offset === variable.offset));
const usedBytes = slotVariables.reduce((acc, s) => acc + s.byteSize, 0);
if (usedBytes < 32) {
// Create an unallocated variable for display purposes
slotVariables.push({
id: 0,
fromSlot: variable.fromSlot,
toSlot: variable.fromSlot,
byteSize: 32 - usedBytes,
byteOffset: usedBytes,
type: 'unallocated',
attributeType: umlClass_1.AttributeType.UserDefined,
dynamic: false,
displayValue: false,
getValue: false,
contractName: variable.contractName,
name: '',
});
}
const slotVariablesReversed = slotVariables.reverse();
// For each variable in the slot
slotVariablesReversed.forEach((variable, i) => {
if (i === 0) {
dotString += ` | { ${dotVariable(variable, storageSection.name)} `;
}
else {
dotString += ` | ${dotVariable(variable, storageSection.name)} `;
}
});
dotString += '}';
});
// Need to close off the last label
dotString += '}}"]\n';
return dotString;
}
exports.convertStorage2Dot = convertStorage2Dot;
const dotVariable = (variable, contractName) => {
const port = variable.referenceSectionId !== undefined ? `<${variable.id}>` : '';
const contractNamePrefix = variable.contractName !== contractName
? `${variable.contractName}.`
: '';
const variableValue = variable.parsedValue
? `\\n\\ ${variable.parsedValue}`
: '';
const variableName = variable.name
? `: ${contractNamePrefix}${variable.name}`
: '';
return `${port} ${variable.type}${variableName} (${variable.byteSize})${variableValue}`;
};
//# sourceMappingURL=converterStorage2Dot.js.map