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