-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathroute-utils.ts
86 lines (75 loc) · 2.96 KB
/
route-utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import * as ts from 'typescript';
import { Change, NoopChange } from '@schematics/angular/utility/change';
import { findNodes } from '@schematics/angular/utility/ast-utils';
import { insertBeforeFirstOccurence } from './ts-utils';
/**
* Add Import `import { symbolName } from fileName` if the import doesn't exit
* already. Assumes fileToEdit can be resolved and accessed.
* @param fileToEdit (file we want to add import to)
* @param symbolName (item to import)
* @param fileName (path to the file)
* @param quote (specifies the type of quotes that should be used)
* @param isDefault (if true, import follows style for importing default exports)
* @return Change
*/
export function insertImport(
source: ts.SourceFile,
fileToEdit: string,
symbolName: string,
fileName: string,
quote: '\"'|'\''|'\`' = '\"',
isDefault = false,
): Change {
const rootNode = source;
const allImports = findNodes(<any>rootNode, ts.SyntaxKind.ImportDeclaration);
// get nodes that map to import statements from the file fileName
const relevantImports = allImports.filter((node) => {
// StringLiteral of the ImportDeclaration is the import file (fileName in this case).
const importFiles = node.getChildren()
.filter((child) => child.kind === ts.SyntaxKind.StringLiteral)
.map((n) => (n as any).text);
return importFiles.filter((file) => file === fileName).length === 1;
});
if (relevantImports.length > 0) {
let importsAsterisk = false;
// imports from import file
const imports: Array<ts.Node> = [];
relevantImports.forEach((n) => {
Array.prototype.push.apply(imports, findNodes(n, ts.SyntaxKind.Identifier));
if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) {
importsAsterisk = true;
}
});
// if imports * from fileName, don't add symbolName
if (importsAsterisk) {
return new NoopChange();
}
const importTextNodes = imports.filter((n) => (n as ts.Identifier).text === symbolName);
// insert import if it's not there
if (importTextNodes.length === 0) {
const fallbackPosition =
findNodes(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].getStart() ||
findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
return insertBeforeFirstOccurence(imports, `, ${symbolName}`, fileToEdit, fallbackPosition);
}
return new NoopChange();
}
// no such import declaration exists
const useStrict = findNodes(<any>rootNode, ts.SyntaxKind.StringLiteral)
.filter((n: any) => n.text === 'use strict');
let fallbackPos = 0;
if (useStrict.length > 0) {
fallbackPos = useStrict[0].end;
}
const open = isDefault ? '' : '{ ';
const close = isDefault ? '' : ' }';
const toInsert = `import ${open}${symbolName}${close}` +
` from ${quote}${fileName}${quote};\n`;
return insertBeforeFirstOccurence(
<any>allImports,
toInsert,
fileToEdit,
fallbackPos,
// ts.SyntaxKind.StringLiteral,
);
}