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.
- package/lib/associations.js +39 -5
- package/lib/converterAST2Classes.js +5 -1
- package/lib/converterClasses2Storage.js +3 -2
- package/lib/parserFiles.js +2 -2
- package/lib/umlClass.d.ts +3 -0
- package/lib/umlClass.js +3 -7
- package/package.json +1 -1
package/lib/associations.js
CHANGED
|
@@ -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) =>
|
|
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.
|
|
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.
|
|
28
|
-
|
|
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}"
|
|
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
|
|
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
|
};
|
package/lib/parserFiles.js
CHANGED
|
@@ -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
|
|
20
|
-
umlClasses = umlClasses.concat(
|
|
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[
|
|
71
|
-
this.associations[
|
|
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[
|
|
78
|
-
ReferenceType.Storage;
|
|
74
|
+
this.associations[association.targetUmlClassName].referenceType = ReferenceType.Storage;
|
|
79
75
|
}
|
|
80
76
|
}
|
|
81
77
|
}
|