ts2famix 1.0.1 → 1.0.4
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/dist/analyze.js +102 -0
- package/dist/analyze_functions/processAccesses.js +47 -0
- package/dist/analyze_functions/processFiles.js +540 -0
- package/dist/analyze_functions/processImportClauses.js +70 -0
- package/dist/analyze_functions/processInheritances.js +73 -0
- package/dist/analyze_functions/processInvocations.js +49 -0
- package/dist/famix2puml.js +125 -0
- package/dist/famix_functions/famix_functions.js +513 -0
- package/dist/famix_functions/famix_functions_associations.js +205 -0
- package/dist/famix_functions/famix_functions_index.js +62 -0
- package/dist/famix_functions/famix_functions_types.js +110 -0
- package/dist/fqn.js +126 -0
- package/dist/fqp_implementation.js +73 -0
- package/dist/lib/famix/src/famix_JSON_exporter.js +54 -0
- package/dist/lib/famix/src/famix_base_element.js +13 -0
- package/dist/lib/famix/src/famix_repository.js +187 -0
- package/dist/lib/famix/src/index.js +30 -0
- package/dist/lib/famix/src/model/famix/access.js +39 -0
- package/dist/lib/famix/src/model/famix/accessor.js +16 -0
- package/dist/lib/famix/src/model/famix/alias.js +32 -0
- package/dist/lib/famix/src/model/famix/association.js +36 -0
- package/dist/lib/famix/src/model/famix/behavioral_entity.js +81 -0
- package/dist/lib/famix/src/model/famix/c_source_language.js +16 -0
- package/dist/lib/famix/src/model/famix/class.js +70 -0
- package/dist/lib/famix/src/model/famix/comment.js +38 -0
- package/dist/lib/famix/src/model/famix/container_entity.js +125 -0
- package/dist/lib/famix/src/model/famix/custom_source_language.js +23 -0
- package/dist/lib/famix/src/model/famix/decorator.js +31 -0
- package/dist/lib/famix/src/model/famix/entity.js +16 -0
- package/dist/lib/famix/src/model/famix/enum.js +30 -0
- package/dist/lib/famix/src/model/famix/enum_value.js +24 -0
- package/dist/lib/famix/src/model/famix/function.js +16 -0
- package/dist/lib/famix/src/model/famix/implicit_variable.js +16 -0
- package/dist/lib/famix/src/model/famix/import_clause.js +39 -0
- package/dist/lib/famix/src/model/famix/index.js +87 -0
- package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +37 -0
- package/dist/lib/famix/src/model/famix/inheritance.js +32 -0
- package/dist/lib/famix/src/model/famix/interface.js +63 -0
- package/dist/lib/famix/src/model/famix/invocation.js +53 -0
- package/dist/lib/famix/src/model/famix/method.js +66 -0
- package/dist/lib/famix/src/model/famix/module.js +30 -0
- package/dist/lib/famix/src/model/famix/named_entity.js +77 -0
- package/dist/lib/famix/src/model/famix/namespace.js +24 -0
- package/dist/lib/famix/src/model/famix/parameter.js +24 -0
- package/dist/lib/famix/src/model/famix/parameterizable_class.js +30 -0
- package/dist/lib/famix/src/model/famix/parameterizable_interface.js +30 -0
- package/dist/lib/famix/src/model/famix/parameterized_type.js +36 -0
- package/dist/lib/famix/src/model/famix/primitive_type.js +16 -0
- package/dist/lib/famix/src/model/famix/property.js +44 -0
- package/dist/lib/famix/src/model/famix/reference.js +32 -0
- package/dist/lib/famix/src/model/famix/scoping_entity.js +30 -0
- package/dist/lib/famix/src/model/famix/script_entity.js +30 -0
- package/dist/lib/famix/src/model/famix/source_anchor.js +26 -0
- package/dist/lib/famix/src/model/famix/source_language.js +30 -0
- package/dist/lib/famix/src/model/famix/sourced_entity.js +55 -0
- package/dist/lib/famix/src/model/famix/structural_entity.js +38 -0
- package/dist/lib/famix/src/model/famix/text_anchor.js +37 -0
- package/dist/lib/famix/src/model/famix/type.js +71 -0
- package/dist/lib/famix/src/model/famix/type_parameter.js +24 -0
- package/dist/lib/famix/src/model/famix/variable.js +23 -0
- package/dist/lib/ts-complex/cyclomatic-service.js +83 -0
- package/dist/ts2famix-cli.js +51 -0
- package/dist/ts2famix-tsconfig.js +53 -0
- package/doc-uml/.gitkeep +0 -0
- package/docs/.gitkeep +0 -0
- package/jest.config.json +10 -0
- package/package.json +1 -1
- package/tsconfig.json +1 -1
- package/.github/workflows/node.js.yml +0 -60
- package/doc-metamodel/skins.include.puml +0 -2
- package/test/abstractClassWithComments.test.ts +0 -58
- package/test/abstracts.test.ts +0 -53
- package/test/access.test.ts +0 -62
- package/test/accesses.test.ts +0 -42
- package/test/accessorsWithDecorators.test.ts +0 -98
- package/test/alias.test.ts +0 -39
- package/test/classExtendsUndefinedClass.test.ts +0 -41
- package/test/classImplementsUndefinedInterface.test.ts +0 -45
- package/test/classWithDecorators.test.ts +0 -65
- package/test/entities.test.ts +0 -232
- package/test/entities_json.test.ts +0 -48
- package/test/enum.test.ts +0 -55
- package/test/functionReturnsFunction.test.ts +0 -53
- package/test/functionWithParameters.test.ts +0 -38
- package/test/functionWithVariables.test.ts +0 -64
- package/test/functions.test.ts +0 -23
- package/test/functionsInFunction.test.ts +0 -40
- package/test/functionsInMethod.test.ts +0 -42
- package/test/genericClass.test.ts +0 -42
- package/test/genericClassInheritsInterface.test.ts +0 -47
- package/test/genericInterface.test.ts +0 -38
- package/test/genericMethod.test.ts +0 -65
- package/test/genericWithInvocation.test.ts +0 -71
- package/test/generics.test.ts +0 -68
- package/test/inheritance.test.ts +0 -50
- package/test/interfaceInheritsInterface.test.ts +0 -40
- package/test/interfaceInheritsUndefinedInterface.test.ts +0 -41
- package/test/invocation.test.ts +0 -94
- package/test/invocationWithFunction.test.ts +0 -42
- package/test/invocationWithVariable.test.ts +0 -46
- package/test/invocation_json.test.ts +0 -63
- package/test/invocations.test.ts +0 -131
- package/test/jsDoc.test.ts +0 -31
- package/test/methodWithDecorator.test.ts +0 -44
- package/test/methods.test.ts +0 -42
- package/test/metrics.test.ts +0 -51
- package/test/module.test.ts +0 -71
- package/test/namespaces.test.ts +0 -54
- package/test/namespacesAndClasses.test.ts +0 -66
- package/test/parameterWithDecorators.test.ts +0 -54
- package/test/propertyWithDecorators.test.ts +0 -80
- package/test/sample.test.ts +0 -13
- package/test/simpleFunction.test.ts +0 -32
- package/test/simpleTest.test.ts +0 -18
- package/test/simpleTest2.test.ts +0 -36
- package/test/types.test.ts +0 -58
- package/test_src/sample.ts +0 -103
- package/test_src/sampleForModule.ts +0 -10
- package/test_src/sampleForModule2.ts +0 -7
- package/test_src/sampleForModule3.ts +0 -2
- /package/{jest.config.ts → jest.config-old.ts} +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProcessImportClauses = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* This class is used to build a Famix model for the import clauses
|
|
6
|
+
*/
|
|
7
|
+
class ProcessImportClauses {
|
|
8
|
+
/**
|
|
9
|
+
* Initializes the ProcessImportClauses object
|
|
10
|
+
* @param famixFunctions FamixFunctions object, it contains all the functions needed to create Famix entities
|
|
11
|
+
*/
|
|
12
|
+
constructor(famixFunctions) {
|
|
13
|
+
this.famixFunctions = famixFunctions;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds a Famix model for the import clauses of the source files which are modules
|
|
17
|
+
* @param modules An array of modules
|
|
18
|
+
* @param exports An array of maps of exported declarations
|
|
19
|
+
*/
|
|
20
|
+
processImportClauses(modules, exports) {
|
|
21
|
+
console.info(`processImportClauses: Creating import clauses:`);
|
|
22
|
+
modules.forEach(f => {
|
|
23
|
+
f.getImportDeclarations().forEach(i => {
|
|
24
|
+
const path = this.getModulePath(i);
|
|
25
|
+
i.getNamedImports().forEach(ni => {
|
|
26
|
+
console.info(`processImportClauses: Importing (named) ${ni.getName()} from ${i.getModuleSpecifierValue()}`);
|
|
27
|
+
const importedEntityName = ni.getName();
|
|
28
|
+
let bool = false;
|
|
29
|
+
exports.forEach(e => {
|
|
30
|
+
if (e.has(importedEntityName)) {
|
|
31
|
+
bool = true;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
this.famixFunctions.createFamixImportClause(f, i.getModuleSpecifierValue(), path, ni, bool, false);
|
|
35
|
+
});
|
|
36
|
+
const defaultImport = i.getDefaultImport();
|
|
37
|
+
if (defaultImport !== undefined) {
|
|
38
|
+
console.info(`processImportClauses: Importing (default) ${defaultImport.getText()} from ${i.getModuleSpecifierValue()}`);
|
|
39
|
+
this.famixFunctions.createFamixImportClause(f, i.getModuleSpecifierValue(), path, defaultImport, false, true);
|
|
40
|
+
}
|
|
41
|
+
const namespaceImport = i.getNamespaceImport();
|
|
42
|
+
if (namespaceImport !== undefined) {
|
|
43
|
+
console.info(`processImportClauses: Importing (namespace) ${namespaceImport.getText()} from ${i.getModuleSpecifierValue()}`);
|
|
44
|
+
this.famixFunctions.createFamixImportClause(f, i.getModuleSpecifierValue(), path, namespaceImport, false, false);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Gets the path of a module to be imported
|
|
51
|
+
* @param i An import declaration
|
|
52
|
+
* @returns The path of the module to be imported
|
|
53
|
+
*/
|
|
54
|
+
getModulePath(i) {
|
|
55
|
+
let path;
|
|
56
|
+
if (i.getModuleSpecifierSourceFile() === undefined) {
|
|
57
|
+
if (i.getModuleSpecifierValue().substring(i.getModuleSpecifierValue().length - 3) === ".ts") {
|
|
58
|
+
path = i.getModuleSpecifierValue();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
path = i.getModuleSpecifierValue() + ".ts";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
path = i.getModuleSpecifierSourceFile().getFilePath();
|
|
66
|
+
}
|
|
67
|
+
return path;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.ProcessImportClauses = ProcessImportClauses;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProcessInheritances = void 0;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
/**
|
|
6
|
+
* This class is used to build a Famix model for the inheritances
|
|
7
|
+
*/
|
|
8
|
+
class ProcessInheritances {
|
|
9
|
+
/**
|
|
10
|
+
* Initializes the ProcessInheritances object
|
|
11
|
+
* @param famixFunctions FamixFunctions object, it contains all the functions needed to create Famix entities
|
|
12
|
+
*/
|
|
13
|
+
constructor(famixFunctions) {
|
|
14
|
+
this.famixFunctions = famixFunctions;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds a Famix model for the inheritances of the classes and interfaces of the source files
|
|
18
|
+
* @param classes An array of classes
|
|
19
|
+
* @param interfaces An array of interfaces
|
|
20
|
+
*/
|
|
21
|
+
processInheritances(classes, interfaces) {
|
|
22
|
+
console.info(`processInheritances: Creating inheritances:`);
|
|
23
|
+
classes.forEach(cls => {
|
|
24
|
+
console.info(`processInheritances: Checking class inheritance for ${cls.getName()}`);
|
|
25
|
+
const extClass = cls.getBaseClass();
|
|
26
|
+
if (extClass !== undefined) {
|
|
27
|
+
this.famixFunctions.createFamixInheritance(cls, extClass);
|
|
28
|
+
console.info(`processInheritances: class: ${cls.getName()}, (${cls.getType().getText()}), extClass: ${extClass.getName()}, (${extClass.getType().getText()})`);
|
|
29
|
+
}
|
|
30
|
+
console.info(`processInheritances: Checking interface inheritance for ${cls.getName()}`);
|
|
31
|
+
const implementedInterfaces = this.getImplementedOrExtendedInterfaces(interfaces, cls);
|
|
32
|
+
implementedInterfaces.forEach(impInter => {
|
|
33
|
+
this.famixFunctions.createFamixInheritance(cls, impInter);
|
|
34
|
+
console.info(`processInheritances: class: ${cls.getName()}, (${cls.getType().getText()}), impInter: ${(impInter instanceof ts_morph_1.InterfaceDeclaration) ? impInter.getName() : impInter.getExpression().getText()}, (${(impInter instanceof ts_morph_1.InterfaceDeclaration) ? impInter.getType().getText() : impInter.getExpression().getText()})`);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
interfaces.forEach(inter => {
|
|
38
|
+
console.info(`processInheritances: Checking interface inheritance for ${inter.getName()}`);
|
|
39
|
+
const extendedInterfaces = this.getImplementedOrExtendedInterfaces(interfaces, inter);
|
|
40
|
+
extendedInterfaces.forEach(extInter => {
|
|
41
|
+
this.famixFunctions.createFamixInheritance(inter, extInter);
|
|
42
|
+
console.info(`processInheritances: inter: ${inter.getName()}, (${inter.getType().getText()}), extInter: ${(extInter instanceof ts_morph_1.InterfaceDeclaration) ? extInter.getName() : extInter.getExpression().getText()}, (${(extInter instanceof ts_morph_1.InterfaceDeclaration) ? extInter.getType().getText() : extInter.getExpression().getText()})`);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the interfaces implemented or extended by a class or an interface
|
|
48
|
+
* @param interfaces An array of interfaces
|
|
49
|
+
* @param subClass A class or an interface
|
|
50
|
+
* @returns An array of InterfaceDeclaration and ExpressionWithTypeArguments containing the interfaces implemented or extended by the subClass
|
|
51
|
+
*/
|
|
52
|
+
getImplementedOrExtendedInterfaces(interfaces, subClass) {
|
|
53
|
+
let impOrExtInterfaces;
|
|
54
|
+
if (subClass instanceof ts_morph_1.ClassDeclaration) {
|
|
55
|
+
impOrExtInterfaces = subClass.getImplements();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
impOrExtInterfaces = subClass.getExtends();
|
|
59
|
+
}
|
|
60
|
+
const interfacesNames = interfaces.map(i => i.getName());
|
|
61
|
+
const implementedOrExtendedInterfaces = new Array();
|
|
62
|
+
impOrExtInterfaces.forEach(i => {
|
|
63
|
+
if (interfacesNames.includes(i.getExpression().getText())) {
|
|
64
|
+
implementedOrExtendedInterfaces.push(interfaces[interfacesNames.indexOf(i.getExpression().getText())]);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
implementedOrExtendedInterfaces.push(i);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return implementedOrExtendedInterfaces;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.ProcessInheritances = ProcessInheritances;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProcessInvocations = void 0;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
/**
|
|
6
|
+
* This class is used to build a Famix model for the invocations
|
|
7
|
+
*/
|
|
8
|
+
class ProcessInvocations {
|
|
9
|
+
/**
|
|
10
|
+
* Initializes the ProcessInvocations object
|
|
11
|
+
* @param famixFunctions FamixFunctions object, it contains all the functions needed to create Famix entities
|
|
12
|
+
*/
|
|
13
|
+
constructor(famixFunctions) {
|
|
14
|
+
this.famixFunctions = famixFunctions;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds a Famix model for the invocations of the methods and functions of the source files
|
|
18
|
+
* @param methodsAndFunctionsWithId A map of methods and functions with their id
|
|
19
|
+
*/
|
|
20
|
+
processInvocations(methodsAndFunctionsWithId) {
|
|
21
|
+
console.info(`Creating invocations:`);
|
|
22
|
+
methodsAndFunctionsWithId.forEach((m, id) => {
|
|
23
|
+
console.info(`Invocations to ${(m instanceof ts_morph_1.MethodDeclaration || m instanceof ts_morph_1.GetAccessorDeclaration || m instanceof ts_morph_1.SetAccessorDeclaration || m instanceof ts_morph_1.FunctionDeclaration) ? m.getName() : ((m instanceof ts_morph_1.ConstructorDeclaration) ? 'constructor' : (m.getName() ? m.getName() : 'anonymous'))}`);
|
|
24
|
+
try {
|
|
25
|
+
const temp_nodes = m.findReferencesAsNodes();
|
|
26
|
+
temp_nodes.forEach(node => this.processNodeForInvocations(node, m, id));
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
console.error(`> WARNING: got exception ${error}. Continuing...`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Builds a Famix model for an invocation of a method or a function
|
|
35
|
+
* @param n A node
|
|
36
|
+
* @param m A method or a function
|
|
37
|
+
* @param id The id of the method or the function
|
|
38
|
+
*/
|
|
39
|
+
processNodeForInvocations(n, m, id) {
|
|
40
|
+
try {
|
|
41
|
+
this.famixFunctions.createFamixInvocation(n, m, id);
|
|
42
|
+
console.info(`node: node, (${n.getType().getText()})`);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.ProcessInvocations = ProcessInvocations;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const fs = __importStar(require("fs"));
|
|
30
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
31
|
+
const argv = yargs_1.default
|
|
32
|
+
.example('ts-node src/famix2puml.ts -i JSONModels/projectName.json -o PUMLModels/projectName.puml', 'creates a PlantUML class diagram from a JSON-format model of a typescript project')
|
|
33
|
+
.alias('i', 'input')
|
|
34
|
+
.nargs('i', 1)
|
|
35
|
+
.alias('o', 'output')
|
|
36
|
+
.nargs('o', 1)
|
|
37
|
+
.demandOption('input').demandOption('output').parseSync();
|
|
38
|
+
const INHERITANCE_LINK_COLOR = 'blue';
|
|
39
|
+
const jsonFileName = argv.input;
|
|
40
|
+
const pumlFileName = argv.output.substring(argv.output.indexOf("/") + 1, argv.output.lastIndexOf('.'));
|
|
41
|
+
const parsedModel = JSON.parse(fs.readFileSync(jsonFileName, 'utf-8'));
|
|
42
|
+
const classNameMap = new Map();
|
|
43
|
+
const associations = new Array();
|
|
44
|
+
// maps all class names to their id
|
|
45
|
+
parsedModel.forEach(element => {
|
|
46
|
+
// map has id as key and unique (plantuml) class name
|
|
47
|
+
classNameMap.set(element.id, uniqueElementName(element));
|
|
48
|
+
const nameWithoutPrefix = element.FM3.split('.')[1];
|
|
49
|
+
// special case association
|
|
50
|
+
if (nameWithoutPrefix.endsWith('Inheritance')) {
|
|
51
|
+
const subclass = element['subclass'].ref;
|
|
52
|
+
const superclass = element['superclass'].ref;
|
|
53
|
+
associations.push({ from: subclass, to: superclass, name: nameWithoutPrefix });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// generates plantuml
|
|
57
|
+
let plantUMLOutString = `@startuml ${pumlFileName}
|
|
58
|
+
skinparam style strictuml
|
|
59
|
+
title Object diagram for ${jsonFileName}
|
|
60
|
+
`;
|
|
61
|
+
parsedModel.forEach(element => {
|
|
62
|
+
plantUMLOutString += `${toPlantUML(element)}\n`;
|
|
63
|
+
});
|
|
64
|
+
// creates associations
|
|
65
|
+
associations.forEach(association => {
|
|
66
|
+
// inheritance is a special case, show it in UML even though it doesn't make 100% sense in object diagrams
|
|
67
|
+
const isInheritance = association.name.startsWith('Inheritance');
|
|
68
|
+
if (isInheritance) {
|
|
69
|
+
plantUMLOutString += `${classNameMap.get(association.from)} --|> ${classNameMap.get(association.to)} #line:${INHERITANCE_LINK_COLOR}\n`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
plantUMLOutString += `${classNameMap.get(association.from)} ..> "${association.name}" ${classNameMap.get(association.to)}\n`;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
plantUMLOutString += '@enduml';
|
|
76
|
+
// writes to output file
|
|
77
|
+
fs.writeFile(argv.output, plantUMLOutString, (err) => {
|
|
78
|
+
if (err) {
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
function uniqueElementName(element) {
|
|
83
|
+
return `${element.FM3}${element.id}`;
|
|
84
|
+
}
|
|
85
|
+
function toPlantUML(element) {
|
|
86
|
+
let plantUMLString = '';
|
|
87
|
+
const optionalName = element.name || '';
|
|
88
|
+
const nameWithoutPrefix = element.FM3.split('.')[1];
|
|
89
|
+
plantUMLString += `object "${optionalName}:${nameWithoutPrefix}" as ${uniqueElementName(element)} {\n`;
|
|
90
|
+
plantUMLString += `id = ${element.id}\n`;
|
|
91
|
+
plantUMLString += propertiesToPlantUML(element);
|
|
92
|
+
plantUMLString += '}\n';
|
|
93
|
+
return plantUMLString;
|
|
94
|
+
}
|
|
95
|
+
function propertiesToPlantUML(element) {
|
|
96
|
+
let plantUMLString = '';
|
|
97
|
+
for (const property in element) {
|
|
98
|
+
const attribute = element[property];
|
|
99
|
+
const isOneToManyReference = typeof attribute !== 'string' && attribute.length; // array but not a string
|
|
100
|
+
switch (property) {
|
|
101
|
+
// ignores these properties
|
|
102
|
+
case 'subclass':
|
|
103
|
+
case 'superclass':
|
|
104
|
+
case 'FM3':
|
|
105
|
+
case 'id':
|
|
106
|
+
case 'name':
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
if (isOneToManyReference) {
|
|
110
|
+
attribute.forEach((composite, index) => {
|
|
111
|
+
associations.push({ from: element.id, to: composite.ref, name: `${property}[${index}]` });
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else if (typeof attribute === 'object') {
|
|
115
|
+
associations.push({ from: element.id, to: attribute.ref, name: property });
|
|
116
|
+
}
|
|
117
|
+
else { // typeof string, boolean, number, etc
|
|
118
|
+
// treats it as a simple attribute
|
|
119
|
+
plantUMLString += `${property} = ${element[property]}\n`;
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return plantUMLString;
|
|
125
|
+
}
|