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,552 @@
1
+ import { ClassDeclaration, ConstructorDeclaration, FunctionDeclaration, Identifier, InterfaceDeclaration, MethodDeclaration, MethodSignature, ModuleDeclaration, PropertyDeclaration, PropertySignature, SourceFile, TypeParameterDeclaration, VariableDeclaration, ParameterDeclaration, Decorator, GetAccessorDeclaration, SetAccessorDeclaration, ImportSpecifier, CommentRange, EnumDeclaration, EnumMember, TypeAliasDeclaration, FunctionExpression, ExpressionWithTypeArguments } from "ts-morph";
2
+ import * as Famix from "../lib/famix/src/model/famix";
3
+ import { FamixRepository } from "../lib/famix/src/famix_repository";
4
+ import { FQNFunctions } from "../fqn";
5
+ import { FamixFunctionsIndex } from "./famix_functions_index";
6
+ import { FamixFunctionsAssociations } from "./famix_functions_associations";
7
+ import { FamixFunctionsTypes } from "./famix_functions_types";
8
+
9
+ /**
10
+ * This class contains all the functions needed to create Famix entities
11
+ */
12
+ export class FamixFunctions {
13
+
14
+ private famixRep = new FamixRepository(); // The Famix repository
15
+ private FQNFunctions = new FQNFunctions(); // The fully qualified name functions
16
+ private fmxAliases = new Map<string, Famix.Alias>(); // Maps the alias names to their Famix model
17
+ private fmxClasses = new Map<string, Famix.Class | Famix.ParameterizableClass>(); // Maps the class names to their Famix model
18
+ private fmxInterfaces = new Map<string, Famix.Interface | Famix.ParameterizableInterface>(); // Maps the interface names to their Famix model
19
+ private fmxNamespaces = new Map<string, Famix.Namespace>(); // Maps the namespace names to their Famix model
20
+ private fmxFiles = new Map<string, Famix.ScriptEntity | Famix.Module>(); // Maps the source file names to their Famix model
21
+ private famixFunctionsIndex = new FamixFunctionsIndex(this.famixRep); // FamixFunctionsIndex object, it contains all the functions needed to create Famix index file anchors
22
+ private famixFunctionsAssociations = new FamixFunctionsAssociations(this.famixRep, this.fmxClasses, this.fmxInterfaces); // FamixFunctionsAssociations object, it contains all the functions needed to create Famix associations
23
+ private famixFunctionsTypes = new FamixFunctionsTypes(this.famixRep); // FamixFunctionsTypes object, it contains all the functions needed to create Famix types
24
+ private UNKNOWN_VALUE = '(unknown due to parsing error)'; // The value to use when a name is not usable
25
+
26
+ /**
27
+ * Gets the Famix repository
28
+ * @returns The Famix repository
29
+ */
30
+ public getFamixRepository(): FamixRepository {
31
+ return this.famixRep;
32
+ }
33
+
34
+ /**
35
+ * Creates or gets a Famix script entity or module
36
+ * @param f A source file
37
+ * @param isModule A boolean indicating if the source file is a module
38
+ * @returns The Famix model of the source file
39
+ */
40
+ public createOrGetFamixFile(f: SourceFile, isModule: boolean): Famix.ScriptEntity | Famix.Module {
41
+ let fmxFile: Famix.ScriptEntity | Famix.Module;
42
+ const fileName = f.getBaseName();
43
+ if (!this.fmxFiles.has(fileName)) {
44
+ if (isModule) {
45
+ fmxFile = new Famix.Module(this.famixRep);
46
+ }
47
+ else {
48
+ fmxFile = new Famix.ScriptEntity(this.famixRep);
49
+ }
50
+ fmxFile.setName(fileName);
51
+ fmxFile.setNumberOfLinesOfText(f.getEndLineNumber() - f.getStartLineNumber());
52
+ fmxFile.setNumberOfCharacters(f.getFullText().length);
53
+
54
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(f, fmxFile);
55
+
56
+ this.fmxFiles.set(fileName, fmxFile);
57
+ }
58
+ else {
59
+ fmxFile = this.fmxFiles.get(fileName);
60
+ }
61
+ return fmxFile;
62
+ }
63
+
64
+ /**
65
+ * Creates or gets a Famix namespace
66
+ * @param m A namespace
67
+ * @returns The Famix model of the namespace
68
+ */
69
+ public createOrGetFamixNamespace(m: ModuleDeclaration): Famix.Namespace {
70
+ let fmxNamespace: Famix.Namespace;
71
+ const namespaceName = m.getName();
72
+ if (!this.fmxNamespaces.has(namespaceName)) {
73
+ fmxNamespace = new Famix.Namespace(this.famixRep);
74
+ fmxNamespace.setName(namespaceName);
75
+
76
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(m, fmxNamespace);
77
+
78
+ this.fmxNamespaces.set(namespaceName, fmxNamespace);
79
+ }
80
+ else {
81
+ fmxNamespace = this.fmxNamespaces.get(namespaceName);
82
+ }
83
+ return fmxNamespace;
84
+ }
85
+
86
+ /**
87
+ * Creates a Famix alias
88
+ * @param a An alias
89
+ * @returns The Famix model of the alias
90
+ */
91
+ public createFamixAlias(a: TypeAliasDeclaration): Famix.Alias {
92
+ let fmxAlias: Famix.Alias;
93
+ const aliasName = a.getName();
94
+ if (!this.fmxAliases.has(aliasName)) {
95
+ fmxAlias = new Famix.Alias(this.famixRep);
96
+ fmxAlias.setName(a.getName());
97
+
98
+ const fmxType = this.createOrGetFamixType(aliasName, a);
99
+ fmxAlias.setAliasedEntity(fmxType);
100
+
101
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(a, fmxAlias);
102
+
103
+ this.fmxAliases.set(aliasName, fmxAlias);
104
+ }
105
+ else {
106
+ fmxAlias = this.fmxAliases.get(aliasName);
107
+ }
108
+ return fmxAlias;
109
+ }
110
+
111
+ /**
112
+ * Creates or gets a Famix class or parameterizable class
113
+ * @param cls A class
114
+ * @returns The Famix model of the class
115
+ */
116
+ public createOrGetFamixClass(cls: ClassDeclaration): Famix.Class | Famix.ParameterizableClass {
117
+ let fmxClass: Famix.Class | Famix.ParameterizableClass;
118
+ const isAbstract = cls.isAbstract();
119
+ const clsName = cls.getName();
120
+ if (!this.fmxClasses.has(clsName)) {
121
+ const isGeneric = cls.getTypeParameters().length;
122
+ if (isGeneric) {
123
+ fmxClass = new Famix.ParameterizableClass(this.famixRep);
124
+ }
125
+ else {
126
+ fmxClass = new Famix.Class(this.famixRep);
127
+ }
128
+
129
+ fmxClass.setName(clsName);
130
+ fmxClass.setIsAbstract(isAbstract);
131
+
132
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(cls, fmxClass);
133
+
134
+ this.fmxClasses.set(clsName, fmxClass);
135
+ }
136
+ else {
137
+ fmxClass = this.fmxClasses.get(clsName) as (Famix.Class | Famix.ParameterizableClass);
138
+ }
139
+ return fmxClass;
140
+ }
141
+
142
+ /**
143
+ * Creates or gets a Famix interface or parameterizable interface
144
+ * @param inter An interface
145
+ * @returns The Famix model of the interface
146
+ */
147
+ public createOrGetFamixInterface(inter: InterfaceDeclaration): Famix.Interface | Famix.ParameterizableInterface {
148
+ let fmxInterface: Famix.Interface | Famix.ParameterizableInterface;
149
+ const interName = inter.getName();
150
+ if (!this.fmxInterfaces.has(interName)) {
151
+ const isGeneric = inter.getTypeParameters().length;
152
+ if (isGeneric) {
153
+ fmxInterface = new Famix.ParameterizableInterface(this.famixRep);
154
+ }
155
+ else {
156
+ fmxInterface = new Famix.Interface(this.famixRep);
157
+ }
158
+
159
+ fmxInterface.setName(interName);
160
+
161
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(inter, fmxInterface);
162
+
163
+ this.fmxInterfaces.set(interName, fmxInterface);
164
+ }
165
+ else {
166
+ fmxInterface = this.fmxInterfaces.get(interName) as (Famix.Interface | Famix.ParameterizableInterface);
167
+ }
168
+ return fmxInterface;
169
+ }
170
+
171
+ /**
172
+ * Creates a Famix property
173
+ * @param property A property
174
+ * @returns The Famix model of the property
175
+ */
176
+ public createFamixProperty(property: PropertyDeclaration | PropertySignature): Famix.Property {
177
+ const fmxProperty = new Famix.Property(this.famixRep);
178
+ const isSignature = property instanceof PropertySignature;
179
+ fmxProperty.setName(property.getName());
180
+
181
+ let propTypeName = this.UNKNOWN_VALUE;
182
+ try {
183
+ propTypeName = property.getType().getText().trim();
184
+ } catch (error) {
185
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for property: ${property.getName()}. Continuing...`);
186
+ }
187
+
188
+ const fmxType = this.createOrGetFamixType(propTypeName, property);
189
+ fmxProperty.setDeclaredType(fmxType);
190
+
191
+ property.getModifiers().forEach(m => fmxProperty.addModifier(m.getText()));
192
+ if (!isSignature && property.getExclamationTokenNode()) {
193
+ fmxProperty.addModifier("!");
194
+ }
195
+ if (property.getQuestionTokenNode()) {
196
+ fmxProperty.addModifier("?");
197
+ }
198
+ if (property.getName().substring(0, 1) === "#") {
199
+ fmxProperty.addModifier("#");
200
+ }
201
+
202
+ if (fmxProperty.getModifiers().has("static")) {
203
+ fmxProperty.setIsClassSide(true);
204
+ }
205
+ else {
206
+ fmxProperty.setIsClassSide(false);
207
+ }
208
+
209
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(property, fmxProperty);
210
+
211
+ return fmxProperty;
212
+ }
213
+
214
+ /**
215
+ * Creates a Famix method or accessor
216
+ * @param method A method or an accessor
217
+ * @param currentCC The cyclomatic complexity metrics of the current source file
218
+ * @returns The Famix model of the method or the accessor
219
+ */
220
+ public createFamixMethod(method: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration, currentCC: unknown): Famix.Method | Famix.Accessor {
221
+ let fmxMethod: Famix.Method | Famix.Accessor;
222
+ if (method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) {
223
+ fmxMethod = new Famix.Accessor(this.famixRep);
224
+ const isGetter = method instanceof GetAccessorDeclaration;
225
+ const isSetter = method instanceof SetAccessorDeclaration;
226
+ if (isGetter) {(fmxMethod as Famix.Accessor).setKind("getter");}
227
+ if (isSetter) {(fmxMethod as Famix.Accessor).setKind("setter");}
228
+ }
229
+ else {
230
+ fmxMethod = new Famix.Method(this.famixRep);
231
+ }
232
+ const isConstructor = method instanceof ConstructorDeclaration;
233
+ const isSignature = method instanceof MethodSignature;
234
+ const isGeneric = method.getTypeParameters().length > 0;
235
+ fmxMethod.setIsGeneric(isGeneric);
236
+
237
+ let isAbstract = false;
238
+ let isStatic = false;
239
+ if (method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) {
240
+ isAbstract = method.isAbstract();
241
+ isStatic = method.isStatic();
242
+ }
243
+
244
+ if (isConstructor) {(fmxMethod as Famix.Accessor).setKind("constructor");}
245
+ fmxMethod.setIsAbstract(isAbstract);
246
+ fmxMethod.setIsClassSide(isStatic);
247
+ fmxMethod.setIsPrivate((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false);
248
+ fmxMethod.setIsProtected((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false);
249
+ fmxMethod.setSignature(this.computeSignature(method.getText()));
250
+
251
+ let methodName: string;
252
+ if (isConstructor) {
253
+ methodName = "constructor";
254
+ }
255
+ else {
256
+ methodName = (method as MethodDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration).getName();
257
+ }
258
+ fmxMethod.setName(methodName);
259
+
260
+ if (!isConstructor) {
261
+ if (method.getName().substring(0, 1) === "#") {
262
+ fmxMethod.setIsPrivate(true);
263
+ }
264
+ }
265
+
266
+ if (!fmxMethod.getIsPrivate() && !fmxMethod.getIsProtected()) {
267
+ fmxMethod.setIsPublic(true);
268
+ }
269
+ else {
270
+ fmxMethod.setIsPublic(false);
271
+ }
272
+
273
+ if (!isSignature) {
274
+ fmxMethod.setCyclomaticComplexity(currentCC[fmxMethod.getName()]);
275
+ }
276
+ else {
277
+ fmxMethod.setCyclomaticComplexity(0);
278
+ }
279
+
280
+ let methodTypeName = this.UNKNOWN_VALUE;
281
+ try {
282
+ methodTypeName = method.getReturnType().getText().trim();
283
+ } catch (error) {
284
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.getName()}. Continuing...`);
285
+ }
286
+
287
+ const fmxType = this.createOrGetFamixType(methodTypeName, method);
288
+ fmxMethod.setDeclaredType(fmxType);
289
+ fmxMethod.setNumberOfLinesOfCode(method.getEndLineNumber() - method.getStartLineNumber());
290
+ const parameters = method.getParameters();
291
+ fmxMethod.setNumberOfParameters(parameters.length);
292
+
293
+ if (!isSignature) {
294
+ fmxMethod.setNumberOfStatements(method.getStatements().length);
295
+ }
296
+ else {
297
+ fmxMethod.setNumberOfStatements(0);
298
+ }
299
+
300
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(method, fmxMethod);
301
+
302
+ return fmxMethod;
303
+ }
304
+
305
+ /**
306
+ * Creates a Famix function
307
+ * @param func A function
308
+ * @param currentCC The cyclomatic complexity metrics of the current source file
309
+ * @returns The Famix model of the function
310
+ */
311
+ public createFamixFunction(func: FunctionDeclaration | FunctionExpression, currentCC: unknown): Famix.Function {
312
+ const fmxFunction = new Famix.Function(this.famixRep);
313
+ if (func.getName()) {
314
+ fmxFunction.setName(func.getName());
315
+ }
316
+ else {
317
+ fmxFunction.setName("anonymous");
318
+ }
319
+ fmxFunction.setSignature(this.computeSignature(func.getText()));
320
+ fmxFunction.setCyclomaticComplexity(currentCC[fmxFunction.getName()]);
321
+ const isGeneric = func.getTypeParameters().length > 0;
322
+ fmxFunction.setIsGeneric(isGeneric);
323
+
324
+ let functionTypeName = this.UNKNOWN_VALUE;
325
+ try {
326
+ functionTypeName = func.getReturnType().getText().trim();
327
+ } catch (error) {
328
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of function: ${func.getName()}. Continuing...`);
329
+ }
330
+
331
+ const fmxType = this.createOrGetFamixType(functionTypeName, func);
332
+ fmxFunction.setDeclaredType(fmxType);
333
+ fmxFunction.setNumberOfLinesOfCode(func.getEndLineNumber() - func.getStartLineNumber());
334
+ const parameters = func.getParameters();
335
+ fmxFunction.setNumberOfParameters(parameters.length);
336
+ fmxFunction.setNumberOfStatements(func.getStatements().length);
337
+
338
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(func, fmxFunction);
339
+
340
+ return fmxFunction;
341
+ }
342
+
343
+ /**
344
+ * Creates a Famix parameter
345
+ * @param param A parameter
346
+ * @returns The Famix model of the parameter
347
+ */
348
+ public createFamixParameter(param: ParameterDeclaration): Famix.Parameter {
349
+ const fmxParam = new Famix.Parameter(this.famixRep);
350
+
351
+ let paramTypeName = this.UNKNOWN_VALUE;
352
+ try {
353
+ paramTypeName = param.getType().getText().trim();
354
+ } catch (error) {
355
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for parameter: ${param.getName()}. Continuing...`);
356
+ }
357
+
358
+ const fmxType = this.createOrGetFamixType(paramTypeName, param);
359
+ fmxParam.setDeclaredType(fmxType);
360
+ fmxParam.setName(param.getName());
361
+
362
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(param, fmxParam);
363
+
364
+ return fmxParam;
365
+ }
366
+
367
+ /**
368
+ * Creates a Famix type parameter
369
+ * @param tp A type parameter
370
+ * @returns The Famix model of the type parameter
371
+ */
372
+ public createFamixTypeParameter(tp: TypeParameterDeclaration): Famix.TypeParameter {
373
+ const fmxTypeParameter = new Famix.TypeParameter(this.famixRep);
374
+ fmxTypeParameter.setName(tp.getName());
375
+
376
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(tp, fmxTypeParameter);
377
+
378
+ return fmxTypeParameter;
379
+ }
380
+
381
+ /**
382
+ * Creates a Famix variable
383
+ * @param variable A variable
384
+ * @returns The Famix model of the variable
385
+ */
386
+ public createFamixVariable(variable: VariableDeclaration): Famix.Variable {
387
+ const fmxVariable = new Famix.Variable(this.famixRep);
388
+
389
+ let variableTypeName = this.UNKNOWN_VALUE;
390
+ try {
391
+ variableTypeName = variable.getType().getText().trim();
392
+ } catch (error) {
393
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for variable: ${variable.getName()}. Continuing...`);
394
+ }
395
+
396
+ const fmxType = this.createOrGetFamixType(variableTypeName, variable);
397
+ fmxVariable.setDeclaredType(fmxType);
398
+ fmxVariable.setName(variable.getName());
399
+
400
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(variable, fmxVariable);
401
+
402
+ return fmxVariable;
403
+ }
404
+
405
+ /**
406
+ * Creates a Famix enum
407
+ * @param enumEntity An enum
408
+ * @returns The Famix model of the enum
409
+ */
410
+ public createFamixEnum(enumEntity: EnumDeclaration): Famix.Enum {
411
+ const fmxEnum = new Famix.Enum(this.famixRep);
412
+ fmxEnum.setName(enumEntity.getName());
413
+
414
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(enumEntity, fmxEnum);
415
+
416
+ return fmxEnum;
417
+ }
418
+
419
+ /**
420
+ * Creates a Famix enum value
421
+ * @param enumMember An enum member
422
+ * @returns The Famix model of the enum member
423
+ */
424
+ public createFamixEnumValue(enumMember: EnumMember): Famix.EnumValue {
425
+ const fmxEnumValue = new Famix.EnumValue(this.famixRep);
426
+
427
+ let enumValueTypeName = this.UNKNOWN_VALUE;
428
+ try {
429
+ enumValueTypeName = enumMember.getType().getText().trim();
430
+ } catch (error) {
431
+ console.error(`> WARNING: got exception ${error}. Failed to get usable name for enum value: ${enumMember.getName()}. Continuing...`);
432
+ }
433
+
434
+ const fmxType = this.createOrGetFamixType(enumValueTypeName, enumMember);
435
+ fmxEnumValue.setDeclaredType(fmxType);
436
+ fmxEnumValue.setName(enumMember.getName());
437
+
438
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(enumMember, fmxEnumValue);
439
+
440
+ return fmxEnumValue;
441
+ }
442
+
443
+ /**
444
+ * Creates or gets a Famix decorator
445
+ * @param decorator A decorator
446
+ * @param decoratedEntity A class, a method, a parameter or a property
447
+ * @returns The Famix model of the decorator
448
+ */
449
+ public createOrGetFamixDecorator(decorator: Decorator, decoratedEntity: ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ParameterDeclaration | PropertyDeclaration): Famix.Decorator {
450
+ const fmxDecorator = new Famix.Decorator(this.famixRep);
451
+ const decoratorName = "@" + decorator.getName();
452
+ const decoratorExpression = decorator.getText().substring(1);
453
+
454
+ fmxDecorator.setName(decoratorName);
455
+ fmxDecorator.setDecoratorExpression(decoratorExpression);
456
+ const decoratedEntityFullyQualifiedName = this.FQNFunctions.getFQN(decoratedEntity);
457
+ const fmxDecoratedEntity = this.getFamixEntityByFullyQualifiedName(decoratedEntityFullyQualifiedName) as Famix.NamedEntity;
458
+ fmxDecorator.setDecoratedEntity(fmxDecoratedEntity);
459
+
460
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(decorator, fmxDecorator);
461
+
462
+ return fmxDecorator;
463
+ }
464
+
465
+ /**
466
+ * Creates a Famix comment
467
+ * @param comment A comment
468
+ * @param fmxScope The Famix model of the comment's container
469
+ * @param isJSDoc A boolean indicating if the comment is a JSDoc
470
+ * @returns The Famix model of the comment
471
+ */
472
+ public createFamixComment(comment: CommentRange, fmxScope: Famix.NamedEntity, isJSDoc: boolean): Famix.Comment {
473
+ const fmxComment = new Famix.Comment(this.famixRep);
474
+ fmxComment.setContent(comment.getText());
475
+ fmxComment.setContainer(fmxScope);
476
+ fmxComment.setIsJSDoc(isJSDoc);
477
+
478
+ this.famixFunctionsIndex.makeFamixIndexFileAnchor(comment, fmxComment);
479
+
480
+ return fmxComment;
481
+ }
482
+
483
+ /**
484
+ * Creates or gets a Famix type
485
+ * @param typeName A type name
486
+ * @param element A ts-morph element
487
+ * @returns The Famix model of the type
488
+ */
489
+ private createOrGetFamixType(typeName: string, element: TypeAliasDeclaration | PropertyDeclaration | PropertySignature | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | EnumMember): Famix.Type | Famix.PrimitiveType | Famix.ParameterizedType {
490
+ return this.famixFunctionsTypes.createOrGetFamixType(typeName, element);
491
+ }
492
+
493
+ /**
494
+ * Creates a Famix access
495
+ * @param node A node
496
+ * @param id An id of a parameter, a variable, a property or an enum member
497
+ */
498
+ public createFamixAccess(node: Identifier, id: number): void {
499
+ this.famixFunctionsAssociations.createFamixAccess(node, id);
500
+ }
501
+
502
+ /**
503
+ * Creates a Famix invocation
504
+ * @param node A node
505
+ * @param m A method or a function
506
+ * @param id The id of the method or the function
507
+ */
508
+ public createFamixInvocation(node: Identifier, m: MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression, id: number): void {
509
+ this.famixFunctionsAssociations.createFamixInvocation(node, m, id);
510
+ }
511
+
512
+ /**
513
+ * Creates a Famix inheritance
514
+ * @param cls A class or an interface (subclass)
515
+ * @param inhClass The inherited class or interface (superclass)
516
+ */
517
+ public createFamixInheritance(cls: ClassDeclaration | InterfaceDeclaration, inhClass: ClassDeclaration | InterfaceDeclaration | ExpressionWithTypeArguments): void {
518
+ this.famixFunctionsAssociations.createFamixInheritance(cls, inhClass);
519
+ }
520
+
521
+ /**
522
+ * Creates a Famix import clause
523
+ * @param importer A source file which is a module
524
+ * @param moduleSpecifier The name of the module where the export declaration is
525
+ * @param moduleSpecifierFilePath The path of the module where the export declaration is
526
+ * @param importElement The imported entity
527
+ * @param isInExports A boolean indicating if the imported entity is in the exports
528
+ * @param isDefaultExport A boolean indicating if the imported entity is a default export
529
+ */
530
+ public createFamixImportClause(importer: SourceFile, moduleSpecifier: string, moduleSpecifierFilePath: string, importElement: ImportSpecifier | Identifier, isInExports: boolean, isDefaultExport: boolean): void {
531
+ this.famixFunctionsAssociations.createFamixImportClause(importer, moduleSpecifier, moduleSpecifierFilePath, importElement, isInExports, isDefaultExport);
532
+ }
533
+
534
+ /**
535
+ * Gets a Famix entity by fully qualified name
536
+ * @param fullyQualifiedName A fully qualified name
537
+ * @returns The Famix entity corresponding to the fully qualified name
538
+ */
539
+ private getFamixEntityByFullyQualifiedName(fullyQualifiedName: string): Famix.Entity {
540
+ return this.famixRep.getFamixEntityByFullyQualifiedName(fullyQualifiedName) as Famix.Entity;
541
+ }
542
+
543
+ /**
544
+ * Gets the signature of a method or a function
545
+ * @param text A method or a function source code
546
+ * @returns The signature of the method or the function
547
+ */
548
+ private computeSignature(text: string): string {
549
+ const endSignatureText = text.indexOf("{");
550
+ return text.substring(0, endSignatureText).trim();
551
+ }
552
+ }