sol2uml 2.5.18 → 2.5.20
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 +2 -0
- package/lib/associations.js +69 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -373,3 +373,5 @@ sol2uml uses [@solidity-parser/parser](https://github.com/solidity-parser/parser
|
|
|
373
373
|
The [Solidity language grammar](https://solidity.readthedocs.io/en/develop/miscellaneous.html#language-grammar) is published with each major release.
|
|
374
374
|
|
|
375
375
|
The diagrams are generated using [viz.js](https://github.com/mdaines/viz.js/) which uses [Graphviz](http://www.graphviz.org/) to render a [Scalable Vector Graphics (SVG)](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) file. [Graphviz Online](https://dreampuf.github.io/GraphvizOnline/) allows dot files to be edited and rendered into a SVG dynamically.
|
|
376
|
+
|
|
377
|
+
The `diff` command use's Google's [Diff Match and Patch library](https://github.com/google/diff-match-patch).
|
package/lib/associations.js
CHANGED
|
@@ -13,42 +13,48 @@ const findAssociatedClass = (association, sourceUmlClass, umlClasses, searchedAb
|
|
|
13
13
|
// If a link was found
|
|
14
14
|
if (umlClass)
|
|
15
15
|
return umlClass;
|
|
16
|
-
// Could not find
|
|
16
|
+
// Could not find association so now need to recursively look at imports of imports
|
|
17
17
|
// add to already recursively processed files to avoid getting stuck in circular imports
|
|
18
18
|
searchedAbsolutePaths.push(sourceUmlClass.absolutePath);
|
|
19
|
-
|
|
19
|
+
const importedType = findChainedImport(association, sourceUmlClass, umlClasses, searchedAbsolutePaths);
|
|
20
|
+
if (importedType)
|
|
21
|
+
return importedType;
|
|
22
|
+
// Still could not find association so now need to recursively look for inherited types
|
|
23
|
+
const inheritedType = findInheritedType(association, sourceUmlClass, umlClasses);
|
|
24
|
+
if (inheritedType)
|
|
25
|
+
return inheritedType;
|
|
26
|
+
return undefined;
|
|
20
27
|
};
|
|
21
28
|
exports.findAssociatedClass = findAssociatedClass;
|
|
22
29
|
// Tests if source class can be linked to the target class via an association
|
|
23
|
-
const isAssociated = (association, sourceUmlClass, targetUmlClass,
|
|
30
|
+
const isAssociated = (association, sourceUmlClass, targetUmlClass, targetParentUmlClass) => {
|
|
24
31
|
if (association.parentUmlClassName) {
|
|
25
32
|
return (
|
|
26
33
|
// class is in the same source file
|
|
27
34
|
(association.targetUmlClassName === targetUmlClass.name &&
|
|
28
|
-
association.parentUmlClassName ===
|
|
35
|
+
association.parentUmlClassName === targetParentUmlClass?.name &&
|
|
29
36
|
sourceUmlClass.absolutePath === targetUmlClass.absolutePath) ||
|
|
30
37
|
// imported classes with no explicit import names
|
|
31
38
|
(association.targetUmlClassName === targetUmlClass.name &&
|
|
32
|
-
association.parentUmlClassName ===
|
|
39
|
+
association.parentUmlClassName === targetParentUmlClass?.name &&
|
|
33
40
|
sourceUmlClass.imports.some((i) => i.absolutePath === targetUmlClass.absolutePath &&
|
|
34
41
|
i.classNames.length === 0)) ||
|
|
35
42
|
// imported classes with explicit import names or import aliases
|
|
36
43
|
sourceUmlClass.imports.some((importLink) => importLink.absolutePath === targetUmlClass.absolutePath &&
|
|
37
44
|
importLink.classNames.some((importedClass) =>
|
|
38
45
|
// If a parent contract with no import alias
|
|
39
|
-
(association.
|
|
46
|
+
(association.targetUmlClassName ===
|
|
47
|
+
targetUmlClass.name &&
|
|
40
48
|
association.parentUmlClassName ===
|
|
41
49
|
importedClass.className &&
|
|
42
|
-
importedClass.className ===
|
|
43
|
-
targetUmlClass.name &&
|
|
44
50
|
importedClass.alias == undefined) ||
|
|
45
51
|
// If a parent contract with import alias
|
|
46
|
-
(association.
|
|
52
|
+
(association.targetUmlClassName ===
|
|
53
|
+
targetUmlClass.name &&
|
|
47
54
|
association.parentUmlClassName ===
|
|
48
|
-
importedClass.alias
|
|
49
|
-
importedClass.className ===
|
|
50
|
-
targetUmlClass.name))));
|
|
55
|
+
importedClass.alias))));
|
|
51
56
|
}
|
|
57
|
+
// No parent class in the association
|
|
52
58
|
return (
|
|
53
59
|
// class is in the same source file
|
|
54
60
|
(association.targetUmlClassName === targetUmlClass.name &&
|
|
@@ -70,11 +76,48 @@ const isAssociated = (association, sourceUmlClass, targetUmlClass, targetParentm
|
|
|
70
76
|
importedClass.alias &&
|
|
71
77
|
importedClass.className === targetUmlClass.name))));
|
|
72
78
|
};
|
|
73
|
-
const
|
|
74
|
-
// Get all
|
|
75
|
-
const
|
|
76
|
-
// For each
|
|
77
|
-
for (const
|
|
79
|
+
const findInheritedType = (association, sourceUmlClass, umlClasses) => {
|
|
80
|
+
// Get all realized associations.
|
|
81
|
+
const parentAssociations = sourceUmlClass.getParentContracts();
|
|
82
|
+
// For each parent association
|
|
83
|
+
for (const parentAssociation of parentAssociations) {
|
|
84
|
+
const parent = (0, exports.findAssociatedClass)(parentAssociation, sourceUmlClass, umlClasses);
|
|
85
|
+
if (!parent)
|
|
86
|
+
continue;
|
|
87
|
+
// For each struct on the parent
|
|
88
|
+
for (const structId of parent.structs) {
|
|
89
|
+
const structUmlClass = umlClasses.find((c) => c.id === structId);
|
|
90
|
+
if (!structUmlClass)
|
|
91
|
+
continue;
|
|
92
|
+
if (structUmlClass.name === association.targetUmlClassName) {
|
|
93
|
+
return structUmlClass;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// For each enum on the parent
|
|
97
|
+
for (const enumId of parent.enums) {
|
|
98
|
+
const enumUmlClass = umlClasses.find((c) => c.id === enumId);
|
|
99
|
+
if (!enumUmlClass)
|
|
100
|
+
continue;
|
|
101
|
+
if (enumUmlClass.name === association.targetUmlClassName) {
|
|
102
|
+
return enumUmlClass;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Recursively look for inherited types
|
|
106
|
+
const targetClass = findInheritedType(association, parent, umlClasses);
|
|
107
|
+
if (targetClass)
|
|
108
|
+
return targetClass;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
};
|
|
112
|
+
const findChainedImport = (association, sourceUmlClass, umlClasses, searchedRelativePaths) => {
|
|
113
|
+
// Get all valid imports. That is, imports that do not explicitly import contracts or interfaces
|
|
114
|
+
// or explicitly import the source class
|
|
115
|
+
const imports = sourceUmlClass.imports.filter((i) => i.classNames.length === 0 ||
|
|
116
|
+
i.classNames.some((cn) => (association.targetUmlClassName === cn.className &&
|
|
117
|
+
!cn.alias) ||
|
|
118
|
+
association.targetUmlClassName === cn.alias));
|
|
119
|
+
// For each import
|
|
120
|
+
for (const importDetail of imports) {
|
|
78
121
|
// Find a class with the same absolute path as the import so we can get the new imports
|
|
79
122
|
const newSourceUmlClass = umlClasses.find((c) => c.absolutePath === importDetail.absolutePath);
|
|
80
123
|
if (!newSourceUmlClass) {
|
|
@@ -86,10 +129,18 @@ const findImplicitImport = (association, sourceUmlClass, umlClasses, searchedRel
|
|
|
86
129
|
// Have already recursively looked for imports of imports in this file
|
|
87
130
|
continue;
|
|
88
131
|
}
|
|
89
|
-
//
|
|
132
|
+
// find class linked to the association without aliased imports
|
|
90
133
|
const umlClass = (0, exports.findAssociatedClass)(association, newSourceUmlClass, umlClasses, searchedRelativePaths);
|
|
91
134
|
if (umlClass)
|
|
92
135
|
return umlClass;
|
|
136
|
+
// find all aliased imports
|
|
137
|
+
const aliasedImports = importDetail.classNames.filter((cn) => cn.alias);
|
|
138
|
+
// For each aliased import
|
|
139
|
+
for (const aliasedImport of aliasedImports) {
|
|
140
|
+
const umlClass = (0, exports.findAssociatedClass)({ ...association, targetUmlClassName: aliasedImport.className }, newSourceUmlClass, umlClasses, searchedRelativePaths);
|
|
141
|
+
if (umlClass)
|
|
142
|
+
return umlClass;
|
|
143
|
+
}
|
|
93
144
|
}
|
|
94
145
|
return undefined;
|
|
95
146
|
};
|