@@ -6,6 +6,7 @@ import * as tstl from "./LuaAST";
66import { LuaLibFeature } from "./LuaLib" ;
77import { ContextType , TSHelper as tsHelper } from "./TSHelper" ;
88import { TSTLErrors } from "./TSTLErrors" ;
9+ import { luaKeywords , luaBuiltins } from "./LuaKeywords" ;
910
1011export type StatementVisitResult = tstl . Statement | tstl . Statement [ ] | undefined ;
1112export type ExpressionVisitResult = tstl . Expression ;
@@ -49,13 +50,6 @@ export interface DiagnosticsProducingTypeChecker extends ts.TypeChecker {
4950}
5051
5152export class LuaTransformer {
52- public luaKeywords : Set < string > = new Set ( [
53- "_G" , "and" , "assert" , "break" , "coroutine" , "debug" , "do" , "else" , "elseif" , "end" , "error" , "false" , "for" ,
54- "function" , "goto" , "if" , "ipairs" , "in" , "local" , "math" , "nil" , "not" , "or" , "pairs" , "pcall" , "print" ,
55- "rawget" , "rawset" , "repeat" , "return" , "require" , "self" , "string" , "table" , "then" , "tostring" , "type" ,
56- "unpack" , "until" , "while" ,
57- ] ) ;
58-
5953 private isStrict : boolean ;
6054 private luaTarget : LuaTarget ;
6155
@@ -3449,8 +3443,9 @@ export class LuaTransformer {
34493443 } else if ( ts . isShorthandPropertyAssignment ( element ) ) {
34503444 let identifier : tstl . Expression | undefined ;
34513445 const valueSymbol = this . checker . getShorthandAssignmentValueSymbol ( element ) ;
3452- if ( valueSymbol !== undefined && this . symbolIds . has ( valueSymbol ) ) {
3453- // Ignore unknown symbols so things like NaN still get transformed properly
3446+ if ( valueSymbol !== undefined
3447+ // Ignore declarations for things like NaN
3448+ && ! tsHelper . isStandardLibraryDeclaration ( valueSymbol . valueDeclaration , this . program ) ) {
34543449 identifier = this . createIdentifierFromSymbol ( valueSymbol , element . name ) ;
34553450 } else {
34563451 identifier = this . transformIdentifierExpression ( element . name ) ;
@@ -3818,13 +3813,20 @@ export class LuaTransformer {
38183813 if ( ! signatureDeclaration
38193814 || tsHelper . getDeclarationContextType ( signatureDeclaration , this . checker ) !== ContextType . Void )
38203815 {
3821- // table:name()
3822- return tstl . createMethodCallExpression (
3823- table ,
3824- this . transformIdentifier ( node . expression . name ) ,
3825- parameters ,
3826- node
3827- ) ;
3816+ if ( luaKeywords . has ( node . expression . name . text )
3817+ || ! tsHelper . isValidLuaIdentifier ( node . expression . name . text ) )
3818+ {
3819+ return this . transformElementCall ( node ) ;
3820+
3821+ } else {
3822+ // table:name()
3823+ return tstl . createMethodCallExpression (
3824+ table ,
3825+ this . transformIdentifier ( node . expression . name ) ,
3826+ parameters ,
3827+ node
3828+ ) ;
3829+ }
38283830 } else {
38293831 // table.name()
38303832 const callPath = tstl . createTableIndexExpression (
@@ -3839,7 +3841,7 @@ export class LuaTransformer {
38393841 }
38403842
38413843 public transformElementCall ( node : ts . CallExpression ) : ExpressionVisitResult {
3842- if ( ! ts . isElementAccessExpression ( node . expression ) ) {
3844+ if ( ! ts . isElementAccessExpression ( node . expression ) && ! ts . isPropertyAccessExpression ( node . expression ) ) {
38433845 throw TSTLErrors . InvalidElementCall ( node ) ;
38443846 }
38453847
@@ -3862,7 +3864,10 @@ export class LuaTransformer {
38623864
38633865 // Cache left-side if it has effects
38643866 //(function() local ____TS_self = context; return ____TS_self[argument](parameters); end)()
3865- const argument = this . transformExpression ( node . expression . argumentExpression ) ;
3867+ const argumentExpression = ts . isElementAccessExpression ( node . expression )
3868+ ? node . expression . argumentExpression
3869+ : ts . createStringLiteral ( node . expression . name . text ) ;
3870+ const argument = this . transformExpression ( argumentExpression ) ;
38663871 const selfIdentifier = tstl . createIdentifier ( "____TS_self" ) ;
38673872 const selfAssignment = tstl . createVariableDeclarationStatement ( selfIdentifier , context ) ;
38683873 const index = tstl . createTableIndexExpression ( selfIdentifier , argument ) ;
@@ -5269,11 +5274,11 @@ export class LuaTransformer {
52695274 }
52705275
52715276 protected isUnsafeName ( name : string ) : boolean {
5272- return this . luaKeywords . has ( name ) || ! tsHelper . isValidLuaIdentifier ( name ) ;
5277+ return luaKeywords . has ( name ) || luaBuiltins . has ( name ) || ! tsHelper . isValidLuaIdentifier ( name ) ;
52735278 }
52745279
52755280 protected hasUnsafeSymbolName ( symbol : ts . Symbol ) : boolean {
5276- if ( this . luaKeywords . has ( symbol . name ) ) {
5281+ if ( luaKeywords . has ( symbol . name ) || luaBuiltins . has ( symbol . name ) ) {
52775282 // lua keywords are only unsafe when non-ambient and not exported
52785283 const isNonAmbient = symbol . declarations . find ( d => ! tsHelper . isAmbient ( d ) ) !== undefined ;
52795284 return isNonAmbient && ! this . isSymbolExported ( symbol ) ;
@@ -5284,6 +5289,10 @@ export class LuaTransformer {
52845289 protected hasUnsafeIdentifierName ( identifier : ts . Identifier ) : boolean {
52855290 const symbol = this . checker . getSymbolAtLocation ( identifier ) ;
52865291 if ( symbol !== undefined ) {
5292+ if ( luaKeywords . has ( symbol . name ) && symbol . declarations . find ( d => ! tsHelper . isAmbient ( d ) ) === undefined ) {
5293+ // Catch ambient declarations of identifiers with lua keyword names
5294+ throw TSTLErrors . InvalidAmbientLuaKeywordIdentifier ( identifier ) ;
5295+ }
52875296 return this . hasUnsafeSymbolName ( symbol ) ;
52885297 }
52895298 return false ;
0 commit comments