@@ -854,7 +854,44 @@ const visitor = (node: ts.Node): ts.Node => {
854854
855855#### Find a specific parent
856856
857- > ** TODO** - Is this possible?
857+ While there doesn't exist an out of the box method you can basically roll your own.
858+ Given a node:
859+
860+ ``` ts
861+ const findParent = (node : ts .Node , predicate : (node : ts .Node ) => boolean ) => {
862+ if (! node .parent ) {
863+ return undefined ;
864+ }
865+
866+ if (predicate (node .parent )) {
867+ return node .parent ;
868+ }
869+
870+ return findParent (node .parent , predicate );
871+ };
872+
873+ const visitor = (node : ts .Node ): ts .Node => {
874+ if (ts .isStringLiteral (node )) {
875+ const parent = findParent (node , ts .isFunctionDeclaration );
876+ if (parent ) {
877+ console .log (' string literal has a function declaration parent' );
878+ }
879+ return node ;
880+ }
881+ };
882+ ```
883+
884+ Will log to console ` string literal has a function declaration parent ` with the following source:
885+
886+ ``` ts
887+ function hello() {
888+ if (true ) {
889+ ' world' ;
890+ }
891+ }
892+ ```
893+
894+ > ** Tip** - You can see the source for this at [ /example-transformers/find-parent] ( /example-transformers/find-parent )
858895
859896#### Stopping traversal
860897
@@ -1107,21 +1144,40 @@ This also may or may not break when type checking is turned off.
11071144> ** TODO** - Is this possible in a robust way?
11081145
11091146``` ts
1110- if (
1111- ts .isImportDeclaration (node ) &&
1112- ts .isStringLiteral (node .moduleSpecifier ) &&
1113- ts .isNamedImports (node .importClause .namedBindings )
1114- ) {
1115- const moduleImportName = node .moduleSpecifier .text ;
1116- const { resolvedFileName } = sourceFile .resolvedModules .get (moduleImportName );
1117- const moduleSourceFile = program .getSourceFile (resolvedFileName );
1118-
1119- moduleSourceFile .symbol .exports .forEach ((_ , key ) => {
1120- console .log (` found export ${key } ` );
1121- });
1147+ // We need to use a Program transformer to get ahold of the program object.
1148+ const transformerProgram = (program : ts .Program ) => {
1149+ const transformerFactory: ts .TransformerFactory <ts .SourceFile > = context => {
1150+ return sourceFile => {
1151+ const visitor = (node : ts .Node ): ts .Node => {
1152+ if (
1153+ ts .isImportDeclaration (node ) &&
1154+ ts .isStringLiteral (node .moduleSpecifier ) &&
1155+ ts .isNamedImports (node .importClause .namedBindings )
1156+ ) {
1157+ // Grab the module name
1158+ const moduleImportName = node .moduleSpecifier .text ;
1159+ // Grab the modules file name
1160+ const { resolvedFileName } = (sourceFile as any ).resolvedModules .get (moduleImportName );
1161+ // Grab the modules source file
1162+ const moduleSourceFile = program .getSourceFile (resolvedFileName );
1163+
1164+ // Access the exports on the source file symbol
1165+ (moduleSourceFile as any ).symbol .exports .forEach ((_ , key ) => {
1166+ console .log (` found export ${key } ` );
1167+ });
1168+
1169+ return node ;
1170+ }
11221171
1123- return node ;
1124- }
1172+ return ts .visitEachChild (node , visitor , context );
1173+ };
1174+
1175+ return ts .visitNode (sourceFile , visitor );
1176+ };
1177+ };
1178+
1179+ return transformerFactory ;
1180+ };
11251181```
11261182
11271183Which will log this to the console:
@@ -1177,7 +1233,8 @@ so you'll have to cast it to `any` to gain access to it.
11771233
11781234## Throwing a syntax error to ease the developer experience
11791235
1180- > ** TODO** - Is this possible like it is in Babel? Or we use a [ language service plugin] ( https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin ) ?
1236+ > ** TODO** - Is this possible like it is in Babel?
1237+ > Or we use a [ language service plugin] ( https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin ) ?
11811238
11821239## Testing
11831240
0 commit comments