Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/LuaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -3056,15 +3055,14 @@ 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);
const isInDestructingAssignment = tsHelper.isInDestructingAssignment(node);
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);
Expand Down
20 changes: 3 additions & 17 deletions src/TSHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down
43 changes: 26 additions & 17 deletions test/unit/loops.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,8 @@ export class LuaLoopTests
public forofLuaIterator(): void {
const code = `const arr = ["a", "b", "c"];
/** @luaIterator */
function luaIter(): Iterable<string> {
interface Iter extends Iterable<string> {}
function luaIter(): Iter {
let i = 0;
return (() => arr[i++]) as any;
}
Expand All @@ -545,7 +546,8 @@ export class LuaLoopTests
public forofLuaIteratorExistingVar(): void {
const code = `const arr = ["a", "b", "c"];
/** @luaIterator */
function luaIter(): Iterable<string> {
interface Iter extends Iterable<string> {}
function luaIter(): Iter {
let i = 0;
return (() => arr[i++]) as any;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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++]] || []; }
Expand All @@ -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++]] || []; }
Expand All @@ -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,
Expand All @@ -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 = {
Expand All @@ -694,14 +702,15 @@ export class LuaLoopTests
const code =
`const arr = ["a", "b", "c"];
/** @luaIterator */
function luaIter(): Iterable<string> {
interface Iter extends Iterable<string> {}
function luaIter(): Iter {
let i = 0;
function iter() { return arr[i++]; }
return iter as any;
}
/** @luaIterator */
function forward(): Iterable<string> {
return luaIter();
function forward() {
const iter = luaIter();
return iter;
}
let result = "";
for (let a of forward()) { result += a; }
Expand All @@ -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; }
Expand Down