sol2uml 2.5.17 → 2.5.18

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.
@@ -3,7 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findAssociatedClass = void 0;
4
4
  // Find the UML class linked to the association
5
5
  const findAssociatedClass = (association, sourceUmlClass, umlClasses, searchedAbsolutePaths = []) => {
6
- const umlClass = umlClasses.find((targetUmlClass) => isAssociated(association, sourceUmlClass, targetUmlClass));
6
+ const umlClass = umlClasses.find((targetUmlClass) => {
7
+ const targetParentClass = association.parentUmlClassName &&
8
+ targetUmlClass.parentId !== undefined
9
+ ? umlClasses[targetUmlClass.parentId]
10
+ : undefined;
11
+ return isAssociated(association, sourceUmlClass, targetUmlClass, targetParentClass);
12
+ });
7
13
  // If a link was found
8
14
  if (umlClass)
9
15
  return umlClass;
@@ -14,18 +20,46 @@ const findAssociatedClass = (association, sourceUmlClass, umlClasses, searchedAb
14
20
  };
15
21
  exports.findAssociatedClass = findAssociatedClass;
16
22
  // Tests if source class can be linked to the target class via an association
17
- const isAssociated = (association, sourceUmlClass, targetUmlClass) => {
23
+ const isAssociated = (association, sourceUmlClass, targetUmlClass, targetParentmlClass) => {
24
+ if (association.parentUmlClassName) {
25
+ return (
26
+ // class is in the same source file
27
+ (association.targetUmlClassName === targetUmlClass.name &&
28
+ association.parentUmlClassName === targetParentmlClass?.name &&
29
+ sourceUmlClass.absolutePath === targetUmlClass.absolutePath) ||
30
+ // imported classes with no explicit import names
31
+ (association.targetUmlClassName === targetUmlClass.name &&
32
+ association.parentUmlClassName === targetParentmlClass?.name &&
33
+ sourceUmlClass.imports.some((i) => i.absolutePath === targetUmlClass.absolutePath &&
34
+ i.classNames.length === 0)) ||
35
+ // imported classes with explicit import names or import aliases
36
+ sourceUmlClass.imports.some((importLink) => importLink.absolutePath === targetUmlClass.absolutePath &&
37
+ importLink.classNames.some((importedClass) =>
38
+ // If a parent contract with no import alias
39
+ (association.parentUmlClassName !== undefined &&
40
+ association.parentUmlClassName ===
41
+ importedClass.className &&
42
+ importedClass.className ===
43
+ targetUmlClass.name &&
44
+ importedClass.alias == undefined) ||
45
+ // If a parent contract with import alias
46
+ (association.parentUmlClassName !== undefined &&
47
+ association.parentUmlClassName ===
48
+ importedClass.alias &&
49
+ importedClass.className ===
50
+ targetUmlClass.name))));
51
+ }
18
52
  return (
19
53
  // class is in the same source file
20
54
  (association.targetUmlClassName === targetUmlClass.name &&
21
55
  sourceUmlClass.absolutePath === targetUmlClass.absolutePath) ||
22
56
  // imported classes with no explicit import names
23
57
  (association.targetUmlClassName === targetUmlClass.name &&
24
- sourceUmlClass.imports.find((i) => i.absolutePath === targetUmlClass.absolutePath &&
58
+ sourceUmlClass.imports.some((i) => i.absolutePath === targetUmlClass.absolutePath &&
25
59
  i.classNames.length === 0)) ||
26
60
  // imported classes with explicit import names or import aliases
27
- sourceUmlClass.imports.find((i) => i.absolutePath === targetUmlClass.absolutePath &&
28
- i.classNames.find((importedClass) =>
61
+ sourceUmlClass.imports.some((importLink) => importLink.absolutePath === targetUmlClass.absolutePath &&
62
+ importLink.classNames.some((importedClass) =>
29
63
  // no import alias
30
64
  (association.targetUmlClassName ===
31
65
  importedClass.className &&
@@ -51,9 +51,9 @@ function convertAST2UmlClasses(node, relativePath, remappings, filesystem = fals
51
51
  : relativePath,
52
52
  relativePath,
53
53
  });
54
+ umlClasses.push(umlClass);
54
55
  parseContractDefinition(childNode, umlClass);
55
56
  debug(`Added contract ${childNode.name}`);
56
- umlClasses.push(umlClass);
57
57
  }
58
58
  else if (childNode.type === 'StructDefinition') {
59
59
  debug(`Adding file level struct ${childNode.name}`);
@@ -349,6 +349,7 @@ function parseContractDefinition(node, umlClass) {
349
349
  name: subNode.name,
350
350
  absolutePath: umlClass.absolutePath,
351
351
  relativePath: umlClass.relativePath,
352
+ parentId: umlClass.id,
352
353
  stereotype: umlClass_1.ClassStereotype.Struct,
353
354
  });
354
355
  parseStructDefinition(subNode, structClass);
@@ -361,6 +362,7 @@ function parseContractDefinition(node, umlClass) {
361
362
  name: subNode.name,
362
363
  absolutePath: umlClass.absolutePath,
363
364
  relativePath: umlClass.relativePath,
365
+ parentId: umlClass.id,
364
366
  stereotype: umlClass_1.ClassStereotype.Enum,
365
367
  });
366
368
  parseEnumDefinition(subNode, enumClass);
@@ -397,6 +399,7 @@ function addAssociations(nodes, umlClass) {
397
399
  }
398
400
  if (node.typeName.type === 'UserDefinedTypeName') {
399
401
  // Library references can have a Library dot variable notation. eg Set.Data
402
+ // Structs and enums can also be under a library or contract
400
403
  const { umlClassName, structOrEnum } = parseClassName(node.typeName.namePath);
401
404
  umlClass.addAssociation({
402
405
  referenceType,
@@ -405,6 +408,7 @@ function addAssociations(nodes, umlClass) {
405
408
  if (structOrEnum) {
406
409
  umlClass.addAssociation({
407
410
  referenceType,
411
+ parentUmlClassName: umlClassName,
408
412
  targetUmlClassName: structOrEnum,
409
413
  });
410
414
  }
@@ -131,7 +131,7 @@ const parseVariables = (umlClass, umlClasses, variables, storageSections, inheri
131
131
  newInheritedContracts.forEach((parent) => {
132
132
  const parentClass = (0, associations_1.findAssociatedClass)(parent, umlClass, umlClasses);
133
133
  if (!parentClass) {
134
- throw Error(`Failed to find inherited contract "${parent.targetUmlClassName}" of "${umlClass.absolutePath}"`);
134
+ throw Error(`Failed to find inherited contract "${parent.targetUmlClassName}" sourced from "${umlClass.name}" with path "${umlClass.absolutePath}"`);
135
135
  }
136
136
  // recursively parse inherited contract
137
137
  parseVariables(parentClass, umlClasses, variables, storageSections, inheritedContracts, mapping, arrayItems, noExpandVariables);
@@ -438,10 +438,11 @@ const findTypeClass = (userType, attribute, umlClass, otherClasses) => {
438
438
  const association = {
439
439
  referenceType: umlClass_1.ReferenceType.Memory,
440
440
  targetUmlClassName: types.length === 1 ? types[0] : types[1],
441
+ parentUmlClassName: types.length === 1 ? undefined : types[0],
441
442
  };
442
443
  const typeClass = (0, associations_1.findAssociatedClass)(association, umlClass, otherClasses);
443
444
  if (!typeClass) {
444
- throw Error(`Failed to find user defined type "${userType}" in attribute "${attribute.name}" of type "${attribute.attributeType}""`);
445
+ throw Error(`Failed to find user defined type "${userType}" in attribute "${attribute.name}" of from class "${umlClass.name}" with path "${umlClass.absolutePath}"`);
445
446
  }
446
447
  return typeClass;
447
448
  };
@@ -16,8 +16,8 @@ const parseUmlClassesFromFiles = async (filesOrFolders, ignoreFilesOrFolders, su
16
16
  for (const file of files) {
17
17
  const node = await parseSolidityFile(file);
18
18
  const relativePath = (0, path_1.relative)(process.cwd(), file);
19
- const umlClass = (0, converterAST2Classes_1.convertAST2UmlClasses)(node, relativePath, [], true);
20
- umlClasses = umlClasses.concat(umlClass);
19
+ const newUmlClasses = (0, converterAST2Classes_1.convertAST2UmlClasses)(node, relativePath, [], true);
20
+ umlClasses = umlClasses.concat(newUmlClasses);
21
21
  }
22
22
  return umlClasses;
23
23
  };
package/lib/umlClass.d.ts CHANGED
@@ -66,6 +66,7 @@ export declare enum ReferenceType {
66
66
  }
67
67
  export interface Association {
68
68
  referenceType: ReferenceType;
69
+ parentUmlClassName?: string;
69
70
  targetUmlClassName: string;
70
71
  realization?: boolean;
71
72
  }
@@ -78,6 +79,7 @@ export interface ClassProperties {
78
79
  name: string;
79
80
  absolutePath: string;
80
81
  relativePath: string;
82
+ parentId?: number;
81
83
  importedFileNames?: string[];
82
84
  stereotype?: ClassStereotype;
83
85
  enums?: number[];
@@ -95,6 +97,7 @@ export declare class UmlClass implements ClassProperties {
95
97
  name: string;
96
98
  absolutePath: string;
97
99
  relativePath: string;
100
+ parentId?: number;
98
101
  imports: Import[];
99
102
  stereotype?: ClassStereotype;
100
103
  constants: Constants[];
package/lib/umlClass.js CHANGED
@@ -63,19 +63,15 @@ class UmlClass {
63
63
  if (!association || !association.targetUmlClassName) {
64
64
  throw TypeError(`Failed to add association. targetUmlClassName was missing`);
65
65
  }
66
- // Will not duplicate lines to the same class and stereotype
67
- // const targetUmlClass = `${association.targetUmlClassName}#${association.targetUmlClassStereotype}`
68
- const targetUmlClass = association.targetUmlClassName;
69
66
  // If association doesn't already exist
70
- if (!this.associations[targetUmlClass]) {
71
- this.associations[targetUmlClass] = association;
67
+ if (!this.associations[association.targetUmlClassName]) {
68
+ this.associations[association.targetUmlClassName] = association;
72
69
  }
73
70
  // associate already exists
74
71
  else {
75
72
  // If new attribute reference type is Storage
76
73
  if (association.referenceType === ReferenceType.Storage) {
77
- this.associations[targetUmlClass].referenceType =
78
- ReferenceType.Storage;
74
+ this.associations[association.targetUmlClassName].referenceType = ReferenceType.Storage;
79
75
  }
80
76
  }
81
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sol2uml",
3
- "version": "2.5.17",
3
+ "version": "2.5.18",
4
4
  "description": "Solidity contract visualisation tool.",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",