1 | import * as Handlebars from 'handlebars';
|
2 | import * as JSON5 from 'json5';
|
3 | import * as _ from 'lodash';
|
4 | import * as path from 'path';
|
5 | import Ast, { ts, SourceFile, SyntaxKind, TypeGuards } from 'ts-simple-ast';
|
6 |
|
7 | import FileEngine from '../app/engines/file.engine';
|
8 | import { RoutingGraphNode } from '../app/nodes/routing-graph-node';
|
9 |
|
10 | import ImportsUtil from './imports.util';
|
11 | import { logger } from './logger';
|
12 |
|
13 | const traverse = require('traverse');
|
14 |
|
15 | const ast = new Ast();
|
16 |
|
17 | export class RouterParserUtil {
|
18 | private routes: any[] = [];
|
19 | private incompleteRoutes = [];
|
20 | private modules = [];
|
21 | private modulesTree;
|
22 | private rootModule: string;
|
23 | private cleanModulesTree;
|
24 | private modulesWithRoutes = [];
|
25 | private transformAngular8ImportSyntax = /(['"]loadChildren['"]:)\(\)=>"import\((\\'|'|")([^'"]+?)(\\'|'|")\)\.then\(\w+?=>\S+?\.([^)]+?)\)(\\'|'|")/g;
|
26 |
|
27 | private static instance: RouterParserUtil;
|
28 | private constructor() {}
|
29 | public static getInstance() {
|
30 | if (!RouterParserUtil.instance) {
|
31 | RouterParserUtil.instance = new RouterParserUtil();
|
32 | }
|
33 | return RouterParserUtil.instance;
|
34 | }
|
35 |
|
36 | public addRoute(route): void {
|
37 | this.routes.push(route);
|
38 | this.routes = _.sortBy(_.uniqWith(this.routes, _.isEqual), ['name']);
|
39 | }
|
40 |
|
41 | public addIncompleteRoute(route): void {
|
42 | this.incompleteRoutes.push(route);
|
43 | this.incompleteRoutes = _.sortBy(_.uniqWith(this.incompleteRoutes, _.isEqual), ['name']);
|
44 | }
|
45 |
|
46 | public addModuleWithRoutes(moduleName, moduleImports, filename): void {
|
47 | this.modulesWithRoutes.push({
|
48 | name: moduleName,
|
49 | importsNode: moduleImports,
|
50 | filename: filename
|
51 | });
|
52 | this.modulesWithRoutes = _.sortBy(_.uniqWith(this.modulesWithRoutes, _.isEqual), ['name']);
|
53 | }
|
54 |
|
55 | public addModule(moduleName: string, moduleImports): void {
|
56 | this.modules.push({
|
57 | name: moduleName,
|
58 | importsNode: moduleImports
|
59 | });
|
60 | this.modules = _.sortBy(_.uniqWith(this.modules, _.isEqual), ['name']);
|
61 | }
|
62 |
|
63 | public cleanRawRouteParsed(route: string): object {
|
64 | let routesWithoutSpaces = route.replace(/ /gm, '');
|
65 | let testTrailingComma = routesWithoutSpaces.indexOf('},]');
|
66 | if (testTrailingComma !== -1) {
|
67 | routesWithoutSpaces = routesWithoutSpaces.replace('},]', '}]');
|
68 | }
|
69 |
|
70 | routesWithoutSpaces = routesWithoutSpaces.replace(
|
71 | this.transformAngular8ImportSyntax,
|
72 | '$1"$3#$5"'
|
73 | );
|
74 |
|
75 | return JSON5.parse(routesWithoutSpaces);
|
76 | }
|
77 |
|
78 | public cleanRawRoute(route: string): string {
|
79 | let routesWithoutSpaces = route.replace(/ /gm, '');
|
80 | let testTrailingComma = routesWithoutSpaces.indexOf('},]');
|
81 | if (testTrailingComma !== -1) {
|
82 | routesWithoutSpaces = routesWithoutSpaces.replace('},]', '}]');
|
83 | }
|
84 |
|
85 | routesWithoutSpaces = routesWithoutSpaces.replace(
|
86 | this.transformAngular8ImportSyntax,
|
87 | '$1"$3#$5"'
|
88 | );
|
89 |
|
90 | return routesWithoutSpaces;
|
91 | }
|
92 |
|
93 | public setRootModule(module: string): void {
|
94 | this.rootModule = module;
|
95 | }
|
96 |
|
97 | public hasRouterModuleInImports(imports: Array<any>): boolean {
|
98 | for (let i = 0; i < imports.length; i++) {
|
99 | if (
|
100 | imports[i].name.indexOf('RouterModule.forChild') !== -1 ||
|
101 | imports[i].name.indexOf('RouterModule.forRoot') !== -1 ||
|
102 | imports[i].name.indexOf('RouterModule') !== -1
|
103 | ) {
|
104 | return true;
|
105 | }
|
106 | }
|
107 |
|
108 | return false;
|
109 | }
|
110 |
|
111 | public fixIncompleteRoutes(miscellaneousVariables: Array<any>): void {
|
112 | let matchingVariables = [];
|
113 |
|
114 |
|
115 | for (let i = 0; i < this.incompleteRoutes.length; i++) {
|
116 | for (let j = 0; j < miscellaneousVariables.length; j++) {
|
117 | if (this.incompleteRoutes[i].data.indexOf(miscellaneousVariables[j].name) !== -1) {
|
118 | console.log('found one misc var inside incompleteRoute');
|
119 | console.log(miscellaneousVariables[j].name);
|
120 | matchingVariables.push(miscellaneousVariables[j]);
|
121 | }
|
122 | }
|
123 |
|
124 | this.incompleteRoutes[i].data = this.incompleteRoutes[i].data.replace('[', '');
|
125 | this.incompleteRoutes[i].data = this.incompleteRoutes[i].data.replace(']', '');
|
126 | }
|
127 | }
|
128 |
|
129 | public linkModulesAndRoutes(): void {
|
130 | let i = 0;
|
131 | let len = this.modulesWithRoutes.length;
|
132 | for (i; i < len; i++) {
|
133 | _.forEach(this.modulesWithRoutes[i].importsNode, (node: ts.PropertyDeclaration) => {
|
134 | let initializer = node.initializer as ts.ArrayLiteralExpression;
|
135 | if (initializer) {
|
136 | if (initializer.elements) {
|
137 | _.forEach(initializer.elements, (element: ts.CallExpression) => {
|
138 |
|
139 | if (element.arguments) {
|
140 | _.forEach(element.arguments, (argument: ts.Identifier) => {
|
141 | _.forEach(this.routes, route => {
|
142 | if (
|
143 | argument.text &&
|
144 | route.name === argument.text &&
|
145 | route.filename === this.modulesWithRoutes[i].filename
|
146 | ) {
|
147 | route.module = this.modulesWithRoutes[i].name;
|
148 | } else if (
|
149 | argument.text &&
|
150 | route.name === argument.text &&
|
151 | route.filename !== this.modulesWithRoutes[i].filename
|
152 | ) {
|
153 | let argumentImportPath = ImportsUtil.findFilePathOfImportedVariable(
|
154 | argument.text,
|
155 | this.modulesWithRoutes[i].filename
|
156 | );
|
157 |
|
158 | argumentImportPath = argumentImportPath
|
159 | .replace(process.cwd() + path.sep, '')
|
160 | .replace(/\\/g, '/');
|
161 |
|
162 | if (
|
163 | argument.text &&
|
164 | route.name === argument.text &&
|
165 | route.filename === argumentImportPath
|
166 | ) {
|
167 | route.module = this.modulesWithRoutes[i].name;
|
168 | }
|
169 | }
|
170 | });
|
171 | });
|
172 | }
|
173 | });
|
174 | }
|
175 | }
|
176 | |
177 |
|
178 |
|
179 |
|
180 | if (ts.isCallExpression(node)) {
|
181 | if (node.arguments) {
|
182 | _.forEach(node.arguments, (argument: ts.Identifier) => {
|
183 | _.forEach(this.routes, route => {
|
184 | if (
|
185 | argument.text &&
|
186 | route.name === argument.text &&
|
187 | route.filename === this.modulesWithRoutes[i].filename
|
188 | ) {
|
189 | route.module = this.modulesWithRoutes[i].name;
|
190 | }
|
191 | });
|
192 | });
|
193 | }
|
194 | }
|
195 | });
|
196 | }
|
197 | }
|
198 |
|
199 | public foundRouteWithModuleName(moduleName: string): any {
|
200 | return _.find(this.routes, { module: moduleName });
|
201 | }
|
202 |
|
203 | public foundLazyModuleWithPath(modulePath: string): string {
|
204 |
|
205 | let split = modulePath.split('#');
|
206 | let lazyModulePath = split[0];
|
207 | let lazyModuleName = split[1];
|
208 | return lazyModuleName;
|
209 | }
|
210 |
|
211 | public constructRoutesTree() {
|
212 |
|
213 |
|
214 |
|
215 | traverse(this.modulesTree).forEach(function(node) {
|
216 | if (node) {
|
217 | if (node.parent) {
|
218 | delete node.parent;
|
219 | }
|
220 | if (node.initializer) {
|
221 | delete node.initializer;
|
222 | }
|
223 | if (node.importsNode) {
|
224 | delete node.importsNode;
|
225 | }
|
226 | }
|
227 | });
|
228 |
|
229 | this.cleanModulesTree = _.cloneDeep(this.modulesTree);
|
230 |
|
231 | let routesTree = {
|
232 | name: '<root>',
|
233 | kind: 'module',
|
234 | className: this.rootModule,
|
235 | children: []
|
236 | };
|
237 |
|
238 | let loopModulesParser = node => {
|
239 | if (node.children && node.children.length > 0) {
|
240 |
|
241 | for (let i in node.children) {
|
242 | let route = this.foundRouteWithModuleName(node.children[i].name);
|
243 | if (route && route.data) {
|
244 | try {
|
245 | route.children = JSON5.parse(route.data);
|
246 | } catch (e) {
|
247 | logger.error(
|
248 | 'Error during generation of routes JSON file, maybe a trailing comma or an external variable inside one route.'
|
249 | );
|
250 | }
|
251 | delete route.data;
|
252 | route.kind = 'module';
|
253 | routesTree.children.push(route);
|
254 | }
|
255 | if (node.children[i].children) {
|
256 | loopModulesParser(node.children[i]);
|
257 | }
|
258 | }
|
259 | } else {
|
260 |
|
261 | let rawRoutes = this.foundRouteWithModuleName(node.name);
|
262 |
|
263 | if (rawRoutes) {
|
264 | let routes = JSON5.parse(rawRoutes.data);
|
265 | if (routes) {
|
266 | let i = 0;
|
267 | let len = routes.length;
|
268 | let routeAddedOnce = false;
|
269 | for (i; i < len; i++) {
|
270 | let route = routes[i];
|
271 | if (routes[i].component) {
|
272 | routeAddedOnce = true;
|
273 | routesTree.children.push({
|
274 | kind: 'component',
|
275 | component: routes[i].component,
|
276 | path: routes[i].path
|
277 | });
|
278 | }
|
279 | }
|
280 | if (!routeAddedOnce) {
|
281 | routesTree.children = [...routesTree.children, ...routes];
|
282 | }
|
283 | }
|
284 | }
|
285 | }
|
286 | };
|
287 |
|
288 | let startModule = _.find(this.cleanModulesTree, { name: this.rootModule });
|
289 |
|
290 | if (startModule) {
|
291 | loopModulesParser(startModule);
|
292 |
|
293 |
|
294 | }
|
295 |
|
296 | let cleanedRoutesTree = undefined;
|
297 |
|
298 | let cleanRoutesTree = route => {
|
299 | for (let i in route.children) {
|
300 | let routes = route.children[i].routes;
|
301 | }
|
302 | return route;
|
303 | };
|
304 |
|
305 | cleanedRoutesTree = cleanRoutesTree(routesTree);
|
306 |
|
307 |
|
308 |
|
309 | let loopInsideModule = (mod, _rawModule) => {
|
310 | if (mod.children) {
|
311 | for (let z in mod.children) {
|
312 | let route = this.foundRouteWithModuleName(mod.children[z].name);
|
313 | if (typeof route !== 'undefined') {
|
314 | if (route.data) {
|
315 | route.children = JSON5.parse(route.data);
|
316 | delete route.data;
|
317 | route.kind = 'module';
|
318 | _rawModule.children.push(route);
|
319 | }
|
320 | }
|
321 | }
|
322 | } else {
|
323 | let route = this.foundRouteWithModuleName(mod.name);
|
324 | if (typeof route !== 'undefined') {
|
325 | if (route.data) {
|
326 | route.children = JSON5.parse(route.data);
|
327 | delete route.data;
|
328 | route.kind = 'module';
|
329 | _rawModule.children.push(route);
|
330 | }
|
331 | }
|
332 | }
|
333 | };
|
334 |
|
335 | let loopRoutesParser = route => {
|
336 | if (route.children) {
|
337 | for (let i in route.children) {
|
338 | if (route.children[i].loadChildren) {
|
339 | let child = this.foundLazyModuleWithPath(route.children[i].loadChildren);
|
340 | let module: RoutingGraphNode = _.find(this.cleanModulesTree, {
|
341 | name: child
|
342 | });
|
343 | if (module) {
|
344 | let _rawModule: RoutingGraphNode = {};
|
345 | _rawModule.kind = 'module';
|
346 | _rawModule.children = [];
|
347 | _rawModule.module = module.name;
|
348 | loopInsideModule(module, _rawModule);
|
349 |
|
350 | route.children[i].children = [];
|
351 | route.children[i].children.push(_rawModule);
|
352 | }
|
353 | }
|
354 | loopRoutesParser(route.children[i]);
|
355 | }
|
356 | }
|
357 | };
|
358 | loopRoutesParser(cleanedRoutesTree);
|
359 |
|
360 | return cleanedRoutesTree;
|
361 | }
|
362 |
|
363 | public constructModulesTree(): void {
|
364 | let getNestedChildren = (arr, parent?) => {
|
365 | let out = [];
|
366 | for (let i in arr) {
|
367 | if (arr[i].parent === parent) {
|
368 | let children = getNestedChildren(arr, arr[i].name);
|
369 | if (children.length) {
|
370 | arr[i].children = children;
|
371 | }
|
372 | out.push(arr[i]);
|
373 | }
|
374 | }
|
375 | return out;
|
376 | };
|
377 |
|
378 |
|
379 | _.forEach(this.modules, firstLoopModule => {
|
380 | _.forEach(firstLoopModule.importsNode, importNode => {
|
381 | _.forEach(this.modules, module => {
|
382 | if (module.name === importNode.name) {
|
383 | module.parent = firstLoopModule.name;
|
384 | }
|
385 | });
|
386 | });
|
387 | });
|
388 | this.modulesTree = getNestedChildren(this.modules);
|
389 | }
|
390 |
|
391 | public generateRoutesIndex(outputFolder: string, routes: Array<any>): Promise<void> {
|
392 | return FileEngine.get(__dirname + '/../src/templates/partials/routes-index.hbs').then(
|
393 | data => {
|
394 | let template: any = Handlebars.compile(data);
|
395 | let result = template({
|
396 | routes: JSON.stringify(routes)
|
397 | });
|
398 | let testOutputDir = outputFolder.match(process.cwd());
|
399 |
|
400 | if (testOutputDir && testOutputDir.length > 0) {
|
401 | outputFolder = outputFolder.replace(process.cwd() + path.sep, '');
|
402 | }
|
403 |
|
404 | return FileEngine.write(
|
405 | outputFolder + path.sep + '/js/routes/routes_index.js',
|
406 | result
|
407 | );
|
408 | },
|
409 | err => Promise.reject('Error during routes index generation')
|
410 | );
|
411 | }
|
412 |
|
413 | public routesLength(): number {
|
414 | let _n = 0;
|
415 | let routesParser = route => {
|
416 | if (typeof route.path !== 'undefined') {
|
417 | _n += 1;
|
418 | }
|
419 | if (route.children) {
|
420 | for (let j in route.children) {
|
421 | routesParser(route.children[j]);
|
422 | }
|
423 | }
|
424 | };
|
425 |
|
426 | for (let i in this.routes) {
|
427 | routesParser(this.routes[i]);
|
428 | }
|
429 |
|
430 | return _n;
|
431 | }
|
432 |
|
433 | public printRoutes(): void {
|
434 | console.log('');
|
435 | console.log('printRoutes: ');
|
436 | console.log(this.routes);
|
437 | }
|
438 |
|
439 | public printModulesRoutes(): void {
|
440 | console.log('');
|
441 | console.log('printModulesRoutes: ');
|
442 | console.log(this.modulesWithRoutes);
|
443 | }
|
444 |
|
445 | public isVariableRoutes(node) {
|
446 | let result = false;
|
447 | if (node.declarationList && node.declarationList.declarations) {
|
448 | let i = 0;
|
449 | let len = node.declarationList.declarations.length;
|
450 | for (i; i < len; i++) {
|
451 | if (node.declarationList.declarations[i].type) {
|
452 | if (
|
453 | node.declarationList.declarations[i].type.typeName &&
|
454 | node.declarationList.declarations[i].type.typeName.text === 'Routes'
|
455 | ) {
|
456 | result = true;
|
457 | }
|
458 | }
|
459 | }
|
460 | }
|
461 | return result;
|
462 | }
|
463 |
|
464 | public cleanFileIdentifiers(sourceFile: SourceFile): SourceFile {
|
465 | let file = sourceFile;
|
466 | const identifiers = file.getDescendantsOfKind(SyntaxKind.Identifier).filter(p => {
|
467 | return (
|
468 | TypeGuards.isArrayLiteralExpression(p.getParentOrThrow()) ||
|
469 | TypeGuards.isPropertyAssignment(p.getParentOrThrow())
|
470 | );
|
471 | });
|
472 |
|
473 | let identifiersInRoutesVariableStatement = [];
|
474 |
|
475 | for (const identifier of identifiers) {
|
476 |
|
477 | let foundParentVariableStatement = false;
|
478 | let parent = identifier.getParentWhile(n => {
|
479 | if (n.getKind() === SyntaxKind.VariableStatement) {
|
480 | if (this.isVariableRoutes(n.compilerNode)) {
|
481 | foundParentVariableStatement = true;
|
482 | }
|
483 | }
|
484 | return true;
|
485 | });
|
486 | if (foundParentVariableStatement) {
|
487 | identifiersInRoutesVariableStatement.push(identifier);
|
488 | }
|
489 | }
|
490 |
|
491 |
|
492 | for (const identifier of identifiersInRoutesVariableStatement) {
|
493 | const identifierDeclaration = identifier
|
494 | .getSymbolOrThrow()
|
495 | .getValueDeclarationOrThrow();
|
496 | if (
|
497 | !TypeGuards.isPropertyAssignment(identifierDeclaration) &&
|
498 | TypeGuards.isVariableDeclaration(identifierDeclaration) &&
|
499 | (TypeGuards.isPropertyAssignment(identifierDeclaration) &&
|
500 | !TypeGuards.isVariableDeclaration(identifierDeclaration))
|
501 | ) {
|
502 | throw new Error(
|
503 | `Not implemented referenced declaration kind: ${identifierDeclaration.getKindName()}`
|
504 | );
|
505 | }
|
506 | if (TypeGuards.isVariableDeclaration(identifierDeclaration)) {
|
507 | identifier.replaceWithText(identifierDeclaration.getInitializerOrThrow().getText());
|
508 | }
|
509 | }
|
510 |
|
511 | return file;
|
512 | }
|
513 |
|
514 | public cleanFileSpreads(sourceFile: SourceFile): SourceFile {
|
515 | let file = sourceFile;
|
516 | const spreadElements = file
|
517 | .getDescendantsOfKind(SyntaxKind.SpreadElement)
|
518 | .filter(p => TypeGuards.isArrayLiteralExpression(p.getParentOrThrow()));
|
519 |
|
520 | let spreadElementsInRoutesVariableStatement = [];
|
521 |
|
522 | for (const spreadElement of spreadElements) {
|
523 |
|
524 | let foundParentVariableStatement = false;
|
525 | let parent = spreadElement.getParentWhile(n => {
|
526 | if (n.getKind() === SyntaxKind.VariableStatement) {
|
527 | if (this.isVariableRoutes(n.compilerNode)) {
|
528 | foundParentVariableStatement = true;
|
529 | }
|
530 | }
|
531 | return true;
|
532 | });
|
533 | if (foundParentVariableStatement) {
|
534 | spreadElementsInRoutesVariableStatement.push(spreadElement);
|
535 | }
|
536 | }
|
537 |
|
538 |
|
539 | for (const spreadElement of spreadElementsInRoutesVariableStatement) {
|
540 | let spreadElementIdentifier = spreadElement.getExpression().getText(),
|
541 | searchedImport,
|
542 | aliasOriginalName = '',
|
543 | foundWithAliasInImports = false,
|
544 | foundWithAlias = false;
|
545 |
|
546 |
|
547 | const imports = file.getImportDeclarations();
|
548 |
|
549 | imports.forEach(i => {
|
550 | let namedImports = i.getNamedImports(),
|
551 | namedImportsLength = namedImports.length,
|
552 | j = 0;
|
553 |
|
554 | if (namedImportsLength > 0) {
|
555 | for (j; j < namedImportsLength; j++) {
|
556 | let importName = namedImports[j].getNameNode().getText() as string,
|
557 | importAlias;
|
558 |
|
559 | if (namedImports[j].getAliasIdentifier()) {
|
560 | importAlias = namedImports[j].getAliasIdentifier().getText();
|
561 | }
|
562 |
|
563 | if (importName === spreadElementIdentifier) {
|
564 | foundWithAliasInImports = true;
|
565 | searchedImport = i;
|
566 | break;
|
567 | }
|
568 | if (importAlias === spreadElementIdentifier) {
|
569 | foundWithAliasInImports = true;
|
570 | foundWithAlias = true;
|
571 | aliasOriginalName = importName;
|
572 | searchedImport = i;
|
573 | break;
|
574 | }
|
575 | }
|
576 | }
|
577 | });
|
578 |
|
579 | let referencedDeclaration;
|
580 |
|
581 | if (foundWithAliasInImports) {
|
582 | if (typeof searchedImport !== 'undefined') {
|
583 | let importPath = path.resolve(
|
584 | path.dirname(file.getFilePath()) +
|
585 | '/' +
|
586 | searchedImport.getModuleSpecifierValue() +
|
587 | '.ts'
|
588 | );
|
589 | const sourceFileImport =
|
590 | typeof ast.getSourceFile(importPath) !== 'undefined'
|
591 | ? ast.getSourceFile(importPath)
|
592 | : ast.addExistingSourceFile(importPath);
|
593 | if (sourceFileImport) {
|
594 | let variableName = foundWithAlias
|
595 | ? aliasOriginalName
|
596 | : spreadElementIdentifier;
|
597 | referencedDeclaration = sourceFileImport.getVariableDeclaration(
|
598 | variableName
|
599 | );
|
600 | }
|
601 | }
|
602 | } else {
|
603 |
|
604 | referencedDeclaration = spreadElement
|
605 | .getExpression()
|
606 | .getSymbolOrThrow()
|
607 | .getValueDeclarationOrThrow();
|
608 | }
|
609 |
|
610 | if (!TypeGuards.isVariableDeclaration(referencedDeclaration)) {
|
611 | throw new Error(
|
612 | `Not implemented referenced declaration kind: ${referencedDeclaration.getKindName()}`
|
613 | );
|
614 | }
|
615 |
|
616 | const referencedArray = referencedDeclaration.getInitializerIfKindOrThrow(
|
617 | SyntaxKind.ArrayLiteralExpression
|
618 | );
|
619 | const spreadElementArray = spreadElement.getParentIfKindOrThrow(
|
620 | SyntaxKind.ArrayLiteralExpression
|
621 | );
|
622 | const insertIndex = spreadElementArray.getElements().indexOf(spreadElement);
|
623 | spreadElementArray.removeElement(spreadElement);
|
624 | spreadElementArray.insertElements(
|
625 | insertIndex,
|
626 | referencedArray.getElements().map(e => e.getText())
|
627 | );
|
628 | }
|
629 |
|
630 | return file;
|
631 | }
|
632 |
|
633 | public cleanFileDynamics(sourceFile: SourceFile): SourceFile {
|
634 | let file = sourceFile;
|
635 | const propertyAccessExpressions = file
|
636 | .getDescendantsOfKind(SyntaxKind.PropertyAccessExpression)
|
637 | .filter(p => !TypeGuards.isPropertyAccessExpression(p.getParentOrThrow()));
|
638 |
|
639 | let propertyAccessExpressionsInRoutesVariableStatement = [];
|
640 |
|
641 | for (const propertyAccessExpression of propertyAccessExpressions) {
|
642 |
|
643 | let foundParentVariableStatement = false;
|
644 | let parent = propertyAccessExpression.getParentWhile(n => {
|
645 | if (n.getKind() === SyntaxKind.VariableStatement) {
|
646 | if (this.isVariableRoutes(n.compilerNode)) {
|
647 | foundParentVariableStatement = true;
|
648 | }
|
649 | }
|
650 | return true;
|
651 | });
|
652 | if (foundParentVariableStatement) {
|
653 | propertyAccessExpressionsInRoutesVariableStatement.push(propertyAccessExpression);
|
654 | }
|
655 | }
|
656 |
|
657 |
|
658 | for (const propertyAccessExpression of propertyAccessExpressionsInRoutesVariableStatement) {
|
659 | const referencedDeclaration = propertyAccessExpression
|
660 | .getNameNode()
|
661 | .getSymbolOrThrow()
|
662 | .getValueDeclarationOrThrow();
|
663 | if (
|
664 | !TypeGuards.isPropertyAssignment(referencedDeclaration) &&
|
665 | TypeGuards.isEnumMember(referencedDeclaration) &&
|
666 | (TypeGuards.isPropertyAssignment(referencedDeclaration) &&
|
667 | !TypeGuards.isEnumMember(referencedDeclaration))
|
668 | ) {
|
669 | throw new Error(
|
670 | `Not implemented referenced declaration kind: ${referencedDeclaration.getKindName()}`
|
671 | );
|
672 | }
|
673 | if (typeof referencedDeclaration.getInitializerOrThrow !== 'undefined') {
|
674 | propertyAccessExpression.replaceWithText(
|
675 | referencedDeclaration.getInitializerOrThrow().getText()
|
676 | );
|
677 | }
|
678 | }
|
679 |
|
680 | return file;
|
681 | }
|
682 |
|
683 | |
684 |
|
685 |
|
686 |
|
687 | public cleanCallExpressions(sourceFile: SourceFile): SourceFile {
|
688 | let file = sourceFile;
|
689 |
|
690 | const variableStatements = sourceFile.getVariableDeclaration(v => {
|
691 | let result = false;
|
692 | if (typeof v.compilerNode.type !== 'undefined') {
|
693 | result = v.compilerNode.type.typeName.text === 'Routes';
|
694 | }
|
695 | return result;
|
696 | });
|
697 |
|
698 | const initializer = variableStatements.getInitializer();
|
699 |
|
700 | for (const callExpr of initializer.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
701 | if (callExpr.wasForgotten()) {
|
702 | continue;
|
703 | }
|
704 | callExpr.replaceWithText(writer => writer.quote(callExpr.getText()));
|
705 | }
|
706 |
|
707 | return file;
|
708 | }
|
709 |
|
710 | |
711 |
|
712 |
|
713 |
|
714 |
|
715 |
|
716 |
|
717 |
|
718 |
|
719 |
|
720 |
|
721 |
|
722 |
|
723 |
|
724 |
|
725 |
|
726 |
|
727 |
|
728 |
|
729 |
|
730 |
|
731 |
|
732 |
|
733 |
|
734 |
|
735 |
|
736 |
|
737 | public cleanRoutesDefinitionWithImport(
|
738 | initializer: ts.ArrayLiteralExpression,
|
739 | node: ts.Node,
|
740 | sourceFile: ts.SourceFile
|
741 | ): ts.Node {
|
742 | initializer.elements.forEach((element: ts.ObjectLiteralExpression) => {
|
743 | element.properties.forEach((property: ts.PropertyAssignment) => {
|
744 | let propertyName = property.name.getText(),
|
745 | propertyInitializer = property.initializer;
|
746 | switch (propertyName) {
|
747 | case 'path':
|
748 | case 'redirectTo':
|
749 | case 'outlet':
|
750 | case 'pathMatch':
|
751 | if (propertyInitializer) {
|
752 | if (propertyInitializer.kind !== SyntaxKind.StringLiteral) {
|
753 |
|
754 |
|
755 | if (
|
756 | propertyInitializer.kind === SyntaxKind.PropertyAccessExpression
|
757 | ) {
|
758 | let lastObjectLiteralAttributeName = propertyInitializer.name.getText(),
|
759 | firstObjectLiteralAttributeName;
|
760 | if (propertyInitializer.expression) {
|
761 | firstObjectLiteralAttributeName = propertyInitializer.expression.getText();
|
762 | let result = ImportsUtil.findPropertyValueInImportOrLocalVariables(
|
763 | firstObjectLiteralAttributeName +
|
764 | '.' +
|
765 | lastObjectLiteralAttributeName,
|
766 | sourceFile
|
767 | );
|
768 | if (result !== '') {
|
769 | propertyInitializer.kind = 9;
|
770 | propertyInitializer.text = result;
|
771 | }
|
772 | }
|
773 | }
|
774 | }
|
775 | }
|
776 | break;
|
777 | }
|
778 | });
|
779 | });
|
780 | return initializer;
|
781 | }
|
782 | }
|
783 |
|
784 | export default RouterParserUtil.getInstance();
|