ts2famix 1.0.11 → 1.0.13

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