ts2famix 1.3.1 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/analyze.js +38 -27
  2. package/dist/analyze_functions/process_functions.js +723 -0
  3. package/dist/famix_functions/EntityDictionary.js +798 -0
  4. package/dist/famix_functions/helpers_creation.js +97 -0
  5. package/dist/fqn.js +106 -95
  6. package/dist/lib/famix/src/famix_base_element.js +8 -4
  7. package/dist/lib/famix/src/famix_repository.js +32 -15
  8. package/dist/lib/ts-complex/cyclomatic-service.js +2 -3
  9. package/doc-uml/metamodel-full.svg +1 -0
  10. package/doc-uml/metamodel.svg +1 -0
  11. package/package.json +1 -1
  12. package/plantuml.jar +0 -0
  13. package/src/analyze.ts +48 -29
  14. package/src/analyze_functions/process_functions.ts +838 -0
  15. package/src/famix_functions/EntityDictionary.ts +915 -0
  16. package/src/famix_functions/helpers_creation.ts +77 -0
  17. package/src/fqn.ts +101 -92
  18. package/src/lib/famix/src/famix_base_element.ts +9 -5
  19. package/src/lib/famix/src/famix_repository.ts +45 -23
  20. package/src/lib/ts-complex/cyclomatic-service.ts +2 -4
  21. package/src/ts2famix-cli.ts +1 -0
  22. package/dist/analyze_functions/processAccesses.js +0 -56
  23. package/dist/analyze_functions/processFiles.js +0 -554
  24. package/dist/analyze_functions/processImportClauses.js +0 -88
  25. package/dist/analyze_functions/processInheritances.js +0 -74
  26. package/dist/analyze_functions/processInvocations.js +0 -50
  27. package/dist/famix_functions/famix_functions.js +0 -523
  28. package/dist/famix_functions/famix_functions_associations.js +0 -238
  29. package/dist/famix_functions/famix_functions_index.js +0 -135
  30. package/dist/famix_functions/famix_functions_types.js +0 -115
  31. package/docs/.gitkeep +0 -0
  32. package/src/analyze_functions/processAccesses.ts +0 -58
  33. package/src/analyze_functions/processFiles.ts +0 -667
  34. package/src/analyze_functions/processImportClauses.ts +0 -95
  35. package/src/analyze_functions/processInheritances.ts +0 -85
  36. package/src/analyze_functions/processInvocations.ts +0 -52
  37. package/src/famix_functions/famix_functions.ts +0 -562
  38. package/src/famix_functions/famix_functions_associations.ts +0 -242
  39. package/src/famix_functions/famix_functions_index.ts +0 -120
  40. package/src/famix_functions/famix_functions_types.ts +0 -106
@@ -0,0 +1,723 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.processInvocations = exports.processInheritances = exports.processImportClausesForModules = exports.processImportClausesForImportEqualsDeclarations = exports.processAccesses = exports.processFiles = exports.getImplementedOrExtendedInterfaces = exports.getModulePath = exports.currentCC = exports.exportedMap = exports.modules = exports.interfaces = exports.classes = exports.accessMap = exports.methodsAndFunctionsWithId = void 0;
27
+ const ts_morph_1 = require("ts-morph");
28
+ const Famix = __importStar(require("../lib/famix/src/model/famix"));
29
+ const cyclomatic_service_1 = require("../lib/ts-complex/cyclomatic-service");
30
+ const fs = __importStar(require("fs"));
31
+ const analyze_1 = require("../analyze");
32
+ exports.methodsAndFunctionsWithId = new Map(); // Maps the Famix method, constructor, getter, setter and function ids to their ts-morph method, constructor, getter, setter or function object
33
+ exports.accessMap = new Map(); // Maps the Famix parameter, variable, property and enum value ids to their ts-morph parameter, variable, property or enum member object
34
+ exports.classes = new Array(); // Array of all the classes of the source files
35
+ exports.interfaces = new Array(); // Array of all the interfaces of the source files
36
+ exports.modules = new Array(); // Array of all the source files which are modules
37
+ exports.exportedMap = new Array(); // Array of all the exports
38
+ /**
39
+ * Checks if the file has any imports or exports to be considered a module
40
+ * @param sourceFile A source file
41
+ * @returns A boolean indicating if the file is a module
42
+ */
43
+ function ismodule(sourceFile) {
44
+ return sourceFile.getImportDeclarations().length > 0 || sourceFile.getExportedDeclarations().size > 0;
45
+ }
46
+ /**
47
+ * Gets the path of a module to be imported
48
+ * @param i An import declaration
49
+ * @returns The path of the module to be imported
50
+ */
51
+ function getModulePath(i) {
52
+ let path;
53
+ if (i.getModuleSpecifierSourceFile() === undefined) {
54
+ if (i.getModuleSpecifierValue().substring(i.getModuleSpecifierValue().length - 3) === ".ts") {
55
+ path = i.getModuleSpecifierValue();
56
+ }
57
+ else {
58
+ path = i.getModuleSpecifierValue() + ".ts";
59
+ }
60
+ }
61
+ else {
62
+ path = i.getModuleSpecifierSourceFile().getFilePath();
63
+ }
64
+ return path;
65
+ }
66
+ exports.getModulePath = getModulePath;
67
+ /**
68
+ * Gets the interfaces implemented or extended by a class or an interface
69
+ * @param interfaces An array of interfaces
70
+ * @param subClass A class or an interface
71
+ * @returns An array of InterfaceDeclaration and ExpressionWithTypeArguments containing the interfaces implemented or extended by the subClass
72
+ */
73
+ function getImplementedOrExtendedInterfaces(interfaces, subClass) {
74
+ let impOrExtInterfaces;
75
+ if (subClass instanceof ts_morph_1.ClassDeclaration) {
76
+ impOrExtInterfaces = subClass.getImplements();
77
+ }
78
+ else {
79
+ impOrExtInterfaces = subClass.getExtends();
80
+ }
81
+ const interfacesNames = interfaces.map(i => i.getName());
82
+ const implementedOrExtendedInterfaces = new Array();
83
+ impOrExtInterfaces.forEach(i => {
84
+ if (interfacesNames.includes(i.getExpression().getText())) {
85
+ implementedOrExtendedInterfaces.push(interfaces[interfacesNames.indexOf(i.getExpression().getText())]);
86
+ }
87
+ else {
88
+ implementedOrExtendedInterfaces.push(i);
89
+ }
90
+ });
91
+ return implementedOrExtendedInterfaces;
92
+ }
93
+ exports.getImplementedOrExtendedInterfaces = getImplementedOrExtendedInterfaces;
94
+ /**
95
+ * Builds a Famix model for an array of source files
96
+ * @param sourceFiles An array of source files
97
+ */
98
+ function processFiles(sourceFiles) {
99
+ sourceFiles.forEach(file => {
100
+ analyze_1.logger.info(`File: >>>>>>>>>> ${file.getFilePath()}`);
101
+ // Computes the cyclomatic complexity metrics for the current source file if it exists (i.e. if it is not from a jest test)
102
+ if (fs.existsSync(file.getFilePath()))
103
+ exports.currentCC = (0, cyclomatic_service_1.calculate)(file.getFilePath());
104
+ else
105
+ exports.currentCC = 0;
106
+ processFile(file);
107
+ });
108
+ }
109
+ exports.processFiles = processFiles;
110
+ /**
111
+ * Builds a Famix model for a source file
112
+ * @param f A source file
113
+ */
114
+ function processFile(f) {
115
+ const isModule = ismodule(f);
116
+ if (isModule) {
117
+ exports.modules.push(f);
118
+ exports.exportedMap.push(f.getExportedDeclarations());
119
+ }
120
+ const fmxFile = analyze_1.entityDictionary.createOrGetFamixFile(f, isModule);
121
+ analyze_1.logger.debug(`processFile: file: ${f.getBaseName()}, fqn = ${fmxFile.getFullyQualifiedName()}`);
122
+ processComments(f, fmxFile);
123
+ processAliases(f, fmxFile);
124
+ processClasses(f, fmxFile);
125
+ processInterfaces(f, fmxFile);
126
+ processVariables(f, fmxFile);
127
+ processEnums(f, fmxFile);
128
+ processFunctions(f, fmxFile);
129
+ processNamespaces(f, fmxFile);
130
+ }
131
+ /**
132
+ * Builds a Famix model for a namespace
133
+ * @param m A namespace
134
+ * @returns A Famix.Namespace representing the namespace
135
+ */
136
+ function processNamespace(m) {
137
+ const fmxNamespace = analyze_1.entityDictionary.createOrGetFamixNamespace(m);
138
+ analyze_1.logger.debug(`processNamespace: namespace: ${m.getName()}, (${m.getType().getText()}), ${fmxNamespace.getFullyQualifiedName()}`);
139
+ processComments(m, fmxNamespace);
140
+ processAliases(m, fmxNamespace);
141
+ processClasses(m, fmxNamespace);
142
+ processInterfaces(m, fmxNamespace);
143
+ processVariables(m, fmxNamespace);
144
+ processEnums(m, fmxNamespace);
145
+ processFunctions(m, fmxNamespace);
146
+ processNamespaces(m, fmxNamespace);
147
+ return fmxNamespace;
148
+ }
149
+ /**
150
+ * Builds a Famix model for the aliases of a container
151
+ * @param m A container (a source file, a namespace, a function or a method)
152
+ * @param fmxScope The Famix model of the container
153
+ */
154
+ function processAliases(m, fmxScope) {
155
+ analyze_1.logger.debug(`processAliases: ---------- Finding Aliases:`);
156
+ m.getTypeAliases().forEach(a => {
157
+ const fmxAlias = processAlias(a);
158
+ fmxScope.addAlias(fmxAlias);
159
+ });
160
+ }
161
+ /**
162
+ * Builds a Famix model for the classes of a container
163
+ * @param m A container (a source file or a namespace)
164
+ * @param fmxScope The Famix model of the container
165
+ */
166
+ function processClasses(m, fmxScope) {
167
+ analyze_1.logger.debug(`processClasses: ---------- Finding Classes:`);
168
+ m.getClasses().forEach(c => {
169
+ const fmxClass = processClass(c);
170
+ fmxScope.addType(fmxClass);
171
+ });
172
+ }
173
+ /**
174
+ * Builds a Famix model for the interfaces of a container
175
+ * @param m A container (a source file or a namespace)
176
+ * @param fmxScope The Famix model of the container
177
+ */
178
+ function processInterfaces(m, fmxScope) {
179
+ analyze_1.logger.debug(`processInterfaces: ---------- Finding Interfaces:`);
180
+ m.getInterfaces().forEach(i => {
181
+ const fmxInterface = processInterface(i);
182
+ fmxScope.addType(fmxInterface);
183
+ });
184
+ }
185
+ /**
186
+ * Builds a Famix model for the variables of a container
187
+ * @param m A container (a source file, a namespace, a function or a method)
188
+ * @param fmxScope The Famix model of the container
189
+ */
190
+ function processVariables(m, fmxScope) {
191
+ analyze_1.logger.debug(`processVariables: ---------- Finding Variables:`);
192
+ m.getVariableStatements().forEach(v => {
193
+ const fmxVariables = processVariableStatement(v);
194
+ fmxVariables.forEach(fmxVariable => {
195
+ fmxScope.addVariable(fmxVariable);
196
+ });
197
+ });
198
+ }
199
+ /**
200
+ * Builds a Famix model for the enums of a container
201
+ * @param m A container (a source file, a namespace, a function or a method)
202
+ * @param fmxScope The Famix model of the container
203
+ */
204
+ function processEnums(m, fmxScope) {
205
+ analyze_1.logger.debug(`processEnums: ---------- Finding Enums:`);
206
+ m.getEnums().forEach(e => {
207
+ const fmxEnum = processEnum(e);
208
+ fmxScope.addType(fmxEnum);
209
+ });
210
+ }
211
+ /**
212
+ * Builds a Famix model for the functions of a container
213
+ * @param m A container (a source file, a namespace, a function or a method)
214
+ * @param fmxScope The Famix model of the container
215
+ */
216
+ function processFunctions(m, fmxScope) {
217
+ analyze_1.logger.debug(`Finding Functions:`);
218
+ m.getFunctions().forEach(f => {
219
+ const fmxFunction = processFunction(f);
220
+ fmxScope.addFunction(fmxFunction);
221
+ });
222
+ }
223
+ /**
224
+ * Builds a Famix model for the namespaces of a container
225
+ * @param m A container (a source file or a namespace)
226
+ * @param fmxScope The Famix model of the container
227
+ */
228
+ function processNamespaces(m, fmxScope) {
229
+ analyze_1.logger.debug(`Finding Namespaces:`);
230
+ m.getModules().forEach(md => {
231
+ const fmxNsp = processNamespace(md);
232
+ fmxScope.addNamespace(fmxNsp);
233
+ });
234
+ }
235
+ /**
236
+ * Builds a Famix model for an alias
237
+ * @param a An alias
238
+ * @returns A Famix.Alias representing the alias
239
+ */
240
+ function processAlias(a) {
241
+ const fmxAlias = analyze_1.entityDictionary.createFamixAlias(a);
242
+ analyze_1.logger.debug(`Alias: ${a.getName()}, (${a.getType().getText()}), fqn = ${fmxAlias.getFullyQualifiedName()}`);
243
+ processComments(a, fmxAlias);
244
+ return fmxAlias;
245
+ }
246
+ /**
247
+ * Builds a Famix model for a class
248
+ * @param c A class
249
+ * @returns A Famix.Class or a Famix.ParameterizableClass representing the class
250
+ */
251
+ function processClass(c) {
252
+ exports.classes.push(c);
253
+ const fmxClass = analyze_1.entityDictionary.createOrGetFamixClass(c);
254
+ analyze_1.logger.debug(`Class: ${c.getName()}, (${c.getType().getText()}), fqn = ${fmxClass.getFullyQualifiedName()}`);
255
+ processComments(c, fmxClass);
256
+ processDecorators(c, fmxClass);
257
+ processStructuredType(c, fmxClass);
258
+ c.getConstructors().forEach(con => {
259
+ const fmxCon = processMethod(con);
260
+ fmxClass.addMethod(fmxCon);
261
+ });
262
+ c.getGetAccessors().forEach(acc => {
263
+ const fmxAcc = processMethod(acc);
264
+ fmxClass.addMethod(fmxAcc);
265
+ });
266
+ c.getSetAccessors().forEach(acc => {
267
+ const fmxAcc = processMethod(acc);
268
+ fmxClass.addMethod(fmxAcc);
269
+ });
270
+ return fmxClass;
271
+ }
272
+ /**
273
+ * Builds a Famix model for an interface
274
+ * @param i An interface
275
+ * @returns A Famix.Interface or a Famix.ParameterizableInterface representing the interface
276
+ */
277
+ function processInterface(i) {
278
+ exports.interfaces.push(i);
279
+ const fmxInterface = analyze_1.entityDictionary.createOrGetFamixInterface(i);
280
+ analyze_1.logger.debug(`Interface: ${i.getName()}, (${i.getType().getText()}), fqn = ${fmxInterface.getFullyQualifiedName()}`);
281
+ processComments(i, fmxInterface);
282
+ processStructuredType(i, fmxInterface);
283
+ return fmxInterface;
284
+ }
285
+ /**
286
+ * Builds a Famix model for the type parameters, properties and methods of a structured type
287
+ * @param c A structured type (a class or an interface)
288
+ * @param fmxScope The Famix model of the structured type
289
+ */
290
+ function processStructuredType(c, fmxScope) {
291
+ analyze_1.logger.debug(`Finding Properties and Methods:`);
292
+ if (fmxScope instanceof Famix.ParameterizableClass || fmxScope instanceof Famix.ParameterizableInterface) {
293
+ processTypeParameters(c, fmxScope);
294
+ }
295
+ c.getProperties().forEach(prop => {
296
+ const fmxProperty = processProperty(prop);
297
+ fmxScope.addProperty(fmxProperty);
298
+ });
299
+ c.getMethods().forEach(m => {
300
+ const fmxMethod = processMethod(m);
301
+ fmxScope.addMethod(fmxMethod);
302
+ });
303
+ }
304
+ /**
305
+ * Builds a Famix model for a property
306
+ * @param p A property
307
+ * @returns A Famix.Property representing the property
308
+ */
309
+ function processProperty(p) {
310
+ const fmxProperty = analyze_1.entityDictionary.createFamixProperty(p);
311
+ analyze_1.logger.debug(`property: ${p.getName()}, (${p.getType().getText()}), fqn = ${fmxProperty.getFullyQualifiedName()}`);
312
+ analyze_1.logger.debug(` ---> It's a Property${(p instanceof ts_morph_1.PropertySignature) ? "Signature" : "Declaration"}!`);
313
+ const ancestor = p.getFirstAncestorOrThrow();
314
+ analyze_1.logger.debug(` ---> Its first ancestor is a ${ancestor.getKindName()}`);
315
+ if (!(p instanceof ts_morph_1.PropertySignature)) {
316
+ processDecorators(p, fmxProperty);
317
+ // only add access if the p's first ancestor is not a PropertyDeclaration
318
+ if (ancestor.getKindName() !== "PropertyDeclaration") {
319
+ analyze_1.logger.debug(`adding access: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxProperty.getName()}`);
320
+ exports.accessMap.set(fmxProperty.id, p);
321
+ }
322
+ }
323
+ processComments(p, fmxProperty);
324
+ return fmxProperty;
325
+ }
326
+ /**
327
+ * Builds a Famix model for a method or an accessor
328
+ * @param m A method or an accessor
329
+ * @returns A Famix.Method or a Famix.Accessor representing the method or the accessor
330
+ */
331
+ function processMethod(m) {
332
+ const fmxMethod = analyze_1.entityDictionary.createFamixMethod(m, exports.currentCC);
333
+ analyze_1.logger.debug(`Method: ${!(m instanceof ts_morph_1.ConstructorDeclaration) ? m.getName() : "constructor"}, (${m.getType().getText()}), parent: ${m.getParent().getName()}, fqn = ${fmxMethod.getFullyQualifiedName()}`);
334
+ processComments(m, fmxMethod);
335
+ processTypeParameters(m, fmxMethod);
336
+ processParameters(m, fmxMethod);
337
+ if (!(m instanceof ts_morph_1.MethodSignature)) {
338
+ processAliases(m, fmxMethod);
339
+ processVariables(m, fmxMethod);
340
+ processEnums(m, fmxMethod);
341
+ processFunctions(m, fmxMethod);
342
+ processFunctionExpressions(m, fmxMethod);
343
+ exports.methodsAndFunctionsWithId.set(fmxMethod.id, m);
344
+ }
345
+ if (m instanceof ts_morph_1.MethodDeclaration || m instanceof ts_morph_1.GetAccessorDeclaration || m instanceof ts_morph_1.SetAccessorDeclaration) {
346
+ processDecorators(m, fmxMethod);
347
+ }
348
+ return fmxMethod;
349
+ }
350
+ /**
351
+ * Builds a Famix model for a function
352
+ * @param f A function
353
+ * @returns A Famix.Function representing the function
354
+ */
355
+ function processFunction(f) {
356
+ const fmxFunction = analyze_1.entityDictionary.createFamixFunction(f, exports.currentCC);
357
+ analyze_1.logger.debug(`Function: ${(f.getName()) ? f.getName() : "anonymous"}, (${f.getType().getText()}), fqn = ${fmxFunction.getFullyQualifiedName()}`);
358
+ processComments(f, fmxFunction);
359
+ processAliases(f, fmxFunction);
360
+ processTypeParameters(f, fmxFunction);
361
+ processParameters(f, fmxFunction);
362
+ processVariables(f, fmxFunction);
363
+ processEnums(f, fmxFunction);
364
+ processFunctions(f, fmxFunction);
365
+ if (f instanceof ts_morph_1.FunctionDeclaration && !(f.getParent() instanceof ts_morph_1.Block)) {
366
+ processFunctionExpressions(f, fmxFunction);
367
+ }
368
+ exports.methodsAndFunctionsWithId.set(fmxFunction.id, f);
369
+ return fmxFunction;
370
+ }
371
+ /**
372
+ * Builds a Famix model for the function expressions of a function or a method
373
+ * @param f A function or a method
374
+ * @param fmxScope The Famix model of the function or the method
375
+ */
376
+ function processFunctionExpressions(f, fmxScope) {
377
+ analyze_1.logger.debug(`Finding Function Expressions:`);
378
+ const functionExpressions = f.getDescendantsOfKind(ts_morph_1.SyntaxKind.FunctionExpression);
379
+ functionExpressions.forEach((func) => {
380
+ const fmxFunc = processFunction(func);
381
+ fmxScope.addFunction(fmxFunc);
382
+ });
383
+ }
384
+ /**
385
+ * Builds a Famix model for the parameters of a method or a function
386
+ * @param m A method or a function
387
+ * @param fmxScope The Famix model of the method or the function
388
+ */
389
+ function processParameters(m, fmxScope) {
390
+ analyze_1.logger.debug(`Finding Parameters:`);
391
+ m.getParameters().forEach(param => {
392
+ const fmxParam = processParameter(param);
393
+ fmxScope.addParameter(fmxParam);
394
+ });
395
+ }
396
+ /**
397
+ * Builds a Famix model for a parameter
398
+ * @param p A parameter
399
+ * @returns A Famix.Parameter representing the parameter
400
+ */
401
+ function processParameter(p) {
402
+ const fmxParam = analyze_1.entityDictionary.createFamixParameter(p);
403
+ analyze_1.logger.debug(`parameter: ${p.getName()}, (${p.getType().getText()}), fqn = ${fmxParam.getFullyQualifiedName()}`);
404
+ processComments(p, fmxParam);
405
+ processDecorators(p, fmxParam);
406
+ const parent = p.getParent();
407
+ if (!(parent instanceof ts_morph_1.MethodSignature)) {
408
+ analyze_1.logger.debug(`adding access: ${p.getName()}, (${p.getType().getText()}) Famix ${fmxParam.getName()}`);
409
+ exports.accessMap.set(fmxParam.id, p);
410
+ }
411
+ return fmxParam;
412
+ }
413
+ /**
414
+ * Builds a Famix model for the type parameters of a class, an interface, a method or a function
415
+ * @param e A class, an interface, a method or a function
416
+ * @param fmxScope The Famix model of the class, the interface, the method or the function
417
+ */
418
+ function processTypeParameters(e, fmxScope) {
419
+ analyze_1.logger.debug(`Finding Type Parameters:`);
420
+ e.getTypeParameters().forEach(tp => {
421
+ const fmxParam = processTypeParameter(tp);
422
+ fmxScope.addParameterType(fmxParam);
423
+ });
424
+ }
425
+ /**
426
+ * Builds a Famix model for a type parameter
427
+ * @param tp A type parameter
428
+ * @returns A Famix.TypeParameter representing the type parameter
429
+ */
430
+ function processTypeParameter(tp) {
431
+ const fmxTypeParameter = analyze_1.entityDictionary.createFamixParameterType(tp);
432
+ analyze_1.logger.debug(`type parameter: ${tp.getName()}, (${tp.getType().getText()}), fqn = ${fmxTypeParameter.getFullyQualifiedName()}`);
433
+ processComments(tp, fmxTypeParameter);
434
+ return fmxTypeParameter;
435
+ }
436
+ /**
437
+ * Builds a Famix model for the variables of a variable statement
438
+ * @param v A variable statement
439
+ * @returns An array of Famix.Variable representing the variables
440
+ */
441
+ function processVariableStatement(v) {
442
+ const fmxVariables = new Array();
443
+ analyze_1.logger.debug(`Variable statement: ${v.getText()}, (${v.getType().getText()}), ${v.getDeclarationKindKeywords()[0]}, fqn = ${v.getDeclarations()[0].getName()}`);
444
+ v.getDeclarations().forEach(variable => {
445
+ const fmxVar = processVariable(variable);
446
+ processComments(v, fmxVar);
447
+ fmxVariables.push(fmxVar);
448
+ });
449
+ return fmxVariables;
450
+ }
451
+ /**
452
+ * Builds a Famix model for a variable
453
+ * @param v A variable
454
+ * @returns A Famix.Variable representing the variable
455
+ */
456
+ function processVariable(v) {
457
+ const fmxVar = analyze_1.entityDictionary.createFamixVariable(v);
458
+ analyze_1.logger.debug(`variable: ${v.getName()}, (${v.getType().getText()}), ${v.getInitializer() ? "initializer: " + v.getInitializer().getText() : "initializer: "}, fqn = ${fmxVar.getFullyQualifiedName()}`);
459
+ processComments(v, fmxVar);
460
+ analyze_1.logger.debug(`adding access: ${v.getName()}, (${v.getType().getText()}) Famix ${fmxVar.getName()}`);
461
+ exports.accessMap.set(fmxVar.id, v);
462
+ return fmxVar;
463
+ }
464
+ /**
465
+ * Builds a Famix model for an enum
466
+ * @param e An enum
467
+ * @returns A Famix.Enum representing the enum
468
+ */
469
+ function processEnum(e) {
470
+ const fmxEnum = analyze_1.entityDictionary.createFamixEnum(e);
471
+ analyze_1.logger.debug(`enum: ${e.getName()}, (${e.getType().getText()}), fqn = ${fmxEnum.getFullyQualifiedName()}`);
472
+ processComments(e, fmxEnum);
473
+ e.getMembers().forEach(m => {
474
+ const fmxEnumValue = processEnumValue(m);
475
+ fmxEnum.addValue(fmxEnumValue);
476
+ });
477
+ return fmxEnum;
478
+ }
479
+ /**
480
+ * Builds a Famix model for an enum member
481
+ * @param v An enum member
482
+ * @returns A Famix.EnumValue representing the enum member
483
+ */
484
+ function processEnumValue(v) {
485
+ const fmxEnumValue = analyze_1.entityDictionary.createFamixEnumValue(v);
486
+ analyze_1.logger.debug(`enum value: ${v.getName()}, (${v.getType().getText()}), fqn = ${fmxEnumValue.getFullyQualifiedName()}`);
487
+ processComments(v, fmxEnumValue);
488
+ analyze_1.logger.debug(`adding access: ${v.getName()}, (${v.getType().getText()}) Famix ${fmxEnumValue.getName()}`);
489
+ exports.accessMap.set(fmxEnumValue.id, v);
490
+ return fmxEnumValue;
491
+ }
492
+ /**
493
+ * Builds a Famix model for the decorators of a class, a method, a parameter or a property
494
+ * @param e A class, a method, a parameter or a property
495
+ * @param fmxScope The Famix model of the class, the method, the parameter or the property
496
+ */
497
+ function processDecorators(e, fmxScope) {
498
+ analyze_1.logger.debug(`Finding Decorators:`);
499
+ e.getDecorators().forEach(dec => {
500
+ const fmxDec = processDecorator(dec, e);
501
+ fmxScope.addDecorator(fmxDec);
502
+ });
503
+ }
504
+ /**
505
+ * Builds a Famix model for a decorator
506
+ * @param d A decorator
507
+ * @param e A class, a method, a parameter or a property
508
+ * @returns A Famix.Decorator representing the decorator
509
+ */
510
+ function processDecorator(d, e) {
511
+ const fmxDec = analyze_1.entityDictionary.createOrGetFamixDecorator(d, e);
512
+ analyze_1.logger.debug(`decorator: ${d.getName()}, (${d.getType().getText()}), fqn = ${fmxDec.getFullyQualifiedName()}`);
513
+ processComments(d, fmxDec);
514
+ return fmxDec;
515
+ }
516
+ /**
517
+ * Builds a Famix model for the comments
518
+ * @param e A ts-morph element
519
+ * @param fmxScope The Famix model of the named entity
520
+ */
521
+ function processComments(e, fmxScope) {
522
+ analyze_1.logger.debug(`Process comments:`);
523
+ e.getLeadingCommentRanges().forEach(c => {
524
+ const fmxComment = processComment(c, fmxScope);
525
+ analyze_1.logger.debug(`leading comments, addComment: '${c.getText()}'`);
526
+ fmxScope.addComment(fmxComment); // redundant, but just in case
527
+ });
528
+ e.getTrailingCommentRanges().forEach(c => {
529
+ const fmxComment = processComment(c, fmxScope);
530
+ analyze_1.logger.debug(`trailing comments, addComment: '${c.getText()}'`);
531
+ fmxScope.addComment(fmxComment);
532
+ });
533
+ }
534
+ /**
535
+ * Builds a Famix model for a comment
536
+ * @param c A comment
537
+ * @param fmxScope The Famix model of the comment's container
538
+ * @returns A Famix.Comment representing the comment
539
+ */
540
+ function processComment(c, fmxScope) {
541
+ const isJSDoc = c.getText().startsWith("/**");
542
+ analyze_1.logger.debug(`processComment: comment: ${c.getText()}, isJSDoc = ${isJSDoc}`);
543
+ const fmxComment = analyze_1.entityDictionary.createFamixComment(c, fmxScope, isJSDoc);
544
+ return fmxComment;
545
+ }
546
+ /**
547
+ * Builds a Famix model for the accesses on the parameters, variables, properties and enum members of the source files
548
+ * @param accessMap A map of parameters, variables, properties and enum members with their id
549
+ */
550
+ function processAccesses(accessMap) {
551
+ analyze_1.logger.debug(`processAccesses: Creating accesses:`);
552
+ accessMap.forEach((v, id) => {
553
+ analyze_1.logger.debug(`processAccesses: Accesses to ${v.getName()}`);
554
+ try {
555
+ const temp_nodes = v.findReferencesAsNodes();
556
+ temp_nodes.forEach(node => processNodeForAccesses(node, id));
557
+ }
558
+ catch (error) {
559
+ analyze_1.logger.error(`> WARNING: got exception ${error}. Continuing...`);
560
+ }
561
+ });
562
+ }
563
+ exports.processAccesses = processAccesses;
564
+ /**
565
+ * Builds a Famix model for an access on a parameter, variable, property or enum member
566
+ * @param n A node
567
+ * @param id An id of a parameter, a variable, a property or an enum member
568
+ */
569
+ function processNodeForAccesses(n, id) {
570
+ try {
571
+ // sometimes node's first ancestor is a PropertyDeclaration, which is not an access
572
+ // see https://github.com/fuhrmanator/FamixTypeScriptImporter/issues/9
573
+ // check for a node whose first ancestor is a property declaration and bail?
574
+ // This may be a bug in ts-morph?
575
+ if (n.getFirstAncestorOrThrow().getKindName() === "PropertyDeclaration") {
576
+ analyze_1.logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})'s first ancestor is a PropertyDeclaration. Skipping...`);
577
+ return;
578
+ }
579
+ analyze_1.entityDictionary.createFamixAccess(n, id);
580
+ analyze_1.logger.debug(`processNodeForAccesses: node kind: ${n.getKindName()}, ${n.getText()}, (${n.getType().getText()})`);
581
+ }
582
+ catch (error) {
583
+ analyze_1.logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
584
+ }
585
+ }
586
+ function processImportClausesForImportEqualsDeclarations(sourceFiles, exports) {
587
+ analyze_1.logger.info(`Creating import clauses from ImportEqualsDeclarations in source files:`);
588
+ sourceFiles.forEach(sourceFile => {
589
+ sourceFile.forEachDescendant(node => {
590
+ if (ts_morph_1.Node.isImportEqualsDeclaration(node)) {
591
+ // You've found an ImportEqualsDeclaration
592
+ analyze_1.logger.info("Declaration Name:", node.getName());
593
+ analyze_1.logger.info("Module Reference Text:", node.getModuleReference().getText());
594
+ // create a famix import clause
595
+ const namedImport = node.getNameNode();
596
+ analyze_1.entityDictionary.createFamixImportClause({ importDeclaration: node,
597
+ importer: sourceFile,
598
+ moduleSpecifierFilePath: node.getModuleReference().getText(),
599
+ importElement: namedImport,
600
+ isInExports: exports.find(e => e.has(namedImport.getText())) !== undefined,
601
+ isDefaultExport: false });
602
+ }
603
+ });
604
+ });
605
+ }
606
+ exports.processImportClausesForImportEqualsDeclarations = processImportClausesForImportEqualsDeclarations;
607
+ /**
608
+ * Builds a Famix model for the import clauses of the source files which are modules
609
+ * @param modules An array of modules
610
+ * @param exports An array of maps of exported declarations
611
+ */
612
+ function processImportClausesForModules(modules, exports) {
613
+ analyze_1.logger.info(`Creating import clauses from ${modules.length} modules:`);
614
+ modules.forEach(module => {
615
+ module.getImportDeclarations().forEach(impDecl => {
616
+ analyze_1.logger.debug(`Importing ${impDecl.getModuleSpecifierValue()}`);
617
+ const path = getModulePath(impDecl);
618
+ impDecl.getNamedImports().forEach(namedImport => {
619
+ analyze_1.logger.debug(`Importing (named) ${namedImport.getName()} from ${impDecl.getModuleSpecifierValue()}`);
620
+ const importedEntityName = namedImport.getName();
621
+ let importFoundInExports = false;
622
+ exports.forEach(e => {
623
+ if (e.has(importedEntityName)) {
624
+ importFoundInExports = true;
625
+ }
626
+ });
627
+ analyze_1.entityDictionary.createFamixImportClause({ importDeclaration: impDecl,
628
+ importer: module,
629
+ moduleSpecifierFilePath: path,
630
+ importElement: namedImport,
631
+ isInExports: importFoundInExports,
632
+ isDefaultExport: false });
633
+ });
634
+ const defaultImport = impDecl.getDefaultImport();
635
+ if (defaultImport !== undefined) {
636
+ analyze_1.logger.debug(`Importing (default) ${defaultImport.getText()} from ${impDecl.getModuleSpecifierValue()}`);
637
+ // call with module, impDecl.getModuleSpecifierValue(), path, defaultImport, false, true
638
+ analyze_1.entityDictionary.createFamixImportClause({ importDeclaration: impDecl,
639
+ importer: module,
640
+ moduleSpecifierFilePath: path,
641
+ importElement: defaultImport,
642
+ isInExports: false,
643
+ isDefaultExport: true });
644
+ }
645
+ const namespaceImport = impDecl.getNamespaceImport();
646
+ if (namespaceImport !== undefined) {
647
+ analyze_1.logger.debug(`Importing (namespace) ${namespaceImport.getText()} from ${impDecl.getModuleSpecifierValue()}`);
648
+ analyze_1.entityDictionary.createFamixImportClause({ importDeclaration: impDecl,
649
+ importer: module,
650
+ moduleSpecifierFilePath: path,
651
+ importElement: namespaceImport,
652
+ isInExports: false,
653
+ isDefaultExport: false });
654
+ // entityDictionary.createFamixImportClause(module, impDecl.getModuleSpecifierValue(), path, namespaceImport, false, false);
655
+ }
656
+ });
657
+ });
658
+ }
659
+ exports.processImportClausesForModules = processImportClausesForModules;
660
+ /**
661
+ * Builds a Famix model for the inheritances of the classes and interfaces of the source files
662
+ * @param classes An array of classes
663
+ * @param interfaces An array of interfaces
664
+ */
665
+ function processInheritances(classes, interfaces) {
666
+ analyze_1.logger.info(`processInheritances: Creating inheritances:`);
667
+ classes.forEach(cls => {
668
+ analyze_1.logger.debug(`processInheritances: Checking class inheritance for ${cls.getName()}`);
669
+ const extClass = cls.getBaseClass();
670
+ if (extClass !== undefined) {
671
+ analyze_1.entityDictionary.createFamixInheritance(cls, extClass);
672
+ analyze_1.logger.debug(`processInheritances: class: ${cls.getName()}, (${cls.getType().getText()}), extClass: ${extClass.getName()}, (${extClass.getType().getText()})`);
673
+ }
674
+ analyze_1.logger.debug(`processInheritances: Checking interface inheritance for ${cls.getName()}`);
675
+ const implementedInterfaces = getImplementedOrExtendedInterfaces(interfaces, cls);
676
+ implementedInterfaces.forEach(impInter => {
677
+ analyze_1.entityDictionary.createFamixInheritance(cls, impInter);
678
+ analyze_1.logger.debug(`processInheritances: class: ${cls.getName()}, (${cls.getType().getText()}), impInter: ${(impInter instanceof ts_morph_1.InterfaceDeclaration) ? impInter.getName() : impInter.getExpression().getText()}, (${(impInter instanceof ts_morph_1.InterfaceDeclaration) ? impInter.getType().getText() : impInter.getExpression().getText()})`);
679
+ });
680
+ });
681
+ interfaces.forEach(inter => {
682
+ analyze_1.logger.debug(`processInheritances: Checking interface inheritance for ${inter.getName()}`);
683
+ const extendedInterfaces = getImplementedOrExtendedInterfaces(interfaces, inter);
684
+ extendedInterfaces.forEach(extInter => {
685
+ analyze_1.entityDictionary.createFamixInheritance(inter, extInter);
686
+ analyze_1.logger.debug(`processInheritances: inter: ${inter.getName()}, (${inter.getType().getText()}), extInter: ${(extInter instanceof ts_morph_1.InterfaceDeclaration) ? extInter.getName() : extInter.getExpression().getText()}, (${(extInter instanceof ts_morph_1.InterfaceDeclaration) ? extInter.getType().getText() : extInter.getExpression().getText()})`);
687
+ });
688
+ });
689
+ }
690
+ exports.processInheritances = processInheritances;
691
+ /**
692
+ * Builds a Famix model for the invocations of the methods and functions of the source files
693
+ * @param methodsAndFunctionsWithId A map of methods and functions with their id
694
+ */
695
+ function processInvocations(methodsAndFunctionsWithId) {
696
+ analyze_1.logger.info(`Creating invocations:`);
697
+ methodsAndFunctionsWithId.forEach((m, id) => {
698
+ analyze_1.logger.debug(`Invocations to ${(m instanceof ts_morph_1.MethodDeclaration || m instanceof ts_morph_1.GetAccessorDeclaration || m instanceof ts_morph_1.SetAccessorDeclaration || m instanceof ts_morph_1.FunctionDeclaration) ? m.getName() : ((m instanceof ts_morph_1.ConstructorDeclaration) ? 'constructor' : (m.getName() ? m.getName() : 'anonymous'))}`);
699
+ try {
700
+ const temp_nodes = m.findReferencesAsNodes();
701
+ temp_nodes.forEach(node => processNodeForInvocations(node, m, id));
702
+ }
703
+ catch (error) {
704
+ analyze_1.logger.error(`> WARNING: got exception ${error}. Continuing...`);
705
+ }
706
+ });
707
+ }
708
+ exports.processInvocations = processInvocations;
709
+ /**
710
+ * Builds a Famix model for an invocation of a method or a function
711
+ * @param n A node
712
+ * @param m A method or a function
713
+ * @param id The id of the method or the function
714
+ */
715
+ function processNodeForInvocations(n, m, id) {
716
+ try {
717
+ analyze_1.entityDictionary.createFamixInvocation(n, m, id);
718
+ analyze_1.logger.debug(`node: node, (${n.getType().getText()})`);
719
+ }
720
+ catch (error) {
721
+ analyze_1.logger.error(`> WARNING: got exception ${error}. ScopeDeclaration invalid for ${n.getSymbol().getFullyQualifiedName()}. Continuing...`);
722
+ }
723
+ }