ts2famix 1.4.0 → 2.0.0

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 (119) hide show
  1. package/README.md +1 -1
  2. package/dist/analyze.js +6 -3
  3. package/dist/analyze_functions/process_functions.js +248 -100
  4. package/dist/famix2puml.js +1 -0
  5. package/dist/famix_functions/EntityDictionary.js +661 -155
  6. package/dist/famix_functions/helpers_creation.js +26 -6
  7. package/dist/fqn.js +156 -69
  8. package/dist/lib/famix/src/famix_JSON_exporter.js +1 -0
  9. package/dist/lib/famix/src/famix_base_element.js +1 -0
  10. package/dist/lib/famix/src/famix_repository.js +9 -8
  11. package/dist/lib/famix/src/index.js +1 -0
  12. package/dist/lib/famix/src/model/famix/access.js +3 -2
  13. package/dist/lib/famix/src/model/famix/accessor.js +1 -0
  14. package/dist/lib/famix/src/model/famix/alias.js +2 -1
  15. package/dist/lib/famix/src/model/famix/arrowFunction.js +17 -0
  16. package/dist/lib/famix/src/model/famix/behavioral_entity.js +13 -15
  17. package/dist/lib/famix/src/model/famix/class.js +1 -0
  18. package/dist/lib/famix/src/model/famix/comment.js +2 -1
  19. package/dist/lib/famix/src/model/famix/concretisation.js +31 -0
  20. package/dist/lib/famix/src/model/famix/container_entity.js +7 -6
  21. package/dist/lib/famix/src/model/famix/decorator.js +2 -1
  22. package/dist/lib/famix/src/model/famix/entity.js +1 -0
  23. package/dist/lib/famix/src/model/famix/enum.js +2 -1
  24. package/dist/lib/famix/src/model/famix/enum_value.js +2 -1
  25. package/dist/lib/famix/src/model/famix/function.js +1 -0
  26. package/dist/lib/famix/src/model/famix/implicit_variable.js +1 -0
  27. package/dist/lib/famix/src/model/famix/import_clause.js +5 -3
  28. package/dist/lib/famix/src/model/famix/index.js +18 -11
  29. package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +3 -2
  30. package/dist/lib/famix/src/model/famix/inheritance.js +3 -2
  31. package/dist/lib/famix/src/model/famix/interface.js +2 -1
  32. package/dist/lib/famix/src/model/famix/invocation.js +3 -2
  33. package/dist/lib/famix/src/model/famix/method.js +2 -1
  34. package/dist/lib/famix/src/model/famix/module.js +53 -0
  35. package/dist/lib/famix/src/model/famix/named_entity.js +4 -3
  36. package/dist/lib/famix/src/model/famix/parameter.js +2 -1
  37. package/dist/lib/famix/src/model/famix/parameterConcretisation.js +44 -0
  38. package/dist/lib/famix/src/model/famix/parameter_type.js +22 -1
  39. package/dist/lib/famix/src/model/famix/parametric_arrow_function.js +31 -0
  40. package/dist/lib/famix/src/model/famix/parametric_class.js +44 -0
  41. package/dist/lib/famix/src/model/famix/parametric_function.js +31 -0
  42. package/dist/lib/famix/src/model/famix/parametric_interface.js +44 -0
  43. package/dist/lib/famix/src/model/famix/parametric_method.js +31 -0
  44. package/dist/lib/famix/src/model/famix/primitive_type.js +1 -0
  45. package/dist/lib/famix/src/model/famix/property.js +91 -9
  46. package/dist/lib/famix/src/model/famix/reference.js +3 -2
  47. package/dist/lib/famix/src/model/famix/scoping_entity.js +12 -10
  48. package/dist/lib/famix/src/model/famix/script_entity.js +1 -2
  49. package/dist/lib/famix/src/model/famix/source_anchor.js +1 -0
  50. package/dist/lib/famix/src/model/famix/source_language.js +1 -1
  51. package/dist/lib/famix/src/model/famix/sourced_entity.js +2 -1
  52. package/dist/lib/famix/src/model/famix/structural_entity.js +1 -0
  53. package/dist/lib/famix/src/model/famix/text_anchor.js +1 -0
  54. package/dist/lib/famix/src/model/famix/type.js +6 -4
  55. package/dist/lib/famix/src/model/famix/variable.js +1 -0
  56. package/dist/lib/ts-complex/cyclomatic-service.js +2 -2
  57. package/dist/ts2famix-cli-wrapper.js +16 -0
  58. package/dist/ts2famix-cli.js +8 -1
  59. package/dist/ts2famix-tsconfig.js +1 -0
  60. package/doc-uml/famix-typescript-model.puml +559 -0
  61. package/doc-uml/famix-typescript-model.svg +1 -0
  62. package/jest.config.json +2 -1
  63. package/package.json +10 -10
  64. package/src/analyze.ts +25 -22
  65. package/src/analyze_functions/process_functions.ts +272 -96
  66. package/src/famix_functions/EntityDictionary.ts +731 -182
  67. package/src/famix_functions/helpers_creation.ts +28 -2
  68. package/src/fqn.ts +132 -10
  69. package/src/lib/famix/src/famix_repository.ts +9 -9
  70. package/src/lib/famix/src/model/famix/access.ts +2 -2
  71. package/src/lib/famix/src/model/famix/alias.ts +1 -1
  72. package/src/lib/famix/src/model/famix/arrowFunction.ts +15 -0
  73. package/src/lib/famix/src/model/famix/behavioral_entity.ts +12 -19
  74. package/src/lib/famix/src/model/famix/comment.ts +1 -1
  75. package/src/lib/famix/src/model/famix/concretisation.ts +42 -0
  76. package/src/lib/famix/src/model/famix/container_entity.ts +6 -6
  77. package/src/lib/famix/src/model/famix/decorator.ts +1 -1
  78. package/src/lib/famix/src/model/famix/enum.ts +1 -1
  79. package/src/lib/famix/src/model/famix/enum_value.ts +1 -1
  80. package/src/lib/famix/src/model/famix/import_clause.ts +4 -3
  81. package/src/lib/famix/src/model/famix/index.ts +8 -5
  82. package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +2 -2
  83. package/src/lib/famix/src/model/famix/inheritance.ts +3 -4
  84. package/src/lib/famix/src/model/famix/interface.ts +1 -1
  85. package/src/lib/famix/src/model/famix/invocation.ts +2 -2
  86. package/src/lib/famix/src/model/famix/method.ts +1 -1
  87. package/src/lib/famix/src/model/famix/module.ts +67 -1
  88. package/src/lib/famix/src/model/famix/named_entity.ts +3 -3
  89. package/src/lib/famix/src/model/famix/parameter.ts +1 -1
  90. package/src/lib/famix/src/model/famix/parameterConcretisation.ts +54 -0
  91. package/src/lib/famix/src/model/famix/parameter_type.ts +33 -6
  92. package/src/lib/famix/src/model/famix/parametric_arrow_function.ts +32 -0
  93. package/src/lib/famix/src/model/famix/parametric_class.ts +49 -0
  94. package/src/lib/famix/src/model/famix/parametric_function.ts +32 -0
  95. package/src/lib/famix/src/model/famix/parametric_interface.ts +49 -0
  96. package/src/lib/famix/src/model/famix/parametric_method.ts +32 -0
  97. package/src/lib/famix/src/model/famix/property.ts +109 -11
  98. package/src/lib/famix/src/model/famix/reference.ts +2 -2
  99. package/src/lib/famix/src/model/famix/scoping_entity.ts +12 -11
  100. package/src/lib/famix/src/model/famix/script_entity.ts +0 -2
  101. package/src/lib/famix/src/model/famix/source_language.ts +0 -1
  102. package/src/lib/famix/src/model/famix/sourced_entity.ts +1 -1
  103. package/src/lib/famix/src/model/famix/type.ts +5 -4
  104. package/src/ts2famix-cli-wrapper.ts +17 -0
  105. package/src/ts2famix-cli.ts +7 -1
  106. package/tsconfig.json +5 -5
  107. package/dist/lib/famix/src/model/famix/association.js +0 -36
  108. package/dist/lib/famix/src/model/famix/namespace.js +0 -24
  109. package/dist/lib/famix/src/model/famix/parameterizable_class.js +0 -30
  110. package/dist/lib/famix/src/model/famix/parameterizable_interface.js +0 -30
  111. package/dist/lib/famix/src/model/famix/parameterized_type.js +0 -36
  112. package/doc-uml/metamodel-full.svg +0 -1
  113. package/doc-uml/metamodel.svg +0 -1
  114. package/plantuml.jar +0 -0
  115. package/src/lib/famix/src/model/famix/association.ts +0 -44
  116. package/src/lib/famix/src/model/famix/namespace.ts +0 -28
  117. package/src/lib/famix/src/model/famix/parameterizable_class.ts +0 -31
  118. package/src/lib/famix/src/model/famix/parameterizable_interface.ts +0 -31
  119. package/src/lib/famix/src/model/famix/parameterized_type.ts +0 -40
@@ -1,15 +1,20 @@
1
- import { ClassDeclaration, MethodDeclaration, VariableStatement, FunctionDeclaration, VariableDeclaration, InterfaceDeclaration, ParameterDeclaration, ConstructorDeclaration, MethodSignature, SourceFile, ModuleDeclaration, PropertyDeclaration, PropertySignature, Decorator, GetAccessorDeclaration, SetAccessorDeclaration, ExportedDeclarations, CommentRange, EnumDeclaration, EnumMember, TypeParameterDeclaration, TypeAliasDeclaration, SyntaxKind, FunctionExpression, Block, Identifier, ExpressionWithTypeArguments, ImportDeclaration, Node } from "ts-morph";
1
+ import { ClassDeclaration, MethodDeclaration, VariableStatement, FunctionDeclaration, VariableDeclaration, InterfaceDeclaration, ParameterDeclaration, ConstructorDeclaration, MethodSignature, SourceFile, ModuleDeclaration, PropertyDeclaration, PropertySignature, Decorator, GetAccessorDeclaration, SetAccessorDeclaration, ExportedDeclarations, CommentRange, EnumDeclaration, EnumMember, TypeParameterDeclaration, TypeAliasDeclaration, SyntaxKind, FunctionExpression, Block, Identifier, ExpressionWithTypeArguments, ImportDeclaration, Node, ArrowFunction, Scope, ClassExpression } from "ts-morph";
2
2
  import * as Famix from "../lib/famix/src/model/famix";
3
3
  import { calculate } from "../lib/ts-complex/cyclomatic-service";
4
4
  import * as fs from 'fs';
5
5
  import { logger , entityDictionary } from "../analyze";
6
+ import { getFQN } from "../fqn";
6
7
 
7
- export const methodsAndFunctionsWithId = new Map<number, MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression>(); // Maps the Famix method, constructor, getter, setter and function ids to their ts-morph method, constructor, getter, setter or function object
8
- export const accessMap = new Map<number, ParameterDeclaration | VariableDeclaration | PropertyDeclaration | EnumMember>(); // Maps the Famix parameter, variable, property and enum value ids to their ts-morph parameter, variable, property or enum member object
8
+ export type AccessibleTSMorphElement = ParameterDeclaration | VariableDeclaration | PropertyDeclaration | EnumMember;
9
+ export type FamixID = number;
10
+
11
+ export const methodsAndFunctionsWithId = new Map<number, MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ArrowFunction>(); // Maps the Famix method, constructor, getter, setter and function ids to their ts-morph method, constructor, getter, setter or function object
12
+
13
+ export const accessMap = new Map<FamixID, AccessibleTSMorphElement>(); // Maps the Famix parameter, variable, property and enum value ids to their ts-morph parameter, variable, property or enum member object
9
14
  export const classes = new Array<ClassDeclaration>(); // Array of all the classes of the source files
10
15
  export const interfaces = new Array<InterfaceDeclaration>(); // Array of all the interfaces of the source files
11
16
  export const modules = new Array<SourceFile>(); // Array of all the source files which are modules
12
- export const exportedMap = new Array<ReadonlyMap<string, ExportedDeclarations[]>>(); // Array of all the exports
17
+ export const listOfExportMaps = new Array<ReadonlyMap<string, ExportedDeclarations[]>>(); // Array of all the export maps
13
18
  export let currentCC: unknown; // Stores the cyclomatic complexity metrics for the current source file
14
19
 
15
20
  /**
@@ -17,7 +22,7 @@ export let currentCC: unknown; // Stores the cyclomatic complexity metrics for t
17
22
  * @param sourceFile A source file
18
23
  * @returns A boolean indicating if the file is a module
19
24
  */
20
- function ismodule(sourceFile: SourceFile): boolean {
25
+ function isSourceFileAModule(sourceFile: SourceFile): boolean {
21
26
  return sourceFile.getImportDeclarations().length > 0 || sourceFile.getExportedDeclarations().size > 0;
22
27
  }
23
28
 
@@ -95,13 +100,15 @@ export function processFiles(sourceFiles: Array<SourceFile>): void {
95
100
  * @param f A source file
96
101
  */
97
102
  function processFile(f: SourceFile): void {
98
- const isModule = ismodule(f);
103
+ const isModule = isSourceFileAModule(f);
99
104
 
100
105
  if (isModule) {
101
106
  modules.push(f);
102
- exportedMap.push(f.getExportedDeclarations());
103
107
  }
104
108
 
109
+ const exportMap = f.getExportedDeclarations();
110
+ if (exportMap) listOfExportMaps.push(exportMap);
111
+
105
112
  const fmxFile = entityDictionary.createOrGetFamixFile(f, isModule);
106
113
 
107
114
  logger.debug(`processFile: file: ${f.getBaseName()}, fqn = ${fmxFile.getFullyQualifiedName()}`);
@@ -120,44 +127,59 @@ function processFile(f: SourceFile): void {
120
127
 
121
128
  processFunctions(f, fmxFile);
122
129
 
123
- processNamespaces(f, fmxFile);
130
+ processModules(f, fmxFile);
131
+ }
132
+
133
+ export function isAmbient(node: ModuleDeclaration): boolean {
134
+ // An ambient module has the DeclareKeyword modifier.
135
+ return (node.getModifiers()?.some(modifier => modifier.getKind() === SyntaxKind.DeclareKeyword)) ?? false;
136
+ }
137
+
138
+ export function isNamespace(node: ModuleDeclaration): boolean {
139
+ // Check if the module declaration has a namespace keyword.
140
+ // This approach uses the getChildren() method to inspect the syntax directly.
141
+ return node.getChildrenOfKind(SyntaxKind.NamespaceKeyword).length > 0;
124
142
  }
125
143
 
126
144
  /**
127
- * Builds a Famix model for a namespace
145
+ * Builds a Famix model for a module (also namespace)
128
146
  * @param m A namespace
129
- * @returns A Famix.Namespace representing the namespace
147
+ * @returns A Famix.Module representing the module
130
148
  */
131
- function processNamespace(m: ModuleDeclaration): Famix.Namespace {
132
- const fmxNamespace = entityDictionary.createOrGetFamixNamespace(m);
149
+ function processModule(m: ModuleDeclaration): Famix.Module {
150
+ const fmxModule = entityDictionary.createOrGetFamixModule(m);
133
151
 
134
- logger.debug(`processNamespace: namespace: ${m.getName()}, (${m.getType().getText()}), ${fmxNamespace.getFullyQualifiedName()}`);
152
+ logger.debug(`module: ${m.getName()}, (${m.getType().getText()}), ${fmxModule.getFullyQualifiedName()}`);
135
153
 
136
- processComments(m, fmxNamespace);
154
+ processComments(m, fmxModule);
137
155
 
138
- processAliases(m, fmxNamespace);
156
+ processAliases(m, fmxModule);
139
157
 
140
- processClasses(m, fmxNamespace);
158
+ processClasses(m, fmxModule);
141
159
 
142
- processInterfaces(m, fmxNamespace);
160
+ processInterfaces(m, fmxModule);
143
161
 
144
- processVariables(m, fmxNamespace);
162
+ processVariables(m, fmxModule);
145
163
 
146
- processEnums(m, fmxNamespace);
164
+ processEnums(m, fmxModule);
147
165
 
148
- processFunctions(m, fmxNamespace);
166
+ processFunctions(m, fmxModule);
149
167
 
150
- processNamespaces(m, fmxNamespace);
168
+ processModules(m, fmxModule);
151
169
 
152
- return fmxNamespace;
170
+ return fmxModule;
153
171
  }
154
172
 
173
+ type ContainerTypes = SourceFile | ModuleDeclaration | FunctionDeclaration | FunctionExpression | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ArrowFunction;
174
+
175
+ type ScopedTypes = Famix.ScriptEntity | Famix.Module | Famix.Function | Famix.Method | Famix.Accessor;
176
+
155
177
  /**
156
178
  * Builds a Famix model for the aliases of a container
157
179
  * @param m A container (a source file, a namespace, a function or a method)
158
180
  * @param fmxScope The Famix model of the container
159
181
  */
160
- function processAliases(m: SourceFile | ModuleDeclaration | FunctionDeclaration | FunctionExpression | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace | Famix.Function | Famix.Method | Famix.Accessor): void {
182
+ function processAliases(m: ContainerTypes, fmxScope: ScopedTypes): void {
161
183
  logger.debug(`processAliases: ---------- Finding Aliases:`);
162
184
  m.getTypeAliases().forEach(a => {
163
185
  const fmxAlias = processAlias(a);
@@ -170,20 +192,47 @@ function processAliases(m: SourceFile | ModuleDeclaration | FunctionDeclaration
170
192
  * @param m A container (a source file or a namespace)
171
193
  * @param fmxScope The Famix model of the container
172
194
  */
173
- function processClasses(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace): void {
195
+ function processClasses(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module ): void {
174
196
  logger.debug(`processClasses: ---------- Finding Classes:`);
175
- m.getClasses().forEach(c => {
197
+ const classesInArrowFunctions = getClassesDeclaredInArrowFunctions(m);
198
+ const classes = m.getClasses().concat(classesInArrowFunctions);
199
+ classes.forEach(c => {
176
200
  const fmxClass = processClass(c);
177
201
  fmxScope.addType(fmxClass);
178
202
  });
179
203
  }
180
204
 
205
+ function getArrowFunctionClasses(f: ArrowFunction): ClassDeclaration[] {
206
+ const classes: ClassDeclaration[] = [];
207
+
208
+ function findClasses(node: any) {
209
+ if (node.getKind() === SyntaxKind.ClassDeclaration) {
210
+ classes.push(node as ClassDeclaration);
211
+ }
212
+ node.getChildren().forEach(findClasses);
213
+ }
214
+
215
+ findClasses(f);
216
+ return classes;
217
+ }
218
+
219
+ /**
220
+ * ts-morph doesn't find classes in arrow functions, so we need to find them manually
221
+ * @param s A source file
222
+ * @returns the ClassDeclaration objects found in arrow functions of the source file
223
+ */
224
+ function getClassesDeclaredInArrowFunctions(s: SourceFile | ModuleDeclaration): ClassDeclaration[] {
225
+ const arrowFunctions = s.getDescendantsOfKind(SyntaxKind.ArrowFunction);
226
+ const classesInArrowFunctions = arrowFunctions.map(f => getArrowFunctionClasses(f)).flat();
227
+ return classesInArrowFunctions;
228
+ }
229
+
181
230
  /**
182
231
  * Builds a Famix model for the interfaces of a container
183
232
  * @param m A container (a source file or a namespace)
184
233
  * @param fmxScope The Famix model of the container
185
234
  */
186
- function processInterfaces(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace): void {
235
+ function processInterfaces(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module ): void {
187
236
  logger.debug(`processInterfaces: ---------- Finding Interfaces:`);
188
237
  m.getInterfaces().forEach(i => {
189
238
  const fmxInterface = processInterface(i);
@@ -196,7 +245,7 @@ function processInterfaces(m: SourceFile | ModuleDeclaration, fmxScope: Famix.Sc
196
245
  * @param m A container (a source file, a namespace, a function or a method)
197
246
  * @param fmxScope The Famix model of the container
198
247
  */
199
- function processVariables(m: SourceFile | ModuleDeclaration | FunctionDeclaration | FunctionExpression | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace | Famix.Function | Famix.Method | Famix.Accessor): void {
248
+ function processVariables(m: ContainerTypes, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Function | Famix.Method | Famix.Accessor): void {
200
249
  logger.debug(`processVariables: ---------- Finding Variables:`);
201
250
  m.getVariableStatements().forEach(v => {
202
251
  const fmxVariables = processVariableStatement(v);
@@ -211,7 +260,7 @@ function processVariables(m: SourceFile | ModuleDeclaration | FunctionDeclaratio
211
260
  * @param m A container (a source file, a namespace, a function or a method)
212
261
  * @param fmxScope The Famix model of the container
213
262
  */
214
- function processEnums(m: SourceFile | ModuleDeclaration | FunctionDeclaration | FunctionExpression | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace | Famix.Function | Famix.Method | Famix.Accessor): void {
263
+ function processEnums(m: ContainerTypes, fmxScope: ScopedTypes): void {
215
264
  logger.debug(`processEnums: ---------- Finding Enums:`);
216
265
  m.getEnums().forEach(e => {
217
266
  const fmxEnum = processEnum(e);
@@ -224,24 +273,32 @@ function processEnums(m: SourceFile | ModuleDeclaration | FunctionDeclaration |
224
273
  * @param m A container (a source file, a namespace, a function or a method)
225
274
  * @param fmxScope The Famix model of the container
226
275
  */
227
- function processFunctions(m: SourceFile | ModuleDeclaration | FunctionDeclaration | FunctionExpression | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace | Famix.Function | Famix.Method | Famix.Accessor): void {
276
+ function processFunctions(m: ContainerTypes, fmxScope: ScopedTypes): void {
228
277
  logger.debug(`Finding Functions:`);
229
278
  m.getFunctions().forEach(f => {
230
279
  const fmxFunction = processFunction(f);
231
280
  fmxScope.addFunction(fmxFunction);
232
281
  });
282
+
283
+ //find arrow functions
284
+ logger.debug(`Finding Functions:`);
285
+ const arrowFunctions = m.getDescendantsOfKind(SyntaxKind.ArrowFunction);
286
+ arrowFunctions.forEach(af => {
287
+ const fmxFunction = processFunction(af);
288
+ fmxScope.addFunction(fmxFunction);
289
+ })
233
290
  }
234
291
 
235
292
  /**
236
- * Builds a Famix model for the namespaces of a container
293
+ * Builds a Famix model for the modules of a container.
237
294
  * @param m A container (a source file or a namespace)
238
295
  * @param fmxScope The Famix model of the container
239
296
  */
240
- function processNamespaces(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module | Famix.Namespace): void {
241
- logger.debug(`Finding Namespaces:`);
297
+ function processModules(m: SourceFile | ModuleDeclaration, fmxScope: Famix.ScriptEntity | Famix.Module ): void {
298
+ logger.debug(`Finding Modules:`);
242
299
  m.getModules().forEach(md => {
243
- const fmxNsp = processNamespace(md);
244
- fmxScope.addNamespace(fmxNsp);
300
+ const fmxModule = processModule(md);
301
+ fmxScope.addModule(fmxModule);
245
302
  });
246
303
  }
247
304
 
@@ -263,9 +320,9 @@ function processAlias(a: TypeAliasDeclaration): Famix.Alias {
263
320
  /**
264
321
  * Builds a Famix model for a class
265
322
  * @param c A class
266
- * @returns A Famix.Class or a Famix.ParameterizableClass representing the class
323
+ * @returns A Famix.Class or a Famix.ParametricClass representing the class
267
324
  */
268
- function processClass(c: ClassDeclaration): Famix.Class | Famix.ParameterizableClass {
325
+ function processClass(c: ClassDeclaration): Famix.Class | Famix.ParametricClass {
269
326
  classes.push(c);
270
327
 
271
328
  const fmxClass = entityDictionary.createOrGetFamixClass(c);
@@ -299,9 +356,9 @@ function processClass(c: ClassDeclaration): Famix.Class | Famix.ParameterizableC
299
356
  /**
300
357
  * Builds a Famix model for an interface
301
358
  * @param i An interface
302
- * @returns A Famix.Interface or a Famix.ParameterizableInterface representing the interface
359
+ * @returns A Famix.Interface or a Famix.ParametricInterface representing the interface
303
360
  */
304
- function processInterface(i: InterfaceDeclaration): Famix.Interface | Famix.ParameterizableInterface {
361
+ function processInterface(i: InterfaceDeclaration): Famix.Interface | Famix.ParametricInterface {
305
362
  interfaces.push(i);
306
363
 
307
364
  const fmxInterface = entityDictionary.createOrGetFamixInterface(i);
@@ -320,9 +377,9 @@ function processInterface(i: InterfaceDeclaration): Famix.Interface | Famix.Para
320
377
  * @param c A structured type (a class or an interface)
321
378
  * @param fmxScope The Famix model of the structured type
322
379
  */
323
- function processStructuredType(c: ClassDeclaration | InterfaceDeclaration, fmxScope: Famix.Class | Famix.ParameterizableClass | Famix.Interface | Famix.ParameterizableInterface): void {
380
+ function processStructuredType(c: ClassDeclaration | InterfaceDeclaration, fmxScope: Famix.Class | Famix.ParametricClass | Famix.Interface | Famix.ParametricInterface): void {
324
381
  logger.debug(`Finding Properties and Methods:`);
325
- if (fmxScope instanceof Famix.ParameterizableClass || fmxScope instanceof Famix.ParameterizableInterface) {
382
+ if (fmxScope instanceof Famix.ParametricClass || fmxScope instanceof Famix.ParametricInterface) {
326
383
  processTypeParameters(c, fmxScope);
327
384
  }
328
385
 
@@ -350,11 +407,12 @@ function processProperty(p: PropertyDeclaration | PropertySignature): Famix.Prop
350
407
  const ancestor = p.getFirstAncestorOrThrow();
351
408
  logger.debug(` ---> Its first ancestor is a ${ancestor.getKindName()}`);
352
409
 
410
+ // decorators
353
411
  if (!(p instanceof PropertySignature)) {
354
412
  processDecorators(p, fmxProperty);
355
413
  // only add access if the p's first ancestor is not a PropertyDeclaration
356
414
  if (ancestor.getKindName() !== "PropertyDeclaration") {
357
- logger.debug(`adding access: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxProperty.getName()}`);
415
+ logger.debug(`adding access to map: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxProperty.getName()} id: ${fmxProperty.id}`);
358
416
  accessMap.set(fmxProperty.id, p);
359
417
  }
360
418
  }
@@ -370,7 +428,7 @@ function processProperty(p: PropertyDeclaration | PropertySignature): Famix.Prop
370
428
  * @returns A Famix.Method or a Famix.Accessor representing the method or the accessor
371
429
  */
372
430
  function processMethod(m: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration): Famix.Method | Famix.Accessor {
373
- const fmxMethod = entityDictionary.createFamixMethod(m, currentCC);
431
+ const fmxMethod = entityDictionary.createOrGetFamixMethod(m, currentCC);
374
432
 
375
433
  logger.debug(`Method: ${!(m instanceof ConstructorDeclaration) ? m.getName() : "constructor"}, (${m.getType().getText()}), parent: ${(m.getParent() as ClassDeclaration | InterfaceDeclaration).getName()}, fqn = ${fmxMethod.getFullyQualifiedName()}`);
376
434
 
@@ -406,10 +464,16 @@ function processMethod(m: MethodDeclaration | ConstructorDeclaration | MethodSig
406
464
  * @param f A function
407
465
  * @returns A Famix.Function representing the function
408
466
  */
409
- function processFunction(f: FunctionDeclaration | FunctionExpression): Famix.Function {
410
- const fmxFunction = entityDictionary.createFamixFunction(f, currentCC);
467
+ function processFunction(f: FunctionDeclaration | FunctionExpression | ArrowFunction): Famix.Function {
411
468
 
412
- logger.debug(`Function: ${(f.getName()) ? f.getName() : "anonymous"}, (${f.getType().getText()}), fqn = ${fmxFunction.getFullyQualifiedName()}`);
469
+ logger.debug(`Function: ${(f instanceof ArrowFunction ? "anonymous" : f.getName() ? f.getName() : "anonymous")}, (${f.getType().getText()}), fqn = ${getFQN(f)}`);
470
+
471
+ let fmxFunction;
472
+ if( f instanceof ArrowFunction) {
473
+ fmxFunction = entityDictionary.createFamixArrowFunction(f, currentCC);
474
+ } else {
475
+ fmxFunction = entityDictionary.createOrGetFamixFunction(f, currentCC);
476
+ }
413
477
 
414
478
  processComments(f, fmxFunction);
415
479
 
@@ -453,14 +517,84 @@ function processFunctionExpressions(f: FunctionDeclaration | MethodDeclaration |
453
517
  * @param m A method or a function
454
518
  * @param fmxScope The Famix model of the method or the function
455
519
  */
456
- function processParameters(m: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression, fmxScope: Famix.Method | Famix.Accessor | Famix.Function): void {
520
+ function processParameters(m: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ArrowFunction, fmxScope: Famix.Method | Famix.Accessor | Famix.Function): void {
457
521
  logger.debug(`Finding Parameters:`);
458
522
  m.getParameters().forEach(param => {
459
523
  const fmxParam = processParameter(param);
460
524
  fmxScope.addParameter(fmxParam);
525
+ // Additional handling for Parameter Properties in constructors
526
+ if (m instanceof ConstructorDeclaration) {
527
+ // Check if the parameter has any visibility modifier
528
+ if (param.hasModifier(SyntaxKind.PrivateKeyword) || param.hasModifier(SyntaxKind.PublicKeyword) || param.hasModifier(SyntaxKind.ProtectedKeyword) || param.hasModifier(SyntaxKind.ReadonlyKeyword)) {
529
+ const classOfConstructor = m.getParent();
530
+ logger.info(`Parameter Property ${param.getName()} in constructor of ${classOfConstructor.getName()}.`);
531
+ // Treat the parameter as a property and add it to the class
532
+ const fmxProperty = processParameterAsProperty(param, classOfConstructor);
533
+ fmxProperty.readOnly = param.hasModifier(SyntaxKind.ReadonlyKeyword);
534
+ }
535
+ }
536
+
461
537
  });
462
538
  }
463
539
 
540
+ // This function should create a Famix.Property model from a ParameterDeclaration
541
+ // You'll need to implement it according to your Famix model structure
542
+ function processParameterAsProperty(param: ParameterDeclaration, c: ClassDeclaration | ClassExpression): Famix.Property {
543
+ // Convert the parameter into a Property
544
+ const propertyRepresentation = convertParameterToPropertyRepresentation(param);
545
+
546
+ // Add the property to the class so we can have a PropertyDeclaration object
547
+ c.addProperty(propertyRepresentation);
548
+
549
+ const p = c.getProperty(propertyRepresentation.name);
550
+ const fmxProperty = entityDictionary.createFamixProperty(p);
551
+ if (c instanceof ClassDeclaration) {
552
+ const fmxClass = entityDictionary.createOrGetFamixClass(c);
553
+ fmxClass.addProperty(fmxProperty);
554
+ } else {
555
+ throw new Error("Unexpected type ClassExpression.");
556
+ }
557
+
558
+ processComments(p, fmxProperty);
559
+
560
+ // remove the property from the class
561
+ p.remove();
562
+
563
+ return fmxProperty;
564
+
565
+ }
566
+
567
+ function convertParameterToPropertyRepresentation(param: ParameterDeclaration) {
568
+ // Extract name
569
+ const paramName = param.getName();
570
+
571
+ // Extract type
572
+ const paramType = param.getType().getText(param);
573
+
574
+ // Determine visibility
575
+ let scope: Scope;
576
+ if (param.hasModifier(SyntaxKind.PrivateKeyword)) {
577
+ scope = Scope.Private;
578
+ } else if (param.hasModifier(SyntaxKind.ProtectedKeyword)) {
579
+ scope = Scope.Protected;
580
+ } else if (param.hasModifier(SyntaxKind.PublicKeyword)) {
581
+ scope = Scope.Public;
582
+ }
583
+
584
+ // Determine if readonly
585
+ const isReadonly = param.hasModifier(SyntaxKind.ReadonlyKeyword);
586
+
587
+ // Create a representation of the property
588
+ const propertyRepresentation = {
589
+ name: paramName,
590
+ type: paramType,
591
+ scope: scope,
592
+ isReadonly: isReadonly,
593
+ };
594
+
595
+ return propertyRepresentation;
596
+ }
597
+
464
598
  /**
465
599
  * Builds a Famix model for a parameter
466
600
  * @param p A parameter
@@ -490,11 +624,11 @@ function processParameter(p: ParameterDeclaration): Famix.Parameter {
490
624
  * @param e A class, an interface, a method or a function
491
625
  * @param fmxScope The Famix model of the class, the interface, the method or the function
492
626
  */
493
- function processTypeParameters(e: ClassDeclaration | InterfaceDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression, fmxScope: Famix.ParameterizableClass | Famix.ParameterizableInterface | Famix.Method | Famix.Accessor | Famix.Function): void {
627
+ function processTypeParameters(e: ClassDeclaration | InterfaceDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression |ArrowFunction, fmxScope: Famix.ParametricClass | Famix.ParametricInterface | Famix.Method | Famix.Accessor | Famix.Function | Famix.ArrowFunction): void {
494
628
  logger.debug(`Finding Type Parameters:`);
495
629
  e.getTypeParameters().forEach(tp => {
496
630
  const fmxParam = processTypeParameter(tp);
497
- fmxScope.addParameterType(fmxParam);
631
+ fmxScope.addGenericParameter(fmxParam);
498
632
  });
499
633
  }
500
634
 
@@ -593,7 +727,7 @@ function processEnumValue(v: EnumMember): Famix.EnumValue {
593
727
  * @param e A class, a method, a parameter or a property
594
728
  * @param fmxScope The Famix model of the class, the method, the parameter or the property
595
729
  */
596
- function processDecorators(e: ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ParameterDeclaration | PropertyDeclaration, fmxScope: Famix.Class | Famix.ParameterizableClass | Famix.Method | Famix.Accessor | Famix.Parameter | Famix.Property): void {
730
+ function processDecorators(e: ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ParameterDeclaration | PropertyDeclaration, fmxScope: Famix.Class | Famix.ParametricClass | Famix.Method | Famix.Accessor | Famix.Parameter | Famix.Property): void {
597
731
  logger.debug(`Finding Decorators:`);
598
732
  e.getDecorators().forEach(dec => {
599
733
  const fmxDec = processDecorator(dec, e);
@@ -622,7 +756,7 @@ function processDecorator(d: Decorator, e: ClassDeclaration | MethodDeclaration
622
756
  * @param e A ts-morph element
623
757
  * @param fmxScope The Famix model of the named entity
624
758
  */
625
- function processComments(e: SourceFile | ModuleDeclaration | ClassDeclaration | InterfaceDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | PropertyDeclaration | PropertySignature | Decorator | EnumDeclaration | EnumMember | TypeParameterDeclaration | VariableStatement | TypeAliasDeclaration, fmxScope: Famix.NamedEntity): void {
759
+ function processComments(e: SourceFile | ModuleDeclaration | ClassDeclaration | InterfaceDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | PropertyDeclaration | PropertySignature | Decorator | EnumDeclaration | EnumMember | TypeParameterDeclaration | VariableStatement | TypeAliasDeclaration | ArrowFunction, fmxScope: Famix.NamedEntity): void {
626
760
  logger.debug(`Process comments:`);
627
761
  e.getLeadingCommentRanges().forEach(c => {
628
762
  const fmxComment = processComment(c, fmxScope);
@@ -654,16 +788,16 @@ function processComment(c: CommentRange, fmxScope: Famix.NamedEntity): Famix.Com
654
788
  * Builds a Famix model for the accesses on the parameters, variables, properties and enum members of the source files
655
789
  * @param accessMap A map of parameters, variables, properties and enum members with their id
656
790
  */
657
- export function processAccesses(accessMap: Map<number, ParameterDeclaration | VariableDeclaration | PropertyDeclaration | EnumMember>): void {
658
- logger.debug(`processAccesses: Creating accesses:`);
791
+ export function processAccesses(accessMap: Map<FamixID, AccessibleTSMorphElement>): void {
792
+ logger.debug(`Creating accesses:`);
659
793
  accessMap.forEach((v, id) => {
660
- logger.debug(`processAccesses: Accesses to ${v.getName()}`);
661
- try {
794
+ logger.debug(`Accesses to ${v.getName()}`);
795
+ // try {
662
796
  const temp_nodes = v.findReferencesAsNodes() as Array<Identifier>;
663
797
  temp_nodes.forEach(node => processNodeForAccesses(node, id));
664
- } catch (error) {
665
- logger.error(`> WARNING: got exception ${error}. Continuing...`);
666
- }
798
+ // } catch (error) {
799
+ // logger.error(`> WARNING: got exception "${error}".\nContinuing...`);
800
+ // }
667
801
  });
668
802
  }
669
803
 
@@ -673,7 +807,7 @@ export function processAccesses(accessMap: Map<number, ParameterDeclaration | Va
673
807
  * @param id An id of a parameter, a variable, a property or an enum member
674
808
  */
675
809
  function processNodeForAccesses(n: Identifier, id: number): void {
676
- try {
810
+ // try {
677
811
  // sometimes node's first ancestor is a PropertyDeclaration, which is not an access
678
812
  // see https://github.com/fuhrmanator/FamixTypeScriptImporter/issues/9
679
813
  // check for a node whose first ancestor is a property declaration and bail?
@@ -684,11 +818,15 @@ function processNodeForAccesses(n: Identifier, id: number): void {
684
818
  }
685
819
  entityDictionary.createFamixAccess(n, id);
686
820
  logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})`);
687
- } catch (error) {
688
- logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
689
- }
821
+ // } catch (error) {
822
+ // logger.error(`> Got exception "${error}".\nScopeDeclaration invalid for "${n.getSymbol().getFullyQualifiedName()}".\nContinuing...`);
823
+ // }
690
824
  }
691
825
 
826
+
827
+ // exports has name -> Declaration -- the declaration can be used to find the FamixElement
828
+
829
+ // handle `import path = require("path")` for example
692
830
  export function processImportClausesForImportEqualsDeclarations(sourceFiles: Array<SourceFile>, exports: Array<ReadonlyMap<string, ExportedDeclarations[]>>): void {
693
831
  logger.info(`Creating import clauses from ImportEqualsDeclarations in source files:`);
694
832
  sourceFiles.forEach(sourceFile => {
@@ -697,44 +835,42 @@ export function processImportClausesForImportEqualsDeclarations(sourceFiles: Arr
697
835
  // You've found an ImportEqualsDeclaration
698
836
  logger.info("Declaration Name:", node.getName());
699
837
  logger.info("Module Reference Text:", node.getModuleReference().getText());
838
+ // what's the name of the imported entity?
839
+ // const importedEntity = node.getName();
700
840
  // create a famix import clause
701
841
  const namedImport = node.getNameNode();
702
- entityDictionary.createFamixImportClause({importDeclaration: node,
703
- importer: sourceFile,
842
+ entityDictionary.oldCreateFamixImportClause({importDeclaration: node,
843
+ importerSourceFile: sourceFile,
704
844
  moduleSpecifierFilePath: node.getModuleReference().getText(),
705
845
  importElement: namedImport,
706
846
  isInExports: exports.find(e => e.has(namedImport.getText())) !== undefined,
707
847
  isDefaultExport: false});
848
+ // entityDictionary.createFamixImportClause(importedEntity, importingEntity);
708
849
  }
709
850
  });
710
851
  }
711
852
  );
712
-
713
853
  }
714
854
 
715
855
  /**
716
- * Builds a Famix model for the import clauses of the source files which are modules
717
- * @param modules An array of modules
718
- * @param exports An array of maps of exported declarations
719
- */
856
+ * Builds a Famix model for the import clauses of the source files which are modules
857
+ * @param modules An array of modules
858
+ * @param exports An array of maps of exported declarations
859
+ */
720
860
  export function processImportClausesForModules(modules: Array<SourceFile>, exports: Array<ReadonlyMap<string, ExportedDeclarations[]>>): void {
721
861
  logger.info(`Creating import clauses from ${modules.length} modules:`);
722
862
  modules.forEach(module => {
863
+ const modulePath = module.getFilePath() + module.getBaseName();
723
864
  module.getImportDeclarations().forEach(impDecl => {
724
- logger.debug(`Importing ${impDecl.getModuleSpecifierValue()}`);
865
+ logger.info(`Importing ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
725
866
  const path = getModulePath(impDecl);
726
867
 
727
868
  impDecl.getNamedImports().forEach(namedImport => {
728
- logger.debug(`Importing (named) ${namedImport.getName()} from ${impDecl.getModuleSpecifierValue()}`);
869
+ logger.info(`Importing (named) ${namedImport.getName()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
729
870
  const importedEntityName = namedImport.getName();
730
- let importFoundInExports = false;
731
- exports.forEach(e => {
732
- if (e.has(importedEntityName)) {
733
- importFoundInExports = true;
734
- }
735
- });
736
- entityDictionary.createFamixImportClause({importDeclaration: impDecl,
737
- importer: module,
871
+ let importFoundInExports = isInExports(exports, importedEntityName);
872
+ entityDictionary.oldCreateFamixImportClause({importDeclaration: impDecl,
873
+ importerSourceFile: module,
738
874
  moduleSpecifierFilePath: path,
739
875
  importElement: namedImport,
740
876
  isInExports: importFoundInExports,
@@ -743,10 +879,10 @@ export function processImportClausesForModules(modules: Array<SourceFile>, expor
743
879
 
744
880
  const defaultImport = impDecl.getDefaultImport();
745
881
  if (defaultImport !== undefined) {
746
- logger.debug(`Importing (default) ${defaultImport.getText()} from ${impDecl.getModuleSpecifierValue()}`);
882
+ logger.info(`Importing (default) ${defaultImport.getText()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
747
883
  // call with module, impDecl.getModuleSpecifierValue(), path, defaultImport, false, true
748
- entityDictionary.createFamixImportClause({importDeclaration: impDecl,
749
- importer: module,
884
+ entityDictionary.oldCreateFamixImportClause({importDeclaration: impDecl,
885
+ importerSourceFile: module,
750
886
  moduleSpecifierFilePath: path,
751
887
  importElement: defaultImport,
752
888
  isInExports: false,
@@ -755,9 +891,9 @@ export function processImportClausesForModules(modules: Array<SourceFile>, expor
755
891
 
756
892
  const namespaceImport = impDecl.getNamespaceImport();
757
893
  if (namespaceImport !== undefined) {
758
- logger.debug(`Importing (namespace) ${namespaceImport.getText()} from ${impDecl.getModuleSpecifierValue()}`);
759
- entityDictionary.createFamixImportClause({importDeclaration: impDecl,
760
- importer: module,
894
+ logger.info(`Importing (namespace) ${namespaceImport.getText()} from ${impDecl.getModuleSpecifierValue()} in ${modulePath}`);
895
+ entityDictionary.oldCreateFamixImportClause({importDeclaration: impDecl,
896
+ importerSourceFile: module,
761
897
  moduleSpecifierFilePath: path,
762
898
  importElement: namespaceImport,
763
899
  isInExports: false,
@@ -768,11 +904,21 @@ export function processImportClausesForModules(modules: Array<SourceFile>, expor
768
904
  });
769
905
  }
770
906
 
907
+ function isInExports(exports: ReadonlyMap<string, ExportedDeclarations[]>[], importedEntityName: string) {
908
+ let importFoundInExports = false;
909
+ exports.forEach(e => {
910
+ if (e.has(importedEntityName)) {
911
+ importFoundInExports = true;
912
+ }
913
+ });
914
+ return importFoundInExports;
915
+ }
916
+
771
917
  /**
772
- * Builds a Famix model for the inheritances of the classes and interfaces of the source files
773
- * @param classes An array of classes
774
- * @param interfaces An array of interfaces
775
- */
918
+ * Builds a Famix model for the inheritances of the classes and interfaces of the source files
919
+ * @param classes An array of classes
920
+ * @param interfaces An array of interfaces
921
+ */
776
922
  export function processInheritances(classes: ClassDeclaration[], interfaces: InterfaceDeclaration[]): void {
777
923
  logger.info(`processInheritances: Creating inheritances:`);
778
924
  classes.forEach(cls => {
@@ -808,15 +954,17 @@ export function processInheritances(classes: ClassDeclaration[], interfaces: Int
808
954
  * Builds a Famix model for the invocations of the methods and functions of the source files
809
955
  * @param methodsAndFunctionsWithId A map of methods and functions with their id
810
956
  */
811
- export function processInvocations(methodsAndFunctionsWithId: Map<number, MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression>): void {
957
+ export function processInvocations(methodsAndFunctionsWithId: Map<number, MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ArrowFunction>): void {
812
958
  logger.info(`Creating invocations:`);
813
959
  methodsAndFunctionsWithId.forEach((m, id) => {
814
- logger.debug(`Invocations to ${(m instanceof MethodDeclaration || m instanceof GetAccessorDeclaration || m instanceof SetAccessorDeclaration || m instanceof FunctionDeclaration) ? m.getName() : ((m instanceof ConstructorDeclaration) ? 'constructor' : (m.getName() ? m.getName() : 'anonymous'))}`);
815
- try {
816
- const temp_nodes = m.findReferencesAsNodes() as Array<Identifier>;
817
- temp_nodes.forEach(node => processNodeForInvocations(node, m, id));
818
- } catch (error) {
819
- logger.error(`> WARNING: got exception ${error}. Continuing...`);
960
+ if (!(m instanceof ArrowFunction)) {
961
+ logger.debug(`Invocations to ${(m instanceof MethodDeclaration || m instanceof GetAccessorDeclaration || m instanceof SetAccessorDeclaration || m instanceof FunctionDeclaration) ? m.getName() : ((m instanceof ConstructorDeclaration) ? 'constructor' : (m.getName() ? m.getName() : 'anonymous'))}`);
962
+ try {
963
+ const temp_nodes = m.findReferencesAsNodes() as Array<Identifier>;
964
+ temp_nodes.forEach(node => processNodeForInvocations(node, m, id));
965
+ } catch (error) {
966
+ logger.error(`> WARNING: got exception ${error}. Continuing...`);
967
+ }
820
968
  }
821
969
  });
822
970
  }
@@ -835,4 +983,32 @@ function processNodeForInvocations(n: Identifier, m: MethodDeclaration | Constru
835
983
  } catch (error) {
836
984
  logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
837
985
  }
838
- }
986
+ }
987
+
988
+ /**
989
+ * Builds a Famix model for the inheritances of the classes and interfaces of the source files
990
+ * @param classes An array of classes
991
+ * @param interfaces An array of interfaces
992
+ */
993
+ export function processConcretisations(classes: ClassDeclaration[], interfaces: InterfaceDeclaration[], functions: Map<number, MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ArrowFunction>): void {
994
+ logger.info(`processConcretisations: Creating concretisations:`);
995
+ classes.forEach(cls => {
996
+ logger.debug(`processConcretisations: Checking class concretisation for ${cls.getName()}`);
997
+ entityDictionary.createFamixConcretisationClassOrInterfaceSpecialisation(cls);
998
+ entityDictionary.createFamixConcretisationGenericInstantiation(cls);
999
+ entityDictionary.createFamixConcretisationInterfaceClass(cls);
1000
+ entityDictionary.createFamixConcretisationTypeInstanciation(cls);
1001
+
1002
+ });
1003
+ interfaces.forEach(inter => {
1004
+ logger.debug(`processConcretisations: Checking interface concretisation for ${inter.getName()}`);
1005
+ entityDictionary.createFamixConcretisationTypeInstanciation(inter);
1006
+ entityDictionary.createFamixConcretisationClassOrInterfaceSpecialisation(inter)
1007
+ });
1008
+ functions.forEach(func => {
1009
+ if(func instanceof FunctionDeclaration || func instanceof MethodDeclaration ){
1010
+ logger.debug(`processConcretisations: Checking Method concretisation`);
1011
+ entityDictionary.createFamixConcretisationFunctionInstantiation(func);
1012
+ }
1013
+ })
1014
+ }