From 5e5b673e91fdf347d40b2275683225af72837ade Mon Sep 17 00:00:00 2001 From: Tom <26638278+tomblind@users.noreply.github.com> Date: Sun, 24 Feb 2019 07:04:14 -0700 Subject: [PATCH] Changed `@luaIterator` so that it must be applied to the iterator type, not the generator function. --- src/LuaTransformer.ts | 14 ++++++-------- src/TSHelper.ts | 20 +++---------------- test/unit/loops.spec.ts | 43 +++++++++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/LuaTransformer.ts b/src/LuaTransformer.ts index e04c594da..e752ac0f4 100644 --- a/src/LuaTransformer.ts +++ b/src/LuaTransformer.ts @@ -1792,10 +1792,7 @@ export class LuaTransformer { // If return expression is an array literal, leave out brackets. return tstl.createReturnStatement(statement.expression.elements .map(elem => this.transformExpression(elem))); - } else if ( - !tsHelper.isTupleReturnCall(statement.expression, this.checker) - && !tsHelper.isInLuaIteratorFunction(statement, this.checker)) - { + } else if (!tsHelper.isTupleReturnCall(statement.expression, this.checker)) { // If return expression is not another TupleReturn call, unpack it const expression = this.createUnpackCall( this.transformExpression(statement.expression), @@ -1971,7 +1968,9 @@ export class LuaTransformer { public transformForOfLuaIteratorStatement(statement: ts.ForOfStatement, block: tstl.Block): StatementVisitResult { const luaIterator = this.transformExpression(statement.expression); - if (tsHelper.isTupleReturnCall(statement.expression, this.checker)) { + const type = this.checker.getTypeAtLocation(statement.expression); + const tupleReturn = tsHelper.getCustomDecorators(type, this.checker).has(DecoratorKind.TupleReturn); + if (tupleReturn) { // LuaIterator + TupleReturn if (ts.isVariableDeclarationList(statement.initializer)) { // Variables declared in for loop @@ -2073,7 +2072,7 @@ export class LuaTransformer { // Arrays return this.transformForOfArrayStatement(statement, body); - } else if (tsHelper.isLuaIteratorCall(statement.expression, this.checker)) { + } else if (tsHelper.isLuaIteratorType(statement.expression, this.checker)) { // LuaIterators return this.transformForOfLuaIteratorStatement(statement, body); @@ -3056,7 +3055,6 @@ export class LuaTransformer { // Check for calls on primitives to override let parameters: tstl.Expression[] = []; - const isLuaIterator = tsHelper.isLuaIteratorCall(node, this.checker); const isTupleReturn = tsHelper.isTupleReturnCall(node, this.checker); const isTupleReturnForward = node.parent && ts.isReturnStatement(node.parent) && tsHelper.isInTupleReturnFunction(node, this.checker); @@ -3064,7 +3062,7 @@ export class LuaTransformer { const isInSpread = node.parent && ts.isSpreadElement(node.parent); const returnValueIsUsed = node.parent && !ts.isExpressionStatement(node.parent); const wrapResult = isTupleReturn && !isTupleReturnForward && !isInDestructingAssignment - && !isInSpread && returnValueIsUsed && !isLuaIterator; + && !isInSpread && returnValueIsUsed; if (ts.isPropertyAccessExpression(node.expression)) { const result = this.transformPropertyCall(node); diff --git a/src/TSHelper.ts b/src/TSHelper.ts index 347f165cb..a6ec285ef 100644 --- a/src/TSHelper.ts +++ b/src/TSHelper.ts @@ -165,13 +165,9 @@ export class TSHelper { return TSHelper.forTypeOrAnySupertype(type, checker, t => TSHelper.isExplicitArrayType(t, checker)); } - public static isLuaIteratorCall(node: ts.Node, checker: ts.TypeChecker): boolean { - if (ts.isCallExpression(node) && node.parent && ts.isForOfStatement(node.parent)) { - const type = checker.getTypeAtLocation(node.expression); - return TSHelper.getCustomDecorators(type, checker).has(DecoratorKind.LuaIterator); - } else { - return false; - } + public static isLuaIteratorType(node: ts.Node, checker: ts.TypeChecker): boolean { + const type = checker.getTypeAtLocation(node); + return TSHelper.getCustomDecorators(type, checker).has(DecoratorKind.LuaIterator); } public static isTupleReturnCall(node: ts.Node, checker: ts.TypeChecker): boolean { @@ -200,16 +196,6 @@ export class TSHelper { } } - public static isInLuaIteratorFunction(node: ts.Node, checker: ts.TypeChecker): boolean { - const declaration = TSHelper.findFirstNodeAbove(node, ts.isFunctionLike); - if (declaration) { - const decorators = TSHelper.getCustomDecorators(checker.getTypeAtLocation(declaration), checker); - return decorators.has(DecoratorKind.LuaIterator); - } else { - return false; - } - } - public static getContainingFunctionReturnType(node: ts.Node, checker: ts.TypeChecker): ts.Type { const declaration = TSHelper.findFirstNodeAbove(node, ts.isFunctionLike); if (declaration) { diff --git a/test/unit/loops.spec.ts b/test/unit/loops.spec.ts index 26eb44443..8487e1510 100644 --- a/test/unit/loops.spec.ts +++ b/test/unit/loops.spec.ts @@ -525,7 +525,8 @@ export class LuaLoopTests public forofLuaIterator(): void { const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ - function luaIter(): Iterable { + interface Iter extends Iterable {} + function luaIter(): Iter { let i = 0; return (() => arr[i++]) as any; } @@ -545,7 +546,8 @@ export class LuaLoopTests public forofLuaIteratorExistingVar(): void { const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ - function luaIter(): Iterable { + interface Iter extends Iterable {} + function luaIter(): Iter { let i = 0; return (() => arr[i++]) as any; } @@ -566,7 +568,8 @@ export class LuaLoopTests public forofLuaIteratorDestructuring(): void { const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ - function luaIter(): Iterable<[string, string]> { + interface Iter extends Iterable<[string, string]> {} + function luaIter(): Iter { let i = 0; return (() => arr[i] && [i.toString(), arr[i++]]) as any; } @@ -586,7 +589,8 @@ export class LuaLoopTests public forofLuaIteratorDestructuringExistingVar(): void { const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ - function luaIter(): Iterable<[string, string]> { + interface Iter extends Iterable<[string, string]> {} + function luaIter(): Iter { let i = 0; return (() => arr[i] && [i.toString(), arr[i++]]) as any; } @@ -609,7 +613,8 @@ export class LuaLoopTests const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ /** @tupleReturn */ - function luaIter(): Iterable<[string, string]> { + interface Iter extends Iterable<[string, string]> {} + function luaIter(): Iter { let i = 0; /** @tupleReturn */ function iter() { return arr[i] && [i.toString(), arr[i++]] || []; } @@ -632,7 +637,8 @@ export class LuaLoopTests const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ /** @tupleReturn */ - function luaIter(): Iterable<[string, string]> { + interface Iter extends Iterable<[string, string]> {} + function luaIter(): Iter { let i = 0; /** @tupleReturn */ function iter() { return arr[i] && [i.toString(), arr[i++]] || []; } @@ -656,7 +662,8 @@ export class LuaLoopTests public forofLuaIteratorTupleReturnSingleVar(): void { const code = `/** @luaIterator */ /** @tupleReturn */ - declare function luaIter(): Iterable<[string, string]>; + interface Iter extends Iterable<[string, string]> {} + declare function luaIter(): Iter; for (let x of luaIter()) {}`; const compilerOptions = { luaLibImport: LuaLibImportKind.Require, @@ -674,7 +681,8 @@ export class LuaLoopTests public forofLuaIteratorTupleReturnSingleExistingVar(): void { const code = `/** @luaIterator */ /** @tupleReturn */ - declare function luaIter(): Iterable<[string, string]>; + interface Iter extends Iterable<[string, string]> {} + declare function luaIter(): Iter; let x: [string, string]; for (x of luaIter()) {}`; const compilerOptions = { @@ -694,14 +702,15 @@ export class LuaLoopTests const code = `const arr = ["a", "b", "c"]; /** @luaIterator */ - function luaIter(): Iterable { + interface Iter extends Iterable {} + function luaIter(): Iter { let i = 0; function iter() { return arr[i++]; } return iter as any; } - /** @luaIterator */ - function forward(): Iterable { - return luaIter(); + function forward() { + const iter = luaIter(); + return iter; } let result = ""; for (let a of forward()) { result += a; } @@ -721,16 +730,16 @@ export class LuaLoopTests `const arr = ["a", "b", "c"]; /** @luaIterator */ /** @tupleReturn */ - function luaIter(): Iterable<[string, string]> { + interface Iter extends Iterable<[string, string]> {} + function luaIter(): Iter { let i = 0; /** @tupleReturn */ function iter() { return arr[i] && [i.toString(), arr[i++]] || []; } return iter as any; } - /** @luaIterator */ - /** @tupleReturn */ - function forward(): Iterable<[string, string]> { - return luaIter(); + function forward() { + const iter = luaIter(); + return iter; } let result = ""; for (let [a, b] of forward()) { result += a + b; }