@@ -3,10 +3,10 @@ import { LuaTarget } from "../../CompilerOptions";
33import * as lua from "../../LuaAST" ;
44import { TransformationContext } from "../context" ;
55import { getCurrentNamespace } from "../visitors/namespace" ;
6- import { UndefinedScope } from "./errors" ;
6+ import { UnsupportedVarDeclaration } from "./errors" ;
77import { createExportedIdentifier , getIdentifierExportScope } from "./export" ;
88import { findScope , peekScope , ScopeType } from "./scope" ;
9- import { isFirstDeclaration , isFunctionType } from "./typescript" ;
9+ import { isFunctionType } from "./typescript" ;
1010
1111export type OneToManyVisitorResult < T extends lua . Node > = T | T [ ] | undefined ;
1212export function unwrapVisitorResult < T extends lua . Node > ( result : OneToManyVisitorResult < T > ) : T [ ] {
@@ -27,22 +27,6 @@ export function createExportsIdentifier(): lua.Identifier {
2727 return lua . createIdentifier ( "____exports" ) ;
2828}
2929
30- export function replaceStatementInParent ( oldNode : lua . Statement , newNode ?: lua . Statement ) : void {
31- if ( ! oldNode . parent ) {
32- throw new Error ( "node has not yet been assigned a parent" ) ;
33- }
34-
35- if ( lua . isBlock ( oldNode . parent ) || lua . isDoStatement ( oldNode . parent ) ) {
36- if ( newNode ) {
37- oldNode . parent . statements . splice ( oldNode . parent . statements . indexOf ( oldNode ) , 1 , newNode ) ;
38- } else {
39- oldNode . parent . statements . splice ( oldNode . parent . statements . indexOf ( oldNode ) , 1 ) ;
40- }
41- } else {
42- throw new Error ( "unexpected parent type" ) ;
43- }
44- }
45-
4630export function createExpressionPlusOne ( expression : lua . Expression ) : lua . Expression {
4731 if ( lua . isNumericLiteral ( expression ) ) {
4832 const newNode = lua . cloneNode ( expression ) ;
@@ -111,10 +95,9 @@ export function createHoistableVariableDeclarationStatement(
11195 context : TransformationContext ,
11296 identifier : lua . Identifier ,
11397 initializer ?: lua . Expression ,
114- tsOriginal ?: ts . Node ,
115- parent ?: lua . Node
98+ tsOriginal ?: ts . Node
11699) : lua . AssignmentStatement | lua . VariableDeclarationStatement {
117- const declaration = lua . createVariableDeclarationStatement ( identifier , initializer , tsOriginal , parent ) ;
100+ const declaration = lua . createVariableDeclarationStatement ( identifier , initializer , tsOriginal ) ;
118101 if ( ! context . options . noHoisting && identifier . symbolId ) {
119102 const scope = peekScope ( context ) ;
120103 if ( ! scope . variableDeclarations ) {
@@ -132,19 +115,26 @@ export function createLocalOrExportedOrGlobalDeclaration(
132115 lhs : lua . Identifier | lua . Identifier [ ] ,
133116 rhs ?: lua . Expression | lua . Expression [ ] ,
134117 tsOriginal ?: ts . Node ,
135- parent ?: lua . Node ,
136118 overrideExportScope ?: ts . SourceFile | ts . ModuleDeclaration
137119) : lua . Statement [ ] {
138120 let declaration : lua . VariableDeclarationStatement | undefined ;
139121 let assignment : lua . AssignmentStatement | undefined ;
140122
141- const functionDeclaration = tsOriginal && ts . isFunctionDeclaration ( tsOriginal ) ? tsOriginal : undefined ;
123+ const isFunctionDeclaration = tsOriginal !== undefined && ts . isFunctionDeclaration ( tsOriginal ) ;
142124
143125 const identifiers = Array . isArray ( lhs ) ? lhs : [ lhs ] ;
144126 if ( identifiers . length === 0 ) {
145127 return [ ] ;
146128 }
147129
130+ let isVariableDeclaration = false ;
131+ if ( tsOriginal && ts . isVariableDeclaration ( tsOriginal ) ) {
132+ isVariableDeclaration = true ;
133+ if ( tsOriginal . parent && ( tsOriginal . parent . flags & ( ts . NodeFlags . Let | ts . NodeFlags . Const ) ) === 0 ) {
134+ throw UnsupportedVarDeclaration ( tsOriginal . parent ) ;
135+ }
136+ }
137+
148138 const exportScope = overrideExportScope || getIdentifierExportScope ( context , identifiers [ 0 ] ) ;
149139 if ( exportScope ) {
150140 // exported
@@ -154,48 +144,31 @@ export function createLocalOrExportedOrGlobalDeclaration(
154144 assignment = lua . createAssignmentStatement (
155145 identifiers . map ( identifier => createExportedIdentifier ( context , identifier , exportScope ) ) ,
156146 rhs ,
157- tsOriginal ,
158- parent
147+ tsOriginal
159148 ) ;
160149 }
161150 } else {
162151 const insideFunction = findScope ( context , ScopeType . Function ) !== undefined ;
163- let isLetOrConst = false ;
164- let isVariableFirstDeclaration = true ; // var can have multiple declarations for the same variable :/
165- if ( tsOriginal && ts . isVariableDeclaration ( tsOriginal ) && tsOriginal . parent ) {
166- isLetOrConst = ( tsOriginal . parent . flags & ( ts . NodeFlags . Let | ts . NodeFlags . Const ) ) !== 0 ;
167- isVariableFirstDeclaration = isLetOrConst || isFirstDeclaration ( context , tsOriginal ) ;
168- }
169152
170- if (
171- ( context . isModule || getCurrentNamespace ( context ) || insideFunction || isLetOrConst ) &&
172- isVariableFirstDeclaration
173- ) {
153+ if ( context . isModule || getCurrentNamespace ( context ) || insideFunction || isVariableDeclaration ) {
174154 // local
175155 const isPossibleWrappedFunction =
176- ! functionDeclaration &&
156+ ! isFunctionDeclaration &&
177157 tsOriginal &&
178158 ts . isVariableDeclaration ( tsOriginal ) &&
179159 tsOriginal . initializer &&
180160 isFunctionType ( context , context . checker . getTypeAtLocation ( tsOriginal . initializer ) ) ;
181161 if ( isPossibleWrappedFunction ) {
182162 // Split declaration and assignment for wrapped function types to allow recursion
183- declaration = lua . createVariableDeclarationStatement ( lhs , undefined , tsOriginal , parent ) ;
184- assignment = lua . createAssignmentStatement ( lhs , rhs , tsOriginal , parent ) ;
163+ declaration = lua . createVariableDeclarationStatement ( lhs , undefined , tsOriginal ) ;
164+ assignment = lua . createAssignmentStatement ( lhs , rhs , tsOriginal ) ;
185165 } else {
186- declaration = lua . createVariableDeclarationStatement ( lhs , rhs , tsOriginal , parent ) ;
166+ declaration = lua . createVariableDeclarationStatement ( lhs , rhs , tsOriginal ) ;
187167 }
188168
189169 if ( ! context . options . noHoisting ) {
190170 // Remember local variable declarations for hoisting later
191- const scope =
192- isLetOrConst || functionDeclaration
193- ? peekScope ( context )
194- : findScope ( context , ScopeType . Function | ScopeType . File ) ;
195-
196- if ( scope === undefined ) {
197- throw UndefinedScope ( ) ;
198- }
171+ const scope = peekScope ( context ) ;
199172
200173 if ( ! scope . variableDeclarations ) {
201174 scope . variableDeclarations = [ ] ;
@@ -205,13 +178,13 @@ export function createLocalOrExportedOrGlobalDeclaration(
205178 }
206179 } else if ( rhs ) {
207180 // global
208- assignment = lua . createAssignmentStatement ( lhs , rhs , tsOriginal , parent ) ;
181+ assignment = lua . createAssignmentStatement ( lhs , rhs , tsOriginal ) ;
209182 } else {
210183 return [ ] ;
211184 }
212185 }
213186
214- if ( ! context . options . noHoisting && functionDeclaration ) {
187+ if ( ! context . options . noHoisting && isFunctionDeclaration ) {
215188 // Remember function definitions for hoisting later
216189 const functionSymbolId = ( lhs as lua . Identifier ) . symbolId ;
217190 const scope = peekScope ( context ) ;
0 commit comments