ts2famix 1.0.1

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.
Files changed (128) hide show
  1. package/.eslintrc.json +24 -0
  2. package/.github/workflows/node.js.yml +60 -0
  3. package/LICENSE +23 -0
  4. package/README.md +111 -0
  5. package/doc-metamodel/skins.include.puml +2 -0
  6. package/jest.config.ts +199 -0
  7. package/package.json +47 -0
  8. package/src/analyze.ts +90 -0
  9. package/src/analyze_functions/processAccesses.ts +50 -0
  10. package/src/analyze_functions/processFiles.ts +656 -0
  11. package/src/analyze_functions/processImportClauses.ts +77 -0
  12. package/src/analyze_functions/processInheritances.ts +84 -0
  13. package/src/analyze_functions/processInvocations.ts +51 -0
  14. package/src/famix2puml.ts +119 -0
  15. package/src/famix_functions/famix_functions.ts +552 -0
  16. package/src/famix_functions/famix_functions_associations.ts +208 -0
  17. package/src/famix_functions/famix_functions_index.ts +44 -0
  18. package/src/famix_functions/famix_functions_types.ts +100 -0
  19. package/src/fqn.ts +127 -0
  20. package/src/fqp_implementation.ts +66 -0
  21. package/src/generate_uml.sh +16 -0
  22. package/src/lib/famix/License.md +23 -0
  23. package/src/lib/famix/package-lock.json +301 -0
  24. package/src/lib/famix/package.json +28 -0
  25. package/src/lib/famix/readme.md +5 -0
  26. package/src/lib/famix/src/famix_JSON_exporter.ts +56 -0
  27. package/src/lib/famix/src/famix_base_element.ts +18 -0
  28. package/src/lib/famix/src/famix_repository.ts +199 -0
  29. package/src/lib/famix/src/index.ts +8 -0
  30. package/src/lib/famix/src/model/famix/access.ts +53 -0
  31. package/src/lib/famix/src/model/famix/accessor.ts +15 -0
  32. package/src/lib/famix/src/model/famix/alias.ts +41 -0
  33. package/src/lib/famix/src/model/famix/association.ts +44 -0
  34. package/src/lib/famix/src/model/famix/behavioral_entity.ts +107 -0
  35. package/src/lib/famix/src/model/famix/c_source_language.ts +15 -0
  36. package/src/lib/famix/src/model/famix/class.ts +86 -0
  37. package/src/lib/famix/src/model/famix/comment.ts +50 -0
  38. package/src/lib/famix/src/model/famix/container_entity.ts +165 -0
  39. package/src/lib/famix/src/model/famix/custom_source_language.ts +27 -0
  40. package/src/lib/famix/src/model/famix/decorator.ts +39 -0
  41. package/src/lib/famix/src/model/famix/entity.ts +15 -0
  42. package/src/lib/famix/src/model/famix/enum.ts +31 -0
  43. package/src/lib/famix/src/model/famix/enum_value.ts +29 -0
  44. package/src/lib/famix/src/model/famix/function.ts +15 -0
  45. package/src/lib/famix/src/model/famix/implicit_variable.ts +15 -0
  46. package/src/lib/famix/src/model/famix/import_clause.ts +53 -0
  47. package/src/lib/famix/src/model/famix/index.ts +42 -0
  48. package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +49 -0
  49. package/src/lib/famix/src/model/famix/inheritance.ts +42 -0
  50. package/src/lib/famix/src/model/famix/interface.ts +75 -0
  51. package/src/lib/famix/src/model/famix/invocation.ts +68 -0
  52. package/src/lib/famix/src/model/famix/method.ts +96 -0
  53. package/src/lib/famix/src/model/famix/module.ts +31 -0
  54. package/src/lib/famix/src/model/famix/named_entity.ts +98 -0
  55. package/src/lib/famix/src/model/famix/namespace.ts +28 -0
  56. package/src/lib/famix/src/model/famix/parameter.ts +29 -0
  57. package/src/lib/famix/src/model/famix/parameterizable_class.ts +31 -0
  58. package/src/lib/famix/src/model/famix/parameterizable_interface.ts +31 -0
  59. package/src/lib/famix/src/model/famix/parameterized_type.ts +40 -0
  60. package/src/lib/famix/src/model/famix/primitive_type.ts +15 -0
  61. package/src/lib/famix/src/model/famix/property.ts +54 -0
  62. package/src/lib/famix/src/model/famix/reference.ts +42 -0
  63. package/src/lib/famix/src/model/famix/scoping_entity.ts +31 -0
  64. package/src/lib/famix/src/model/famix/script_entity.ts +38 -0
  65. package/src/lib/famix/src/model/famix/source_anchor.ts +31 -0
  66. package/src/lib/famix/src/model/famix/source_language.ts +31 -0
  67. package/src/lib/famix/src/model/famix/sourced_entity.ts +70 -0
  68. package/src/lib/famix/src/model/famix/structural_entity.ts +44 -0
  69. package/src/lib/famix/src/model/famix/text_anchor.ts +49 -0
  70. package/src/lib/famix/src/model/famix/type.ts +88 -0
  71. package/src/lib/famix/src/model/famix/type_parameter.ts +33 -0
  72. package/src/lib/famix/src/model/famix/variable.ts +28 -0
  73. package/src/lib/famix/tsconfig.json +27 -0
  74. package/src/lib/famix/tslint.json +15 -0
  75. package/src/lib/ts-complex/cyclomatic-service.ts +85 -0
  76. package/src/ts2famix-cli.ts +26 -0
  77. package/src/ts2famix-tsconfig.ts +30 -0
  78. package/test/abstractClassWithComments.test.ts +58 -0
  79. package/test/abstracts.test.ts +53 -0
  80. package/test/access.test.ts +62 -0
  81. package/test/accesses.test.ts +42 -0
  82. package/test/accessorsWithDecorators.test.ts +98 -0
  83. package/test/alias.test.ts +39 -0
  84. package/test/classExtendsUndefinedClass.test.ts +41 -0
  85. package/test/classImplementsUndefinedInterface.test.ts +45 -0
  86. package/test/classWithDecorators.test.ts +65 -0
  87. package/test/entities.test.ts +232 -0
  88. package/test/entities_json.test.ts +48 -0
  89. package/test/enum.test.ts +55 -0
  90. package/test/functionReturnsFunction.test.ts +53 -0
  91. package/test/functionWithParameters.test.ts +38 -0
  92. package/test/functionWithVariables.test.ts +64 -0
  93. package/test/functions.test.ts +23 -0
  94. package/test/functionsInFunction.test.ts +40 -0
  95. package/test/functionsInMethod.test.ts +42 -0
  96. package/test/genericClass.test.ts +42 -0
  97. package/test/genericClassInheritsInterface.test.ts +47 -0
  98. package/test/genericInterface.test.ts +38 -0
  99. package/test/genericMethod.test.ts +65 -0
  100. package/test/genericWithInvocation.test.ts +71 -0
  101. package/test/generics.test.ts +68 -0
  102. package/test/inheritance.test.ts +50 -0
  103. package/test/interfaceInheritsInterface.test.ts +40 -0
  104. package/test/interfaceInheritsUndefinedInterface.test.ts +41 -0
  105. package/test/invocation.test.ts +94 -0
  106. package/test/invocationWithFunction.test.ts +42 -0
  107. package/test/invocationWithVariable.test.ts +46 -0
  108. package/test/invocation_json.test.ts +63 -0
  109. package/test/invocations.test.ts +131 -0
  110. package/test/jsDoc.test.ts +31 -0
  111. package/test/methodWithDecorator.test.ts +44 -0
  112. package/test/methods.test.ts +42 -0
  113. package/test/metrics.test.ts +51 -0
  114. package/test/module.test.ts +71 -0
  115. package/test/namespaces.test.ts +54 -0
  116. package/test/namespacesAndClasses.test.ts +66 -0
  117. package/test/parameterWithDecorators.test.ts +54 -0
  118. package/test/propertyWithDecorators.test.ts +80 -0
  119. package/test/sample.test.ts +13 -0
  120. package/test/simpleFunction.test.ts +32 -0
  121. package/test/simpleTest.test.ts +18 -0
  122. package/test/simpleTest2.test.ts +36 -0
  123. package/test/types.test.ts +58 -0
  124. package/test_src/sample.ts +103 -0
  125. package/test_src/sampleForModule.ts +10 -0
  126. package/test_src/sampleForModule2.ts +7 -0
  127. package/test_src/sampleForModule3.ts +2 -0
  128. package/tsconfig.json +70 -0
@@ -0,0 +1,232 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Method, Function, Variable} from '../src/lib/famix/src/model/famix';
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("entities",
7
+ 'namespace MyNamespace {\n\
8
+ \n\
9
+ class EntityClass {\n\
10
+ public name: string;\n\
11
+ private p1: boolean; // type-only private\n\
12
+ #p2: boolean; // runtime private\n\
13
+ protected prot1: Map<any, any>;\n\
14
+ trustMe!: string;\n\
15
+ readonly ro = "yes";\n\
16
+ static #userCount: number;\n\
17
+ optional?: string;\n\
18
+ \n\
19
+ constructor() {}\n\
20
+ public move() {}\n\
21
+ private move2(family: string): void {}\n\
22
+ #move3() {}\n\
23
+ }\n\
24
+ \n\
25
+ class class2 extends EntityClass {}\n\
26
+ \n\
27
+ class clsInNsp {\n\
28
+ public static aStaticMethod() {}\n\
29
+ }\n\
30
+ }\n\
31
+ \n\
32
+ // global scope\n\
33
+ var globalA;\n\
34
+ function globalFunc() {}\n\
35
+ ');
36
+
37
+ describe('Entities', () => {
38
+
39
+ const theClass = fmxRep._getFamixClass("EntityClass");
40
+ const theSubclass = fmxRep._getFamixClass("class2");
41
+
42
+ it("should contain an EntityClass", () => {
43
+ const theClass = fmxRep._getFamixClass("EntityClass");
44
+ expect(theClass).toBeTruthy();
45
+ });
46
+
47
+ it("should contain an EntityClass with four methods", () => {
48
+ const theClass = fmxRep._getFamixClass("EntityClass");
49
+ if (theClass) expect(theClass.getMethods().size).toBe(4);
50
+ });
51
+
52
+ it("should contain methods with correct names", () => {
53
+ if (theClass) {
54
+ const mNames = fmxRep._methodNamesAsSetFromClass("EntityClass");
55
+ expect(mNames.has("move") &&
56
+ mNames.has("move2") &&
57
+ mNames.has("constructor")).toBe(true);
58
+ }
59
+ });
60
+
61
+ it("should contain a private method named move2 that returns void", () => {
62
+ if (theClass) {
63
+ const move2Method = fmxRep._getFamixMethod("move2");
64
+ expect(move2Method).toBeTruthy();
65
+ if (move2Method) {
66
+ expect(move2Method.getIsPrivate()).toBe(true);
67
+ }
68
+ }
69
+ });
70
+
71
+ it("should contain a private method named move2 with a signature 'private move2(family: string): void'", () => {
72
+ if (theClass) {
73
+ const move2Method = fmxRep._getFamixMethod("move2");
74
+ expect(move2Method).toBeTruthy();
75
+ if (move2Method) {
76
+ expect(move2Method.getSignature()).toBe('private move2(family: string): void');
77
+ }
78
+ }
79
+ });
80
+
81
+ it("should contain a constructor in EntityClass", () => {
82
+ const theConstructor = fmxRep._getFamixMethod("constructor") as Method;
83
+ expect(theConstructor).toBeTruthy();
84
+ expect(theConstructor.getKind()).toBe("constructor");
85
+ });
86
+
87
+ it("should have a parent relationship between EntityClass and its methods", () => {
88
+ if (theClass) {
89
+ const mParents = fmxRep._methodParentsAsSetFromClass("EntityClass");
90
+ expect(mParents.size).toBe(1);
91
+ expect(Array.from(mParents)[0]).toEqual(theClass);
92
+ }
93
+ });
94
+
95
+ it("should contain an EntityClass with eight attributes", () => {
96
+ expect(theClass?.getProperties().size).toBe(8);
97
+ });
98
+
99
+ it("should contain an EntityClass with an attribute named 'name' that is public", () => {
100
+ if (theClass) {
101
+ const nameAttribute = Array.from(theClass.getProperties())[0];
102
+ expect(nameAttribute.getName()).toBe("name");
103
+ expect(nameAttribute.getModifiers()).toContain("public");
104
+ }
105
+ });
106
+
107
+ it("should contain an EntityClass with an attribute named 'name' of type string", () => {
108
+ if (theClass) {
109
+ expect(Array.from(theClass.getProperties())[0].getDeclaredType().getName()).toBe("string");
110
+ }
111
+ });
112
+
113
+ it("should contain an EntityClass with an attribute named 'p1' that is private and of type boolean", () => {
114
+ if (theClass) {
115
+ const p1Attribute = Array.from(theClass.getProperties())[1];
116
+ expect(p1Attribute.getName()).toBe("p1");
117
+ expect(p1Attribute.getModifiers()).toContain("private");
118
+ expect(p1Attribute.getDeclaredType().getName()).toBe("boolean");
119
+ }
120
+ });
121
+
122
+ it("should contain an EntityClass with an attribute named '#p2' that is run-time private and of type boolean", () => {
123
+ if (theClass) {
124
+ const p2Attribute = Array.from(theClass.getProperties())[2];
125
+ expect(p2Attribute.getName()).toBe("#p2");
126
+ expect(p2Attribute.getDeclaredType().getName()).toBe("boolean");
127
+ }
128
+ });
129
+
130
+ it("should contain an EntityClass with an attribute named 'prot1' that is protected and of type Map<any, any>", () => {
131
+ if (theClass) {
132
+ const prot1Attribute = Array.from(theClass.getProperties())[3];
133
+ expect(prot1Attribute.getName()).toBe("prot1");
134
+ expect(prot1Attribute.getModifiers()).toContain("protected");
135
+ expect(prot1Attribute.getDeclaredType().getName()).toBe("Map<any, any>");
136
+ }
137
+ });
138
+
139
+ it("should contain an EntityClass with an attribute named 'trustMe' that is guaranteed to be there (!) and of type string", () => {
140
+ if (theClass) {
141
+ const trustMeAttribute = Array.from(theClass.getProperties())[4];
142
+ expect(trustMeAttribute.getName()).toBe("trustMe");
143
+ expect(trustMeAttribute.getModifiers()).toContain("!");
144
+ expect(trustMeAttribute.getDeclaredType().getName()).toBe("string");
145
+ }
146
+ });
147
+
148
+ it("should contain an EntityClass with an attribute named 'ro' that is readonly and of type \"yes\"", () => {
149
+ if (theClass) {
150
+ const roAttribute = Array.from(theClass.getProperties())[5];
151
+ expect(roAttribute.getName()).toBe("ro");
152
+ expect(roAttribute.getModifiers()).toContain("readonly");
153
+ expect(roAttribute.getDeclaredType().getName()).toBe('"yes"');
154
+ }
155
+ });
156
+
157
+ it("should contain an EntityClass with an attribute named '#userCount' that is static and of type number", () => {
158
+ if (theClass) {
159
+ const userCountAttribute = Array.from(theClass.getProperties())[6];
160
+ expect(userCountAttribute.getName()).toBe("#userCount");
161
+ expect(userCountAttribute.getModifiers()).toContain("static");
162
+ expect(userCountAttribute.getDeclaredType().getName()).toBe('number');
163
+ }
164
+ });
165
+
166
+ it("should contain an EntityClass with an attribute named 'optional' that is optional (?) and of type string", () => {
167
+ if (theClass) {
168
+ const userCountAttribute = Array.from(theClass.getProperties())[7];
169
+ expect(userCountAttribute.getName()).toBe("optional");
170
+ expect(userCountAttribute.getModifiers()).toContain("?");
171
+ expect(userCountAttribute.getDeclaredType().getName()).toBe('string');
172
+ }
173
+ });
174
+
175
+ it("should contain an EntityClass with one subclass", () => {
176
+ if (theClass) {
177
+ expect(Array.from(theClass.getSubInheritances()).length).toBe(1);
178
+ }
179
+ });
180
+
181
+ it("should contain an EntityClass with one subclass named 'class2'", () => {
182
+ if (theClass) {
183
+ const theClassSubclass = Array.from(theClass.getSubInheritances())[0].getSubclass();
184
+ expect(theClassSubclass.getName()).toBe("class2");
185
+ if (theSubclass) {
186
+ expect(theSubclass).toBe(theClassSubclass);
187
+ }
188
+ }
189
+ });
190
+
191
+ it("should contain a clsInNsp with a class-side method named 'aStaticMethod'", () => {
192
+ const clsInNSP = fmxRep._getFamixClass("clsInNsp");
193
+ expect(clsInNSP).toBeTruthy();
194
+ if (clsInNSP) {
195
+ const aStaticMethod = Array.from(clsInNSP.getMethods()).find(m => m.getName() === 'aStaticMethod');
196
+ expect(aStaticMethod).toBeTruthy();
197
+ if (aStaticMethod) {
198
+ expect(aStaticMethod.getIsClassSide()).toBe(true);
199
+ }
200
+ }
201
+ });
202
+
203
+ it("should contain a private method named '#move3'", () => {
204
+ const cls = fmxRep._getFamixClass("EntityClass");
205
+ expect(cls).toBeTruthy();
206
+ if (cls) {
207
+ const aMethod = Array.from(cls.getMethods()).find(m => m.getName() === '#move3');
208
+ expect(aMethod).toBeTruthy();
209
+ if (aMethod) {
210
+ expect(aMethod.getIsPrivate()).toBe(true);
211
+ expect(aMethod.getIsProtected()).toBe(false);
212
+ expect(aMethod.getIsPublic()).toBe(false);
213
+ expect(aMethod.getIsClassSide()).toBe(false);
214
+ }
215
+ }
216
+ });
217
+
218
+ // global scope
219
+ it("should contain a function 'globalFunc' with global scope", () => {
220
+ const globalFunc = fmxRep._getFamixFunction('globalFunc') as Function;
221
+ expect(globalFunc).toBeTruthy();
222
+ expect(globalFunc.getName()).toBe('globalFunc');
223
+ expect(globalFunc.getParentContainerEntity().getName()).toBe('entities.ts');
224
+ });
225
+
226
+ it("should contain a variable 'globalA' with global scope", () => {
227
+ const list = Array.from(fmxRep._getAllEntitiesWithType("Variable") as Set<Variable>);
228
+ expect(list).toBeTruthy();
229
+ const globalVar = list.find(p => p.getName() === "globalA");
230
+ expect(globalVar).toBeTruthy();
231
+ });
232
+ });
@@ -0,0 +1,48 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Method } from '../src/lib/famix/src/model/famix';
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("entities_json",
7
+ 'class EntityClass {\n\
8
+ constructor() {}\n\
9
+ public move() {}\n\
10
+ private move2() {}\n\
11
+ }\n\
12
+ ');
13
+
14
+ describe('Entities json', () => {
15
+
16
+ const jsonOutput = fmxRep.getJSON();
17
+ const parsedModel = JSON.parse(jsonOutput);
18
+
19
+ it("should generate valid json", () => { // smoke test parse (change to non-empty)
20
+ expect(parsedModel).toBeTruthy();
21
+ });
22
+
23
+ it("should generate json with FM3 FamixTypeScript.Class for EntityClass", () => {
24
+ expect(jsonOutput).toMatch(/"FM3":"FamixTypeScript.Class","id":[1-9]\d*|0,"sourceAnchor":{"ref":[1-9]\d*|0},"name":"EntityClass"/);
25
+ });
26
+
27
+ it("should contain an EntityClass with three methods", () => {
28
+ const theClass = parsedModel.filter(el => (el.FM3 === "FamixTypeScript.Class" && el.name === "EntityClass"))[0];
29
+ expect(theClass.methods.length).toBe(3);
30
+ });
31
+
32
+ it("should have three methods: move, move2 and constructor", () => {
33
+ const theClass = parsedModel.filter(el => (el.FM3 === "FamixTypeScript.Class" && el.name === "EntityClass"))[0];
34
+ const mNames: Set<string> = new Set();
35
+ theClass.methods.forEach(m => {
36
+ const entityCls = fmxRep.getFamixEntityById(m.ref as number) as Method;
37
+ mNames.add(entityCls.getName());
38
+ });
39
+ expect(mNames.has("move") &&
40
+ mNames.has("move2") &&
41
+ mNames.has("constructor")).toBe(true);
42
+ });
43
+
44
+ it("should have method move", () => {
45
+ const theMethod = parsedModel.filter(el => (el.FM3 === "FamixTypeScript.Method" && el.name === "move"))[0];
46
+ expect(theMethod).toBeTruthy();
47
+ });
48
+ });
@@ -0,0 +1,55 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Access } from '../src/lib/famix/src/model/famix/access';
3
+ import { Enum } from '../src/lib/famix/src/model/famix/enum';
4
+ import { ScriptEntity } from '../src/lib/famix/src/model/famix/script_entity';
5
+
6
+ const importer = new Importer();
7
+
8
+ const fmxRep = importer.famixRepFromSource("enum",
9
+ 'enum Weekday {\n\
10
+ MONDAY = "Monday",\n\
11
+ TUESDAY = "Tuesday",\n\
12
+ WEDNESDAY = "Wednesday",\n\
13
+ THURSDAY = "Thursday",\n\
14
+ FRIDAY = "Friday",\n\
15
+ SATURDAY = "Saturday",\n\
16
+ SUNDAY = "Sunday"\n\
17
+ }\n\
18
+ \n\
19
+ const aDay: Weekday = Weekday.MONDAY;\n\
20
+ ');
21
+
22
+ describe('Tests for enum', () => {
23
+
24
+ const theFile = Array.from(fmxRep._getAllEntitiesWithType("ScriptEntity") as Set<ScriptEntity>)[0];
25
+
26
+ it("should contain one enum with seven enum values", () => {
27
+ expect(fmxRep._getAllEntitiesWithType("Enum").size).toBe(1);
28
+ const theEnum = Array.from(fmxRep._getAllEntitiesWithType("Enum") as Set<Enum>)[0];
29
+ expect(theFile.getTypes().has(theEnum)).toBe(true);
30
+ expect(theEnum.getName()).toBe("Weekday");
31
+ expect(theEnum.getValues().size).toBe(7);
32
+ expect(Array.from(theEnum.getValues())[0].getName()).toBe("MONDAY");
33
+ expect(Array.from(theEnum.getValues())[1].getName()).toBe("TUESDAY");
34
+ expect(Array.from(theEnum.getValues())[2].getName()).toBe("WEDNESDAY");
35
+ expect(Array.from(theEnum.getValues())[3].getName()).toBe("THURSDAY");
36
+ expect(Array.from(theEnum.getValues())[4].getName()).toBe("FRIDAY");
37
+ expect(Array.from(theEnum.getValues())[5].getName()).toBe("SATURDAY");
38
+ expect(Array.from(theEnum.getValues())[6].getName()).toBe("SUNDAY");
39
+ expect(Array.from(theEnum.getValues())[0].getParentEntity()).toBe(theEnum);
40
+ expect(Array.from(theEnum.getValues())[1].getParentEntity()).toBe(theEnum);
41
+ expect(Array.from(theEnum.getValues())[2].getParentEntity()).toBe(theEnum);
42
+ expect(Array.from(theEnum.getValues())[3].getParentEntity()).toBe(theEnum);
43
+ expect(Array.from(theEnum.getValues())[4].getParentEntity()).toBe(theEnum);
44
+ expect(Array.from(theEnum.getValues())[5].getParentEntity()).toBe(theEnum);
45
+ expect(Array.from(theEnum.getValues())[6].getParentEntity()).toBe(theEnum);
46
+ });
47
+
48
+ it("should contain one access", () => {
49
+ expect(fmxRep._getAllEntitiesWithType("Access").size).toBe(1);
50
+ const theAccess = Array.from(fmxRep._getAllEntitiesWithType("Access") as Set<Access>)[0];
51
+ expect(theFile.getAccesses().has(theAccess)).toBe(true);
52
+ expect(theAccess.getAccessor().getName()).toBe("enum.ts");
53
+ expect(theAccess.getVariable().getName()).toBe("MONDAY");
54
+ });
55
+ });
@@ -0,0 +1,53 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Function } from "../src/lib/famix/src/model/famix/function";
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("functionReturnsFunction",
7
+ 'export function deco() {\n\
8
+ function fct() {\n\
9
+ return function logMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n\
10
+ const originalMethod = descriptor.value;\n\
11
+ descriptor.value = function (...args: any[]) {\n\
12
+ console.log(`Calling ${propertyKey} with arguments: ${JSON.stringify(args)}`);\n\
13
+ const result = originalMethod.apply(this, args);\n\
14
+ console.log(`Method ${propertyKey} returned: ${JSON.stringify(result)}`);\n\
15
+ return result;\n\
16
+ };\n\
17
+ return descriptor;\n\
18
+ };\n\
19
+ }\n\
20
+ }\n\
21
+ ');
22
+
23
+ describe('Tests for function returns function', () => {
24
+
25
+ const functionList = fmxRep._getAllEntitiesWithType('Function');
26
+ it("should have four functions", () => {
27
+ expect(functionList?.size).toBe(4);
28
+ });
29
+
30
+ const theFunction = Array.from(functionList)[0] as Function;
31
+ it("should contain a function 'deco'", () => {
32
+ expect(theFunction).toBeTruthy();
33
+ expect(theFunction?.getName()).toBe('deco');
34
+ });
35
+
36
+ const theFunction2 = Array.from(functionList)[1] as Function;
37
+ it("should contain a function 'fct'", () => {
38
+ expect(theFunction2).toBeTruthy();
39
+ expect(theFunction2?.getName()).toBe('fct');
40
+ });
41
+
42
+ const theFunction3 = Array.from(functionList)[2] as Function;
43
+ it("should contain a function 'logMethod'", () => {
44
+ expect(theFunction3).toBeTruthy();
45
+ expect(theFunction3?.getName()).toBe('logMethod');
46
+ });
47
+
48
+ const theFunction4 = Array.from(functionList)[3] as Function;
49
+ it("should contain a function 'anonymous'", () => {
50
+ expect(theFunction4).toBeTruthy();
51
+ expect(theFunction4?.getName()).toBe('anonymous');
52
+ });
53
+ });
@@ -0,0 +1,38 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Function } from "../src/lib/famix/src/model/famix/function";
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("functionWithParameters",
7
+ 'function fct(i: number, x: string): number {\n\
8
+ return 0;\n\
9
+ }\n\
10
+ ');
11
+
12
+ describe('Tests for function with parameters', () => {
13
+
14
+ const theFunction = Array.from(fmxRep._getAllEntitiesWithType('Function'))[0] as Function;
15
+ it("should have two parameters", () => {
16
+ expect(theFunction?.getParameters().size).toBe(2);
17
+ });
18
+
19
+ const firstParam = Array.from(theFunction?.getParameters()).find((p) => p.getName() === "i");
20
+ it("should have a parameter 'i'", () => {
21
+ expect(firstParam).toBeTruthy();
22
+ });
23
+
24
+ it("should be of type number", () => {
25
+ expect(firstParam?.getDeclaredType().getName()).toBe("number");
26
+ expect(firstParam?.getParentEntity()).toBe(theFunction);
27
+ });
28
+
29
+ const secondParam = Array.from(theFunction?.getParameters()).find((p) => p.getName() === "x");
30
+ it("should have a parameter 'x'", () => {
31
+ expect(secondParam).toBeTruthy();
32
+ });
33
+
34
+ it("should be of type string", () => {
35
+ expect(secondParam?.getDeclaredType().getName()).toBe("string");
36
+ expect(secondParam?.getParentEntity()).toBe(theFunction);
37
+ });
38
+ });
@@ -0,0 +1,64 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Function } from "../src/lib/famix/src/model/famix/function";
3
+ import { Comment } from '../src/lib/famix/src/model/famix/comment';
4
+
5
+ const importer = new Importer();
6
+
7
+ const fmxRep = importer.famixRepFromSource("functionWithVariables",
8
+ 'function fct(): number {\n\
9
+ // comment 1\n\
10
+ let i: number /*comment 2*/, j: number; // comment 3\n\
11
+ const x: string = "";\n\
12
+ return 0;\n\
13
+ }\n\
14
+ ');
15
+
16
+ describe('Tests for function with variables', () => {
17
+
18
+ const theFunction = Array.from(fmxRep._getAllEntitiesWithType('Function'))[0] as Function;
19
+ it("should have three variables", () => {
20
+ expect(theFunction?.getVariables().size).toBe(3);
21
+ });
22
+
23
+ const firstVariable = Array.from(theFunction?.getVariables()).find((p) => p.getName() === "i");
24
+ it("should have a variable 'i' with three comments", () => {
25
+ expect(firstVariable).toBeTruthy();
26
+ expect(firstVariable?.getParentContainerEntity()).toBe(theFunction);
27
+ expect(firstVariable?.getComments().size).toBe(3);
28
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[0]?.getContent()).toBe("/*comment 2*/");
29
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[1]?.getContent()).toBe("// comment 1");
30
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[2]?.getContent()).toBe("// comment 3");
31
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[0]?.getContainer()).toBe(firstVariable);
32
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[1]?.getContainer()).toBe(firstVariable);
33
+ expect(Array.from(firstVariable?.getComments() as Set<Comment>)[2]?.getContainer()).toBe(firstVariable);
34
+ });
35
+
36
+ it("should be of type number", () => {
37
+ expect(firstVariable?.getDeclaredType().getName()).toBe("number");
38
+ });
39
+
40
+ const secondVariable = Array.from(theFunction?.getVariables()).find((p) => p.getName() === "j");
41
+ it("should have a variable 'j' with two comments", () => {
42
+ expect(secondVariable).toBeTruthy();
43
+ expect(secondVariable?.getParentContainerEntity()).toBe(theFunction);
44
+ expect(secondVariable?.getComments().size).toBe(2);
45
+ expect(Array.from(secondVariable?.getComments() as Set<Comment>)[0]?.getContent()).toBe("// comment 1");
46
+ expect(Array.from(secondVariable?.getComments() as Set<Comment>)[1]?.getContent()).toBe("// comment 3");
47
+ expect(Array.from(secondVariable?.getComments() as Set<Comment>)[0]?.getContainer()).toBe(secondVariable);
48
+ expect(Array.from(secondVariable?.getComments() as Set<Comment>)[1]?.getContainer()).toBe(secondVariable);
49
+ });
50
+
51
+ it("should be of type number", () => {
52
+ expect(secondVariable?.getDeclaredType().getName()).toBe("number");
53
+ });
54
+
55
+ const thirdVariable = Array.from(theFunction?.getVariables()).find((p) => p.getName() === "x");
56
+ it("should have a variable 'x'", () => {
57
+ expect(thirdVariable).toBeTruthy();
58
+ expect(thirdVariable?.getParentContainerEntity()).toBe(theFunction);
59
+ });
60
+
61
+ it("should be of type string", () => {
62
+ expect(thirdVariable?.getDeclaredType().getName()).toBe("string");
63
+ });
64
+ });
@@ -0,0 +1,23 @@
1
+ import { Importer } from '../src/analyze';
2
+
3
+ const importer = new Importer();
4
+
5
+ const fmxRep = importer.famixRepFromSource("functions",
6
+ 'function a() {}\n\
7
+ function b() {}\n\
8
+ ');
9
+
10
+ describe('Functions', () => {
11
+
12
+ it("should contain function 'a'", () => {
13
+ const functionName = "a";
14
+ const theFunction = fmxRep._getFamixFunction(functionName);
15
+ expect(theFunction).toBeTruthy();
16
+ });
17
+
18
+ it("should contain function 'b'", () => {
19
+ const functionName = "b";
20
+ const theFunction = fmxRep._getFamixFunction(functionName);
21
+ expect(theFunction).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,40 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Function } from "../src/lib/famix/src/model/famix/function";
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("functionsInFunction",
7
+ 'function fct() {\n\
8
+ function fct2() {\n\
9
+ function fct3() {\n\
10
+ return 0;\n\
11
+ }\n\
12
+ }\n\
13
+ }\n\
14
+ ');
15
+
16
+ describe('Tests for functions in function', () => {
17
+
18
+ const theFunction1 = fmxRep._getFamixFunction("fct");
19
+ const theFunction2 = fmxRep._getFamixFunction("fct2");
20
+ const theFunction3 = fmxRep._getFamixFunction("fct3");
21
+
22
+ it("should have one function 'fct' with a function 'fct2'", () => {
23
+ expect(theFunction1).toBeTruthy();
24
+ expect(theFunction2).toBeTruthy();
25
+ expect(theFunction1?.getFunctions().size).toBe(1);
26
+ expect(Array.from(theFunction1?.getFunctions() as Set<Function>)[0]).toBe(theFunction2);
27
+ });
28
+
29
+ it("should have one function 'fct2' with a function 'fct3'", () => {
30
+ expect(theFunction2).toBeTruthy();
31
+ expect(theFunction3).toBeTruthy();
32
+ expect(theFunction2?.getFunctions().size).toBe(1);
33
+ expect(Array.from(theFunction2?.getFunctions() as Set<Function>)[0]).toBe(theFunction3);
34
+ });
35
+
36
+ it("should have one function 'fct3' with no function", () => {
37
+ expect(theFunction3).toBeTruthy();
38
+ expect(theFunction3?.getFunctions().size).toBe(0);
39
+ });
40
+ });
@@ -0,0 +1,42 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { Function } from "../src/lib/famix/src/model/famix/function";
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("functionsInMethod",
7
+ 'class F {\n\
8
+ m() {\n\
9
+ function fct2() {\n\
10
+ function fct3() {\n\
11
+ return 0;\n\
12
+ }\n\
13
+ }\n\
14
+ }\n\
15
+ }\n\
16
+ ');
17
+
18
+ describe('Tests for functions in method', () => {
19
+
20
+ const theMethod = fmxRep._getFamixMethod("m");
21
+ const theFunction2 = fmxRep._getFamixFunction("fct2");
22
+ const theFunction3 = fmxRep._getFamixFunction("fct3");
23
+
24
+ it("should have one method 'm' with a function 'fct2'", () => {
25
+ expect(theMethod).toBeTruthy();
26
+ expect(theFunction2).toBeTruthy();
27
+ expect(theMethod?.getFunctions().size).toBe(1);
28
+ expect(Array.from(theMethod?.getFunctions() as Set<Function>)[0]).toBe(theFunction2);
29
+ });
30
+
31
+ it("should have one function 'fct2' with a function 'fct3'", () => {
32
+ expect(theFunction2).toBeTruthy();
33
+ expect(theFunction3).toBeTruthy();
34
+ expect(theFunction2?.getFunctions().size).toBe(1);
35
+ expect(Array.from(theFunction2?.getFunctions() as Set<Function>)[0]).toBe(theFunction3);
36
+ });
37
+
38
+ it("should have one function 'fct3' with no function", () => {
39
+ expect(theFunction3).toBeTruthy();
40
+ expect(theFunction3?.getFunctions().size).toBe(0);
41
+ });
42
+ });
@@ -0,0 +1,42 @@
1
+ import { Importer } from '../src/analyze';
2
+ import { ParameterizableClass, TypeParameter } from '../src/lib/famix/src/model/famix';
3
+
4
+ const importer = new Importer();
5
+
6
+ const fmxRep = importer.famixRepFromSource("genericClass",
7
+ 'class MyClass<T> {}\n\
8
+ ');
9
+
10
+ describe('Tests for generic class', () => {
11
+
12
+ it("should parse generics", () => {
13
+ expect(fmxRep).toBeTruthy();
14
+ });
15
+
16
+ it("should contain one generic class", () => {
17
+ expect(fmxRep._getAllEntitiesWithType("ParameterizableClass").size).toBe(1);
18
+ });
19
+
20
+ it("should contain a generic class MyClass", () => {
21
+ const listOfNames = Array.from(fmxRep._getAllEntitiesWithType("ParameterizableClass")).map(e => (e as ParameterizableClass).getName());
22
+ expect(listOfNames).toContain("MyClass");
23
+ });
24
+
25
+ it("should contain a generic class MyClass with a type parameter T", () => {
26
+ const pList = Array.from(fmxRep._getAllEntitiesWithType("ParameterizableClass") as Set<ParameterizableClass>);
27
+ expect(pList).toBeTruthy();
28
+ const MyClass = pList.find(p => p.getName() === "MyClass");
29
+ expect(MyClass).toBeTruthy();
30
+ expect(MyClass?.getTypeParameters().size).toBe(1);
31
+ if (MyClass) {
32
+ expect((Array.from(MyClass.getTypeParameters())[0] as TypeParameter).getName()).toBe("T");
33
+ expect((Array.from(MyClass.getTypeParameters())[0] as TypeParameter).getParentGeneric()).toBe(MyClass);
34
+ }
35
+ });
36
+
37
+ const theClass = fmxRep._getFamixClass("MyClass");
38
+ it ("should not be an abstract class", () => {
39
+ expect(theClass).toBeTruthy();
40
+ if (theClass) expect(theClass.getIsAbstract()).toBe(false);
41
+ });
42
+ });