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.
- package/LICENSE +1 -0
- package/README.md +29 -60
- package/dist/analyze.js +1 -1
- package/dist/analyze_functions/process_functions.js +49 -43
- package/dist/famix_functions/EntityDictionary.js +309 -182
- package/dist/famix_functions/helpers_creation.js +36 -5
- package/dist/fqn.js +76 -114
- package/dist/lib/famix/famix_JSON_exporter.js +55 -0
- package/dist/lib/famix/famix_base_element.js +18 -0
- package/dist/lib/famix/famix_repository.js +224 -0
- package/dist/lib/famix/{src/index.js → index.js} +1 -1
- package/dist/lib/famix/model/famix/access.js +40 -0
- package/dist/lib/famix/model/famix/accessor.js +17 -0
- package/dist/lib/famix/model/famix/alias.js +33 -0
- package/dist/lib/famix/model/famix/arrow_function.js +17 -0
- package/dist/lib/famix/model/famix/behavioral_entity.js +79 -0
- package/dist/lib/famix/model/famix/class.js +71 -0
- package/dist/lib/famix/model/famix/comment.js +39 -0
- package/dist/lib/famix/model/famix/concretisation.js +31 -0
- package/dist/lib/famix/model/famix/container_entity.js +126 -0
- package/dist/lib/famix/model/famix/decorator.js +32 -0
- package/dist/lib/famix/model/famix/entity.js +17 -0
- package/dist/lib/famix/model/famix/enum.js +31 -0
- package/dist/lib/famix/model/famix/enum_value.js +25 -0
- package/dist/lib/famix/model/famix/function.js +17 -0
- package/dist/lib/famix/model/famix/import_clause.js +41 -0
- package/dist/lib/famix/{src/model → model}/famix/index.js +6 -10
- package/dist/lib/famix/model/famix/indexed_file_anchor.js +38 -0
- package/dist/lib/famix/model/famix/inheritance.js +33 -0
- package/dist/lib/famix/model/famix/interface.js +64 -0
- package/dist/lib/famix/model/famix/invocation.js +54 -0
- package/dist/lib/famix/model/famix/method.js +67 -0
- package/dist/lib/famix/model/famix/module.js +60 -0
- package/dist/lib/famix/model/famix/named_entity.js +78 -0
- package/dist/lib/famix/model/famix/parameter.js +25 -0
- package/dist/lib/famix/model/famix/parameter_concretisation.js +44 -0
- package/dist/lib/famix/model/famix/parameter_type.js +45 -0
- package/dist/lib/famix/model/famix/parametric_arrow_function.js +31 -0
- package/dist/lib/famix/model/famix/parametric_class.js +44 -0
- package/dist/lib/famix/model/famix/parametric_function.js +31 -0
- package/dist/lib/famix/model/famix/parametric_interface.js +44 -0
- package/dist/lib/famix/model/famix/parametric_method.js +31 -0
- package/dist/lib/famix/model/famix/primitive_type.js +17 -0
- package/dist/lib/famix/model/famix/property.js +73 -0
- package/dist/lib/famix/model/famix/reference.js +33 -0
- package/dist/lib/famix/model/famix/scoping_entity.js +36 -0
- package/dist/lib/famix/model/famix/script_entity.js +29 -0
- package/dist/lib/famix/model/famix/source_anchor.js +27 -0
- package/dist/lib/famix/model/famix/source_language.js +35 -0
- package/dist/lib/famix/model/famix/sourced_entity.js +60 -0
- package/dist/lib/famix/model/famix/structural_entity.js +39 -0
- package/dist/lib/famix/model/famix/type.js +73 -0
- package/dist/lib/famix/model/famix/variable.js +24 -0
- package/dist/lib/ts-complex/cyclomatic-service.js +2 -2
- package/dist/refactorer/refactor-getter-setter.js +142 -0
- package/dist/ts2famix-cli-wrapper.js +29 -3
- package/dist/ts2famix-cli.js +1 -1
- package/doc-uml/famix-typescript-model.puml +390 -341
- package/doc-uml/famix-typescript-model.svg +1 -1
- package/package.json +8 -7
- package/src/analyze.ts +2 -2
- package/src/analyze_functions/process_functions.ts +49 -44
- package/src/famix_functions/EntityDictionary.ts +345 -216
- package/src/famix_functions/helpers_creation.ts +36 -4
- package/src/fqn.ts +76 -125
- package/src/lib/famix/famix_JSON_exporter.ts +56 -0
- package/src/lib/famix/famix_base_element.ts +22 -0
- package/src/lib/famix/famix_repository.ts +243 -0
- package/src/lib/famix/model/famix/access.ts +50 -0
- package/src/lib/famix/model/famix/alias.ts +39 -0
- package/src/lib/famix/model/famix/behavioral_entity.ts +97 -0
- package/src/lib/famix/model/famix/class.ts +85 -0
- package/src/lib/famix/model/famix/comment.ts +47 -0
- package/src/lib/famix/model/famix/concretisation.ts +40 -0
- package/src/lib/famix/model/famix/container_entity.ts +160 -0
- package/src/lib/famix/model/famix/decorator.ts +37 -0
- package/src/lib/famix/model/famix/enum.ts +30 -0
- package/src/lib/famix/model/famix/enum_value.ts +28 -0
- package/src/lib/famix/model/famix/import_clause.ts +51 -0
- package/src/lib/famix/{src/model → model}/famix/index.ts +2 -4
- package/src/lib/famix/model/famix/indexed_file_anchor.ts +46 -0
- package/src/lib/famix/model/famix/inheritance.ts +40 -0
- package/src/lib/famix/model/famix/interface.ts +75 -0
- package/src/lib/famix/model/famix/invocation.ts +65 -0
- package/src/lib/famix/model/famix/method.ts +89 -0
- package/src/lib/famix/model/famix/module.ts +71 -0
- package/src/lib/famix/model/famix/named_entity.ts +95 -0
- package/src/lib/famix/{src/model → model}/famix/parameter.ts +11 -12
- package/src/lib/famix/model/famix/parameter_concretisation.ts +51 -0
- package/src/lib/famix/model/famix/parameter_type.ts +58 -0
- package/src/lib/famix/model/famix/parametric_arrow_function.ts +32 -0
- package/src/lib/famix/model/famix/parametric_class.ts +49 -0
- package/src/lib/famix/model/famix/parametric_function.ts +32 -0
- package/src/lib/famix/model/famix/parametric_interface.ts +49 -0
- package/src/lib/famix/model/famix/parametric_method.ts +32 -0
- package/src/lib/famix/model/famix/primitive_type.ts +15 -0
- package/src/lib/famix/model/famix/property.ts +94 -0
- package/src/lib/famix/model/famix/reference.ts +40 -0
- package/src/lib/famix/model/famix/scoping_entity.ts +35 -0
- package/src/lib/famix/model/famix/script_entity.ts +34 -0
- package/src/lib/famix/model/famix/source_anchor.ts +30 -0
- package/src/lib/famix/model/famix/source_language.ts +35 -0
- package/src/lib/famix/model/famix/sourced_entity.ts +70 -0
- package/src/lib/famix/model/famix/structural_entity.ts +43 -0
- package/src/lib/famix/model/famix/type.ts +87 -0
- package/src/lib/famix/model/famix/variable.ts +27 -0
- package/src/lib/famix/package.json +1 -1
- package/src/lib/ts-complex/cyclomatic-service.ts +10 -10
- package/src/refactorer/refactor-getter-setter.ts +140 -0
- package/src/ts2famix-cli-wrapper.ts +6 -2
- package/src/ts2famix-cli.ts +1 -1
- package/tsconfig.check-tests.json +14 -0
- package/tsconfig.json +70 -68
- package/dist/famix2puml.js +0 -126
- package/dist/lib/famix/src/famix_JSON_exporter.js +0 -55
- package/dist/lib/famix/src/famix_base_element.js +0 -18
- package/dist/lib/famix/src/famix_repository.js +0 -223
- package/dist/lib/famix/src/model/famix/access.js +0 -40
- package/dist/lib/famix/src/model/famix/accessor.js +0 -17
- package/dist/lib/famix/src/model/famix/alias.js +0 -33
- package/dist/lib/famix/src/model/famix/arrowFunction.js +0 -17
- package/dist/lib/famix/src/model/famix/behavioral_entity.js +0 -79
- package/dist/lib/famix/src/model/famix/class.js +0 -71
- package/dist/lib/famix/src/model/famix/comment.js +0 -39
- package/dist/lib/famix/src/model/famix/concretisation.js +0 -31
- package/dist/lib/famix/src/model/famix/container_entity.js +0 -126
- package/dist/lib/famix/src/model/famix/decorator.js +0 -32
- package/dist/lib/famix/src/model/famix/entity.js +0 -17
- package/dist/lib/famix/src/model/famix/enum.js +0 -31
- package/dist/lib/famix/src/model/famix/enum_value.js +0 -25
- package/dist/lib/famix/src/model/famix/function.js +0 -17
- package/dist/lib/famix/src/model/famix/implicit_variable.js +0 -17
- package/dist/lib/famix/src/model/famix/import_clause.js +0 -41
- package/dist/lib/famix/src/model/famix/indexed_file_anchor.js +0 -52
- package/dist/lib/famix/src/model/famix/inheritance.js +0 -33
- package/dist/lib/famix/src/model/famix/interface.js +0 -64
- package/dist/lib/famix/src/model/famix/invocation.js +0 -54
- package/dist/lib/famix/src/model/famix/method.js +0 -67
- package/dist/lib/famix/src/model/famix/module.js +0 -84
- package/dist/lib/famix/src/model/famix/named_entity.js +0 -78
- package/dist/lib/famix/src/model/famix/parameter.js +0 -25
- package/dist/lib/famix/src/model/famix/parameterConcretisation.js +0 -44
- package/dist/lib/famix/src/model/famix/parameter_type.js +0 -45
- package/dist/lib/famix/src/model/famix/parametric_arrow_function.js +0 -31
- package/dist/lib/famix/src/model/famix/parametric_class.js +0 -44
- package/dist/lib/famix/src/model/famix/parametric_function.js +0 -31
- package/dist/lib/famix/src/model/famix/parametric_interface.js +0 -44
- package/dist/lib/famix/src/model/famix/parametric_method.js +0 -31
- package/dist/lib/famix/src/model/famix/primitive_type.js +0 -17
- package/dist/lib/famix/src/model/famix/property.js +0 -126
- package/dist/lib/famix/src/model/famix/reference.js +0 -33
- package/dist/lib/famix/src/model/famix/scoping_entity.js +0 -37
- package/dist/lib/famix/src/model/famix/script_entity.js +0 -29
- package/dist/lib/famix/src/model/famix/source_anchor.js +0 -27
- package/dist/lib/famix/src/model/famix/source_language.js +0 -35
- package/dist/lib/famix/src/model/famix/sourced_entity.js +0 -60
- package/dist/lib/famix/src/model/famix/structural_entity.js +0 -39
- package/dist/lib/famix/src/model/famix/text_anchor.js +0 -38
- package/dist/lib/famix/src/model/famix/type.js +0 -73
- package/dist/lib/famix/src/model/famix/variable.js +0 -24
- package/jest.config-old.ts +0 -199
- package/src/famix2puml.ts +0 -119
- package/src/lib/famix/package-lock.json +0 -301
- package/src/lib/famix/readme.md +0 -5
- package/src/lib/famix/src/famix_JSON_exporter.ts +0 -56
- package/src/lib/famix/src/famix_base_element.ts +0 -22
- package/src/lib/famix/src/famix_repository.ts +0 -243
- package/src/lib/famix/src/model/famix/access.ts +0 -53
- package/src/lib/famix/src/model/famix/alias.ts +0 -41
- package/src/lib/famix/src/model/famix/behavioral_entity.ts +0 -100
- package/src/lib/famix/src/model/famix/class.ts +0 -86
- package/src/lib/famix/src/model/famix/comment.ts +0 -50
- package/src/lib/famix/src/model/famix/concretisation.ts +0 -42
- package/src/lib/famix/src/model/famix/container_entity.ts +0 -165
- package/src/lib/famix/src/model/famix/decorator.ts +0 -39
- package/src/lib/famix/src/model/famix/enum.ts +0 -31
- package/src/lib/famix/src/model/famix/enum_value.ts +0 -29
- package/src/lib/famix/src/model/famix/implicit_variable.ts +0 -15
- package/src/lib/famix/src/model/famix/import_clause.ts +0 -54
- package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +0 -71
- package/src/lib/famix/src/model/famix/inheritance.ts +0 -41
- package/src/lib/famix/src/model/famix/interface.ts +0 -75
- package/src/lib/famix/src/model/famix/invocation.ts +0 -68
- package/src/lib/famix/src/model/famix/method.ts +0 -96
- package/src/lib/famix/src/model/famix/module.ts +0 -97
- package/src/lib/famix/src/model/famix/named_entity.ts +0 -98
- package/src/lib/famix/src/model/famix/parameterConcretisation.ts +0 -54
- package/src/lib/famix/src/model/famix/parameter_type.ts +0 -60
- package/src/lib/famix/src/model/famix/parametric_arrow_function.ts +0 -32
- package/src/lib/famix/src/model/famix/parametric_class.ts +0 -49
- package/src/lib/famix/src/model/famix/parametric_function.ts +0 -32
- package/src/lib/famix/src/model/famix/parametric_interface.ts +0 -49
- package/src/lib/famix/src/model/famix/parametric_method.ts +0 -32
- package/src/lib/famix/src/model/famix/primitive_type.ts +0 -15
- package/src/lib/famix/src/model/famix/property.ts +0 -152
- package/src/lib/famix/src/model/famix/reference.ts +0 -42
- package/src/lib/famix/src/model/famix/scoping_entity.ts +0 -36
- package/src/lib/famix/src/model/famix/script_entity.ts +0 -36
- package/src/lib/famix/src/model/famix/source_anchor.ts +0 -31
- package/src/lib/famix/src/model/famix/source_language.ts +0 -36
- package/src/lib/famix/src/model/famix/sourced_entity.ts +0 -73
- package/src/lib/famix/src/model/famix/structural_entity.ts +0 -44
- package/src/lib/famix/src/model/famix/text_anchor.ts +0 -49
- package/src/lib/famix/src/model/famix/type.ts +0 -89
- package/src/lib/famix/src/model/famix/variable.ts +0 -28
- package/src/lib/famix/tsconfig.json +0 -27
- package/src/lib/famix/tslint.json +0 -15
- /package/src/lib/famix/{src/index.ts → index.ts} +0 -0
- /package/src/lib/famix/{src/model → model}/famix/accessor.ts +0 -0
- /package/src/lib/famix/{src/model/famix/arrowFunction.ts → model/famix/arrow_function.ts} +0 -0
- /package/src/lib/famix/{src/model → model}/famix/entity.ts +0 -0
- /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/
|
|
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.
|
|
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.
|
|
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.
|
|
103
|
-
fmxIndexFileAnchor.
|
|
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
|
-
|
|
111
|
-
|
|
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.
|
|
118
|
-
fmxIndexFileAnchor.
|
|
119
|
-
fmxIndexFileAnchor.
|
|
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
|
-
|
|
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.
|
|
144
|
-
fmxFile.
|
|
145
|
-
fmxFile.
|
|
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 =
|
|
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
|
-
|
|
235
|
+
const foundModuleName = this.fmxModuleMap.get(moduleName);
|
|
236
|
+
if (!foundModuleName) {
|
|
169
237
|
fmxModule = new Famix.Module();
|
|
170
|
-
fmxModule.
|
|
171
|
-
fmxModule
|
|
172
|
-
fmxModule
|
|
173
|
-
fmxModule
|
|
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 =
|
|
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
|
-
|
|
267
|
+
const foundAlias = this.fmxAliasMap.get(aliasFullyQualifiedName);
|
|
268
|
+
if (!foundAlias) {
|
|
199
269
|
fmxAlias = new Famix.Alias();
|
|
200
|
-
fmxAlias.
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
241
|
-
fmxClass.
|
|
242
|
-
fmxClass.
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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
|
|
296
|
-
* @param
|
|
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(
|
|
374
|
+
public createOrGetFamixConcreteElement(concreteElement : ParametricVariantType,
|
|
375
|
+
concreteElementDeclaration : ConcreteElementTSMorphType,
|
|
376
|
+
concreteArguments: TypeNode[]): ParametricVariantType {
|
|
301
377
|
|
|
302
|
-
let fullyQualifiedFilename =
|
|
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) &&
|
|
316
|
-
|
|
317
|
-
|
|
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 (
|
|
402
|
+
if (concreteElement instanceof Famix.ParametricClass) {
|
|
325
403
|
this.fmxClassMap.set(fullyQualifiedFilename, concElement as Famix.ParametricClass);
|
|
326
|
-
} else if (
|
|
404
|
+
} else if (concreteElement instanceof Famix.ParametricInterface) {
|
|
327
405
|
this.fmxInterfaceMap.set(fullyQualifiedFilename, concElement as Famix.ParametricInterface);
|
|
328
|
-
} else if (
|
|
406
|
+
} else if (concreteElement instanceof Famix.ParametricFunction) {
|
|
329
407
|
this.fmxFunctionAndMethodMap.set(fullyQualifiedFilename, concElement as Famix.ParametricFunction);
|
|
330
|
-
} else if (
|
|
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,
|
|
412
|
+
this.fmxElementObjectMap.set(concElement,concreteElementDeclaration);
|
|
335
413
|
} else {
|
|
336
|
-
if (
|
|
337
|
-
concElement = this.fmxClassMap.get(fullyQualifiedFilename);
|
|
338
|
-
} else if (
|
|
339
|
-
concElement = this.fmxInterfaceMap.get(fullyQualifiedFilename);
|
|
340
|
-
} else if (
|
|
341
|
-
concElement = this.fmxFunctionAndMethodMap.get(fullyQualifiedFilename);
|
|
342
|
-
} else if (
|
|
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.
|
|
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.
|
|
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.
|
|
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:
|
|
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).
|
|
430
|
-
if (isSetter) {(fmxMethod as Famix.Accessor).
|
|
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).
|
|
453
|
-
fmxMethod.
|
|
454
|
-
fmxMethod.
|
|
455
|
-
fmxMethod.
|
|
456
|
-
fmxMethod.
|
|
457
|
-
fmxMethod.
|
|
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.
|
|
545
|
+
fmxMethod.name = methodName;
|
|
467
546
|
|
|
468
547
|
if (!isConstructor) {
|
|
469
548
|
if (method.getName().substring(0, 1) === "#") {
|
|
470
|
-
fmxMethod.
|
|
549
|
+
fmxMethod.isPrivate = true;
|
|
471
550
|
}
|
|
472
551
|
}
|
|
473
552
|
|
|
474
|
-
if (!fmxMethod.
|
|
475
|
-
fmxMethod.
|
|
553
|
+
if (!fmxMethod.isPrivate && !fmxMethod.isProtected) {
|
|
554
|
+
fmxMethod.isPublic = true;
|
|
476
555
|
}
|
|
477
556
|
else {
|
|
478
|
-
fmxMethod.
|
|
557
|
+
fmxMethod.isPublic = false;
|
|
479
558
|
}
|
|
480
559
|
|
|
481
560
|
if (!isSignature) {
|
|
482
|
-
fmxMethod.
|
|
561
|
+
fmxMethod.cyclomaticComplexity = currentCC[fmxMethod.name];
|
|
483
562
|
}
|
|
484
563
|
else {
|
|
485
|
-
fmxMethod.
|
|
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.
|
|
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.
|
|
497
|
-
fmxMethod.
|
|
575
|
+
fmxMethod.declaredType = fmxType;
|
|
576
|
+
fmxMethod.numberOfLinesOfCode = method.getEndLineNumber() - method.getStartLineNumber();
|
|
498
577
|
const parameters = method.getParameters();
|
|
499
|
-
fmxMethod.
|
|
578
|
+
fmxMethod.numberOfParameters = parameters.length;
|
|
500
579
|
|
|
501
580
|
if (!isSignature) {
|
|
502
|
-
fmxMethod.
|
|
581
|
+
fmxMethod.numberOfStatements = method.getStatements().length;
|
|
503
582
|
}
|
|
504
583
|
else {
|
|
505
|
-
fmxMethod.
|
|
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:
|
|
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
|
-
|
|
540
|
-
|
|
619
|
+
const name = func.getName();
|
|
620
|
+
if (name) {
|
|
621
|
+
fmxFunction.name = name;
|
|
541
622
|
}
|
|
542
623
|
else {
|
|
543
|
-
fmxFunction.
|
|
624
|
+
fmxFunction.name = "anonymous";
|
|
544
625
|
}
|
|
545
626
|
|
|
546
|
-
fmxFunction.
|
|
547
|
-
fmxFunction.
|
|
548
|
-
fmxFunction.
|
|
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.
|
|
559
|
-
fmxFunction.
|
|
639
|
+
fmxFunction.declaredType = fmxType;
|
|
640
|
+
fmxFunction.numberOfLinesOfCode = func.getEndLineNumber() - func.getStartLineNumber();
|
|
560
641
|
const parameters = func.getParameters();
|
|
561
|
-
fmxFunction.
|
|
562
|
-
fmxFunction.
|
|
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.
|
|
596
|
-
fmxParam.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
755
|
+
fmxParameterType.isStub = true;
|
|
675
756
|
} else {
|
|
676
757
|
fmxParameterType = new Famix.ParameterType();
|
|
677
758
|
}
|
|
678
759
|
|
|
679
|
-
fmxParameterType.
|
|
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
|
-
|
|
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.
|
|
709
|
-
fmxVariable.
|
|
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.
|
|
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.
|
|
755
|
-
fmxEnumValue.
|
|
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.
|
|
778
|
-
fmxDecorator.
|
|
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.
|
|
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.
|
|
888
|
+
logger.debug(`> NOTE: creating comment ${comment.getText()} in scope ${fmxScope.name}.`);
|
|
801
889
|
const fmxComment = new Famix.Comment();
|
|
802
|
-
fmxComment.
|
|
803
|
-
fmxComment.
|
|
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.
|
|
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).
|
|
950
|
+
(fmxType as Famix.ParameterType).baseType = fmxBaseType;
|
|
863
951
|
}
|
|
864
952
|
else {
|
|
865
953
|
fmxType = new Famix.Type();
|
|
866
954
|
}
|
|
867
955
|
|
|
868
|
-
fmxType.
|
|
869
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
909
|
-
fmxAccess.
|
|
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.
|
|
932
|
-
fmxInvocation.
|
|
1027
|
+
fmxInvocation.sender = sender;
|
|
1028
|
+
fmxInvocation.receiver = receiver;
|
|
933
1029
|
fmxInvocation.addCandidate(fmxMethodOrFunction);
|
|
934
|
-
fmxInvocation.
|
|
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.
|
|
992
|
-
superClass.
|
|
993
|
-
superClass.
|
|
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.
|
|
1001
|
-
fmxInheritance.
|
|
1105
|
+
fmxInheritance.subclass = subClass;
|
|
1106
|
+
fmxInheritance.superclass = superClass;
|
|
1002
1107
|
|
|
1003
1108
|
this.famixRep.addElement(fmxInheritance);
|
|
1004
1109
|
|
|
1005
|
-
|
|
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.
|
|
1012
|
-
fmxImportClause.
|
|
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.
|
|
1161
|
+
importedEntity.name = importedEntityName;
|
|
1056
1162
|
if (!isInExports) {
|
|
1057
|
-
importedEntity.
|
|
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.
|
|
1177
|
+
importedEntity.name = importedEntityName;
|
|
1178
|
+
initFQN(importDeclaration, importedEntity);
|
|
1072
1179
|
this.makeFamixIndexFileAnchor(importElement, importedEntity);
|
|
1073
|
-
importedEntity.
|
|
1074
|
-
const anyType = this.createOrGetFamixType('any',
|
|
1075
|
-
(importedEntity as Famix.StructuralEntity).
|
|
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.
|
|
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.
|
|
1089
|
-
fmxImportClause.
|
|
1195
|
+
fmxImportClause.importingEntity = fmxImporter;
|
|
1196
|
+
fmxImportClause.importedEntity = importedEntity;
|
|
1090
1197
|
if (importDeclaration instanceof ImportEqualsDeclaration) {
|
|
1091
|
-
fmxImportClause.
|
|
1198
|
+
fmxImportClause.moduleSpecifier = importDeclaration?.getModuleReference().getText() as string;
|
|
1092
1199
|
} else {
|
|
1093
|
-
fmxImportClause.
|
|
1200
|
+
fmxImportClause.moduleSpecifier = importDeclaration?.getModuleSpecifierValue() as string;
|
|
1094
1201
|
}
|
|
1095
1202
|
|
|
1096
|
-
logger.debug(`createFamixImportClause: ${fmxImportClause.
|
|
1097
|
-
Helpers.getSubTypeName(fmxImportClause.
|
|
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
|
|
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.
|
|
1243
|
+
fmxArrowFunction.name = functionName;
|
|
1137
1244
|
}
|
|
1138
1245
|
else {
|
|
1139
|
-
fmxArrowFunction.
|
|
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.
|
|
1146
|
-
fmxArrowFunction.
|
|
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.
|
|
1157
|
-
fmxArrowFunction.
|
|
1263
|
+
fmxArrowFunction.declaredType = fmxType;
|
|
1264
|
+
fmxArrowFunction.numberOfLinesOfCode = arrowFunction.getEndLineNumber() - arrowFunction.getStartLineNumber();
|
|
1158
1265
|
const parameters = arrowFunction.getParameters();
|
|
1159
|
-
fmxArrowFunction.
|
|
1160
|
-
fmxArrowFunction.
|
|
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.
|
|
1179
|
-
fmxConcretisation.
|
|
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.
|
|
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
|
|
1193
|
-
const conClass = concretisation.
|
|
1194
|
-
const genClass = concretisation.
|
|
1195
|
-
|
|
1196
|
-
const
|
|
1197
|
-
const
|
|
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.
|
|
1315
|
+
if(conClassTypeParameter && genClassTypeParameter && conClassTypeParameter.name != genClassTypeParameter.name){
|
|
1208
1316
|
parameterConcretisations.forEach((param : Famix.ParameterConcretisation) => {
|
|
1209
|
-
if (conClassTypeParameter.
|
|
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.
|
|
1217
|
-
fmxParameterConcretisation.
|
|
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()
|
|
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()
|
|
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.
|
|
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.
|
|
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,
|
|
1469
|
+
genElement = this.createOrGetFamixFunction(element, {}) as Famix.ParametricFunction;
|
|
1352
1470
|
} else {
|
|
1353
|
-
genElement = this.createOrGetFamixMethod(element,
|
|
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.
|
|
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()
|
|
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.
|
|
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.
|
|
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
|
+
|