sol2uml 2.1.6 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,6 +97,7 @@ Options:
97
97
  -hv, --hideVariables hide variables from contracts, interfaces, structs and enums (default: false)
98
98
  -hf, --hideFunctions hide functions from contracts, interfaces and libraries (default: false)
99
99
  -hp, --hidePrivates hide private and internal attributes and operators (default: false)
100
+ -hc, --hideConstants hide file level constants (default: false)
100
101
  -he, --hideEnums hide enum types (default: false)
101
102
  -hs, --hideStructs hide data structures (default: false)
102
103
  -hl, --hideLibraries hide libraries (default: false)
@@ -48,7 +48,7 @@ function convertAST2UmlClasses(node, relativePath, filesystem = false) {
48
48
  umlClasses.push(umlClass);
49
49
  }
50
50
  else if (childNode.type === 'StructDefinition') {
51
- debug(`Adding struct ${childNode.name}`);
51
+ debug(`Adding file level struct ${childNode.name}`);
52
52
  let umlClass = new umlClass_1.UmlClass({
53
53
  name: childNode.name,
54
54
  stereotype: umlClass_1.ClassStereotype.Struct,
@@ -62,7 +62,7 @@ function convertAST2UmlClasses(node, relativePath, filesystem = false) {
62
62
  umlClasses.push(umlClass);
63
63
  }
64
64
  else if (childNode.type === 'EnumDefinition') {
65
- debug(`Adding enum ${childNode.name}`);
65
+ debug(`Adding file level enum ${childNode.name}`);
66
66
  let umlClass = new umlClass_1.UmlClass({
67
67
  name: childNode.name,
68
68
  stereotype: umlClass_1.ClassStereotype.Enum,
@@ -123,7 +123,36 @@ function convertAST2UmlClasses(node, relativePath, filesystem = false) {
123
123
  imports.push(newImport);
124
124
  }
125
125
  }
126
- // TODO add file level constants
126
+ else if (childNode.type === 'FileLevelConstant') {
127
+ debug(`Adding file level constant ${childNode.name}`);
128
+ const [type, attributeType] = parseTypeName(childNode.typeName);
129
+ const umlClass = new umlClass_1.UmlClass({
130
+ name: childNode.name,
131
+ stereotype: umlClass_1.ClassStereotype.Constant,
132
+ absolutePath: filesystem
133
+ ? path.resolve(relativePath) // resolve the absolute path
134
+ : relativePath,
135
+ relativePath,
136
+ attributes: [
137
+ {
138
+ name: childNode.name,
139
+ type,
140
+ attributeType,
141
+ },
142
+ ],
143
+ });
144
+ if (childNode?.initialValue?.type === 'NumberLiteral') {
145
+ umlClass.constants.push({
146
+ name: childNode.name,
147
+ value: parseInt(childNode.initialValue.number),
148
+ });
149
+ }
150
+ // TODO handle expressions. eg N_COINS * 2
151
+ umlClasses.push(umlClass);
152
+ }
153
+ else if (childNode.type !== 'PragmaDirective') {
154
+ debug(`node type "${childNode.type}" not parsed in ${relativePath}`);
155
+ }
127
156
  });
128
157
  }
129
158
  else {
@@ -347,13 +376,22 @@ function addAssociations(nodes, umlClass) {
347
376
  ], umlClass);
348
377
  // Array of user defined types
349
378
  }
350
- else if (node.typeName.type == 'ArrayTypeName' &&
351
- node.typeName.baseTypeName.type === 'UserDefinedTypeName') {
352
- const { umlClassName } = parseClassName(node.typeName.baseTypeName.namePath);
353
- umlClass.addAssociation({
354
- referenceType,
355
- targetUmlClassName: umlClassName,
356
- });
379
+ else if (node.typeName.type == 'ArrayTypeName') {
380
+ if (node.typeName.baseTypeName.type ===
381
+ 'UserDefinedTypeName') {
382
+ const { umlClassName } = parseClassName(node.typeName.baseTypeName.namePath);
383
+ umlClass.addAssociation({
384
+ referenceType,
385
+ targetUmlClassName: umlClassName,
386
+ });
387
+ }
388
+ else if (node.typeName.length?.type === 'Identifier') {
389
+ const { umlClassName } = parseClassName(node.typeName.length.name);
390
+ umlClass.addAssociation({
391
+ referenceType,
392
+ targetUmlClassName: umlClassName,
393
+ });
394
+ }
357
395
  }
358
396
  break;
359
397
  case 'UserDefinedTypeName':
@@ -1,5 +1,6 @@
1
1
  import { UmlClass } from './umlClass';
2
2
  export interface ClassOptions {
3
+ hideConstants?: boolean;
3
4
  hideVariables?: boolean;
4
5
  hideFunctions?: boolean;
5
6
  hideStructs?: boolean;
@@ -14,7 +14,9 @@ const convertClass2Dot = (umlClass, options = {}) => {
14
14
  umlClass.stereotype === umlClass_1.ClassStereotype.Abstract) ||
15
15
  (options.hideStructs &&
16
16
  umlClass.stereotype === umlClass_1.ClassStereotype.Struct) ||
17
- (options.hideEnums && umlClass.stereotype === umlClass_1.ClassStereotype.Enum)) {
17
+ (options.hideEnums && umlClass.stereotype === umlClass_1.ClassStereotype.Enum) ||
18
+ (options.hideConstants &&
19
+ umlClass.stereotype === umlClass_1.ClassStereotype.Constant)) {
18
20
  return '';
19
21
  }
20
22
  let dotString = `\n${umlClass.id} [label="{${dotClassTitle(umlClass, options)}`;
@@ -51,6 +53,9 @@ const dotClassTitle = (umlClass, options = {}) => {
51
53
  case umlClass_1.ClassStereotype.Enum:
52
54
  stereoName = 'Enum';
53
55
  break;
56
+ case umlClass_1.ClassStereotype.Constant:
57
+ stereoName = 'Constant';
58
+ break;
54
59
  default:
55
60
  // Contract or undefined stereotype will just return the UmlClass name
56
61
  return `${umlClass.name}${relativePath}`;
@@ -61,9 +66,10 @@ const dotAttributeVisibilities = (umlClass, options = {}) => {
61
66
  if (umlClass.attributes.length === 0)
62
67
  return '';
63
68
  let dotString = '| ';
64
- // if a struct or enum then no visibility group
69
+ // if a struct, enum or constant then no visibility group
65
70
  if (umlClass.stereotype === umlClass_1.ClassStereotype.Struct ||
66
- umlClass.stereotype === umlClass_1.ClassStereotype.Enum) {
71
+ umlClass.stereotype === umlClass_1.ClassStereotype.Enum ||
72
+ umlClass.stereotype === umlClass_1.ClassStereotype.Constant) {
67
73
  return dotString + dotAttributes(umlClass.attributes, undefined, false);
68
74
  }
69
75
  // For each visibility group
@@ -90,7 +90,7 @@ function addAssociationsToDot(umlClasses, classOptions = {}) {
90
90
  exports.addAssociationsToDot = addAssociationsToDot;
91
91
  function addAssociationToDot(sourceUmlClass, targetUmlClass, association, classOptions = {}) {
92
92
  // do not include library or interface associations if hidden
93
- // Or associations to Structs or Enums if they are hidden
93
+ // Or associations to Structs, Enums or Constants if they are hidden
94
94
  if ((classOptions.hideLibraries &&
95
95
  (sourceUmlClass.stereotype === umlClass_1.ClassStereotype.Library ||
96
96
  targetUmlClass.stereotype === umlClass_1.ClassStereotype.Library)) ||
@@ -103,7 +103,9 @@ function addAssociationToDot(sourceUmlClass, targetUmlClass, association, classO
103
103
  (classOptions.hideStructs &&
104
104
  targetUmlClass.stereotype === umlClass_1.ClassStereotype.Struct) ||
105
105
  (classOptions.hideEnums &&
106
- targetUmlClass.stereotype === umlClass_1.ClassStereotype.Enum)) {
106
+ targetUmlClass.stereotype === umlClass_1.ClassStereotype.Enum) ||
107
+ (classOptions.hideConstants &&
108
+ targetUmlClass.stereotype === umlClass_1.ClassStereotype.Constant)) {
107
109
  return '';
108
110
  }
109
111
  let dotString = `\n${sourceUmlClass.id} -> ${targetUmlClass.id} [`;
@@ -177,25 +177,29 @@ const parseReferenceStorage = (attribute, umlClass, otherClasses, storages) => {
177
177
  attributeType: baseAttributeType,
178
178
  };
179
179
  const { size: arrayItemSize } = (0, exports.calcStorageByteSize)(baseAttribute, umlClass, otherClasses);
180
- const firstVariable = {
180
+ const arraySlotSize = arrayItemSize > 16
181
+ ? 32 * Math.ceil(arrayItemSize / 32)
182
+ : arrayItemSize;
183
+ const variables = [];
184
+ variables[0] = {
181
185
  id: variableId++,
182
186
  fromSlot: 0,
183
- toSlot: Math.floor((arrayItemSize - 1) / 32),
187
+ toSlot: Math.floor((arraySlotSize - 1) / 32),
184
188
  byteSize: arrayItemSize,
185
189
  byteOffset: 0,
186
190
  type: baseType,
187
191
  dynamic,
188
192
  noValue: false,
189
193
  };
190
- const variables = [firstVariable];
191
194
  if (arrayLength > 1) {
195
+ // For fixed length arrays. Dynamic arrays will have undefined arrayLength
192
196
  for (let i = 1; i < arrayLength; i++) {
193
197
  variables.push({
194
198
  id: variableId++,
195
- fromSlot: Math.floor((i * arrayItemSize) / 32),
196
- toSlot: Math.floor(((i + 1) * arrayItemSize - 1) / 32),
199
+ fromSlot: Math.floor((i * arraySlotSize) / 32),
200
+ toSlot: Math.floor(((i + 1) * arraySlotSize - 1) / 32),
197
201
  byteSize: arrayItemSize,
198
- byteOffset: (i * arrayItemSize) % 32,
202
+ byteOffset: (i * arraySlotSize) % 32,
199
203
  type: baseType,
200
204
  dynamic,
201
205
  noValue: false,
@@ -205,7 +209,7 @@ const parseReferenceStorage = (attribute, umlClass, otherClasses, storages) => {
205
209
  // recursively add storage
206
210
  if (baseAttributeType !== umlClass_1.AttributeType.Elementary) {
207
211
  const referenceStorage = (0, exports.parseReferenceStorage)(baseAttribute, umlClass, otherClasses, storages);
208
- firstVariable.referenceStorageId = referenceStorage?.id;
212
+ variables[0].referenceStorageId = referenceStorage?.id;
209
213
  }
210
214
  const newStorage = {
211
215
  id: storageId++,
package/lib/sol2uml.js CHANGED
@@ -60,6 +60,7 @@ If an Ethereum address with a 0x prefix is passed, the verified source code from
60
60
  .option('-hv, --hideVariables', 'hide variables from contracts, interfaces, structs and enums', false)
61
61
  .option('-hf, --hideFunctions', 'hide functions from contracts, interfaces and libraries', false)
62
62
  .option('-hp, --hidePrivates', 'hide private and internal attributes and operators', false)
63
+ .option('-hc, --hideConstants', 'hide file level constants', false)
63
64
  .option('-he, --hideEnums', 'hide enum types', false)
64
65
  .option('-hs, --hideStructs', 'hide data structures', false)
65
66
  .option('-hl, --hideLibraries', 'hide libraries', false)
package/lib/umlClass.d.ts CHANGED
@@ -12,7 +12,8 @@ export declare enum ClassStereotype {
12
12
  Abstract = 3,
13
13
  Contract = 4,
14
14
  Struct = 5,
15
- Enum = 6
15
+ Enum = 6,
16
+ Constant = 7
16
17
  }
17
18
  export declare enum OperatorStereotype {
18
19
  None = 0,
package/lib/umlClass.js CHANGED
@@ -18,6 +18,7 @@ var ClassStereotype;
18
18
  ClassStereotype[ClassStereotype["Contract"] = 4] = "Contract";
19
19
  ClassStereotype[ClassStereotype["Struct"] = 5] = "Struct";
20
20
  ClassStereotype[ClassStereotype["Enum"] = 6] = "Enum";
21
+ ClassStereotype[ClassStereotype["Constant"] = 7] = "Constant";
21
22
  })(ClassStereotype = exports.ClassStereotype || (exports.ClassStereotype = {}));
22
23
  var OperatorStereotype;
23
24
  (function (OperatorStereotype) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sol2uml",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "Solidity contract visualisation tool.",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",