UNPKG

18.4 kBPlain TextView Raw
1import * as path from 'path';
2
3import Ast, { ts, PropertyDeclaration, SyntaxKind } from 'ts-simple-ast';
4
5const ast = new Ast();
6
7export class ImportsUtil {
8 private static instance: ImportsUtil;
9 private constructor() {}
10 public static getInstance() {
11 if (!ImportsUtil.instance) {
12 ImportsUtil.instance = new ImportsUtil();
13 }
14 return ImportsUtil.instance;
15 }
16 /**
17 * Find for a sourceFile a variable value in a local enum
18 * @param srcFile
19 * @param variableName
20 * @param variableValue
21 */
22 private findInEnums(srcFile, variableName: string, variableValue: string) {
23 let res = '';
24 srcFile.getEnum(e => {
25 if (e.getName() === variableName) {
26 e.getMember(m => {
27 if (m.getName() === variableValue) {
28 res = m.getValue();
29 }
30 });
31 }
32 });
33 return res;
34 }
35
36 /**
37 * Find for a sourceFile a variable value in a local static class
38 * @param srcFile
39 * @param variableName
40 * @param variableValue
41 */
42 private findInClasses(srcFile, variableName: string, variableValue: string) {
43 let res = '';
44 srcFile.getClass(c => {
45 let staticProperty: PropertyDeclaration = c.getStaticProperty(variableValue);
46 if (staticProperty) {
47 if (staticProperty.getInitializer()) {
48 res = staticProperty.getInitializer().getText();
49 }
50 }
51 });
52 return res;
53 }
54
55 /**
56 * Find a value in a local variable declaration like an object
57 * @param variableDeclaration
58 * @param variablesAttributes
59 */
60 private findInObjectVariableDeclaration(variableDeclaration, variablesAttributes) {
61 let variableKind = variableDeclaration.getKind();
62 if (variableKind && variableKind === SyntaxKind.VariableDeclaration) {
63 let initializer = variableDeclaration.getInitializer();
64 if (initializer) {
65 let initializerKind = initializer.getKind();
66 if (initializerKind && initializerKind === SyntaxKind.ObjectLiteralExpression) {
67 let compilerNode = initializer.compilerNode as ts.ObjectLiteralExpression,
68 finalValue = '';
69 // Find thestring from AVAR.BVAR.thestring inside properties
70 let depth = 0;
71 let loopProperties = properties => {
72 properties.forEach(prop => {
73 if (prop.name) {
74 if (variablesAttributes[depth + 1]) {
75 if (prop.name.getText() === variablesAttributes[depth + 1]) {
76 if (prop.initializer) {
77 if (prop.initializer.properties) {
78 depth += 1;
79 loopProperties(prop.initializer.properties);
80 } else {
81 finalValue = prop.initializer.text;
82 }
83 } else {
84 finalValue = prop.initializer.text;
85 }
86 }
87 }
88 }
89 });
90 };
91 loopProperties(compilerNode.properties);
92 return finalValue;
93 }
94 }
95 }
96 }
97
98 /**
99 * Find in imports something like myvar
100 * @param {string} inputVariableName like myvar
101 * @return {[type]} myvar value
102 */
103 public findValueInImportOrLocalVariables(inputVariableName: string, sourceFile: ts.SourceFile) {
104 let metadataVariableName = inputVariableName,
105 searchedImport,
106 aliasOriginalName = '',
107 foundWithAlias = false;
108
109 const file =
110 typeof ast.getSourceFile(sourceFile.fileName) !== 'undefined'
111 ? ast.getSourceFile(sourceFile.fileName)
112 : ast.addExistingSourceFileIfExists(sourceFile.fileName); // tslint:disable-line
113 const imports = file.getImportDeclarations();
114
115 /**
116 * Loop through all imports, and find one matching inputVariableName
117 */
118 imports.forEach(i => {
119 let namedImports = i.getNamedImports(),
120 namedImportsLength = namedImports.length,
121 j = 0;
122
123 if (namedImportsLength > 0) {
124 for (j; j < namedImportsLength; j++) {
125 let importName = namedImports[j].getNameNode().getText() as string,
126 importAlias;
127
128 if (namedImports[j].getAliasIdentifier()) {
129 importAlias = namedImports[j].getAliasIdentifier().getText();
130 }
131 if (importName === metadataVariableName) {
132 searchedImport = i;
133 break;
134 }
135 if (importAlias === metadataVariableName) {
136 foundWithAlias = true;
137 aliasOriginalName = importName;
138 searchedImport = i;
139 break;
140 }
141 }
142 }
143 });
144
145 function hasFoundValues(variableDeclaration) {
146 let variableKind = variableDeclaration.getKind();
147
148 if (variableKind && variableKind === SyntaxKind.VariableDeclaration) {
149 let initializer = variableDeclaration.getInitializer();
150 if (initializer) {
151 let initializerKind = initializer.getKind();
152 if (initializerKind && initializerKind === SyntaxKind.ObjectLiteralExpression) {
153 let compilerNode = initializer.compilerNode as ts.ObjectLiteralExpression;
154 return compilerNode.properties;
155 }
156 }
157 }
158 }
159
160 if (typeof searchedImport !== 'undefined') {
161 let importPathReference = searchedImport.getModuleSpecifierSourceFile();
162 let importPath;
163 if (typeof importPathReference !== 'undefined') {
164 importPath = importPathReference.compilerNode.fileName;
165
166 const sourceFileImport =
167 typeof ast.getSourceFile(importPath) !== 'undefined'
168 ? ast.getSourceFile(importPath)
169 : ast.addExistingSourceFileIfExists(importPath); // tslint:disable-line
170
171 if (sourceFileImport) {
172 let variableName = foundWithAlias ? aliasOriginalName : metadataVariableName;
173 let variableDeclaration = sourceFileImport.getVariableDeclaration(variableName);
174
175 if (variableDeclaration) {
176 return hasFoundValues(variableDeclaration);
177 } else {
178 // Try with exports
179 const exportDeclarations = sourceFileImport.getExportDeclarations();
180 if (exportDeclarations && exportDeclarations.length > 0) {
181 let i = 0,
182 len = exportDeclarations.length;
183 for (i; i < len; i++) {
184 let exportDeclaration = exportDeclarations[i];
185 let sourceFileExportedReference = exportDeclaration.getModuleSpecifierSourceFile();
186 if (sourceFileExportedReference) {
187 let sourceFileExportedReferencePath = sourceFileExportedReference.getFilePath();
188
189 const sourceFileExported =
190 typeof ast.getSourceFile(
191 sourceFileExportedReferencePath
192 ) !== 'undefined'
193 ? ast.getSourceFile(sourceFileExportedReferencePath)
194 : ast.addExistingSourceFileIfExists(
195 sourceFileExportedReferencePath
196 );
197
198 if (sourceFileExported) {
199 variableDeclaration = sourceFileExported.getVariableDeclaration(
200 variableName
201 );
202 if (variableDeclaration) {
203 return hasFoundValues(variableDeclaration);
204 }
205 }
206 }
207 }
208 }
209 }
210 }
211 }
212 } else {
213 // Find in local variables of the file
214 const variableDeclaration = file.getVariableDeclaration(metadataVariableName);
215 if (variableDeclaration) {
216 let variableKind = variableDeclaration.getKind();
217
218 if (variableKind && variableKind === SyntaxKind.VariableDeclaration) {
219 let initializer = variableDeclaration.getInitializer();
220 if (initializer) {
221 let initializerKind = initializer.getKind();
222 if (
223 initializerKind &&
224 initializerKind === SyntaxKind.ObjectLiteralExpression
225 ) {
226 let compilerNode = initializer.compilerNode as ts.ObjectLiteralExpression;
227 return compilerNode.properties;
228 } else if (initializerKind) {
229 return variableDeclaration.compilerNode;
230 }
231 }
232 }
233 }
234 }
235
236 return [];
237 }
238
239 public getFileNameOfImport(variableName: string, sourceFile: ts.SourceFile) {
240 const file =
241 typeof ast.getSourceFile(sourceFile.fileName) !== 'undefined'
242 ? ast.getSourceFile(sourceFile.fileName)
243 : ast.addExistingSourceFile(sourceFile.fileName); // tslint:disable-line
244 const imports = file.getImportDeclarations();
245 let searchedImport,
246 aliasOriginalName = '',
247 finalPath = '',
248 foundWithAlias = false;
249 imports.forEach(i => {
250 let namedImports = i.getNamedImports(),
251 namedImportsLength = namedImports.length,
252 j = 0;
253
254 if (namedImportsLength > 0) {
255 for (j; j < namedImportsLength; j++) {
256 let importName = namedImports[j].getNameNode().getText() as string,
257 importAlias;
258
259 if (namedImports[j].getAliasIdentifier()) {
260 importAlias = namedImports[j].getAliasIdentifier().getText();
261 }
262 if (importName === variableName) {
263 searchedImport = i;
264 break;
265 }
266 if (importAlias === variableName) {
267 foundWithAlias = true;
268 aliasOriginalName = importName;
269 searchedImport = i;
270 break;
271 }
272 }
273 }
274 });
275 if (typeof searchedImport !== 'undefined') {
276 let importPath = path.resolve(
277 path.dirname(sourceFile.fileName) +
278 '/' +
279 searchedImport.getModuleSpecifierValue() +
280 '.ts'
281 );
282 let cleaner = (process.cwd() + path.sep).replace(/\\/g, '/');
283 finalPath = importPath.replace(cleaner, '');
284 }
285 return finalPath;
286 }
287
288 /**
289 * Find the file path of imported variable
290 * @param {string} inputVariableName like thestring
291 * @return {[type]} thestring destination path
292 */
293 public findFilePathOfImportedVariable(inputVariableName, sourceFilePath: string) {
294 let searchedImport,
295 finalPath = '',
296 aliasOriginalName = '',
297 foundWithAlias = false;
298 const file =
299 typeof ast.getSourceFile(sourceFilePath) !== 'undefined'
300 ? ast.getSourceFile(sourceFilePath)
301 : ast.addExistingSourceFile(sourceFilePath); // tslint:disable-line
302 const imports = file.getImportDeclarations();
303
304 /**
305 * Loop through all imports, and find one matching inputVariableName
306 */
307 imports.forEach(i => {
308 let namedImports = i.getNamedImports(),
309 namedImportsLength = namedImports.length,
310 j = 0;
311
312 if (namedImportsLength > 0) {
313 for (j; j < namedImportsLength; j++) {
314 let importName = namedImports[j].getNameNode().getText() as string,
315 importAlias;
316
317 if (namedImports[j].getAliasIdentifier()) {
318 importAlias = namedImports[j].getAliasIdentifier().getText();
319 }
320 if (importName === inputVariableName) {
321 searchedImport = i;
322 break;
323 }
324 if (importAlias === inputVariableName) {
325 foundWithAlias = true;
326 aliasOriginalName = importName;
327 searchedImport = i;
328 break;
329 }
330 }
331 }
332 });
333 if (typeof searchedImport !== 'undefined') {
334 finalPath = path.resolve(
335 path.dirname(sourceFilePath) +
336 '/' +
337 searchedImport.getModuleSpecifierValue() +
338 '.ts'
339 );
340 }
341 return finalPath;
342 }
343
344 /**
345 * Find in imports something like VAR.AVAR.BVAR.thestring
346 * @param {string} inputVariableName like VAR.AVAR.BVAR.thestring
347 * @return {[type]} thestring value
348 */
349 public findPropertyValueInImportOrLocalVariables(inputVariableName, sourceFile: ts.SourceFile) {
350 let variablesAttributes = inputVariableName.split('.'),
351 metadataVariableName = variablesAttributes[0],
352 searchedImport,
353 aliasOriginalName = '',
354 foundWithAlias = false;
355
356 const file =
357 typeof ast.getSourceFile(sourceFile.fileName) !== 'undefined'
358 ? ast.getSourceFile(sourceFile.fileName)
359 : ast.addExistingSourceFile(sourceFile.fileName); // tslint:disable-line
360 const imports = file.getImportDeclarations();
361
362 /**
363 * Loop through all imports, and find one matching inputVariableName
364 */
365 imports.forEach(i => {
366 let namedImports = i.getNamedImports(),
367 namedImportsLength = namedImports.length,
368 j = 0;
369
370 if (namedImportsLength > 0) {
371 for (j; j < namedImportsLength; j++) {
372 let importName = namedImports[j].getNameNode().getText() as string,
373 importAlias;
374
375 if (namedImports[j].getAliasIdentifier()) {
376 importAlias = namedImports[j].getAliasIdentifier().getText();
377 }
378 if (importName === metadataVariableName) {
379 searchedImport = i;
380 break;
381 }
382 if (importAlias === metadataVariableName) {
383 foundWithAlias = true;
384 aliasOriginalName = importName;
385 searchedImport = i;
386 break;
387 }
388 }
389 }
390 });
391
392 let fileToSearchIn, variableDeclaration;
393 if (typeof searchedImport !== 'undefined') {
394 let importPath = path.resolve(
395 path.dirname(sourceFile.fileName) +
396 '/' +
397 searchedImport.getModuleSpecifierValue() +
398 '.ts'
399 );
400 const sourceFileImport =
401 typeof ast.getSourceFile(importPath) !== 'undefined'
402 ? ast.getSourceFile(importPath)
403 : ast.addExistingSourceFile(importPath); // tslint:disable-line
404 if (sourceFileImport) {
405 fileToSearchIn = sourceFileImport;
406 let variableName = foundWithAlias ? aliasOriginalName : metadataVariableName;
407 variableDeclaration = fileToSearchIn.getVariableDeclaration(variableName);
408 }
409 } else {
410 fileToSearchIn = file;
411 // Find in local variables of the file
412 variableDeclaration = fileToSearchIn.getVariableDeclaration(metadataVariableName);
413 }
414
415 if (variableDeclaration) {
416 return this.findInObjectVariableDeclaration(variableDeclaration, variablesAttributes);
417 }
418 // Try find it in enums
419 if (variablesAttributes.length > 0) {
420 if (typeof fileToSearchIn !== 'undefined') {
421 let val = this.findInEnums(
422 fileToSearchIn,
423 metadataVariableName,
424 variablesAttributes[1]
425 );
426 if (val !== '') {
427 return val;
428 }
429 val = this.findInClasses(
430 fileToSearchIn,
431 metadataVariableName,
432 variablesAttributes[1]
433 );
434 if (val !== '') {
435 return val;
436 }
437 }
438 }
439 }
440}
441
442export default ImportsUtil.getInstance();