1
1
import * as ts from 'typescript' ;
2
+ import * as fs from 'fs' ;
2
3
import { InsertChange } from './change' ;
3
4
5
+ /**
6
+ * Get TS source file based on path.
7
+ * @param filePath
8
+ * @return source file of ts.SourceFile kind
9
+ */
10
+ export function getSource ( filePath : string ) : ts . SourceFile {
11
+ return ts . createSourceFile ( filePath , fs . readFileSync ( filePath ) . toString ( ) ,
12
+ ts . ScriptTarget . ES6 , true ) ;
13
+ }
14
+
4
15
/**
5
16
* Find all nodes from the AST in the subtree of node of SyntaxKind kind.
6
17
* @param node
7
18
* @param kind
8
- * @return all nodes of kind kind , or [] if none is found
19
+ * @return all nodes of kind, or [] if none is found
9
20
*/
10
21
export function findNodes ( node : ts . Node , kind : ts . SyntaxKind ) : ts . Node [ ] {
11
22
if ( ! node ) {
@@ -19,6 +30,26 @@ export function findNodes(node: ts.Node, kind: ts.SyntaxKind): ts.Node[] {
19
30
foundNodes . concat ( findNodes ( child , kind ) ) , arr ) ;
20
31
}
21
32
33
+ /**
34
+ * Find all nodes from the AST in the subtree based on text.
35
+ * @param node
36
+ * @param text
37
+ * @return all nodes of text, or [] if none is found
38
+ */
39
+ export function findNodesByText ( node : ts . Node , text : string ) : ts . Node [ ] {
40
+ if ( ! node ) {
41
+ return [ ] ;
42
+ }
43
+ let arr : ts . Node [ ] = [ ] ;
44
+ if ( node . getText ( ) === text ) {
45
+ arr . push ( node ) ;
46
+ }
47
+
48
+ return node . getChildren ( ) . reduce ( ( foundNodes , child ) => {
49
+ return foundNodes . concat ( findNodesByText ( child , text ) ) ;
50
+ } , arr ) ;
51
+ }
52
+
22
53
/**
23
54
* Helper for sorting nodes.
24
55
* @return function to sort nodes in increasing order of position in sourceFile
@@ -52,3 +83,40 @@ export function insertAfterLastOccurrence(nodes: ts.Node[], toInsert: string,
52
83
let lastItemPosition : number = lastItem ? lastItem . end : fallbackPos ;
53
84
return new InsertChange ( file , lastItemPosition , toInsert ) ;
54
85
}
86
+
87
+ /**
88
+ * Custom function to insert component (component, pipe, directive)
89
+ * into NgModule declarations. It also imports the component.
90
+ * @param modulePath
91
+ * @param classifiedName
92
+ * @param importPath
93
+ * @return Promise
94
+ */
95
+ export function importComponent ( modulePath : string , classifiedName : string ,
96
+ importPath : string ) : Promise < void > {
97
+ let source : ts . SourceFile = this . getSource ( modulePath ) ;
98
+
99
+ let importNode : ts . Node =
100
+ this . findNodesByText ( source , 'import' ) . pop ( ) ;
101
+ let iPos : ts . LineAndCharacter =
102
+ source . getLineAndCharacterOfPosition ( importNode . getEnd ( ) ) ;
103
+ let iLine : number = iPos . line + 1 ;
104
+ let iStart : number = source . getPositionOfLineAndCharacter ( iLine , 0 ) ;
105
+ let iStr : string = `import { ${ classifiedName } } from ${ importPath } \n` ;
106
+ let changeImport : InsertChange = new InsertChange ( modulePath , iStart , iStr ) ;
107
+
108
+ return changeImport . apply ( ) . then ( ( ) => {
109
+ source = this . getSource ( modulePath ) ;
110
+ let declarationsNode : ts . Node =
111
+ this . findNodesByText ( source , 'declarations' ) . shift ( ) ;
112
+ let dPos : ts . LineAndCharacter =
113
+ source . getLineAndCharacterOfPosition ( declarationsNode . getEnd ( ) ) ;
114
+ let dStart : number =
115
+ source . getPositionOfLineAndCharacter ( dPos . line + 1 , - 1 ) ;
116
+ let dStr : string = `\n ${ classifiedName } ,` ;
117
+ let changeDeclarations : InsertChange = new InsertChange ( modulePath , dStart , dStr ) ;
118
+
119
+ return changeDeclarations . apply ( ) ;
120
+ } ) ;
121
+ }
122
+
0 commit comments