ts2famix 1.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/.eslintrc.json +24 -0
- package/.github/workflows/node.js.yml +60 -0
- package/LICENSE +23 -0
- package/README.md +111 -0
- package/doc-metamodel/skins.include.puml +2 -0
- package/jest.config.ts +199 -0
- package/package.json +47 -0
- package/src/analyze.ts +90 -0
- package/src/analyze_functions/processAccesses.ts +50 -0
- package/src/analyze_functions/processFiles.ts +656 -0
- package/src/analyze_functions/processImportClauses.ts +77 -0
- package/src/analyze_functions/processInheritances.ts +84 -0
- package/src/analyze_functions/processInvocations.ts +51 -0
- package/src/famix2puml.ts +119 -0
- package/src/famix_functions/famix_functions.ts +552 -0
- package/src/famix_functions/famix_functions_associations.ts +208 -0
- package/src/famix_functions/famix_functions_index.ts +44 -0
- package/src/famix_functions/famix_functions_types.ts +100 -0
- package/src/fqn.ts +127 -0
- package/src/fqp_implementation.ts +66 -0
- package/src/generate_uml.sh +16 -0
- package/src/lib/famix/License.md +23 -0
- package/src/lib/famix/package-lock.json +301 -0
- package/src/lib/famix/package.json +28 -0
- package/src/lib/famix/readme.md +5 -0
- package/src/lib/famix/src/famix_JSON_exporter.ts +56 -0
- package/src/lib/famix/src/famix_base_element.ts +18 -0
- package/src/lib/famix/src/famix_repository.ts +199 -0
- package/src/lib/famix/src/index.ts +8 -0
- package/src/lib/famix/src/model/famix/access.ts +53 -0
- package/src/lib/famix/src/model/famix/accessor.ts +15 -0
- package/src/lib/famix/src/model/famix/alias.ts +41 -0
- package/src/lib/famix/src/model/famix/association.ts +44 -0
- package/src/lib/famix/src/model/famix/behavioral_entity.ts +107 -0
- package/src/lib/famix/src/model/famix/c_source_language.ts +15 -0
- package/src/lib/famix/src/model/famix/class.ts +86 -0
- package/src/lib/famix/src/model/famix/comment.ts +50 -0
- package/src/lib/famix/src/model/famix/container_entity.ts +165 -0
- package/src/lib/famix/src/model/famix/custom_source_language.ts +27 -0
- package/src/lib/famix/src/model/famix/decorator.ts +39 -0
- package/src/lib/famix/src/model/famix/entity.ts +15 -0
- package/src/lib/famix/src/model/famix/enum.ts +31 -0
- package/src/lib/famix/src/model/famix/enum_value.ts +29 -0
- package/src/lib/famix/src/model/famix/function.ts +15 -0
- package/src/lib/famix/src/model/famix/implicit_variable.ts +15 -0
- package/src/lib/famix/src/model/famix/import_clause.ts +53 -0
- package/src/lib/famix/src/model/famix/index.ts +42 -0
- package/src/lib/famix/src/model/famix/indexed_file_anchor.ts +49 -0
- package/src/lib/famix/src/model/famix/inheritance.ts +42 -0
- package/src/lib/famix/src/model/famix/interface.ts +75 -0
- package/src/lib/famix/src/model/famix/invocation.ts +68 -0
- package/src/lib/famix/src/model/famix/method.ts +96 -0
- package/src/lib/famix/src/model/famix/module.ts +31 -0
- package/src/lib/famix/src/model/famix/named_entity.ts +98 -0
- package/src/lib/famix/src/model/famix/namespace.ts +28 -0
- package/src/lib/famix/src/model/famix/parameter.ts +29 -0
- package/src/lib/famix/src/model/famix/parameterizable_class.ts +31 -0
- package/src/lib/famix/src/model/famix/parameterizable_interface.ts +31 -0
- package/src/lib/famix/src/model/famix/parameterized_type.ts +40 -0
- package/src/lib/famix/src/model/famix/primitive_type.ts +15 -0
- package/src/lib/famix/src/model/famix/property.ts +54 -0
- package/src/lib/famix/src/model/famix/reference.ts +42 -0
- package/src/lib/famix/src/model/famix/scoping_entity.ts +31 -0
- package/src/lib/famix/src/model/famix/script_entity.ts +38 -0
- package/src/lib/famix/src/model/famix/source_anchor.ts +31 -0
- package/src/lib/famix/src/model/famix/source_language.ts +31 -0
- package/src/lib/famix/src/model/famix/sourced_entity.ts +70 -0
- package/src/lib/famix/src/model/famix/structural_entity.ts +44 -0
- package/src/lib/famix/src/model/famix/text_anchor.ts +49 -0
- package/src/lib/famix/src/model/famix/type.ts +88 -0
- package/src/lib/famix/src/model/famix/type_parameter.ts +33 -0
- package/src/lib/famix/src/model/famix/variable.ts +28 -0
- package/src/lib/famix/tsconfig.json +27 -0
- package/src/lib/famix/tslint.json +15 -0
- package/src/lib/ts-complex/cyclomatic-service.ts +85 -0
- package/src/ts2famix-cli.ts +26 -0
- package/src/ts2famix-tsconfig.ts +30 -0
- package/test/abstractClassWithComments.test.ts +58 -0
- package/test/abstracts.test.ts +53 -0
- package/test/access.test.ts +62 -0
- package/test/accesses.test.ts +42 -0
- package/test/accessorsWithDecorators.test.ts +98 -0
- package/test/alias.test.ts +39 -0
- package/test/classExtendsUndefinedClass.test.ts +41 -0
- package/test/classImplementsUndefinedInterface.test.ts +45 -0
- package/test/classWithDecorators.test.ts +65 -0
- package/test/entities.test.ts +232 -0
- package/test/entities_json.test.ts +48 -0
- package/test/enum.test.ts +55 -0
- package/test/functionReturnsFunction.test.ts +53 -0
- package/test/functionWithParameters.test.ts +38 -0
- package/test/functionWithVariables.test.ts +64 -0
- package/test/functions.test.ts +23 -0
- package/test/functionsInFunction.test.ts +40 -0
- package/test/functionsInMethod.test.ts +42 -0
- package/test/genericClass.test.ts +42 -0
- package/test/genericClassInheritsInterface.test.ts +47 -0
- package/test/genericInterface.test.ts +38 -0
- package/test/genericMethod.test.ts +65 -0
- package/test/genericWithInvocation.test.ts +71 -0
- package/test/generics.test.ts +68 -0
- package/test/inheritance.test.ts +50 -0
- package/test/interfaceInheritsInterface.test.ts +40 -0
- package/test/interfaceInheritsUndefinedInterface.test.ts +41 -0
- package/test/invocation.test.ts +94 -0
- package/test/invocationWithFunction.test.ts +42 -0
- package/test/invocationWithVariable.test.ts +46 -0
- package/test/invocation_json.test.ts +63 -0
- package/test/invocations.test.ts +131 -0
- package/test/jsDoc.test.ts +31 -0
- package/test/methodWithDecorator.test.ts +44 -0
- package/test/methods.test.ts +42 -0
- package/test/metrics.test.ts +51 -0
- package/test/module.test.ts +71 -0
- package/test/namespaces.test.ts +54 -0
- package/test/namespacesAndClasses.test.ts +66 -0
- package/test/parameterWithDecorators.test.ts +54 -0
- package/test/propertyWithDecorators.test.ts +80 -0
- package/test/sample.test.ts +13 -0
- package/test/simpleFunction.test.ts +32 -0
- package/test/simpleTest.test.ts +18 -0
- package/test/simpleTest2.test.ts +36 -0
- package/test/types.test.ts +58 -0
- package/test_src/sample.ts +103 -0
- package/test_src/sampleForModule.ts +10 -0
- package/test_src/sampleForModule2.ts +7 -0
- package/test_src/sampleForModule3.ts +2 -0
- package/tsconfig.json +70 -0
|
@@ -0,0 +1,552 @@
|
|
|
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 } from "ts-morph";
|
|
2
|
+
import * as Famix from "../lib/famix/src/model/famix";
|
|
3
|
+
import { FamixRepository } from "../lib/famix/src/famix_repository";
|
|
4
|
+
import { FQNFunctions } from "../fqn";
|
|
5
|
+
import { FamixFunctionsIndex } from "./famix_functions_index";
|
|
6
|
+
import { FamixFunctionsAssociations } from "./famix_functions_associations";
|
|
7
|
+
import { FamixFunctionsTypes } from "./famix_functions_types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This class contains all the functions needed to create Famix entities
|
|
11
|
+
*/
|
|
12
|
+
export class FamixFunctions {
|
|
13
|
+
|
|
14
|
+
private famixRep = new FamixRepository(); // The Famix repository
|
|
15
|
+
private FQNFunctions = new FQNFunctions(); // The fully qualified name functions
|
|
16
|
+
private fmxAliases = new Map<string, Famix.Alias>(); // Maps the alias names to their Famix model
|
|
17
|
+
private fmxClasses = new Map<string, Famix.Class | Famix.ParameterizableClass>(); // Maps the class names to their Famix model
|
|
18
|
+
private fmxInterfaces = new Map<string, Famix.Interface | Famix.ParameterizableInterface>(); // Maps the interface names to their Famix model
|
|
19
|
+
private fmxNamespaces = new Map<string, Famix.Namespace>(); // Maps the namespace names to their Famix model
|
|
20
|
+
private fmxFiles = new Map<string, Famix.ScriptEntity | Famix.Module>(); // Maps the source file names to their Famix model
|
|
21
|
+
private famixFunctionsIndex = new FamixFunctionsIndex(this.famixRep); // FamixFunctionsIndex object, it contains all the functions needed to create Famix index file anchors
|
|
22
|
+
private famixFunctionsAssociations = new FamixFunctionsAssociations(this.famixRep, this.fmxClasses, this.fmxInterfaces); // FamixFunctionsAssociations object, it contains all the functions needed to create Famix associations
|
|
23
|
+
private famixFunctionsTypes = new FamixFunctionsTypes(this.famixRep); // FamixFunctionsTypes object, it contains all the functions needed to create Famix types
|
|
24
|
+
private UNKNOWN_VALUE = '(unknown due to parsing error)'; // The value to use when a name is not usable
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Gets the Famix repository
|
|
28
|
+
* @returns The Famix repository
|
|
29
|
+
*/
|
|
30
|
+
public getFamixRepository(): FamixRepository {
|
|
31
|
+
return this.famixRep;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates or gets a Famix script entity or module
|
|
36
|
+
* @param f A source file
|
|
37
|
+
* @param isModule A boolean indicating if the source file is a module
|
|
38
|
+
* @returns The Famix model of the source file
|
|
39
|
+
*/
|
|
40
|
+
public createOrGetFamixFile(f: SourceFile, isModule: boolean): Famix.ScriptEntity | Famix.Module {
|
|
41
|
+
let fmxFile: Famix.ScriptEntity | Famix.Module;
|
|
42
|
+
const fileName = f.getBaseName();
|
|
43
|
+
if (!this.fmxFiles.has(fileName)) {
|
|
44
|
+
if (isModule) {
|
|
45
|
+
fmxFile = new Famix.Module(this.famixRep);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
fmxFile = new Famix.ScriptEntity(this.famixRep);
|
|
49
|
+
}
|
|
50
|
+
fmxFile.setName(fileName);
|
|
51
|
+
fmxFile.setNumberOfLinesOfText(f.getEndLineNumber() - f.getStartLineNumber());
|
|
52
|
+
fmxFile.setNumberOfCharacters(f.getFullText().length);
|
|
53
|
+
|
|
54
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(f, fmxFile);
|
|
55
|
+
|
|
56
|
+
this.fmxFiles.set(fileName, fmxFile);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
fmxFile = this.fmxFiles.get(fileName);
|
|
60
|
+
}
|
|
61
|
+
return fmxFile;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Creates or gets a Famix namespace
|
|
66
|
+
* @param m A namespace
|
|
67
|
+
* @returns The Famix model of the namespace
|
|
68
|
+
*/
|
|
69
|
+
public createOrGetFamixNamespace(m: ModuleDeclaration): Famix.Namespace {
|
|
70
|
+
let fmxNamespace: Famix.Namespace;
|
|
71
|
+
const namespaceName = m.getName();
|
|
72
|
+
if (!this.fmxNamespaces.has(namespaceName)) {
|
|
73
|
+
fmxNamespace = new Famix.Namespace(this.famixRep);
|
|
74
|
+
fmxNamespace.setName(namespaceName);
|
|
75
|
+
|
|
76
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(m, fmxNamespace);
|
|
77
|
+
|
|
78
|
+
this.fmxNamespaces.set(namespaceName, fmxNamespace);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
fmxNamespace = this.fmxNamespaces.get(namespaceName);
|
|
82
|
+
}
|
|
83
|
+
return fmxNamespace;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Creates a Famix alias
|
|
88
|
+
* @param a An alias
|
|
89
|
+
* @returns The Famix model of the alias
|
|
90
|
+
*/
|
|
91
|
+
public createFamixAlias(a: TypeAliasDeclaration): Famix.Alias {
|
|
92
|
+
let fmxAlias: Famix.Alias;
|
|
93
|
+
const aliasName = a.getName();
|
|
94
|
+
if (!this.fmxAliases.has(aliasName)) {
|
|
95
|
+
fmxAlias = new Famix.Alias(this.famixRep);
|
|
96
|
+
fmxAlias.setName(a.getName());
|
|
97
|
+
|
|
98
|
+
const fmxType = this.createOrGetFamixType(aliasName, a);
|
|
99
|
+
fmxAlias.setAliasedEntity(fmxType);
|
|
100
|
+
|
|
101
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(a, fmxAlias);
|
|
102
|
+
|
|
103
|
+
this.fmxAliases.set(aliasName, fmxAlias);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
fmxAlias = this.fmxAliases.get(aliasName);
|
|
107
|
+
}
|
|
108
|
+
return fmxAlias;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates or gets a Famix class or parameterizable class
|
|
113
|
+
* @param cls A class
|
|
114
|
+
* @returns The Famix model of the class
|
|
115
|
+
*/
|
|
116
|
+
public createOrGetFamixClass(cls: ClassDeclaration): Famix.Class | Famix.ParameterizableClass {
|
|
117
|
+
let fmxClass: Famix.Class | Famix.ParameterizableClass;
|
|
118
|
+
const isAbstract = cls.isAbstract();
|
|
119
|
+
const clsName = cls.getName();
|
|
120
|
+
if (!this.fmxClasses.has(clsName)) {
|
|
121
|
+
const isGeneric = cls.getTypeParameters().length;
|
|
122
|
+
if (isGeneric) {
|
|
123
|
+
fmxClass = new Famix.ParameterizableClass(this.famixRep);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
fmxClass = new Famix.Class(this.famixRep);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fmxClass.setName(clsName);
|
|
130
|
+
fmxClass.setIsAbstract(isAbstract);
|
|
131
|
+
|
|
132
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(cls, fmxClass);
|
|
133
|
+
|
|
134
|
+
this.fmxClasses.set(clsName, fmxClass);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
fmxClass = this.fmxClasses.get(clsName) as (Famix.Class | Famix.ParameterizableClass);
|
|
138
|
+
}
|
|
139
|
+
return fmxClass;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Creates or gets a Famix interface or parameterizable interface
|
|
144
|
+
* @param inter An interface
|
|
145
|
+
* @returns The Famix model of the interface
|
|
146
|
+
*/
|
|
147
|
+
public createOrGetFamixInterface(inter: InterfaceDeclaration): Famix.Interface | Famix.ParameterizableInterface {
|
|
148
|
+
let fmxInterface: Famix.Interface | Famix.ParameterizableInterface;
|
|
149
|
+
const interName = inter.getName();
|
|
150
|
+
if (!this.fmxInterfaces.has(interName)) {
|
|
151
|
+
const isGeneric = inter.getTypeParameters().length;
|
|
152
|
+
if (isGeneric) {
|
|
153
|
+
fmxInterface = new Famix.ParameterizableInterface(this.famixRep);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
fmxInterface = new Famix.Interface(this.famixRep);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fmxInterface.setName(interName);
|
|
160
|
+
|
|
161
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(inter, fmxInterface);
|
|
162
|
+
|
|
163
|
+
this.fmxInterfaces.set(interName, fmxInterface);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
fmxInterface = this.fmxInterfaces.get(interName) as (Famix.Interface | Famix.ParameterizableInterface);
|
|
167
|
+
}
|
|
168
|
+
return fmxInterface;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Creates a Famix property
|
|
173
|
+
* @param property A property
|
|
174
|
+
* @returns The Famix model of the property
|
|
175
|
+
*/
|
|
176
|
+
public createFamixProperty(property: PropertyDeclaration | PropertySignature): Famix.Property {
|
|
177
|
+
const fmxProperty = new Famix.Property(this.famixRep);
|
|
178
|
+
const isSignature = property instanceof PropertySignature;
|
|
179
|
+
fmxProperty.setName(property.getName());
|
|
180
|
+
|
|
181
|
+
let propTypeName = this.UNKNOWN_VALUE;
|
|
182
|
+
try {
|
|
183
|
+
propTypeName = property.getType().getText().trim();
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for property: ${property.getName()}. Continuing...`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const fmxType = this.createOrGetFamixType(propTypeName, property);
|
|
189
|
+
fmxProperty.setDeclaredType(fmxType);
|
|
190
|
+
|
|
191
|
+
property.getModifiers().forEach(m => fmxProperty.addModifier(m.getText()));
|
|
192
|
+
if (!isSignature && property.getExclamationTokenNode()) {
|
|
193
|
+
fmxProperty.addModifier("!");
|
|
194
|
+
}
|
|
195
|
+
if (property.getQuestionTokenNode()) {
|
|
196
|
+
fmxProperty.addModifier("?");
|
|
197
|
+
}
|
|
198
|
+
if (property.getName().substring(0, 1) === "#") {
|
|
199
|
+
fmxProperty.addModifier("#");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (fmxProperty.getModifiers().has("static")) {
|
|
203
|
+
fmxProperty.setIsClassSide(true);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
fmxProperty.setIsClassSide(false);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(property, fmxProperty);
|
|
210
|
+
|
|
211
|
+
return fmxProperty;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Creates a Famix method or accessor
|
|
216
|
+
* @param method A method or an accessor
|
|
217
|
+
* @param currentCC The cyclomatic complexity metrics of the current source file
|
|
218
|
+
* @returns The Famix model of the method or the accessor
|
|
219
|
+
*/
|
|
220
|
+
public createFamixMethod(method: MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration, currentCC: unknown): Famix.Method | Famix.Accessor {
|
|
221
|
+
let fmxMethod: Famix.Method | Famix.Accessor;
|
|
222
|
+
if (method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) {
|
|
223
|
+
fmxMethod = new Famix.Accessor(this.famixRep);
|
|
224
|
+
const isGetter = method instanceof GetAccessorDeclaration;
|
|
225
|
+
const isSetter = method instanceof SetAccessorDeclaration;
|
|
226
|
+
if (isGetter) {(fmxMethod as Famix.Accessor).setKind("getter");}
|
|
227
|
+
if (isSetter) {(fmxMethod as Famix.Accessor).setKind("setter");}
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
fmxMethod = new Famix.Method(this.famixRep);
|
|
231
|
+
}
|
|
232
|
+
const isConstructor = method instanceof ConstructorDeclaration;
|
|
233
|
+
const isSignature = method instanceof MethodSignature;
|
|
234
|
+
const isGeneric = method.getTypeParameters().length > 0;
|
|
235
|
+
fmxMethod.setIsGeneric(isGeneric);
|
|
236
|
+
|
|
237
|
+
let isAbstract = false;
|
|
238
|
+
let isStatic = false;
|
|
239
|
+
if (method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) {
|
|
240
|
+
isAbstract = method.isAbstract();
|
|
241
|
+
isStatic = method.isStatic();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (isConstructor) {(fmxMethod as Famix.Accessor).setKind("constructor");}
|
|
245
|
+
fmxMethod.setIsAbstract(isAbstract);
|
|
246
|
+
fmxMethod.setIsClassSide(isStatic);
|
|
247
|
+
fmxMethod.setIsPrivate((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'private')) !== undefined : false);
|
|
248
|
+
fmxMethod.setIsProtected((method instanceof MethodDeclaration || method instanceof GetAccessorDeclaration || method instanceof SetAccessorDeclaration) ? (method.getModifiers().find(x => x.getText() === 'protected')) !== undefined : false);
|
|
249
|
+
fmxMethod.setSignature(this.computeSignature(method.getText()));
|
|
250
|
+
|
|
251
|
+
let methodName: string;
|
|
252
|
+
if (isConstructor) {
|
|
253
|
+
methodName = "constructor";
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
methodName = (method as MethodDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration).getName();
|
|
257
|
+
}
|
|
258
|
+
fmxMethod.setName(methodName);
|
|
259
|
+
|
|
260
|
+
if (!isConstructor) {
|
|
261
|
+
if (method.getName().substring(0, 1) === "#") {
|
|
262
|
+
fmxMethod.setIsPrivate(true);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (!fmxMethod.getIsPrivate() && !fmxMethod.getIsProtected()) {
|
|
267
|
+
fmxMethod.setIsPublic(true);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
fmxMethod.setIsPublic(false);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!isSignature) {
|
|
274
|
+
fmxMethod.setCyclomaticComplexity(currentCC[fmxMethod.getName()]);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
fmxMethod.setCyclomaticComplexity(0);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let methodTypeName = this.UNKNOWN_VALUE;
|
|
281
|
+
try {
|
|
282
|
+
methodTypeName = method.getReturnType().getText().trim();
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of method: ${fmxMethod.getName()}. Continuing...`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const fmxType = this.createOrGetFamixType(methodTypeName, method);
|
|
288
|
+
fmxMethod.setDeclaredType(fmxType);
|
|
289
|
+
fmxMethod.setNumberOfLinesOfCode(method.getEndLineNumber() - method.getStartLineNumber());
|
|
290
|
+
const parameters = method.getParameters();
|
|
291
|
+
fmxMethod.setNumberOfParameters(parameters.length);
|
|
292
|
+
|
|
293
|
+
if (!isSignature) {
|
|
294
|
+
fmxMethod.setNumberOfStatements(method.getStatements().length);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
fmxMethod.setNumberOfStatements(0);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(method, fmxMethod);
|
|
301
|
+
|
|
302
|
+
return fmxMethod;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Creates a Famix function
|
|
307
|
+
* @param func A function
|
|
308
|
+
* @param currentCC The cyclomatic complexity metrics of the current source file
|
|
309
|
+
* @returns The Famix model of the function
|
|
310
|
+
*/
|
|
311
|
+
public createFamixFunction(func: FunctionDeclaration | FunctionExpression, currentCC: unknown): Famix.Function {
|
|
312
|
+
const fmxFunction = new Famix.Function(this.famixRep);
|
|
313
|
+
if (func.getName()) {
|
|
314
|
+
fmxFunction.setName(func.getName());
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
fmxFunction.setName("anonymous");
|
|
318
|
+
}
|
|
319
|
+
fmxFunction.setSignature(this.computeSignature(func.getText()));
|
|
320
|
+
fmxFunction.setCyclomaticComplexity(currentCC[fmxFunction.getName()]);
|
|
321
|
+
const isGeneric = func.getTypeParameters().length > 0;
|
|
322
|
+
fmxFunction.setIsGeneric(isGeneric);
|
|
323
|
+
|
|
324
|
+
let functionTypeName = this.UNKNOWN_VALUE;
|
|
325
|
+
try {
|
|
326
|
+
functionTypeName = func.getReturnType().getText().trim();
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for return type of function: ${func.getName()}. Continuing...`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const fmxType = this.createOrGetFamixType(functionTypeName, func);
|
|
332
|
+
fmxFunction.setDeclaredType(fmxType);
|
|
333
|
+
fmxFunction.setNumberOfLinesOfCode(func.getEndLineNumber() - func.getStartLineNumber());
|
|
334
|
+
const parameters = func.getParameters();
|
|
335
|
+
fmxFunction.setNumberOfParameters(parameters.length);
|
|
336
|
+
fmxFunction.setNumberOfStatements(func.getStatements().length);
|
|
337
|
+
|
|
338
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(func, fmxFunction);
|
|
339
|
+
|
|
340
|
+
return fmxFunction;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Creates a Famix parameter
|
|
345
|
+
* @param param A parameter
|
|
346
|
+
* @returns The Famix model of the parameter
|
|
347
|
+
*/
|
|
348
|
+
public createFamixParameter(param: ParameterDeclaration): Famix.Parameter {
|
|
349
|
+
const fmxParam = new Famix.Parameter(this.famixRep);
|
|
350
|
+
|
|
351
|
+
let paramTypeName = this.UNKNOWN_VALUE;
|
|
352
|
+
try {
|
|
353
|
+
paramTypeName = param.getType().getText().trim();
|
|
354
|
+
} catch (error) {
|
|
355
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for parameter: ${param.getName()}. Continuing...`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const fmxType = this.createOrGetFamixType(paramTypeName, param);
|
|
359
|
+
fmxParam.setDeclaredType(fmxType);
|
|
360
|
+
fmxParam.setName(param.getName());
|
|
361
|
+
|
|
362
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(param, fmxParam);
|
|
363
|
+
|
|
364
|
+
return fmxParam;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Creates a Famix type parameter
|
|
369
|
+
* @param tp A type parameter
|
|
370
|
+
* @returns The Famix model of the type parameter
|
|
371
|
+
*/
|
|
372
|
+
public createFamixTypeParameter(tp: TypeParameterDeclaration): Famix.TypeParameter {
|
|
373
|
+
const fmxTypeParameter = new Famix.TypeParameter(this.famixRep);
|
|
374
|
+
fmxTypeParameter.setName(tp.getName());
|
|
375
|
+
|
|
376
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(tp, fmxTypeParameter);
|
|
377
|
+
|
|
378
|
+
return fmxTypeParameter;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Creates a Famix variable
|
|
383
|
+
* @param variable A variable
|
|
384
|
+
* @returns The Famix model of the variable
|
|
385
|
+
*/
|
|
386
|
+
public createFamixVariable(variable: VariableDeclaration): Famix.Variable {
|
|
387
|
+
const fmxVariable = new Famix.Variable(this.famixRep);
|
|
388
|
+
|
|
389
|
+
let variableTypeName = this.UNKNOWN_VALUE;
|
|
390
|
+
try {
|
|
391
|
+
variableTypeName = variable.getType().getText().trim();
|
|
392
|
+
} catch (error) {
|
|
393
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for variable: ${variable.getName()}. Continuing...`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const fmxType = this.createOrGetFamixType(variableTypeName, variable);
|
|
397
|
+
fmxVariable.setDeclaredType(fmxType);
|
|
398
|
+
fmxVariable.setName(variable.getName());
|
|
399
|
+
|
|
400
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(variable, fmxVariable);
|
|
401
|
+
|
|
402
|
+
return fmxVariable;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Creates a Famix enum
|
|
407
|
+
* @param enumEntity An enum
|
|
408
|
+
* @returns The Famix model of the enum
|
|
409
|
+
*/
|
|
410
|
+
public createFamixEnum(enumEntity: EnumDeclaration): Famix.Enum {
|
|
411
|
+
const fmxEnum = new Famix.Enum(this.famixRep);
|
|
412
|
+
fmxEnum.setName(enumEntity.getName());
|
|
413
|
+
|
|
414
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(enumEntity, fmxEnum);
|
|
415
|
+
|
|
416
|
+
return fmxEnum;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Creates a Famix enum value
|
|
421
|
+
* @param enumMember An enum member
|
|
422
|
+
* @returns The Famix model of the enum member
|
|
423
|
+
*/
|
|
424
|
+
public createFamixEnumValue(enumMember: EnumMember): Famix.EnumValue {
|
|
425
|
+
const fmxEnumValue = new Famix.EnumValue(this.famixRep);
|
|
426
|
+
|
|
427
|
+
let enumValueTypeName = this.UNKNOWN_VALUE;
|
|
428
|
+
try {
|
|
429
|
+
enumValueTypeName = enumMember.getType().getText().trim();
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.error(`> WARNING: got exception ${error}. Failed to get usable name for enum value: ${enumMember.getName()}. Continuing...`);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const fmxType = this.createOrGetFamixType(enumValueTypeName, enumMember);
|
|
435
|
+
fmxEnumValue.setDeclaredType(fmxType);
|
|
436
|
+
fmxEnumValue.setName(enumMember.getName());
|
|
437
|
+
|
|
438
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(enumMember, fmxEnumValue);
|
|
439
|
+
|
|
440
|
+
return fmxEnumValue;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Creates or gets a Famix decorator
|
|
445
|
+
* @param decorator A decorator
|
|
446
|
+
* @param decoratedEntity A class, a method, a parameter or a property
|
|
447
|
+
* @returns The Famix model of the decorator
|
|
448
|
+
*/
|
|
449
|
+
public createOrGetFamixDecorator(decorator: Decorator, decoratedEntity: ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ParameterDeclaration | PropertyDeclaration): Famix.Decorator {
|
|
450
|
+
const fmxDecorator = new Famix.Decorator(this.famixRep);
|
|
451
|
+
const decoratorName = "@" + decorator.getName();
|
|
452
|
+
const decoratorExpression = decorator.getText().substring(1);
|
|
453
|
+
|
|
454
|
+
fmxDecorator.setName(decoratorName);
|
|
455
|
+
fmxDecorator.setDecoratorExpression(decoratorExpression);
|
|
456
|
+
const decoratedEntityFullyQualifiedName = this.FQNFunctions.getFQN(decoratedEntity);
|
|
457
|
+
const fmxDecoratedEntity = this.getFamixEntityByFullyQualifiedName(decoratedEntityFullyQualifiedName) as Famix.NamedEntity;
|
|
458
|
+
fmxDecorator.setDecoratedEntity(fmxDecoratedEntity);
|
|
459
|
+
|
|
460
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(decorator, fmxDecorator);
|
|
461
|
+
|
|
462
|
+
return fmxDecorator;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Creates a Famix comment
|
|
467
|
+
* @param comment A comment
|
|
468
|
+
* @param fmxScope The Famix model of the comment's container
|
|
469
|
+
* @param isJSDoc A boolean indicating if the comment is a JSDoc
|
|
470
|
+
* @returns The Famix model of the comment
|
|
471
|
+
*/
|
|
472
|
+
public createFamixComment(comment: CommentRange, fmxScope: Famix.NamedEntity, isJSDoc: boolean): Famix.Comment {
|
|
473
|
+
const fmxComment = new Famix.Comment(this.famixRep);
|
|
474
|
+
fmxComment.setContent(comment.getText());
|
|
475
|
+
fmxComment.setContainer(fmxScope);
|
|
476
|
+
fmxComment.setIsJSDoc(isJSDoc);
|
|
477
|
+
|
|
478
|
+
this.famixFunctionsIndex.makeFamixIndexFileAnchor(comment, fmxComment);
|
|
479
|
+
|
|
480
|
+
return fmxComment;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Creates or gets a Famix type
|
|
485
|
+
* @param typeName A type name
|
|
486
|
+
* @param element A ts-morph element
|
|
487
|
+
* @returns The Famix model of the type
|
|
488
|
+
*/
|
|
489
|
+
private createOrGetFamixType(typeName: string, element: TypeAliasDeclaration | PropertyDeclaration | PropertySignature | MethodDeclaration | ConstructorDeclaration | MethodSignature | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression | ParameterDeclaration | VariableDeclaration | EnumMember): Famix.Type | Famix.PrimitiveType | Famix.ParameterizedType {
|
|
490
|
+
return this.famixFunctionsTypes.createOrGetFamixType(typeName, element);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Creates a Famix access
|
|
495
|
+
* @param node A node
|
|
496
|
+
* @param id An id of a parameter, a variable, a property or an enum member
|
|
497
|
+
*/
|
|
498
|
+
public createFamixAccess(node: Identifier, id: number): void {
|
|
499
|
+
this.famixFunctionsAssociations.createFamixAccess(node, id);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Creates a Famix invocation
|
|
504
|
+
* @param node A node
|
|
505
|
+
* @param m A method or a function
|
|
506
|
+
* @param id The id of the method or the function
|
|
507
|
+
*/
|
|
508
|
+
public createFamixInvocation(node: Identifier, m: MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | FunctionDeclaration | FunctionExpression, id: number): void {
|
|
509
|
+
this.famixFunctionsAssociations.createFamixInvocation(node, m, id);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Creates a Famix inheritance
|
|
514
|
+
* @param cls A class or an interface (subclass)
|
|
515
|
+
* @param inhClass The inherited class or interface (superclass)
|
|
516
|
+
*/
|
|
517
|
+
public createFamixInheritance(cls: ClassDeclaration | InterfaceDeclaration, inhClass: ClassDeclaration | InterfaceDeclaration | ExpressionWithTypeArguments): void {
|
|
518
|
+
this.famixFunctionsAssociations.createFamixInheritance(cls, inhClass);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Creates a Famix import clause
|
|
523
|
+
* @param importer A source file which is a module
|
|
524
|
+
* @param moduleSpecifier The name of the module where the export declaration is
|
|
525
|
+
* @param moduleSpecifierFilePath The path of the module where the export declaration is
|
|
526
|
+
* @param importElement The imported entity
|
|
527
|
+
* @param isInExports A boolean indicating if the imported entity is in the exports
|
|
528
|
+
* @param isDefaultExport A boolean indicating if the imported entity is a default export
|
|
529
|
+
*/
|
|
530
|
+
public createFamixImportClause(importer: SourceFile, moduleSpecifier: string, moduleSpecifierFilePath: string, importElement: ImportSpecifier | Identifier, isInExports: boolean, isDefaultExport: boolean): void {
|
|
531
|
+
this.famixFunctionsAssociations.createFamixImportClause(importer, moduleSpecifier, moduleSpecifierFilePath, importElement, isInExports, isDefaultExport);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Gets a Famix entity by fully qualified name
|
|
536
|
+
* @param fullyQualifiedName A fully qualified name
|
|
537
|
+
* @returns The Famix entity corresponding to the fully qualified name
|
|
538
|
+
*/
|
|
539
|
+
private getFamixEntityByFullyQualifiedName(fullyQualifiedName: string): Famix.Entity {
|
|
540
|
+
return this.famixRep.getFamixEntityByFullyQualifiedName(fullyQualifiedName) as Famix.Entity;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Gets the signature of a method or a function
|
|
545
|
+
* @param text A method or a function source code
|
|
546
|
+
* @returns The signature of the method or the function
|
|
547
|
+
*/
|
|
548
|
+
private computeSignature(text: string): string {
|
|
549
|
+
const endSignatureText = text.indexOf("{");
|
|
550
|
+
return text.substring(0, endSignatureText).trim();
|
|
551
|
+
}
|
|
552
|
+
}
|