@@ -7,6 +7,7 @@ import * as tstl from "./LuaAST";
77import { LuaLib , LuaLibFeature } from "./LuaLib" ;
88import { ContextType , TSHelper as tsHelper } from "./TSHelper" ;
99import { TSTLErrors } from "./TSTLErrors" ;
10+ import { isArray } from "util" ;
1011
1112export type StatementVisitResult = tstl . Statement | tstl . Statement [ ] | undefined ;
1213export type ExpressionVisitResult = tstl . Expression | undefined ;
@@ -758,14 +759,9 @@ export class LuaTransformer {
758759 } else if ( this . isModule && ( ts . getCombinedModifierFlags ( statement ) & ts . ModifierFlags . Export ) ) {
759760 // exports.NS = exports.NS or {}
760761 const namespaceDeclaration = tstl . createAssignmentStatement (
761- tstl . createTableIndexExpression (
762- this . transformIdentifier ( ts . createIdentifier ( "exports" ) ) ,
763- this . transformIdentifier ( statement . name as ts . Identifier )
764- ) ,
762+ this . createExportedIdentifier ( this . transformIdentifier ( statement . name as ts . Identifier ) ) ,
765763 tstl . createBinaryExpression (
766- tstl . createTableIndexExpression (
767- this . transformIdentifier ( ts . createIdentifier ( "exports" ) ) ,
768- this . transformIdentifier ( statement . name as ts . Identifier ) ) ,
764+ this . createExportedIdentifier ( this . transformIdentifier ( statement . name as ts . Identifier ) ) ,
769765 tstl . createTableExpression ( ) ,
770766 tstl . SyntaxKind . OrOperator ) ) ;
771767
@@ -774,9 +770,7 @@ export class LuaTransformer {
774770 // local NS = exports.NS
775771 const localDeclaration = tstl . createVariableDeclarationStatement (
776772 this . transformIdentifier ( statement . name as ts . Identifier ) ,
777- tstl . createTableIndexExpression (
778- this . transformIdentifier ( ts . createIdentifier ( "exports" ) as ts . Identifier ) ,
779- this . transformIdentifier ( statement . name as ts . Identifier ) ) ) ;
773+ this . createExportedIdentifier ( this . transformIdentifier ( statement . name as ts . Identifier ) ) ) ;
780774
781775 result . push ( localDeclaration ) ;
782776 } else {
@@ -919,7 +913,8 @@ export class LuaTransformer {
919913 }
920914
921915 public transformVariableDeclaration ( statement : ts . VariableDeclaration )
922- : [ tstl . VariableDeclarationStatement ] | [ tstl . VariableDeclarationStatement , tstl . AssignmentStatement ]
916+ : [ tstl . AssignmentStatement | tstl . VariableDeclarationStatement ]
917+ | [ tstl . VariableDeclarationStatement , tstl . AssignmentStatement ]
923918 {
924919 if ( statement . initializer ) {
925920 // Validate assignment
@@ -929,6 +924,7 @@ export class LuaTransformer {
929924 }
930925
931926 if ( ts . isIdentifier ( statement . name ) ) {
927+ const isVariableExported = this . isIdentifierExported ( statement . name . escapedText ) ;
932928 // Find variable identifier
933929 const identifierName = this . transformIdentifier ( statement . name ) ;
934930 if ( statement . initializer ) {
@@ -937,15 +933,38 @@ export class LuaTransformer {
937933 // Separate declaration and assignment for functions to allow recursion
938934
939935 // local identifierName; identifierName = value;
940- return [ tstl . createVariableDeclarationStatement ( identifierName ) ,
941- tstl . createAssignmentStatement ( identifierName , value ) ] ;
936+ if ( isVariableExported ) {
937+ return [ tstl . createVariableDeclarationStatement ( identifierName ) ,
938+ tstl . createAssignmentStatement (
939+ this . createExportedIdentifier ( identifierName ) ,
940+ value ) ,
941+ ] ;
942+ } else {
943+ return [ tstl . createVariableDeclarationStatement ( identifierName ) ,
944+ tstl . createAssignmentStatement (
945+ identifierName ,
946+ value ) ,
947+ ] ;
948+ }
942949 } else {
943950 // local identifierName = value;
944- return [ tstl . createVariableDeclarationStatement ( identifierName , value ) ] ;
951+ if ( isVariableExported ) {
952+ return [ tstl . createAssignmentStatement (
953+ this . createExportedIdentifier ( identifierName ) , value ) ] ;
954+ } else {
955+ return [ tstl . createVariableDeclarationStatement ( identifierName , value ) ] ;
956+ }
945957 }
946958 } else {
947959 // local identifierName = nil;
948- return [ tstl . createVariableDeclarationStatement ( identifierName , tstl . createNilLiteral ( ) ) ] ;
960+ if ( isVariableExported ) {
961+ return [ tstl . createAssignmentStatement (
962+ this . createExportedIdentifier ( identifierName ) , tstl . createNilLiteral ( ) ) ] ;
963+ } else {
964+ return [ tstl . createVariableDeclarationStatement (
965+ identifierName , tstl . createNilLiteral ( ) ) ,
966+ ] ;
967+ }
949968 }
950969 } else if ( ts . isArrayBindingPattern ( statement . name ) ) {
951970 // Destructuring type
@@ -956,25 +975,49 @@ export class LuaTransformer {
956975 }
957976
958977 const vars = statement . name . elements . map ( e => this . transformArrayBindingElement ( e ) ) ;
978+ const isSomeVariableExported = vars . some ( i => this . isIdentifierExported ( i . text ) ) ;
959979
960980 // Don't unpack TupleReturn decorated functions
961981 if ( statement . initializer ) {
962982 if ( tsHelper . isTupleReturnCall ( statement . initializer , this . checker ) ) {
963983 // local vars = initializer;
964- return [ tstl . createVariableDeclarationStatement (
965- vars ,
966- this . transformExpression ( statement . initializer )
967- ) ] ;
984+ if ( isSomeVariableExported ) {
985+ return [ tstl . createAssignmentStatement (
986+ vars . map ( i => this . createExportedIdentifier ( i ) ) ,
987+ this . transformExpression ( statement . initializer )
988+ ) ] ;
989+ } else {
990+ return [ tstl . createVariableDeclarationStatement (
991+ vars ,
992+ this . transformExpression ( statement . initializer )
993+ ) ] ;
994+ }
968995 } else {
969996 // local vars = this.transpileDestructingAssignmentValue(node.initializer);
970997 const initializer = this . createUnpackCall (
971998 this . transformExpression ( statement . initializer ) ,
972999 statement . initializer
9731000 ) ;
974- return [ tstl . createVariableDeclarationStatement ( vars , initializer ) ] ;
1001+ if ( isSomeVariableExported ) {
1002+ return [
1003+ tstl . createAssignmentStatement (
1004+ vars . map ( i => this . createExportedIdentifier ( i ) ) ,
1005+ initializer ) ,
1006+ ] ;
1007+ } else {
1008+ return [ tstl . createVariableDeclarationStatement ( vars , initializer ) ] ;
1009+ }
9751010 }
9761011 } else {
977- return [ tstl . createVariableDeclarationStatement ( vars ) ] ;
1012+ if ( isSomeVariableExported ) {
1013+ return [
1014+ tstl . createAssignmentStatement (
1015+ vars . map ( i => this . createExportedIdentifier ( i ) ) ,
1016+ tstl . createNilLiteral ( ) ) ,
1017+ ] ;
1018+ } else {
1019+ return [ tstl . createVariableDeclarationStatement ( vars ) ] ;
1020+ }
9781021 }
9791022 } else {
9801023 throw TSTLErrors . UnsupportedKind ( "variable declaration" , statement . name . kind , statement ) ;
@@ -1144,7 +1187,9 @@ export class LuaTransformer {
11441187 if ( ts . isArrayBindingPattern ( initializer . declarations [ 0 ] . name ) ) {
11451188 expression = this . createUnpackCall ( expression , initializer ) ;
11461189 }
1147- return tstl . createVariableDeclarationStatement ( variableDeclarations [ 0 ] . left , expression ) ;
1190+ // we can safely assume that for vars are not exported and therefore declarationstatenents
1191+ return tstl . createVariableDeclarationStatement (
1192+ ( variableDeclarations [ 0 ] as tstl . VariableDeclarationStatement ) . left , expression ) ;
11481193
11491194 } else {
11501195 // Assignment to existing variable
@@ -1486,7 +1531,7 @@ export class LuaTransformer {
14861531 case ts . SyntaxKind . ElementAccessExpression :
14871532 return this . transformElementAccessExpression ( expression as ts . ElementAccessExpression ) ;
14881533 case ts . SyntaxKind . Identifier :
1489- return this . transformIdentifier ( expression as ts . Identifier ) ;
1534+ return this . transformIdentifierExpression ( expression as ts . Identifier ) ;
14901535 case ts . SyntaxKind . StringLiteral :
14911536 case ts . SyntaxKind . NoSubstitutionTemplateLiteral :
14921537 return this . transformStringLiteral ( expression as ts . StringLiteral ) ;
@@ -2885,31 +2930,58 @@ export class LuaTransformer {
28852930 } else if ( ts . isStringLiteral ( propertyName ) ) {
28862931 return this . transformStringLiteral ( propertyName ) ;
28872932 } else if ( ts . isNumericLiteral ( propertyName ) ) {
2888- const value = + propertyName . text ;
2933+ const value = Number ( propertyName . text ) ;
28892934 return tstl . createNumericLiteral ( value , undefined , propertyName ) ;
28902935 } else {
28912936 return tstl . createStringLiteral ( this . transformIdentifier ( propertyName ) . text ) ;
28922937 }
28932938 }
28942939
2895- public transformIdentifier ( epxression : ts . Identifier , parent ?: tstl . Node ) : tstl . Identifier {
2896- if ( epxression . originalKeywordKind === ts . SyntaxKind . UndefinedKeyword ) {
2940+ public transformIdentifier ( expression : ts . Identifier ) : tstl . Identifier {
2941+ if ( expression . originalKeywordKind === ts . SyntaxKind . UndefinedKeyword ) {
28972942 return tstl . createIdentifier ( "nil" ) ; // TODO this is a hack that allows use to keep Identifier
28982943 // as return time as changing that would break a lot of stuff.
28992944 // But this should be changed to retun tstl.createNilLiteral()
29002945 // at some point.
29012946 }
2902- let escapedText = epxression . escapedText as string ;
2947+ let escapedText = expression . escapedText as string ;
29032948 const underScoreCharCode = "_" . charCodeAt ( 0 ) ;
29042949 if ( escapedText . length >= 3 && escapedText . charCodeAt ( 0 ) === underScoreCharCode &&
29052950 escapedText . charCodeAt ( 1 ) === underScoreCharCode && escapedText . charCodeAt ( 2 ) === underScoreCharCode ) {
29062951 escapedText = escapedText . substr ( 1 ) ;
29072952 }
29082953
29092954 if ( this . luaKeywords . has ( escapedText ) ) {
2910- throw TSTLErrors . KeywordIdentifier ( epxression ) ;
2955+ throw TSTLErrors . KeywordIdentifier ( expression ) ;
29112956 }
2912- return tstl . createIdentifier ( escapedText , parent , epxression ) ;
2957+ return tstl . createIdentifier ( escapedText , undefined , expression ) ;
2958+ }
2959+
2960+ public transformIdentifierExpression ( expression : ts . Identifier ) : tstl . IdentifierOrTableIndexExpression {
2961+ if ( this . isIdentifierExported ( expression . escapedText ) ) {
2962+ return this . createExportedIdentifier ( this . transformIdentifier ( expression ) ) ;
2963+ }
2964+ return this . transformIdentifier ( expression ) ;
2965+ }
2966+
2967+ public isIdentifierExported ( identifierName : string | ts . __String ) : boolean {
2968+ if ( ! this . isModule ) {
2969+ return false ;
2970+ }
2971+ const currentScope = this . currentNamespace ? this . currentNamespace : this . currentSourceFile ;
2972+ const scopeSymbol = this . checker . getSymbolAtLocation ( currentScope )
2973+ ? this . checker . getSymbolAtLocation ( currentScope )
2974+ : this . checker . getTypeAtLocation ( currentScope ) . getSymbol ( ) ;
2975+ return scopeSymbol . exports . has ( identifierName as ts . __String ) ;
2976+ }
2977+
2978+ public createExportedIdentifier ( identifier : tstl . Identifier ) : tstl . TableIndexExpression {
2979+ const exportTable = this . currentNamespace
2980+ ? this . transformIdentifier ( this . currentNamespace . name as ts . Identifier )
2981+ : tstl . createIdentifier ( "exports" ) ;
2982+ return tstl . createTableIndexExpression (
2983+ exportTable ,
2984+ tstl . createStringLiteral ( identifier . text ) ) ;
29132985 }
29142986
29152987 public escapeString ( text : string ) : string {
@@ -3033,7 +3105,16 @@ export class LuaTransformer {
30333105 || this . currentNamespace
30343106 || ( tsOriginal && tsHelper . findFirstNodeAbove ( tsOriginal , ts . isFunctionLike ) )
30353107 ) {
3036- statements . push ( tstl . createVariableDeclarationStatement ( lhs , undefined , parent ) ) ;
3108+ if ( ! isArray ( lhs ) ) {
3109+ lhs = [ lhs ] ;
3110+ }
3111+ const shouldExport = lhs . some ( i => this . isIdentifierExported ( i . text ) ) ;
3112+ if ( shouldExport ) {
3113+ statements . push (
3114+ tstl . createAssignmentStatement ( lhs . map ( i => this . createExportedIdentifier ( i ) ) , undefined , parent ) ) ;
3115+ } else {
3116+ statements . push ( tstl . createVariableDeclarationStatement ( lhs , undefined , parent ) ) ;
3117+ }
30373118 }
30383119 statements . push ( tstl . createAssignmentStatement ( lhs , rhs , parent , tsOriginal ) ) ;
30393120 return statements ;
0 commit comments