@@ -52,7 +52,7 @@ export function transformOutput(
5252 }
5353 opts . outDir = pathLib . join ( outRoot , '/' , locale ) ;
5454 program . emit ( undefined , undefined , undefined , undefined , {
55- before : [ litLocalizeTransform ( translations ) ] ,
55+ before : [ litLocalizeTransform ( translations , program ) ] ,
5656 } ) ;
5757 }
5858}
@@ -61,10 +61,11 @@ export function transformOutput(
6161 * Return a TypeScript TransformerFactory for the lit-localize transformer.
6262 */
6363export function litLocalizeTransform (
64- translations : Map < string , Message > | undefined
64+ translations : Map < string , Message > | undefined ,
65+ program : ts . Program
6566) : ts . TransformerFactory < ts . SourceFile > {
6667 return ( context ) => {
67- const transformer = new Transformer ( context , translations ) ;
68+ const transformer = new Transformer ( context , translations , program ) ;
6869 return ( file ) => ts . visitNode ( file , transformer . boundVisitNode ) ;
6970 } ;
7071}
@@ -75,21 +76,24 @@ export function litLocalizeTransform(
7576class Transformer {
7677 private context : ts . TransformationContext ;
7778 private translations : Map < string , Message > | undefined ;
79+ private typeChecker : ts . TypeChecker ;
7880 boundVisitNode = this . visitNode . bind ( this ) ;
7981
8082 constructor (
8183 context : ts . TransformationContext ,
82- translations : Map < string , Message > | undefined
84+ translations : Map < string , Message > | undefined ,
85+ program : ts . Program
8386 ) {
8487 this . context = context ;
8588 this . translations = translations ;
89+ this . typeChecker = program . getTypeChecker ( ) ;
8690 }
8791
8892 /**
8993 * Top-level delegating visitor for all nodes.
9094 */
9195 visitNode ( node : ts . Node ) : ts . VisitResult < ts . Node > {
92- if ( isMsgCall ( node ) ) {
96+ if ( isMsgCall ( node , this . typeChecker ) ) {
9397 return this . replaceMsgCall ( node ) ;
9498 }
9599 if ( isLitTemplate ( node ) ) {
@@ -101,8 +105,8 @@ class Transformer {
101105 )
102106 ) ;
103107 }
104- if ( ts . isImportDeclaration ( node ) ) {
105- return this . removeMsgImport ( node ) ;
108+ if ( this . isLitLocalizeImport ( node ) ) {
109+ return undefined ;
106110 }
107111 return ts . visitEachChild ( node , this . boundVisitNode , this . context ) ;
108112 }
@@ -329,29 +333,29 @@ class Transformer {
329333 }
330334
331335 /**
332- * Remove import declarations for the lit-localize `msg` function, because we
333- * are transforming away all calls to that function.
336+ * Return whether the given node is an import for the lit-localize module.
334337 */
335- removeMsgImport (
336- imprt : ts . ImportDeclaration
337- ) : ts . ImportDeclaration | undefined {
338- const clause = imprt . importClause ;
339- if ( clause === undefined ) {
340- return imprt ;
338+ isLitLocalizeImport ( node : ts . Node ) : node is ts . ImportDeclaration {
339+ if ( ! ts . isImportDeclaration ( node ) ) {
340+ return false ;
341341 }
342- const bindings = clause . namedBindings ;
343- if ( bindings === undefined || ! ts . isNamedImports ( bindings ) ) {
344- return imprt ;
342+ const moduleSymbol = this . typeChecker . getSymbolAtLocation (
343+ node . moduleSpecifier
344+ ) ;
345+ if ( ! moduleSymbol || ! moduleSymbol . exports ) {
346+ return false ;
345347 }
346- // TODO(aomarks) This is too crude. We should do better to identify only our
347- // `msg` function.
348- if (
349- bindings . elements . length === 1 &&
350- bindings . elements [ 0 ] . name . text === 'msg'
351- ) {
352- return undefined ;
348+ const exports = moduleSymbol . exports . values ( ) ;
349+ for ( const xport of exports as typeof exports & {
350+ [ Symbol . iterator ] ( ) : Iterator < ts . Symbol > ;
351+ } ) {
352+ const type = this . typeChecker . getTypeAtLocation ( xport . valueDeclaration ) ;
353+ const props = this . typeChecker . getPropertiesOfType ( type ) ;
354+ if ( props . some ( ( prop ) => prop . escapedName === '_LIT_LOCALIZE_MSG_' ) ) {
355+ return true ;
356+ }
353357 }
354- return imprt ;
358+ return false ;
355359 }
356360}
357361
0 commit comments