ts2famix 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +29 -60
  3. package/dist/analyze.js +1 -1
  4. package/dist/analyze_functions/process_functions.js +49 -43
  5. package/dist/famix_functions/EntityDictionary.js +309 -182
  6. package/dist/famix_functions/helpers_creation.js +36 -5
  7. package/dist/fqn.js +76 -114
  8. package/dist/lib/famix/famix_JSON_exporter.js +55 -0
  9. package/dist/lib/famix/famix_base_element.js +18 -0
  10. package/dist/lib/famix/famix_repository.js +224 -0
  11. package/dist/lib/famix/{src/index.js → index.js} +1 -1
  12. package/dist/lib/famix/model/famix/access.js +40 -0
  13. package/dist/lib/famix/model/famix/accessor.js +17 -0
  14. package/dist/lib/famix/model/famix/alias.js +33 -0
  15. package/dist/lib/famix/model/famix/arrow_function.js +17 -0
  16. package/dist/lib/famix/model/famix/behavioral_entity.js +79 -0
  17. package/dist/lib/famix/model/famix/class.js +71 -0
  18. package/dist/lib/famix/model/famix/comment.js +39 -0
  19. package/dist/lib/famix/model/famix/concretisation.js +31 -0
  20. package/dist/lib/famix/model/famix/container_entity.js +126 -0
  21. package/dist/lib/famix/model/famix/decorator.js +32 -0
  22. package/dist/lib/famix/model/famix/entity.js +17 -0
  23. package/dist/lib/famix/model/famix/enum.js +31 -0
  24. package/dist/lib/famix/model/famix/enum_value.js +25 -0
  25. package/dist/lib/famix/model/famix/function.js +17 -0
  26. package/dist/lib/famix/model/famix/import_clause.js +41 -0
  27. package/dist/lib/famix/{src/model → model}/famix/index.js +6 -10
  28. package/dist/lib/famix/model/famix/indexed_file_anchor.js +38 -0
  29. package/dist/lib/famix/model/famix/inheritance.js +33 -0
  30. package/dist/lib/famix/model/famix/interface.js +64 -0
  31. package/dist/lib/famix/model/famix/invocation.js +54 -0
  32. package/dist/lib/famix/model/famix/method.js +67 -0
  33. package/dist/lib/famix/model/famix/module.js +60 -0
  34. package/dist/lib/famix/model/famix/named_entity.js +78 -0
  35. package/dist/lib/famix/model/famix/parameter.js +25 -0
  36. package/dist/lib/famix/model/famix/parameter_concretisation.js +44 -0
  37. package/dist/lib/famix/model/famix/parameter_type.js +45 -0
  38. package/dist/lib/famix/model/famix/parametric_arrow_function.js +31 -0
  39. package/dist/lib/famix/model/famix/parametric_class.js +44 -0
  40. package/dist/lib/famix/model/famix/parametric_function.js +31 -0
  41. package/dist/lib/famix/model/famix/parametric_interface.js +44 -0
  42. package/dist/lib/famix/model/famix/parametric_method.js +31 -0
  43. package/dist/lib/famix/model/famix/primitive_type.js +17 -0
  44. package/dist/lib/famix/model/famix/property.js +73 -0
  45. package/dist/lib/famix/model/famix/reference.js +33 -0
  46. package/dist/lib/famix/model/famix/scoping_entity.js +36 -0
  47. package/dist/lib/famix/model/famix/script_entity.js +29 -0
  48. package/dist/lib/famix/model/famix/source_anchor.js +27 -0
  49. package/dist/lib/famix/model/famix/source_language.js +35 -0
  50. package/dist/lib/famix/model/famix/sourced_entity.js +60 -0
  51. package/dist/lib/famix/model/famix/structural_entity.js +39 -0
  52. package/dist/lib/famix/model/famix/type.js +73 -0
  53. package/dist/lib/famix/model/famix/variable.js +24 -0
  54. package/dist/lib/ts-complex/cyclomatic-service.js +2 -2
  55. package/dist/refactorer/refactor-getter-setter.js +142 -0
  56. package/dist/ts2famix-cli-wrapper.js +29 -3
  57. package/dist/ts2famix-cli.js +1 -1
  58. package/doc-uml/famix-typescript-model.puml +390 -341
  59. package/doc-uml/famix-typescript-model.svg +1 -1
  60. package/package.json +8 -7
  61. package/src/analyze.ts +2 -2
  62. package/src/analyze_functions/process_functions.ts +49 -44
  63. package/src/famix_functions/EntityDictionary.ts +345 -216
  64. package/src/famix_functions/helpers_creation.ts +36 -4
  65. package/src/fqn.ts +76 -125
  66. package/src/lib/famix/famix_JSON_exporter.ts +56 -0
  67. package/src/lib/famix/famix_base_element.ts +22 -0
  68. package/src/lib/famix/famix_repository.ts +243 -0
  69. package/src/lib/famix/model/famix/access.ts +50 -0
  70. package/src/lib/famix/model/famix/alias.ts +39 -0
  71. package/src/lib/famix/model/famix/behavioral_entity.ts +97 -0
  72. package/src/lib/famix/model/famix/class.ts +85 -0
  73. package/src/lib/famix/model/famix/comment.ts +47 -0
  74. package/src/lib/famix/model/famix/concretisation.ts +40 -0
  75. package/src/lib/famix/model/famix/container_entity.ts +160 -0
  76. package/src/lib/famix/model/famix/decorator.ts +37 -0
  77. package/src/lib/famix/model/famix/enum.ts +30 -0
  78. package/src/lib/famix/model/famix/enum_value.ts +28 -0
  79. package/src/lib/famix/model/famix/import_clause.ts +51 -0
  80. package/src/lib/famix/{src/model → model}/famix/index.ts +2 -4
  81. package/src/lib/famix/model/famix/indexed_file_anchor.ts +46 -0
  82. package/src/lib/famix/model/famix/inheritance.ts +40 -0
  83. package/src/lib/famix/model/famix/interface.ts +75 -0
  84. package/src/lib/famix/model/famix/invocation.ts +65 -0
  85. package/src/lib/famix/model/famix/method.ts +89 -0
  86. package/src/lib/famix/model/famix/module.ts +71 -0
  87. package/src/lib/famix/model/famix/named_entity.ts +95 -0
  88. package/src/lib/famix/{src/model → model}/famix/parameter.ts +11 -12
  89. package/src/lib/famix/model/famix/parameter_concretisation.ts +51 -0
  90. package/src/lib/famix/model/famix/parameter_type.ts +58 -0
  91. package/src/lib/famix/model/famix/parametric_arrow_function.ts +32 -0
  92. package/src/lib/famix/model/famix/parametric_class.ts +49 -0
  93. package/src/lib/famix/model/famix/parametric_function.ts +32 -0
  94. package/src/lib/famix/model/famix/parametric_interface.ts +49 -0
  95. package/src/lib/famix/model/famix/parametric_method.ts +32 -0
  96. package/src/lib/famix/model/famix/primitive_type.ts +15 -0
  97. package/src/lib/famix/model/famix/property.ts +94 -0
  98. package/src/lib/famix/model/famix/reference.ts +40 -0
  99. package/src/lib/famix/model/famix/scoping_entity.ts +35 -0
  100. package/src/lib/famix/model/famix/script_entity.ts +34 -0
  101. package/src/lib/famix/model/famix/source_anchor.ts +30 -0
  102. package/src/lib/famix/model/famix/source_language.ts +35 -0
  103. package/src/lib/famix/model/famix/sourced_entity.ts +70 -0
  104. package/src/lib/famix/model/famix/structural_entity.ts +43 -0
  105. package/src/lib/famix/model/famix/type.ts +87 -0
  106. package/src/lib/famix/model/famix/variable.ts +27 -0
  107. package/src/lib/famix/package.json +1 -1
  108. package/src/lib/ts-complex/cyclomatic-service.ts +10 -10
  109. package/src/refactorer/refactor-getter-setter.ts +140 -0
  110. package/src/ts2famix-cli-wrapper.ts +6 -2
  111. package/src/ts2famix-cli.ts +1 -1
  112. package/tsconfig.check-tests.json +14 -0
  113. package/tsconfig.json +70 -68
  114. package/dist/famix2puml.js +0 -126
  115. package/dist/lib/famix/src/famix_JSON_exporter.js +0 -55
  116. package/dist/lib/famix/src/famix_base_element.js +0 -18
  117. package/dist/lib/famix/src/famix_repository.js +0 -223
  118. package/dist/lib/famix/src/model/famix/access.js +0 -40
  119. package/dist/lib/famix/src/model/famix/accessor.js +0 -17
  120. package/dist/lib/famix/src/model/famix/alias.js +0 -33
  121. package/dist/lib/famix/src/model/famix/arrowFunction.js +0 -17
  122. package/dist/lib/famix/src/model/famix/behavioral_entity.js +0 -79
  123. package/dist/lib/famix/src/model/famix/class.js +0 -71
  124. package/dist/lib/famix/src/model/famix/comment.js +0 -39
  125. package/dist/lib/famix/src/model/famix/concretisation.js +0 -31
  126. package/dist/lib/famix/src/model/famix/container_entity.js +0 -126
  127. package/dist/lib/famix/src/model/famix/decorator.js +0 -32
  128. package/dist/lib/famix/src/model/famix/entity.js +0 -17
  129. package/dist/lib/famix/src/model/famix/enum.js +0 -31
  130. package/dist/lib/famix/src/model/famix/enum_value.js +0 -25
  131. package/dist/lib/famix/src/model/famix/function.js +0 -17
  132. package/dist/lib/famix/src/model/famix/implicit_variable.js +0 -17
  133. package/dist/lib/famix/src/model/famix/import_clause.js +0 -41
  134. package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +0 -52
  135. package/dist/lib/famix/src/model/famix/inheritance.js +0 -33
  136. package/dist/lib/famix/src/model/famix/interface.js +0 -64
  137. package/dist/lib/famix/src/model/famix/invocation.js +0 -54
  138. package/dist/lib/famix/src/model/famix/method.js +0 -67
  139. package/dist/lib/famix/src/model/famix/module.js +0 -84
  140. package/dist/lib/famix/src/model/famix/named_entity.js +0 -78
  141. package/dist/lib/famix/src/model/famix/parameter.js +0 -25
  142. package/dist/lib/famix/src/model/famix/parameterConcretisation.js +0 -44
  143. package/dist/lib/famix/src/model/famix/parameter_type.js +0 -45
  144. package/dist/lib/famix/src/model/famix/parametric_arrow_function.js +0 -31
  145. package/dist/lib/famix/src/model/famix/parametric_class.js +0 -44
  146. package/dist/lib/famix/src/model/famix/parametric_function.js +0 -31
  147. package/dist/lib/famix/src/model/famix/parametric_interface.js +0 -44
  148. package/dist/lib/famix/src/model/famix/parametric_method.js +0 -31
  149. package/dist/lib/famix/src/model/famix/primitive_type.js +0 -17
  150. package/dist/lib/famix/src/model/famix/property.js +0 -126
  151. package/dist/lib/famix/src/model/famix/reference.js +0 -33
  152. package/dist/lib/famix/src/model/famix/scoping_entity.js +0 -37
  153. package/dist/lib/famix/src/model/famix/script_entity.js +0 -29
  154. package/dist/lib/famix/src/model/famix/source_anchor.js +0 -27
  155. package/dist/lib/famix/src/model/famix/source_language.js +0 -35
  156. package/dist/lib/famix/src/model/famix/sourced_entity.js +0 -60
  157. package/dist/lib/famix/src/model/famix/structural_entity.js +0 -39
  158. package/dist/lib/famix/src/model/famix/text_anchor.js +0 -38
  159. package/dist/lib/famix/src/model/famix/type.js +0 -73
  160. package/dist/lib/famix/src/model/famix/variable.js +0 -24
  161. package/jest.config-old.ts +0 -199
  162. package/src/famix2puml.ts +0 -119
  163. package/src/lib/famix/package-lock.json +0 -301
  164. package/src/lib/famix/readme.md +0 -5
  165. package/src/lib/famix/src/famix_JSON_exporter.ts +0 -56
  166. package/src/lib/famix/src/famix_base_element.ts +0 -22
  167. package/src/lib/famix/src/famix_repository.ts +0 -243
  168. package/src/lib/famix/src/model/famix/access.ts +0 -53
  169. package/src/lib/famix/src/model/famix/alias.ts +0 -41
  170. package/src/lib/famix/src/model/famix/behavioral_entity.ts +0 -100
  171. package/src/lib/famix/src/model/famix/class.ts +0 -86
  172. package/src/lib/famix/src/model/famix/comment.ts +0 -50
  173. package/src/lib/famix/src/model/famix/concretisation.ts +0 -42
  174. package/src/lib/famix/src/model/famix/container_entity.ts +0 -165
  175. package/src/lib/famix/src/model/famix/decorator.ts +0 -39
  176. package/src/lib/famix/src/model/famix/enum.ts +0 -31
  177. package/src/lib/famix/src/model/famix/enum_value.ts +0 -29
  178. package/src/lib/famix/src/model/famix/implicit_variable.ts +0 -15
  179. package/src/lib/famix/src/model/famix/import_clause.ts +0 -54
  180. package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +0 -71
  181. package/src/lib/famix/src/model/famix/inheritance.ts +0 -41
  182. package/src/lib/famix/src/model/famix/interface.ts +0 -75
  183. package/src/lib/famix/src/model/famix/invocation.ts +0 -68
  184. package/src/lib/famix/src/model/famix/method.ts +0 -96
  185. package/src/lib/famix/src/model/famix/module.ts +0 -97
  186. package/src/lib/famix/src/model/famix/named_entity.ts +0 -98
  187. package/src/lib/famix/src/model/famix/parameterConcretisation.ts +0 -54
  188. package/src/lib/famix/src/model/famix/parameter_type.ts +0 -60
  189. package/src/lib/famix/src/model/famix/parametric_arrow_function.ts +0 -32
  190. package/src/lib/famix/src/model/famix/parametric_class.ts +0 -49
  191. package/src/lib/famix/src/model/famix/parametric_function.ts +0 -32
  192. package/src/lib/famix/src/model/famix/parametric_interface.ts +0 -49
  193. package/src/lib/famix/src/model/famix/parametric_method.ts +0 -32
  194. package/src/lib/famix/src/model/famix/primitive_type.ts +0 -15
  195. package/src/lib/famix/src/model/famix/property.ts +0 -152
  196. package/src/lib/famix/src/model/famix/reference.ts +0 -42
  197. package/src/lib/famix/src/model/famix/scoping_entity.ts +0 -36
  198. package/src/lib/famix/src/model/famix/script_entity.ts +0 -36
  199. package/src/lib/famix/src/model/famix/source_anchor.ts +0 -31
  200. package/src/lib/famix/src/model/famix/source_language.ts +0 -36
  201. package/src/lib/famix/src/model/famix/sourced_entity.ts +0 -73
  202. package/src/lib/famix/src/model/famix/structural_entity.ts +0 -44
  203. package/src/lib/famix/src/model/famix/text_anchor.ts +0 -49
  204. package/src/lib/famix/src/model/famix/type.ts +0 -89
  205. package/src/lib/famix/src/model/famix/variable.ts +0 -28
  206. package/src/lib/famix/tsconfig.json +0 -27
  207. package/src/lib/famix/tslint.json +0 -15
  208. /package/src/lib/famix/{src/index.ts → index.ts} +0 -0
  209. /package/src/lib/famix/{src/model → model}/famix/accessor.ts +0 -0
  210. /package/src/lib/famix/{src/model/famix/arrowFunction.ts → model/famix/arrow_function.ts} +0 -0
  211. /package/src/lib/famix/{src/model → model}/famix/entity.ts +0 -0
  212. /package/src/lib/famix/{src/model → model}/famix/function.ts +0 -0
@@ -1,17 +1,21 @@
1
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, ImportDeclaration, ImportEqualsDeclaration, SyntaxKind, Expression, TypeNode, Node, ts, Scope, Type, ArrowFunction } from "ts-morph";
2
2
  import { isAmbient, isNamespace } from "../analyze_functions/process_functions";
3
- import * as Famix from "../lib/famix/src/model/famix";
3
+ import * as Famix from "../lib/famix/model/famix";
4
+ import { FamixRepository } from "../lib/famix/famix_repository";
4
5
  import { logger, config } from "../analyze";
5
6
  import GraphemeSplitter from "grapheme-splitter";
6
7
  import * as Helpers from "./helpers_creation";
7
8
  import * as FQNFunctions from "../fqn";
8
- import { FamixRepository } from "../lib/famix/src/famix_repository";
9
9
  import path from "path";
10
10
  import _ from 'lodash';
11
11
 
12
12
  export type TSMorphObjectType = ImportDeclaration | ImportEqualsDeclaration | SourceFile | ModuleDeclaration | ClassDeclaration | InterfaceDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | PropertyDeclaration | PropertySignature | TypeParameterDeclaration | Identifier | Decorator | GetAccessorDeclaration | SetAccessorDeclaration | ImportSpecifier | CommentRange | EnumDeclaration | EnumMember | TypeAliasDeclaration | ExpressionWithTypeArguments;
13
13
 
14
- export type TypeDeclaration = TypeAliasDeclaration | PropertyDeclaration | PropertySignature | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | EnumMember;
14
+ export type TypeDeclaration = TypeAliasDeclaration | PropertyDeclaration | PropertySignature | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | EnumMember | ImportEqualsDeclaration;
15
+
16
+ type ParametricVariantType = Famix.ParametricClass | Famix.ParametricInterface | Famix.ParametricFunction | Famix.ParametricMethod;
17
+
18
+ type ConcreteElementTSMorphType = ClassDeclaration | InterfaceDeclaration | FunctionDeclaration | MethodDeclaration;
15
19
 
16
20
  export class EntityDictionary {
17
21
 
@@ -25,20 +29,86 @@ export class EntityDictionary {
25
29
  private fmxFunctionAndMethodMap = new Map<string, Famix.Function | Famix.ParametricFunction | Famix.Method | Famix.ParametricMethod> // Maps the function names to their Famix model
26
30
  private UNKNOWN_VALUE = '(unknown due to parsing error)'; // The value to use when a name is not usable
27
31
  public fmxElementObjectMap = new Map<Famix.Entity,TSMorphObjectType>();
32
+ public tsMorphElementObjectMap = new Map<TSMorphObjectType,Famix.Entity>();
28
33
 
29
34
  constructor() {
30
35
  this.famixRep.setFmxElementObjectMap(this.fmxElementObjectMap);
31
36
  }
32
37
 
38
+ public addSourceAnchor(fmx: Famix.SourcedEntity, node: TSMorphObjectType): Famix.IndexedFileAnchor {
39
+ const sourceAnchor: Famix.IndexedFileAnchor = new Famix.IndexedFileAnchor();
40
+ let sourceStart, sourceEnd: number;
41
+ if (fmx && node) {
42
+ // find the start and end positions of the source element
43
+ if (!(node instanceof CommentRange)) {
44
+ sourceStart = node.getStart();
45
+ sourceEnd = node.getEnd();
46
+ } else {
47
+ sourceStart = node.getPos();
48
+ sourceEnd = node.getEnd();
49
+ }
50
+
51
+ if (config.expectGraphemes) {
52
+ /**
53
+ * The following logic handles the case of multi-code point characters (e.g. emoji) in the source text.
54
+ * This is needed because Pharo/Smalltalk treats multi-code point characters as a single character,
55
+ * but JavaScript treats them as multiple characters. This means that the start and end positions
56
+ * of a source element in Pharo/Smalltalk will be different than the start and end positions of the
57
+ * same source element in JavaScript. This logic finds the start and end positions of the source
58
+ * element in JavaScript and then uses those positions to set the start and end positions of the
59
+ * Famix index file anchor.
60
+ * It depends on code in the 'grapheme-splitter' package in npm.
61
+ */
62
+ const splitter = new GraphemeSplitter();
63
+ const sourceFileText = node.getSourceFile().getFullText();
64
+ const hasGraphemeClusters = splitter.countGraphemes(sourceFileText) > 1;
65
+ if (hasGraphemeClusters) {
66
+ const sourceElementText = sourceFileText.substring(sourceStart, sourceEnd);
67
+ const sourceElementTextGraphemes = splitter.splitGraphemes(sourceElementText);
68
+ const sourceFileTextGraphemes = splitter.splitGraphemes(sourceFileText);
69
+ const numberOfGraphemeClustersBeforeStart = splitter.countGraphemes(sourceFileText.substring(0, sourceStart));
70
+
71
+ // find the start of the sourceElementTextGraphemes array in the sourceFileTextGraphemes array
72
+ sourceStart = Helpers.indexOfSplitArray({searchArray: sourceFileTextGraphemes,
73
+ targetArray: sourceElementTextGraphemes,
74
+ start: sourceStart - numberOfGraphemeClustersBeforeStart});
75
+ sourceEnd = sourceStart + sourceElementTextGraphemes.length;
76
+ }
77
+ }
78
+
79
+ // The +1 is because the source anchor (Pharo) is 1-based, but ts-morph is 0-based
80
+ sourceAnchor.startPos = sourceStart + 1;
81
+ sourceAnchor.endPos = sourceEnd + 1;
82
+
83
+ const fileName = node.getSourceFile().getFilePath();
84
+
85
+ sourceAnchor.element = fmx;
86
+ sourceAnchor.fileName = fileName;
87
+ fmx.sourceAnchor = sourceAnchor;
88
+ this.famixRep.addElement(sourceAnchor);
89
+
90
+ }
91
+ return sourceAnchor;
92
+ }
93
+
33
94
  /**
34
95
  * Makes a Famix index file anchor
35
96
  * @param sourceElement A source element
36
97
  * @param famixElement The Famix model of the source element
37
98
  */
38
99
  public makeFamixIndexFileAnchor(sourceElement: TSMorphObjectType, famixElement: Famix.SourcedEntity): void {
100
+ // check if famixElement doesn't have a valid fullyQualifiedName
101
+ if (typeof (famixElement as any).getFullyQualifiedName === 'function') {
102
+ // The method exists
103
+ const fullyQualifiedName = (famixElement as any).fullyQualifiedName;
104
+ if (!fullyQualifiedName || fullyQualifiedName === this.UNKNOWN_VALUE) {
105
+ throw new Error(`Famix element ${famixElement.constructor.name} has no valid fullyQualifiedName.`);
106
+ }
107
+ }
108
+
39
109
  logger.debug("making index file anchor for '" + sourceElement?.getText() + "' with famixElement " + famixElement.getJSON());
40
110
  const fmxIndexFileAnchor = new Famix.IndexedFileAnchor();
41
- fmxIndexFileAnchor.setElement(famixElement);
111
+ fmxIndexFileAnchor.element = famixElement;
42
112
  this.fmxElementObjectMap.set(famixElement, sourceElement);
43
113
 
44
114
  if (sourceElement !== null) {
@@ -60,7 +130,7 @@ export class EntityDictionary {
60
130
  // revert any backslashes to forward slashes (path.normalize on windows introduces them)
61
131
  pathInProject = pathInProject.replace(/\\/g, "/");
62
132
 
63
- fmxIndexFileAnchor.setFileName(pathInProject);
133
+ fmxIndexFileAnchor.fileName = pathInProject;
64
134
  let sourceStart, sourceEnd, sourceLineStart, sourceLineEnd: number;
65
135
  if (!(sourceElement instanceof CommentRange)) {
66
136
  sourceStart = sourceElement.getStart();
@@ -99,24 +169,18 @@ export class EntityDictionary {
99
169
  }
100
170
  }
101
171
  // note: the +1 is because the source anchor is 1-based, but ts-morph is 0-based
102
- fmxIndexFileAnchor.setStartPos(sourceStart + 1);
103
- fmxIndexFileAnchor.setEndPos(sourceEnd + 1);
104
- if (!(sourceElement instanceof CommentRange)) {
105
- fmxIndexFileAnchor.setStartLine(sourceLineStart);
106
- fmxIndexFileAnchor.setEndLine(sourceLineEnd);
107
- }
172
+ fmxIndexFileAnchor.startPos = sourceStart + 1;
173
+ fmxIndexFileAnchor.endPos = sourceEnd + 1;
108
174
 
109
- if (!(famixElement instanceof Famix.ImportClause || famixElement instanceof Famix.Access || famixElement instanceof Famix.Reference || famixElement instanceof Famix.Invocation || famixElement instanceof Famix.Inheritance) && !(famixElement instanceof Famix.Comment) && !(sourceElement instanceof CommentRange) && !(sourceElement instanceof Identifier) && !(sourceElement instanceof ImportSpecifier) && !(sourceElement instanceof ExpressionWithTypeArguments)) {
110
- const fqn = FQNFunctions.getFQN(sourceElement);
111
- logger.debug("Setting fully qualified name for " + famixElement.getJSON() + " to " + fqn);
112
- (famixElement as Famix.NamedEntity).setFullyQualifiedName(fqn);
113
- }
175
+ // if (!(famixElement instanceof Famix.ImportClause || famixElement instanceof Famix.Access || famixElement instanceof Famix.Reference || famixElement instanceof Famix.Invocation || famixElement instanceof Famix.Inheritance) && !(famixElement instanceof Famix.Comment) && !(sourceElement instanceof CommentRange) && !(sourceElement instanceof Identifier) && !(sourceElement instanceof ImportSpecifier) && !(sourceElement instanceof ExpressionWithTypeArguments)) {
176
+ // initFQN(sourceElement, famixElement);
177
+ // }
114
178
  } else {
115
179
  // sourceElement is null
116
180
  logger.warn("sourceElement is null for famixElement " + famixElement.getJSON());
117
- fmxIndexFileAnchor.setFileName("unknown");
118
- fmxIndexFileAnchor.setStartPos(0);
119
- fmxIndexFileAnchor.setEndPos(0);
181
+ fmxIndexFileAnchor.fileName = "unknown";
182
+ fmxIndexFileAnchor.startPos = 0;
183
+ fmxIndexFileAnchor.endPos = 0;
120
184
  }
121
185
 
122
186
  this.famixRep.addElement(fmxIndexFileAnchor);
@@ -133,16 +197,19 @@ export class EntityDictionary {
133
197
 
134
198
  const fileName = f.getBaseName();
135
199
  const fullyQualifiedFilename = f.getFilePath();
136
- if (!this.fmxFileMap.has(fullyQualifiedFilename)) {
200
+ const foundFileName = this.fmxFileMap.get(fullyQualifiedFilename);
201
+ if (!foundFileName) {
137
202
  if (isModule) {
138
203
  fmxFile = new Famix.Module();
139
204
  }
140
205
  else {
141
206
  fmxFile = new Famix.ScriptEntity();
142
207
  }
143
- fmxFile.setName(fileName);
144
- fmxFile.setNumberOfLinesOfText(f.getEndLineNumber() - f.getStartLineNumber());
145
- fmxFile.setNumberOfCharacters(f.getFullText().length);
208
+ fmxFile.name = fileName;
209
+ fmxFile.numberOfLinesOfText = f.getEndLineNumber() - f.getStartLineNumber();
210
+ fmxFile.numberOfCharacters = f.getFullText().length;
211
+
212
+ initFQN(f, fmxFile);
146
213
 
147
214
  this.makeFamixIndexFileAnchor(f, fmxFile);
148
215
 
@@ -150,7 +217,7 @@ export class EntityDictionary {
150
217
  this.famixRep.addElement(fmxFile);
151
218
  }
152
219
  else {
153
- fmxFile = this.fmxFileMap.get(fullyQualifiedFilename);
220
+ fmxFile = foundFileName;
154
221
  }
155
222
 
156
223
  this.fmxElementObjectMap.set(fmxFile,f);
@@ -165,13 +232,15 @@ export class EntityDictionary {
165
232
  public createOrGetFamixModule(m: ModuleDeclaration): Famix.Module {
166
233
  let fmxModule: Famix.Module;
167
234
  const moduleName = m.getName();
168
- if (!this.fmxModuleMap.has(moduleName)) {
235
+ const foundModuleName = this.fmxModuleMap.get(moduleName);
236
+ if (!foundModuleName) {
169
237
  fmxModule = new Famix.Module();
170
- fmxModule.setName(moduleName);
171
- fmxModule.$isAmbient = isAmbient(m);
172
- fmxModule.$isNamespace = isNamespace(m);
173
- fmxModule.$isModule = !fmxModule.$isNamespace && !fmxModule.$isAmbient;
238
+ fmxModule.name = moduleName;
239
+ fmxModule.isAmbient = isAmbient(m);
240
+ fmxModule.isNamespace = isNamespace(m);
241
+ fmxModule.isModule = !fmxModule.isNamespace && !fmxModule.isAmbient;
174
242
 
243
+ initFQN(m, fmxModule);
175
244
  this.makeFamixIndexFileAnchor(m, fmxModule);
176
245
 
177
246
  this.fmxModuleMap.set(moduleName, fmxModule);
@@ -179,7 +248,7 @@ export class EntityDictionary {
179
248
  this.famixRep.addElement(fmxModule);
180
249
  }
181
250
  else {
182
- fmxModule = this.fmxModuleMap.get(moduleName);
251
+ fmxModule = foundModuleName;
183
252
  }
184
253
 
185
254
  this.fmxElementObjectMap.set(fmxModule,m);
@@ -195,15 +264,16 @@ export class EntityDictionary {
195
264
  let fmxAlias: Famix.Alias;
196
265
  const aliasName = a.getName();
197
266
  const aliasFullyQualifiedName = a.getType().getText(); // FQNFunctions.getFQN(a);
198
- if (!this.fmxAliasMap.has(aliasFullyQualifiedName)) {
267
+ const foundAlias = this.fmxAliasMap.get(aliasFullyQualifiedName);
268
+ if (!foundAlias) {
199
269
  fmxAlias = new Famix.Alias();
200
- fmxAlias.setName(a.getName());
270
+ fmxAlias.name = a.getName();
201
271
  const aliasNameWithGenerics = aliasName + (a.getTypeParameters().length ? ("<" + a.getTypeParameters().map(tp => tp.getName()).join(", ") + ">") : "");
202
272
  logger.debug(`> NOTE: alias ${aliasName} has fully qualified name ${aliasFullyQualifiedName} and name with generics ${aliasNameWithGenerics}.`);
203
273
 
204
274
  const fmxType = this.createOrGetFamixType(aliasNameWithGenerics, a);
205
- fmxAlias.setAliasedEntity(fmxType);
206
-
275
+ fmxAlias.aliasedEntity = fmxType;
276
+ initFQN(a, fmxAlias);
207
277
  this.makeFamixIndexFileAnchor(a, fmxAlias);
208
278
 
209
279
  this.fmxAliasMap.set(aliasFullyQualifiedName, fmxAlias);
@@ -211,7 +281,7 @@ export class EntityDictionary {
211
281
  this.famixRep.addElement(fmxAlias);
212
282
  }
213
283
  else {
214
- fmxAlias = this.fmxAliasMap.get(aliasFullyQualifiedName);
284
+ fmxAlias = foundAlias;
215
285
  }
216
286
  this.fmxElementObjectMap.set(fmxAlias,a);
217
287
 
@@ -227,9 +297,10 @@ export class EntityDictionary {
227
297
  let fmxClass: Famix.Class | Famix.ParametricClass;
228
298
  const isAbstract = cls.isAbstract();
229
299
  const classFullyQualifiedName = FQNFunctions.getFQN(cls);
230
- const clsName = cls.getName();
300
+ const clsName = cls.getName() || this.UNKNOWN_VALUE;
231
301
  const isGeneric = cls.getTypeParameters().length;
232
- if (!this.fmxClassMap.has(classFullyQualifiedName)) {
302
+ const foundClass = this.fmxClassMap.get(classFullyQualifiedName);
303
+ if (!foundClass) {
233
304
  if (isGeneric) {
234
305
  fmxClass = new Famix.ParametricClass();
235
306
  }
@@ -237,9 +308,9 @@ export class EntityDictionary {
237
308
  fmxClass = new Famix.Class();
238
309
  }
239
310
 
240
- fmxClass.setName(clsName);
241
- fmxClass.setFullyQualifiedName(classFullyQualifiedName);
242
- fmxClass.setIsAbstract(isAbstract);
311
+ fmxClass.name = clsName;
312
+ fmxClass.fullyQualifiedName = classFullyQualifiedName;
313
+ fmxClass.isAbstract = isAbstract;
243
314
 
244
315
  this.makeFamixIndexFileAnchor(cls, fmxClass);
245
316
 
@@ -250,7 +321,7 @@ export class EntityDictionary {
250
321
  this.fmxElementObjectMap.set(fmxClass,cls);
251
322
  }
252
323
  else {
253
- fmxClass = this.fmxClassMap.get(classFullyQualifiedName) as (Famix.Class | Famix.ParametricClass);
324
+ fmxClass = foundClass;
254
325
  }
255
326
 
256
327
  return fmxClass;
@@ -262,10 +333,12 @@ export class EntityDictionary {
262
333
  * @returns The Famix model of the interface
263
334
  */
264
335
  public createOrGetFamixInterface(inter: InterfaceDeclaration): Famix.Interface | Famix.ParametricInterface {
336
+
265
337
  let fmxInterface: Famix.Interface | Famix.ParametricInterface;
266
338
  const interName = inter.getName();
267
339
  const interFullyQualifiedName = FQNFunctions.getFQN(inter);
268
- if (!this.fmxInterfaceMap.has(interFullyQualifiedName)) {
340
+ const foundInterface = this.fmxInterfaceMap.get(interFullyQualifiedName);
341
+ if (!foundInterface) {
269
342
  const isGeneric = inter.getTypeParameters().length;
270
343
  if (isGeneric) {
271
344
  fmxInterface = new Famix.ParametricInterface();
@@ -274,8 +347,8 @@ export class EntityDictionary {
274
347
  fmxInterface = new Famix.Interface();
275
348
  }
276
349
 
277
- fmxInterface.setName(interName);
278
-
350
+ fmxInterface.name = interName;
351
+ initFQN(inter, fmxInterface);
279
352
  this.makeFamixIndexFileAnchor(inter, fmxInterface);
280
353
 
281
354
  this.fmxInterfaceMap.set(interFullyQualifiedName, fmxInterface);
@@ -285,21 +358,24 @@ export class EntityDictionary {
285
358
  this.fmxElementObjectMap.set(fmxInterface,inter);
286
359
  }
287
360
  else {
288
- fmxInterface = this.fmxInterfaceMap.get(interFullyQualifiedName) as (Famix.Interface | Famix.ParametricInterface);
361
+ fmxInterface = foundInterface;
289
362
  }
290
363
  return fmxInterface;
291
364
  }
292
365
 
366
+
293
367
  /**
294
368
  * Creates or gets a Famix concrete element
295
- * @param el A parametric Element
296
- * @param elDeclaration the element declaration
369
+ * @param concreteElement A parametric Element
370
+ * @param concreteElementDeclaration the element declaration
297
371
  * @param concreteArguments concrete arguments
298
372
  * @returns A parametric Element
299
373
  */
300
- public createOrGetFamixConcreteElement(el : Famix.ParametricClass | Famix.ParametricInterface | Famix.ParametricFunction | Famix.ParametricMethod, elDeclaration : ClassDeclaration | InterfaceDeclaration | FunctionDeclaration | MethodDeclaration, concreteArguments : any): Famix.ParametricClass | Famix.ParametricInterface | Famix.ParametricFunction | Famix.ParametricMethod {
374
+ public createOrGetFamixConcreteElement(concreteElement : ParametricVariantType,
375
+ concreteElementDeclaration : ConcreteElementTSMorphType,
376
+ concreteArguments: TypeNode[]): ParametricVariantType {
301
377
 
302
- let fullyQualifiedFilename = el.getFullyQualifiedName();
378
+ let fullyQualifiedFilename = concreteElement.fullyQualifiedName;
303
379
  let params = "";
304
380
 
305
381
  concreteArguments.map((param) => {
@@ -310,37 +386,39 @@ export class EntityDictionary {
310
386
 
311
387
  fullyQualifiedFilename = Helpers.replaceLastBetweenTags(fullyQualifiedFilename,params);
312
388
 
313
- let concElement;
389
+ let concElement: ParametricVariantType;
314
390
 
315
- if (!this.fmxInterfaceMap.has(fullyQualifiedFilename) && !this.fmxClassMap.has(fullyQualifiedFilename) && !this.fmxFunctionAndMethodMap.has(fullyQualifiedFilename)){
316
- concElement = _.cloneDeep(el);
317
- concElement.setFullyQualifiedName(fullyQualifiedFilename);
391
+ if (!this.fmxInterfaceMap.has(fullyQualifiedFilename) &&
392
+ !this.fmxClassMap.has(fullyQualifiedFilename) &&
393
+ !this.fmxFunctionAndMethodMap.has(fullyQualifiedFilename)){
394
+ concElement = _.cloneDeep(concreteElement);
395
+ concElement.fullyQualifiedName = fullyQualifiedFilename;
318
396
  concElement.clearGenericParameters();
319
397
  concreteArguments.map((param) => {
320
398
  const parameter = this.createOrGetFamixConcreteType(param);
321
399
  concElement.addConcreteParameter(parameter);
322
400
  })
323
401
 
324
- if (el instanceof Famix.ParametricClass) {
402
+ if (concreteElement instanceof Famix.ParametricClass) {
325
403
  this.fmxClassMap.set(fullyQualifiedFilename, concElement as Famix.ParametricClass);
326
- } else if (el instanceof Famix.ParametricInterface) {
404
+ } else if (concreteElement instanceof Famix.ParametricInterface) {
327
405
  this.fmxInterfaceMap.set(fullyQualifiedFilename, concElement as Famix.ParametricInterface);
328
- } else if (el instanceof Famix.ParametricFunction) {
406
+ } else if (concreteElement instanceof Famix.ParametricFunction) {
329
407
  this.fmxFunctionAndMethodMap.set(fullyQualifiedFilename, concElement as Famix.ParametricFunction);
330
- } else if (el instanceof Famix.ParametricMethod) {
408
+ } else { // if (concreteElement instanceof Famix.ParametricMethod) {
331
409
  this.fmxFunctionAndMethodMap.set(fullyQualifiedFilename, concElement as Famix.ParametricMethod);
332
410
  }
333
411
  this.famixRep.addElement(concElement);
334
- this.fmxElementObjectMap.set(concElement,elDeclaration);
412
+ this.fmxElementObjectMap.set(concElement,concreteElementDeclaration);
335
413
  } else {
336
- if (el instanceof Famix.ParametricClass) {
337
- concElement = this.fmxClassMap.get(fullyQualifiedFilename);
338
- } else if (el instanceof Famix.ParametricInterface) {
339
- concElement = this.fmxInterfaceMap.get(fullyQualifiedFilename);
340
- } else if (el instanceof Famix.ParametricFunction) {
341
- concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename);
342
- } else if (el instanceof Famix.ParametricMethod) {
343
- concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename);
414
+ if (concreteElement instanceof Famix.ParametricClass) {
415
+ concElement = this.fmxClassMap.get(fullyQualifiedFilename) as Famix.ParametricClass;
416
+ } else if (concreteElement instanceof Famix.ParametricInterface) {
417
+ concElement = this.fmxInterfaceMap.get(fullyQualifiedFilename) as Famix.ParametricInterface;
418
+ } else if (concreteElement instanceof Famix.ParametricFunction) {
419
+ concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename) as Famix.ParametricFunction;
420
+ } else { // if (concreteElement instanceof Famix.ParametricMethod) {
421
+ concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename) as Famix.ParametricMethod;
344
422
  }
345
423
  }
346
424
  return concElement;
@@ -354,7 +432,7 @@ export class EntityDictionary {
354
432
  public createFamixProperty(property: PropertyDeclaration | PropertySignature): Famix.Property {
355
433
  const fmxProperty = new Famix.Property();
356
434
  const isSignature = property instanceof PropertySignature;
357
- fmxProperty.setName(property.getName());
435
+ fmxProperty.name = property.getName();
358
436
 
359
437
  let propTypeName = this.UNKNOWN_VALUE;
360
438
  try {
@@ -364,7 +442,7 @@ export class EntityDictionary {
364
442
  }
365
443
 
366
444
  const fmxType = this.createOrGetFamixType(propTypeName, property);
367
- fmxProperty.setDeclaredType(fmxType);
445
+ fmxProperty.declaredType = fmxType;
368
446
 
369
447
  // add the visibility (public, private, etc.) to the fmxProperty
370
448
  fmxProperty.visibility = "";
@@ -381,7 +459,7 @@ export class EntityDictionary {
381
459
  fmxProperty.visibility = "private";
382
460
  break;
383
461
  case "static":
384
- fmxProperty.setIsClassSide(true);
462
+ fmxProperty.isClassSide = true;
385
463
  break;
386
464
  case "readonly":
387
465
  fmxProperty.readOnly = true;
@@ -401,6 +479,7 @@ export class EntityDictionary {
401
479
  fmxProperty.isJavaScriptPrivate = true;
402
480
  }
403
481
 
482
+ initFQN(property, fmxProperty);
404
483
  this.makeFamixIndexFileAnchor(property, fmxProperty);
405
484
 
406
485
  this.famixRep.addElement(fmxProperty);
@@ -416,7 +495,7 @@ export class EntityDictionary {
416
495
  * @param currentCC The cyclomatic complexity metrics of the current source file
417
496
  * @returns The Famix model of the method or the accessor
418
497
  */
419
- public createOrGetFamixMethod(method: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration, currentCC: unknown): Famix.Method | Famix.Accessor | Famix.ParametricMethod {
498
+ public createOrGetFamixMethod(method: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration, currentCC: { [key: string]: number }): Famix.Method | Famix.Accessor | Famix.ParametricMethod {
420
499
  let fmxMethod: Famix.Method | Famix.Accessor | Famix.ParametricMethod;
421
500
  const isGeneric = method.getTypeParameters().length > 0;
422
501
  const functionFullyQualifiedName = FQNFunctions.getFQN(method);
@@ -426,8 +505,8 @@ export class EntityDictionary {
426
505
  fmxMethod = new Famix.Accessor();
427
506
  const isGetter = method instanceof GetAccessorDeclaration;
428
507
  const isSetter = method instanceof SetAccessorDeclaration;
429
- if (isGetter) {(fmxMethod as Famix.Accessor).setKind("getter");}
430
- if (isSetter) {(fmxMethod as Famix.Accessor).setKind("setter");}
508
+ if (isGetter) {(fmxMethod as Famix.Accessor).kind = "getter";}
509
+ if (isSetter) {(fmxMethod as Famix.Accessor).kind = "setter";}
431
510
  this.famixRep.addElement(fmxMethod);
432
511
  }
433
512
  else {
@@ -449,12 +528,12 @@ export class EntityDictionary {
449
528
  isStatic = method.isStatic();
450
529
  }
451
530
 
452
- if (isConstructor) {(fmxMethod as Famix.Accessor).setKind("constructor");}
453
- fmxMethod.setIsAbstract(isAbstract);
454
- fmxMethod.setIsClassSide(isStatic);
455
- fmxMethod.setIsPrivate((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false);
456
- fmxMethod.setIsProtected((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false);
457
- fmxMethod.setSignature(Helpers.computeSignature(method.getText()));
531
+ if (isConstructor) {(fmxMethod as Famix.Accessor).kind = "constructor";}
532
+ fmxMethod.isAbstract = isAbstract;
533
+ fmxMethod.isClassSide = isStatic;
534
+ fmxMethod.isPrivate = (method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false;
535
+ fmxMethod.isProtected = (method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false;
536
+ fmxMethod.signature = Helpers.computeSignature(method.getText());
458
537
 
459
538
  let methodName: string;
460
539
  if (isConstructor) {
@@ -463,48 +542,49 @@ export class EntityDictionary {
463
542
  else {
464
543
  methodName = (method as MethodDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration).getName();
465
544
  }
466
- fmxMethod.setName(methodName);
545
+ fmxMethod.name = methodName;
467
546
 
468
547
  if (!isConstructor) {
469
548
  if (method.getName().substring(0, 1) === "#") {
470
- fmxMethod.setIsPrivate(true);
549
+ fmxMethod.isPrivate = true;
471
550
  }
472
551
  }
473
552
 
474
- if (!fmxMethod.getIsPrivate() && !fmxMethod.getIsProtected()) {
475
- fmxMethod.setIsPublic(true);
553
+ if (!fmxMethod.isPrivate && !fmxMethod.isProtected) {
554
+ fmxMethod.isPublic = true;
476
555
  }
477
556
  else {
478
- fmxMethod.setIsPublic(false);
557
+ fmxMethod.isPublic = false;
479
558
  }
480
559
 
481
560
  if (!isSignature) {
482
- fmxMethod.setCyclomaticComplexity(currentCC[fmxMethod.getName()]);
561
+ fmxMethod.cyclomaticComplexity = currentCC[fmxMethod.name];
483
562
  }
484
563
  else {
485
- fmxMethod.setCyclomaticComplexity(0);
564
+ fmxMethod.cyclomaticComplexity = 0;
486
565
  }
487
566
 
488
567
  let methodTypeName = this.UNKNOWN_VALUE;
489
568
  try {
490
569
  methodTypeName = method.getReturnType().getText().trim();
491
570
  } catch (error) {
492
- logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.getName()}. Continuing...`);
571
+ logger.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.name}. Continuing...`);
493
572
  }
494
573
 
495
574
  const fmxType = this.createOrGetFamixType(methodTypeName, method);
496
- fmxMethod.setDeclaredType(fmxType);
497
- fmxMethod.setNumberOfLinesOfCode(method.getEndLineNumber() - method.getStartLineNumber());
575
+ fmxMethod.declaredType = fmxType;
576
+ fmxMethod.numberOfLinesOfCode = method.getEndLineNumber() - method.getStartLineNumber();
498
577
  const parameters = method.getParameters();
499
- fmxMethod.setNumberOfParameters(parameters.length);
578
+ fmxMethod.numberOfParameters = parameters.length;
500
579
 
501
580
  if (!isSignature) {
502
- fmxMethod.setNumberOfStatements(method.getStatements().length);
581
+ fmxMethod.numberOfStatements = method.getStatements().length;
503
582
  }
504
583
  else {
505
- fmxMethod.setNumberOfStatements(0);
584
+ fmxMethod.numberOfStatements = 0;
506
585
  }
507
586
 
587
+ initFQN(method, fmxMethod);
508
588
  this.makeFamixIndexFileAnchor(method, fmxMethod);
509
589
 
510
590
  this.fmxFunctionAndMethodMap.set(functionFullyQualifiedName, fmxMethod);
@@ -524,7 +604,7 @@ export class EntityDictionary {
524
604
  * @param currentCC The cyclomatic complexity metrics of the current source file
525
605
  * @returns The Famix model of the function
526
606
  */
527
- public createOrGetFamixFunction(func: FunctionDeclaration | FunctionExpression, currentCC: unknown): Famix.Function | Famix.ParametricFunction {
607
+ public createOrGetFamixFunction(func: FunctionDeclaration | FunctionExpression, currentCC: { [key: string]: number }): Famix.Function | Famix.ParametricFunction {
528
608
  let fmxFunction: Famix.Function | Famix.ParametricFunction;
529
609
  const isGeneric = func.getTypeParameters().length > 0;
530
610
  const functionFullyQualifiedName = FQNFunctions.getFQN(func);
@@ -536,16 +616,17 @@ export class EntityDictionary {
536
616
  fmxFunction = new Famix.Function();
537
617
  }
538
618
 
539
- if (func.getName()) {
540
- fmxFunction.setName(func.getName());
619
+ const name = func.getName();
620
+ if (name) {
621
+ fmxFunction.name = name;
541
622
  }
542
623
  else {
543
- fmxFunction.setName("anonymous");
624
+ fmxFunction.name = "anonymous";
544
625
  }
545
626
 
546
- fmxFunction.setSignature(Helpers.computeSignature(func.getText()));
547
- fmxFunction.setCyclomaticComplexity(currentCC[fmxFunction.getName()]);
548
- fmxFunction.setFullyQualifiedName(functionFullyQualifiedName);
627
+ fmxFunction.signature = Helpers.computeSignature(func.getText());
628
+ fmxFunction.cyclomaticComplexity = currentCC[fmxFunction.name];
629
+ fmxFunction.fullyQualifiedName = functionFullyQualifiedName;
549
630
 
550
631
  let functionTypeName = this.UNKNOWN_VALUE;
551
632
  try {
@@ -555,12 +636,11 @@ export class EntityDictionary {
555
636
  }
556
637
 
557
638
  const fmxType = this.createOrGetFamixType(functionTypeName, func);
558
- fmxFunction.setDeclaredType(fmxType);
559
- fmxFunction.setNumberOfLinesOfCode(func.getEndLineNumber() - func.getStartLineNumber());
639
+ fmxFunction.declaredType = fmxType;
640
+ fmxFunction.numberOfLinesOfCode = func.getEndLineNumber() - func.getStartLineNumber();
560
641
  const parameters = func.getParameters();
561
- fmxFunction.setNumberOfParameters(parameters.length);
562
- fmxFunction.setNumberOfStatements(func.getStatements().length);
563
-
642
+ fmxFunction.numberOfParameters = parameters.length;
643
+ fmxFunction.numberOfStatements = func.getStatements().length;
564
644
  this.makeFamixIndexFileAnchor(func, fmxFunction);
565
645
 
566
646
  this.famixRep.addElement(fmxFunction);
@@ -592,9 +672,10 @@ export class EntityDictionary {
592
672
  }
593
673
 
594
674
  const fmxType = this.createOrGetFamixType(paramTypeName, param);
595
- fmxParam.setDeclaredType(fmxType);
596
- fmxParam.setName(param.getName());
675
+ fmxParam.declaredType = fmxType;
676
+ fmxParam.name = param.getName();
597
677
 
678
+ initFQN(param, fmxParam);
598
679
  this.makeFamixIndexFileAnchor(param, fmxParam);
599
680
 
600
681
  this.famixRep.addElement(fmxParam);
@@ -613,8 +694,8 @@ export class EntityDictionary {
613
694
 
614
695
  const fmxParameterType = new Famix.ParameterType();
615
696
 
616
- fmxParameterType.setName(tp.getName());
617
-
697
+ fmxParameterType.name = tp.getName();
698
+ initFQN(tp, fmxParameterType);
618
699
  this.makeFamixIndexFileAnchor(tp, fmxParameterType);
619
700
 
620
701
  this.famixRep.addElement(fmxParameterType);
@@ -632,13 +713,13 @@ export class EntityDictionary {
632
713
  public createOrGetFamixConcreteType(param: TypeNode): Famix.ParameterType | Famix.PrimitiveType | Famix.Class | Famix.Interface {
633
714
  const typeParameterDeclaration = param.getSymbol()?.getDeclarations()[0] as TypeParameterDeclaration;
634
715
  const parameterTypeName : string = param.getText();
635
- let fmxParameterType: Famix.Type | Famix.Class | Famix.Interface;
716
+ let fmxParameterType: Famix.Type | Famix.Class | Famix.Interface | undefined = undefined;
636
717
 
637
718
  let isClassOrInterface = false;
638
719
  if (this.fmxClassMap.has(parameterTypeName)){
639
720
  this.fmxClassMap.forEach((obj, name) => {
640
721
  if(obj instanceof Famix.ParametricClass){
641
- if (name === param.getText() && obj.getGenericParameters().size>0) {
722
+ if (name === param.getText() && obj.genericParameters.size>0) {
642
723
  fmxParameterType = obj;
643
724
  isClassOrInterface = true;
644
725
  }
@@ -654,7 +735,7 @@ export class EntityDictionary {
654
735
  if (this.fmxInterfaceMap.has(parameterTypeName)){
655
736
  this.fmxInterfaceMap.forEach((obj, name) => {
656
737
  if(obj instanceof Famix.ParametricInterface){
657
- if (name === param.getText() && obj.getGenericParameters().size>0) {
738
+ if (name === param.getText() && obj.genericParameters.size>0) {
658
739
  fmxParameterType = obj;
659
740
  isClassOrInterface = true;
660
741
  }
@@ -671,21 +752,28 @@ export class EntityDictionary {
671
752
  if (!this.fmxTypeMap.has(parameterTypeName)) {
672
753
  if (parameterTypeName === "number" || parameterTypeName === "string" || parameterTypeName === "boolean" || parameterTypeName === "bigint" || parameterTypeName === "symbol" || parameterTypeName === "undefined" || parameterTypeName === "null" || parameterTypeName === "any" || parameterTypeName === "unknown" || parameterTypeName === "never" || parameterTypeName === "void") {
673
754
  fmxParameterType = new Famix.PrimitiveType();
674
- fmxParameterType.setIsStub(true);
755
+ fmxParameterType.isStub = true;
675
756
  } else {
676
757
  fmxParameterType = new Famix.ParameterType();
677
758
  }
678
759
 
679
- fmxParameterType.setName(parameterTypeName);
760
+ fmxParameterType.name = parameterTypeName;
680
761
  this.famixRep.addElement(fmxParameterType);
681
762
  this.fmxTypeMap.set(parameterTypeName, fmxParameterType);
682
763
  this.fmxElementObjectMap.set(fmxParameterType,typeParameterDeclaration);
683
764
  }
684
765
  else {
685
- fmxParameterType = this.fmxTypeMap.get(parameterTypeName);
766
+ const result = this.fmxTypeMap.get(parameterTypeName);
767
+ if (result) {
768
+ fmxParameterType = result;
769
+ } else {
770
+ throw new Error(`Famix type ${parameterTypeName} is not found in the Type map.`);
771
+ }
686
772
  }
687
773
  }
688
-
774
+ if (!fmxParameterType) {
775
+ throw new Error(`fmxParameterType was undefined for parameterTypeName ${parameterTypeName}`);
776
+ }
689
777
  return fmxParameterType;
690
778
  }
691
779
 
@@ -705,9 +793,9 @@ export class EntityDictionary {
705
793
  }
706
794
 
707
795
  const fmxType = this.createOrGetFamixType(variableTypeName, variable);
708
- fmxVariable.setDeclaredType(fmxType);
709
- fmxVariable.setName(variable.getName());
710
-
796
+ fmxVariable.declaredType = fmxType;
797
+ fmxVariable.name = variable.getName();
798
+ initFQN(variable, fmxVariable);
711
799
  this.makeFamixIndexFileAnchor(variable, fmxVariable);
712
800
 
713
801
  this.famixRep.addElement(fmxVariable);
@@ -724,8 +812,8 @@ export class EntityDictionary {
724
812
  */
725
813
  public createFamixEnum(enumEntity: EnumDeclaration): Famix.Enum {
726
814
  const fmxEnum = new Famix.Enum();
727
- fmxEnum.setName(enumEntity.getName());
728
-
815
+ fmxEnum.name = enumEntity.getName();
816
+ initFQN(enumEntity, fmxEnum);
729
817
  this.makeFamixIndexFileAnchor(enumEntity, fmxEnum);
730
818
 
731
819
  this.famixRep.addElement(fmxEnum);
@@ -751,9 +839,9 @@ export class EntityDictionary {
751
839
  }
752
840
 
753
841
  const fmxType = this.createOrGetFamixType(enumValueTypeName, enumMember);
754
- fmxEnumValue.setDeclaredType(fmxType);
755
- fmxEnumValue.setName(enumMember.getName());
756
-
842
+ fmxEnumValue.declaredType = fmxType;
843
+ fmxEnumValue.name = enumMember.getName();
844
+ initFQN(enumMember, fmxEnumValue);
757
845
  this.makeFamixIndexFileAnchor(enumMember, fmxEnumValue);
758
846
 
759
847
  this.famixRep.addElement(fmxEnumValue);
@@ -774,12 +862,12 @@ export class EntityDictionary {
774
862
  const decoratorName = "@" + decorator.getName();
775
863
  const decoratorExpression = decorator.getText().substring(1);
776
864
 
777
- fmxDecorator.setName(decoratorName);
778
- fmxDecorator.setDecoratorExpression(decoratorExpression);
865
+ fmxDecorator.name = decoratorName;
866
+ fmxDecorator.decoratorExpression = decoratorExpression;
779
867
  const decoratedEntityFullyQualifiedName = FQNFunctions.getFQN(decoratedEntity);
780
868
  const fmxDecoratedEntity = this.famixRep.getFamixEntityByFullyQualifiedName(decoratedEntityFullyQualifiedName) as Famix.NamedEntity;
781
- fmxDecorator.setDecoratedEntity(fmxDecoratedEntity);
782
-
869
+ fmxDecorator.decoratedEntity = fmxDecoratedEntity;
870
+ initFQN(decorator, fmxDecorator);
783
871
  this.makeFamixIndexFileAnchor(decorator, fmxDecorator);
784
872
 
785
873
  this.famixRep.addElement(fmxDecorator);
@@ -797,10 +885,10 @@ export class EntityDictionary {
797
885
  * @returns The Famix model of the comment
798
886
  */
799
887
  public createFamixComment(comment: CommentRange, fmxScope: Famix.NamedEntity, isJSDoc: boolean): Famix.Comment {
800
- logger.debug(`> NOTE: creating comment ${comment.getText()} in scope ${fmxScope.getName()}.`);
888
+ logger.debug(`> NOTE: creating comment ${comment.getText()} in scope ${fmxScope.name}.`);
801
889
  const fmxComment = new Famix.Comment();
802
- fmxComment.setContainer(fmxScope); // adds comment to the container's comments collection
803
- fmxComment.setIsJSDoc(isJSDoc);
890
+ fmxComment.container = fmxScope; // adds comment to the container's comments collection
891
+ fmxComment.isJSDoc = isJSDoc;
804
892
 
805
893
  this.makeFamixIndexFileAnchor(comment, fmxComment);
806
894
 
@@ -823,7 +911,7 @@ export class EntityDictionary {
823
911
  let isParameterType = false;
824
912
 
825
913
  logger.debug("Creating (or getting) type: '" + typeName + "' of element: " + element?.getText() + " of kind: " + element?.getKindName());
826
- let ancestor: Famix.ContainerEntity;
914
+ let ancestor: Famix.ContainerEntity | undefined = undefined;
827
915
  if (element !== undefined) {
828
916
  const typeAncestor = Helpers.findTypeAncestor(element);
829
917
  if (!typeAncestor) {
@@ -848,7 +936,7 @@ export class EntityDictionary {
848
936
  if (!this.fmxTypeMap.has(typeName)) {
849
937
  if (isPrimitiveType) {
850
938
  fmxType = new Famix.PrimitiveType();
851
- fmxType.setIsStub(true);
939
+ fmxType.isStub = true;
852
940
  }
853
941
  else if (isParameterType) {
854
942
  fmxType = new Famix.ParameterType();
@@ -859,15 +947,18 @@ export class EntityDictionary {
859
947
  (fmxType as Famix.ParameterType).addArgument(fmxParameterType);
860
948
  });
861
949
  const fmxBaseType = this.createOrGetFamixType(baseTypeName, element);
862
- (fmxType as Famix.ParameterType).setBaseType(fmxBaseType);
950
+ (fmxType as Famix.ParameterType).baseType = fmxBaseType;
863
951
  }
864
952
  else {
865
953
  fmxType = new Famix.Type();
866
954
  }
867
955
 
868
- fmxType.setName(typeName);
869
- fmxType.setContainer(ancestor);
870
-
956
+ fmxType.name = typeName;
957
+ if (!ancestor) {
958
+ throw new Error(`Ancestor not found for type ${typeName}.`);
959
+ }
960
+ fmxType.container = ancestor;
961
+ initFQN(element, fmxType);
871
962
  this.makeFamixIndexFileAnchor(element, fmxType);
872
963
 
873
964
  this.famixRep.addElement(fmxType);
@@ -875,7 +966,12 @@ export class EntityDictionary {
875
966
  this.fmxTypeMap.set(typeName, fmxType);
876
967
  }
877
968
  else {
878
- fmxType = this.fmxTypeMap.get(typeName);
969
+ const result = this.fmxTypeMap.get(typeName);
970
+ if (result) {
971
+ fmxType = result;
972
+ } else {
973
+ throw new Error(`Famix type ${typeName} is not found in the Type map.`);
974
+ }
879
975
  }
880
976
 
881
977
  this.fmxElementObjectMap.set(fmxType,element);
@@ -894,7 +990,7 @@ export class EntityDictionary {
894
990
  throw new Error(`Famix entity with id ${id} not found, for node ${node.getText()} in ${node.getSourceFile().getBaseName()} at line ${node.getStartLineNumber()}.`);
895
991
  }
896
992
 
897
- logger.debug(`Creating FamixAccess. Node: [${node.getKindName()}] '${node.getText()}' at line ${node.getStartLineNumber()} in ${node.getSourceFile().getBaseName()}, id: ${id} refers to fmxVar '${fmxVar.getFullyQualifiedName()}'.`);
993
+ logger.debug(`Creating FamixAccess. Node: [${node.getKindName()}] '${node.getText()}' at line ${node.getStartLineNumber()} in ${node.getSourceFile().getBaseName()}, id: ${id} refers to fmxVar '${fmxVar.fullyQualifiedName}'.`);
898
994
 
899
995
  const nodeReferenceAncestor = Helpers.findAncestor(node);
900
996
  const ancestorFullyQualifiedName = FQNFunctions.getFQN(nodeReferenceAncestor);
@@ -905,8 +1001,8 @@ export class EntityDictionary {
905
1001
  }
906
1002
 
907
1003
  const fmxAccess = new Famix.Access();
908
- fmxAccess.setAccessor(accessor);
909
- fmxAccess.setVariable(fmxVar);
1004
+ fmxAccess.accessor = accessor;
1005
+ fmxAccess.variable = fmxVar;
910
1006
 
911
1007
  this.famixRep.addElement(fmxAccess);
912
1008
 
@@ -928,10 +1024,10 @@ export class EntityDictionary {
928
1024
  const receiver = this.famixRep.getFamixEntityByFullyQualifiedName(receiverFullyQualifiedName) as Famix.NamedEntity;
929
1025
 
930
1026
  const fmxInvocation = new Famix.Invocation();
931
- fmxInvocation.setSender(sender);
932
- fmxInvocation.setReceiver(receiver);
1027
+ fmxInvocation.sender = sender;
1028
+ fmxInvocation.receiver = receiver;
933
1029
  fmxInvocation.addCandidate(fmxMethodOrFunction);
934
- fmxInvocation.setSignature(fmxMethodOrFunction.getSignature());
1030
+ fmxInvocation.signature = fmxMethodOrFunction.signature;
935
1031
 
936
1032
  this.famixRep.addElement(fmxInvocation);
937
1033
 
@@ -948,19 +1044,25 @@ export class EntityDictionary {
948
1044
  // const clsName = cls.getName();
949
1045
  const classFullyQualifiedName = FQNFunctions.getFQN(cls);
950
1046
  logger.debug(`createFamixInheritance: classFullyQualifiedName: class fqn = ${classFullyQualifiedName}`);
951
- let subClass: Famix.Class | Famix.Interface;
1047
+ let subClass: Famix.Class | Famix.Interface | undefined;
952
1048
  if (cls instanceof ClassDeclaration) {
953
1049
  subClass = this.fmxClassMap.get(classFullyQualifiedName);
954
1050
  }
955
1051
  else {
956
1052
  subClass = this.fmxInterfaceMap.get(classFullyQualifiedName);
957
1053
  }
1054
+ if (!subClass) {
1055
+ throw new Error(`Subclass ${classFullyQualifiedName} not found in Class or Interface maps.`);
1056
+ }
958
1057
 
959
- let inhClassName: string;
1058
+ let inhClassName: string | undefined;
960
1059
  let inhClassFullyQualifiedName: string;
961
- let superClass: Famix.Class | Famix.Interface;
1060
+ let superClass: Famix.Class | Famix.Interface | undefined;
962
1061
  if (inhClass instanceof ClassDeclaration || inhClass instanceof InterfaceDeclaration) {
963
1062
  inhClassName = inhClass.getName();
1063
+ if (!inhClassName) {
1064
+ throw new Error(`Inherited class or interface name not found for ${inhClass.getText()}.`);
1065
+ }
964
1066
  inhClassFullyQualifiedName = FQNFunctions.getFQN(inhClass);
965
1067
  if (inhClass instanceof ClassDeclaration) {
966
1068
  superClass = this.fmxClassMap.get(inhClassFullyQualifiedName);
@@ -968,6 +1070,9 @@ export class EntityDictionary {
968
1070
  else {
969
1071
  superClass = this.fmxInterfaceMap.get(inhClassFullyQualifiedName);
970
1072
  }
1073
+ if (!superClass) {
1074
+ throw new Error(`Superclass ${classFullyQualifiedName} not found in Class or Interface maps.`);
1075
+ }
971
1076
  }
972
1077
  else {
973
1078
  // inhClass is an ExpressionWithTypeArguments
@@ -988,28 +1093,29 @@ export class EntityDictionary {
988
1093
 
989
1094
  this.fmxElementObjectMap.set(superClass,inhClass);
990
1095
 
991
- superClass.setName(inhClassName);
992
- superClass.setFullyQualifiedName(inhClassFullyQualifiedName);
993
- superClass.setIsStub(true);
1096
+ superClass.name = inhClassName;
1097
+ superClass.fullyQualifiedName = inhClassFullyQualifiedName;
1098
+ superClass.isStub = true;
994
1099
 
995
1100
  this.makeFamixIndexFileAnchor(inhClass, superClass);
996
1101
 
997
1102
  this.famixRep.addElement(superClass);
998
1103
  }
999
1104
 
1000
- fmxInheritance.setSubclass(subClass);
1001
- fmxInheritance.setSuperclass(superClass);
1105
+ fmxInheritance.subclass = subClass;
1106
+ fmxInheritance.superclass = superClass;
1002
1107
 
1003
1108
  this.famixRep.addElement(fmxInheritance);
1004
1109
 
1005
- this.fmxElementObjectMap.set(fmxInheritance,null);
1110
+ // We don't map inheritance to the source code element because there are two elements (super, sub)
1111
+ // this.fmxElementObjectMap.set(fmxInheritance, null);
1006
1112
 
1007
1113
  }
1008
1114
 
1009
1115
  public createFamixImportClause(importedEntity: Famix.NamedEntity, importingEntity: Famix.Module) {
1010
1116
  const fmxImportClause = new Famix.ImportClause();
1011
- fmxImportClause.setImportedEntity(importedEntity);
1012
- fmxImportClause.setImportingEntity(importingEntity);
1117
+ fmxImportClause.importedEntity = importedEntity;
1118
+ fmxImportClause.importingEntity = importingEntity;
1013
1119
  importingEntity.addOutgoingImport(fmxImportClause);
1014
1120
  this.famixRep.addElement(fmxImportClause);
1015
1121
  }
@@ -1029,7 +1135,7 @@ export class EntityDictionary {
1029
1135
  logger.debug(`createFamixImportClause: Creating import clause:`);
1030
1136
  const fmxImportClause = new Famix.ImportClause();
1031
1137
 
1032
- let importedEntity: Famix.NamedEntity | Famix.StructuralEntity;
1138
+ let importedEntity: Famix.NamedEntity | Famix.StructuralEntity | undefined = undefined;
1033
1139
  let importedEntityName: string;
1034
1140
 
1035
1141
  const absolutePathProject = this.famixRep.getAbsolutePath();
@@ -1052,12 +1158,12 @@ export class EntityDictionary {
1052
1158
  }
1053
1159
  if (importedEntity === undefined) {
1054
1160
  importedEntity = new Famix.NamedEntity();
1055
- importedEntity.setName(importedEntityName);
1161
+ importedEntity.name = importedEntityName;
1056
1162
  if (!isInExports) {
1057
- importedEntity.setIsStub(true);
1163
+ importedEntity.isStub = true;
1058
1164
  }
1165
+ importedEntity.fullyQualifiedName = pathName;
1059
1166
  this.makeFamixIndexFileAnchor(importElement, importedEntity);
1060
- importedEntity.setFullyQualifiedName(pathName);
1061
1167
  // must add entity to repository
1062
1168
  this.famixRep.addElement(importedEntity);
1063
1169
  }
@@ -1068,39 +1174,40 @@ export class EntityDictionary {
1068
1174
  importedEntityName = importDeclaration?.getName();
1069
1175
  pathName = pathName + importedEntityName;
1070
1176
  importedEntity = new Famix.StructuralEntity();
1071
- importedEntity.setName(importedEntityName);
1177
+ importedEntity.name = importedEntityName;
1178
+ initFQN(importDeclaration, importedEntity);
1072
1179
  this.makeFamixIndexFileAnchor(importElement, importedEntity);
1073
- importedEntity.setFullyQualifiedName(pathName);
1074
- const anyType = this.createOrGetFamixType('any', undefined);
1075
- (importedEntity as Famix.StructuralEntity).setDeclaredType(anyType);
1180
+ importedEntity.fullyQualifiedName = pathName;
1181
+ const anyType = this.createOrGetFamixType('any', importDeclaration);
1182
+ (importedEntity as Famix.StructuralEntity).declaredType = anyType;
1076
1183
  } else { // default imports, e.g. import ClassW from "./complexExportModule";
1077
1184
  importedEntityName = importElement.getText();
1078
1185
  pathName = pathName + (isDefaultExport ? "defaultExport" : "namespaceExport");
1079
1186
  importedEntity = new Famix.NamedEntity();
1080
- importedEntity.setName(importedEntityName);
1187
+ importedEntity.name = importedEntityName;
1188
+ importedEntity.fullyQualifiedName = pathName;
1081
1189
  this.makeFamixIndexFileAnchor(importElement, importedEntity);
1082
- importedEntity.setFullyQualifiedName(pathName);
1083
1190
  }
1084
1191
  // I don't think it should be added to the repository if it exists already
1085
1192
  if (!isInExports) this.famixRep.addElement(importedEntity);
1086
1193
  const importerFullyQualifiedName = FQNFunctions.getFQN(importer);
1087
1194
  const fmxImporter = this.famixRep.getFamixEntityByFullyQualifiedName(importerFullyQualifiedName) as Famix.Module;
1088
- fmxImportClause.setImportingEntity(fmxImporter);
1089
- fmxImportClause.setImportedEntity(importedEntity);
1195
+ fmxImportClause.importingEntity = fmxImporter;
1196
+ fmxImportClause.importedEntity = importedEntity;
1090
1197
  if (importDeclaration instanceof ImportEqualsDeclaration) {
1091
- fmxImportClause.setModuleSpecifier(importDeclaration?.getModuleReference().getText() as string);
1198
+ fmxImportClause.moduleSpecifier = importDeclaration?.getModuleReference().getText() as string;
1092
1199
  } else {
1093
- fmxImportClause.setModuleSpecifier(importDeclaration?.getModuleSpecifierValue() as string);
1200
+ fmxImportClause.moduleSpecifier = importDeclaration?.getModuleSpecifierValue() as string;
1094
1201
  }
1095
1202
 
1096
- logger.debug(`createFamixImportClause: ${fmxImportClause.getImportedEntity()?.getName()} (of type ${
1097
- Helpers.getSubTypeName(fmxImportClause.getImportedEntity())}) is imported by ${fmxImportClause.getImportingEntity()?.getName()}`);
1203
+ logger.debug(`createFamixImportClause: ${fmxImportClause.importedEntity?.name} (of type ${
1204
+ Helpers.getSubTypeName(fmxImportClause.importedEntity)}) is imported by ${fmxImportClause.importingEntity?.name}`);
1098
1205
 
1099
1206
  fmxImporter.addOutgoingImport(fmxImportClause);
1100
1207
 
1101
1208
  this.famixRep.addElement(fmxImportClause);
1102
1209
 
1103
- this.fmxElementObjectMap.set(fmxImportClause,importDeclaration);
1210
+ if (importDeclaration) this.fmxElementObjectMap.set(fmxImportClause, importDeclaration);
1104
1211
  }
1105
1212
 
1106
1213
  /**
@@ -1108,7 +1215,7 @@ export class EntityDictionary {
1108
1215
  * @param arrowExpression An Expression
1109
1216
  * @returns The Famix model of the variable
1110
1217
  */
1111
- public createFamixArrowFunction(arrowExpression: Expression ,currentCC: unknown): Famix.ArrowFunction | Famix.ParametricArrowFunction {
1218
+ public createFamixArrowFunction(arrowExpression: Expression, currentCC: { [key: string]: number } ): Famix.ArrowFunction | Famix.ParametricArrowFunction {
1112
1219
 
1113
1220
  let fmxArrowFunction: Famix.ArrowFunction | Famix.ParametricArrowFunction;
1114
1221
 
@@ -1133,17 +1240,17 @@ export class EntityDictionary {
1133
1240
  }
1134
1241
 
1135
1242
  if (functionName) {
1136
- fmxArrowFunction.setName(functionName);
1243
+ fmxArrowFunction.name = functionName;
1137
1244
  }
1138
1245
  else {
1139
- fmxArrowFunction.setName("anonymous");
1246
+ fmxArrowFunction.name = "anonymous";
1140
1247
  }
1141
1248
 
1142
1249
  // Signature of an arrow function is (parameters) => return_type
1143
1250
  const parametersSignature = arrowFunction.getParameters().map(p => p.getText()).join(", ");
1144
1251
  const returnTypeSignature = arrowFunction.getReturnType().getText();
1145
- fmxArrowFunction.setSignature(`(${parametersSignature}) => ${returnTypeSignature}`);
1146
- fmxArrowFunction.setCyclomaticComplexity(currentCC[fmxArrowFunction.getName()]);
1252
+ fmxArrowFunction.signature = `(${parametersSignature}) => ${returnTypeSignature}`;
1253
+ fmxArrowFunction.cyclomaticComplexity = currentCC[fmxArrowFunction.name];
1147
1254
 
1148
1255
  let functionTypeName = this.UNKNOWN_VALUE;
1149
1256
  try {
@@ -1153,12 +1260,12 @@ export class EntityDictionary {
1153
1260
  }
1154
1261
 
1155
1262
  const fmxType = this.createOrGetFamixType(functionTypeName, arrowFunction as unknown as FunctionDeclaration);
1156
- fmxArrowFunction.setDeclaredType(fmxType);
1157
- fmxArrowFunction.setNumberOfLinesOfCode(arrowFunction.getEndLineNumber() - arrowFunction.getStartLineNumber());
1263
+ fmxArrowFunction.declaredType = fmxType;
1264
+ fmxArrowFunction.numberOfLinesOfCode = arrowFunction.getEndLineNumber() - arrowFunction.getStartLineNumber();
1158
1265
  const parameters = arrowFunction.getParameters();
1159
- fmxArrowFunction.setNumberOfParameters(parameters.length);
1160
- fmxArrowFunction.setNumberOfStatements(arrowFunction.getStatements().length);
1161
-
1266
+ fmxArrowFunction.numberOfParameters = parameters.length;
1267
+ fmxArrowFunction.numberOfStatements = arrowFunction.getStatements().length;
1268
+ initFQN(arrowExpression as unknown as TSMorphObjectType, fmxArrowFunction);
1162
1269
  this.makeFamixIndexFileAnchor(arrowExpression as unknown as TSMorphObjectType, fmxArrowFunction);
1163
1270
  this.famixRep.addElement(fmxArrowFunction);
1164
1271
  this.fmxElementObjectMap.set(fmxArrowFunction,arrowFunction as unknown as TSMorphObjectType);
@@ -1175,11 +1282,11 @@ export class EntityDictionary {
1175
1282
 
1176
1283
  const fmxConcretisation : Famix.Concretisation = new Famix.Concretisation();
1177
1284
 
1178
- fmxConcretisation.setConcreteEntity(conEntity);
1179
- fmxConcretisation.setGenericEntity(genEntity);
1180
- this.fmxElementObjectMap.set(fmxConcretisation,null);
1285
+ fmxConcretisation.concreteEntity = conEntity;
1286
+ fmxConcretisation.genericEntity = genEntity;
1287
+ // this.fmxElementObjectMap.set(fmxConcretisation,null);
1181
1288
  this.famixRep.addElement(fmxConcretisation);
1182
- const parameterConcretisation = this.createFamixParameterConcrestisation(fmxConcretisation);
1289
+ const parameterConcretisation = this.createFamixParameterConcretisation(fmxConcretisation);
1183
1290
 
1184
1291
  return fmxConcretisation;
1185
1292
  }
@@ -1189,41 +1296,47 @@ export class EntityDictionary {
1189
1296
  * @param concretisation A FamixConcretisation
1190
1297
  * @returns The Famix model of the ParameterConcrestisation
1191
1298
  */
1192
- public createFamixParameterConcrestisation(concretisation: Famix.Concretisation): Famix.ParameterConcretisation {
1193
- const conClass = concretisation.getConcreteEntity();
1194
- const genClass = concretisation.getGenericEntity();
1195
- const parameterConcretisations = this.famixRep._getAllEntitiesWithType("ParameterConcretisation");
1196
- const concreteParameters = conClass.getConcreteParameters();
1197
- const genericParameters = genClass.getGenericParameters();
1299
+ public createFamixParameterConcretisation(concretisation: Famix.Concretisation): Famix.ParameterConcretisation | undefined{
1300
+ const conClass = concretisation.concreteEntity;
1301
+ const genClass = concretisation.genericEntity;
1302
+ logger.debug(`Creating parameter concretisation between ${conClass.fullyQualifiedName} and ${genClass.fullyQualifiedName}`);
1303
+ const parameterConcretisations = this.famixRep._getAllEntitiesWithType("ParameterConcretisation") as Set<Famix.ParameterConcretisation>;
1304
+ const concreteParameters = conClass.concreteParameters;
1305
+ const genericParameters = genClass.genericParameters;
1198
1306
 
1199
1307
  let conClassTypeParametersIterator = concreteParameters.values();
1200
1308
  let genClassTypeParametersIterator = genericParameters.values();
1201
- let fmxParameterConcretisation : Famix.ParameterConcretisation;
1309
+ let fmxParameterConcretisation : Famix.ParameterConcretisation | undefined = undefined;
1202
1310
 
1203
1311
  for (let i = 0; i < genericParameters.size; i++) {
1204
- const conClassTypeParameter = conClassTypeParametersIterator.next().value;
1205
- const genClassTypeParameter = genClassTypeParametersIterator.next().value;
1312
+ const conClassTypeParameter = conClassTypeParametersIterator.next().value as Famix.ParameterType;
1313
+ const genClassTypeParameter = genClassTypeParametersIterator.next().value as Famix.ParameterType;
1206
1314
  let createParameterConcretisation : boolean = true;
1207
- if(conClassTypeParameter && genClassTypeParameter && conClassTypeParameter.getName() != genClassTypeParameter.getName()){
1315
+ if(conClassTypeParameter && genClassTypeParameter && conClassTypeParameter.name != genClassTypeParameter.name){
1208
1316
  parameterConcretisations.forEach((param : Famix.ParameterConcretisation) => {
1209
- if (conClassTypeParameter.getName() == param.getConcreteParameter().getName() && genClassTypeParameter.getName() == param.getGenericParameter().getName()) {
1317
+ if (conClassTypeParameter.name == param.concreteParameter.name && genClassTypeParameter.name == param.genericParameter.name) {
1210
1318
  createParameterConcretisation = false;
1211
1319
  fmxParameterConcretisation = param;
1212
1320
  }
1213
1321
  })
1214
1322
  if (createParameterConcretisation) {
1215
1323
  fmxParameterConcretisation = new Famix.ParameterConcretisation();
1216
- fmxParameterConcretisation.setGenericParameter(genClassTypeParameter);
1217
- fmxParameterConcretisation.setConcreteParameter(conClassTypeParameter);
1324
+ fmxParameterConcretisation.genericParameter = genClassTypeParameter;
1325
+ fmxParameterConcretisation.concreteParameter = conClassTypeParameter;
1218
1326
  fmxParameterConcretisation.addConcretisation(concretisation);
1219
- this.fmxElementObjectMap.set(fmxParameterConcretisation,null);
1327
+ // this.fmxElementObjectMap.set(fmxParameterConcretisation,null);
1220
1328
  } else {
1329
+ if (!fmxParameterConcretisation) {
1330
+ throw new Error(`fmxParameterConcretisation was undefined for concretisation with generic parameter ${genClassTypeParameter.name} and concrete parameter ${conClassTypeParameter.name}`);
1331
+ }
1221
1332
  fmxParameterConcretisation.addConcretisation(concretisation);
1222
1333
  }
1223
1334
  this.famixRep.addElement(fmxParameterConcretisation);
1224
1335
  }
1225
1336
  }
1226
-
1337
+ if (!fmxParameterConcretisation) {
1338
+ logger.error(`fmxParameterConcretisation was undefined for concretisation with concrete entity ${conClass.fullyQualifiedName} and generic entity ${genClass.fullyQualifiedName}`);
1339
+ }
1227
1340
  return fmxParameterConcretisation;
1228
1341
 
1229
1342
  }
@@ -1256,10 +1369,10 @@ export class EntityDictionary {
1256
1369
  let EntityDeclaration;
1257
1370
  let genEntity;
1258
1371
  if (superEntity instanceof ExpressionWithTypeArguments) {
1259
- EntityDeclaration = entity.getExpression().getSymbol().getDeclarations()[0] as ClassDeclaration;
1372
+ EntityDeclaration = entity.getExpression().getSymbol()?.getDeclarations()[0] as ClassDeclaration;
1260
1373
  genEntity = this.createOrGetFamixClass(EntityDeclaration) as Famix.ParametricClass;
1261
1374
  } else {
1262
- EntityDeclaration = entity.getExpression().getSymbol().getDeclarations()[0] as InterfaceDeclaration;
1375
+ EntityDeclaration = entity.getExpression().getSymbol()?.getDeclarations()[0] as InterfaceDeclaration;
1263
1376
  genEntity = this.createOrGetFamixInterface(EntityDeclaration) as Famix.ParametricInterface;
1264
1377
  }
1265
1378
  const genParams = EntityDeclaration.getTypeParameters().map((param) => param.getText());
@@ -1268,10 +1381,10 @@ export class EntityDictionary {
1268
1381
  if (!Helpers.arraysAreEqual(conParams,genParams)) {
1269
1382
  let conEntity;
1270
1383
  conEntity = this.createOrGetFamixConcreteElement(genEntity,EntityDeclaration,args);
1271
- const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1384
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation") as Set<Famix.Concretisation>;
1272
1385
  let createConcretisation : boolean = true;
1273
1386
  concretisations.forEach((conc : Famix.Concretisation) => {
1274
- if (genEntity.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conEntity.getFullyQualifiedName()){
1387
+ if (genEntity.fullyQualifiedName == conc.genericEntity.fullyQualifiedName && conc.concreteEntity.fullyQualifiedName == conEntity.fullyQualifiedName){
1275
1388
  createConcretisation = false;
1276
1389
  }
1277
1390
  });
@@ -1282,7 +1395,8 @@ export class EntityDictionary {
1282
1395
  }
1283
1396
  }
1284
1397
  });
1285
- }
1398
+ }
1399
+ // TODO: This function seems unfinished
1286
1400
  }
1287
1401
 
1288
1402
 
@@ -1309,10 +1423,10 @@ export class EntityDictionary {
1309
1423
  if (!Helpers.arraysAreEqual(conParams,genParams)) {
1310
1424
  let conEntity;
1311
1425
  conEntity = this.createOrGetFamixConcreteElement(genEntity,cls,instance.getTypeArguments());
1312
- const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1426
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation") as Set<Famix.Concretisation>;
1313
1427
  let createConcretisation : boolean = true;
1314
1428
  concretisations.forEach((conc : Famix.Concretisation) => {
1315
- if (genEntity.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conEntity.getFullyQualifiedName()){
1429
+ if (genEntity.fullyQualifiedName == conc.genericEntity.fullyQualifiedName && conc.concreteEntity.fullyQualifiedName == conEntity.fullyQualifiedName){
1316
1430
  createConcretisation = false;
1317
1431
  }
1318
1432
  });
@@ -1324,6 +1438,7 @@ export class EntityDictionary {
1324
1438
  }
1325
1439
  })
1326
1440
  }
1441
+ // TODO: This function seems unfinished
1327
1442
  }
1328
1443
 
1329
1444
  /**
@@ -1336,11 +1451,14 @@ export class EntityDictionary {
1336
1451
  const genParams = element.getTypeParameters().map(param => param.getText());
1337
1452
  const uses = element.findReferencesAsNodes();
1338
1453
  uses.forEach(usage => {
1339
- let currentNode = usage;
1454
+ let currentNode: Node | undefined = usage;
1340
1455
 
1341
1456
  while (currentNode) {
1342
1457
  if (currentNode.getKind() === SyntaxKind.CallExpression) {
1343
1458
  const callExpression = currentNode.asKind(SyntaxKind.CallExpression);
1459
+ if (!callExpression) {
1460
+ throw new Error(`CallExpression not found for ${currentNode.getText()}`);
1461
+ }
1344
1462
  const instanceIsGeneric = callExpression.getTypeArguments().length > 0;
1345
1463
  if (instanceIsGeneric) {
1346
1464
  const args = callExpression.getTypeArguments();
@@ -1348,16 +1466,16 @@ export class EntityDictionary {
1348
1466
  if (!Helpers.arraysAreEqual(conParams,genParams)) {
1349
1467
  let genElement;
1350
1468
  if(element instanceof FunctionDeclaration){
1351
- genElement = this.createOrGetFamixFunction(element,0) as Famix.ParametricFunction;
1469
+ genElement = this.createOrGetFamixFunction(element, {}) as Famix.ParametricFunction;
1352
1470
  } else {
1353
- genElement = this.createOrGetFamixMethod(element,0) as Famix.ParametricMethod;
1471
+ genElement = this.createOrGetFamixMethod(element, {}) as Famix.ParametricMethod;
1354
1472
  }
1355
1473
  let concElement;
1356
1474
  concElement = this.createOrGetFamixConcreteElement(genElement,element,args);
1357
- const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1475
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation") as Set<Famix.Concretisation>;
1358
1476
  let createConcretisation : boolean = true;
1359
1477
  concretisations.forEach((conc : Famix.Concretisation) => {
1360
- if (genElement.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == concElement.getFullyQualifiedName()){
1478
+ if (genElement.fullyQualifiedName == conc.genericEntity.fullyQualifiedName && conc.concreteEntity.fullyQualifiedName == concElement.fullyQualifiedName){
1361
1479
  createConcretisation = false;
1362
1480
  }
1363
1481
  });
@@ -1386,17 +1504,17 @@ export class EntityDictionary {
1386
1504
  superInterfaces.forEach(interfaceType => {
1387
1505
  const interfaceIsGeneric = interfaceType.getTypeArguments().length>0;
1388
1506
  if (interfaceIsGeneric) {
1389
- const interfaceDeclaration = interfaceType.getExpression().getSymbol().getDeclarations()[0] as InterfaceDeclaration;
1507
+ const interfaceDeclaration = interfaceType.getExpression().getSymbol()?.getDeclarations()[0] as InterfaceDeclaration;
1390
1508
  const genParams = interfaceDeclaration.getTypeParameters().map((param) => param.getText());
1391
1509
  const conParams = cls.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments().map((param) => param.getText());
1392
1510
  const args = cls.getHeritageClauses()[0].getTypeNodes()[0].getTypeArguments();
1393
1511
  if (!Helpers.arraysAreEqual(conParams,genParams)) {
1394
1512
  const genInterface = this.createOrGetFamixInterface(interfaceDeclaration) as Famix.ParametricInterface;
1395
1513
  const conInterface = this.createOrGetFamixConcreteElement(genInterface,interfaceDeclaration,args);
1396
- const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1514
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation") as Set<Famix.Concretisation>;
1397
1515
  let createConcretisation : boolean = true;
1398
1516
  concretisations.forEach((conc : Famix.Concretisation) => {
1399
- if (genInterface.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == conInterface.getFullyQualifiedName()){
1517
+ if (genInterface.fullyQualifiedName == conc.genericEntity.fullyQualifiedName && conc.concreteEntity.fullyQualifiedName == conInterface.fullyQualifiedName){
1400
1518
  createConcretisation = false;
1401
1519
  }
1402
1520
  });
@@ -1425,6 +1543,9 @@ export class EntityDictionary {
1425
1543
  while (parentNode) {
1426
1544
  if (parentNode.getKind() === SyntaxKind.TypeReference) {
1427
1545
  const typeReferenceNode = parentNode.asKind(SyntaxKind.TypeReference);
1546
+ if (!typeReferenceNode) {
1547
+ throw new Error(`TypeReferenceNode not found for ${parentNode.getText()}`);
1548
+ }
1428
1549
  const typeReferenceNodeIsGeneric = typeReferenceNode.getTypeArguments().length > 0;
1429
1550
  if (typeReferenceNodeIsGeneric) {}
1430
1551
  const args = typeReferenceNode.getTypeArguments();
@@ -1438,10 +1559,10 @@ export class EntityDictionary {
1438
1559
  }
1439
1560
  let concElement;
1440
1561
  concElement = this.createOrGetFamixConcreteElement(genElement,element,args);
1441
- const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation");
1562
+ const concretisations = this.famixRep._getAllEntitiesWithType("Concretisation") as Set<Famix.Concretisation>;
1442
1563
  let createConcretisation : boolean = true;
1443
1564
  concretisations.forEach((conc : Famix.Concretisation) => {
1444
- if (genElement.getFullyQualifiedName() == conc.getGenericEntity().getFullyQualifiedName() && conc.getConcreteEntity().getFullyQualifiedName() == concElement.getFullyQualifiedName()){
1565
+ if (genElement.fullyQualifiedName == conc.genericEntity.fullyQualifiedName && conc.concreteEntity.fullyQualifiedName == concElement.fullyQualifiedName){
1445
1566
  createConcretisation = false;
1446
1567
  }
1447
1568
  });
@@ -1462,3 +1583,11 @@ export class EntityDictionary {
1462
1583
  return absolutePath.replace(absolutePathProject, "").slice(1);
1463
1584
  }
1464
1585
  }
1586
+ function initFQN(sourceElement: TSMorphObjectType, famixElement: Famix.SourcedEntity) {
1587
+ if (!(sourceElement instanceof CommentRange)) {
1588
+ const fqn = FQNFunctions.getFQN(sourceElement);
1589
+ logger.debug("Setting fully qualified name for " + famixElement.getJSON() + " to " + fqn);
1590
+ (famixElement as Famix.NamedEntity).fullyQualifiedName = fqn;
1591
+ }
1592
+ }
1593
+