Skip to content

Commit bbb4813

Browse files
authored
Changed @luaIterator so that it must be applied to the iterator type, not the generator function. (#448)
1 parent f7e95b9 commit bbb4813

File tree

3 files changed

+35
-42
lines changed

3 files changed

+35
-42
lines changed

src/LuaTransformer.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,10 +1792,7 @@ export class LuaTransformer {
17921792
// If return expression is an array literal, leave out brackets.
17931793
return tstl.createReturnStatement(statement.expression.elements
17941794
.map(elem => this.transformExpression(elem)));
1795-
} else if (
1796-
!tsHelper.isTupleReturnCall(statement.expression, this.checker)
1797-
&& !tsHelper.isInLuaIteratorFunction(statement, this.checker))
1798-
{
1795+
} else if (!tsHelper.isTupleReturnCall(statement.expression, this.checker)) {
17991796
// If return expression is not another TupleReturn call, unpack it
18001797
const expression = this.createUnpackCall(
18011798
this.transformExpression(statement.expression),
@@ -1971,7 +1968,9 @@ export class LuaTransformer {
19711968

19721969
public transformForOfLuaIteratorStatement(statement: ts.ForOfStatement, block: tstl.Block): StatementVisitResult {
19731970
const luaIterator = this.transformExpression(statement.expression);
1974-
if (tsHelper.isTupleReturnCall(statement.expression, this.checker)) {
1971+
const type = this.checker.getTypeAtLocation(statement.expression);
1972+
const tupleReturn = tsHelper.getCustomDecorators(type, this.checker).has(DecoratorKind.TupleReturn);
1973+
if (tupleReturn) {
19751974
// LuaIterator + TupleReturn
19761975
if (ts.isVariableDeclarationList(statement.initializer)) {
19771976
// Variables declared in for loop
@@ -2073,7 +2072,7 @@ export class LuaTransformer {
20732072
// Arrays
20742073
return this.transformForOfArrayStatement(statement, body);
20752074

2076-
} else if (tsHelper.isLuaIteratorCall(statement.expression, this.checker)) {
2075+
} else if (tsHelper.isLuaIteratorType(statement.expression, this.checker)) {
20772076
// LuaIterators
20782077
return this.transformForOfLuaIteratorStatement(statement, body);
20792078

@@ -3056,15 +3055,14 @@ export class LuaTransformer {
30563055
// Check for calls on primitives to override
30573056
let parameters: tstl.Expression[] = [];
30583057

3059-
const isLuaIterator = tsHelper.isLuaIteratorCall(node, this.checker);
30603058
const isTupleReturn = tsHelper.isTupleReturnCall(node, this.checker);
30613059
const isTupleReturnForward =
30623060
node.parent && ts.isReturnStatement(node.parent) && tsHelper.isInTupleReturnFunction(node, this.checker);
30633061
const isInDestructingAssignment = tsHelper.isInDestructingAssignment(node);
30643062
const isInSpread = node.parent && ts.isSpreadElement(node.parent);
30653063
const returnValueIsUsed = node.parent && !ts.isExpressionStatement(node.parent);
30663064
const wrapResult = isTupleReturn && !isTupleReturnForward && !isInDestructingAssignment
3067-
&& !isInSpread && returnValueIsUsed && !isLuaIterator;
3065+
&& !isInSpread && returnValueIsUsed;
30683066

30693067
if (ts.isPropertyAccessExpression(node.expression)) {
30703068
const result = this.transformPropertyCall(node);

src/TSHelper.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,9 @@ export class TSHelper {
165165
return TSHelper.forTypeOrAnySupertype(type, checker, t => TSHelper.isExplicitArrayType(t, checker));
166166
}
167167

168-
public static isLuaIteratorCall(node: ts.Node, checker: ts.TypeChecker): boolean {
169-
if (ts.isCallExpression(node) && node.parent && ts.isForOfStatement(node.parent)) {
170-
const type = checker.getTypeAtLocation(node.expression);
171-
return TSHelper.getCustomDecorators(type, checker).has(DecoratorKind.LuaIterator);
172-
} else {
173-
return false;
174-
}
168+
public static isLuaIteratorType(node: ts.Node, checker: ts.TypeChecker): boolean {
169+
const type = checker.getTypeAtLocation(node);
170+
return TSHelper.getCustomDecorators(type, checker).has(DecoratorKind.LuaIterator);
175171
}
176172

177173
public static isTupleReturnCall(node: ts.Node, checker: ts.TypeChecker): boolean {
@@ -200,16 +196,6 @@ export class TSHelper {
200196
}
201197
}
202198

203-
public static isInLuaIteratorFunction(node: ts.Node, checker: ts.TypeChecker): boolean {
204-
const declaration = TSHelper.findFirstNodeAbove(node, ts.isFunctionLike);
205-
if (declaration) {
206-
const decorators = TSHelper.getCustomDecorators(checker.getTypeAtLocation(declaration), checker);
207-
return decorators.has(DecoratorKind.LuaIterator);
208-
} else {
209-
return false;
210-
}
211-
}
212-
213199
public static getContainingFunctionReturnType(node: ts.Node, checker: ts.TypeChecker): ts.Type {
214200
const declaration = TSHelper.findFirstNodeAbove(node, ts.isFunctionLike);
215201
if (declaration) {

test/unit/loops.spec.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ export class LuaLoopTests
525525
public forofLuaIterator(): void {
526526
const code = `const arr = ["a", "b", "c"];
527527
/** @luaIterator */
528-
function luaIter(): Iterable<string> {
528+
interface Iter extends Iterable<string> {}
529+
function luaIter(): Iter {
529530
let i = 0;
530531
return (() => arr[i++]) as any;
531532
}
@@ -545,7 +546,8 @@ export class LuaLoopTests
545546
public forofLuaIteratorExistingVar(): void {
546547
const code = `const arr = ["a", "b", "c"];
547548
/** @luaIterator */
548-
function luaIter(): Iterable<string> {
549+
interface Iter extends Iterable<string> {}
550+
function luaIter(): Iter {
549551
let i = 0;
550552
return (() => arr[i++]) as any;
551553
}
@@ -566,7 +568,8 @@ export class LuaLoopTests
566568
public forofLuaIteratorDestructuring(): void {
567569
const code = `const arr = ["a", "b", "c"];
568570
/** @luaIterator */
569-
function luaIter(): Iterable<[string, string]> {
571+
interface Iter extends Iterable<[string, string]> {}
572+
function luaIter(): Iter {
570573
let i = 0;
571574
return (() => arr[i] && [i.toString(), arr[i++]]) as any;
572575
}
@@ -586,7 +589,8 @@ export class LuaLoopTests
586589
public forofLuaIteratorDestructuringExistingVar(): void {
587590
const code = `const arr = ["a", "b", "c"];
588591
/** @luaIterator */
589-
function luaIter(): Iterable<[string, string]> {
592+
interface Iter extends Iterable<[string, string]> {}
593+
function luaIter(): Iter {
590594
let i = 0;
591595
return (() => arr[i] && [i.toString(), arr[i++]]) as any;
592596
}
@@ -609,7 +613,8 @@ export class LuaLoopTests
609613
const code = `const arr = ["a", "b", "c"];
610614
/** @luaIterator */
611615
/** @tupleReturn */
612-
function luaIter(): Iterable<[string, string]> {
616+
interface Iter extends Iterable<[string, string]> {}
617+
function luaIter(): Iter {
613618
let i = 0;
614619
/** @tupleReturn */
615620
function iter() { return arr[i] && [i.toString(), arr[i++]] || []; }
@@ -632,7 +637,8 @@ export class LuaLoopTests
632637
const code = `const arr = ["a", "b", "c"];
633638
/** @luaIterator */
634639
/** @tupleReturn */
635-
function luaIter(): Iterable<[string, string]> {
640+
interface Iter extends Iterable<[string, string]> {}
641+
function luaIter(): Iter {
636642
let i = 0;
637643
/** @tupleReturn */
638644
function iter() { return arr[i] && [i.toString(), arr[i++]] || []; }
@@ -656,7 +662,8 @@ export class LuaLoopTests
656662
public forofLuaIteratorTupleReturnSingleVar(): void {
657663
const code = `/** @luaIterator */
658664
/** @tupleReturn */
659-
declare function luaIter(): Iterable<[string, string]>;
665+
interface Iter extends Iterable<[string, string]> {}
666+
declare function luaIter(): Iter;
660667
for (let x of luaIter()) {}`;
661668
const compilerOptions = {
662669
luaLibImport: LuaLibImportKind.Require,
@@ -674,7 +681,8 @@ export class LuaLoopTests
674681
public forofLuaIteratorTupleReturnSingleExistingVar(): void {
675682
const code = `/** @luaIterator */
676683
/** @tupleReturn */
677-
declare function luaIter(): Iterable<[string, string]>;
684+
interface Iter extends Iterable<[string, string]> {}
685+
declare function luaIter(): Iter;
678686
let x: [string, string];
679687
for (x of luaIter()) {}`;
680688
const compilerOptions = {
@@ -694,14 +702,15 @@ export class LuaLoopTests
694702
const code =
695703
`const arr = ["a", "b", "c"];
696704
/** @luaIterator */
697-
function luaIter(): Iterable<string> {
705+
interface Iter extends Iterable<string> {}
706+
function luaIter(): Iter {
698707
let i = 0;
699708
function iter() { return arr[i++]; }
700709
return iter as any;
701710
}
702-
/** @luaIterator */
703-
function forward(): Iterable<string> {
704-
return luaIter();
711+
function forward() {
712+
const iter = luaIter();
713+
return iter;
705714
}
706715
let result = "";
707716
for (let a of forward()) { result += a; }
@@ -721,16 +730,16 @@ export class LuaLoopTests
721730
`const arr = ["a", "b", "c"];
722731
/** @luaIterator */
723732
/** @tupleReturn */
724-
function luaIter(): Iterable<[string, string]> {
733+
interface Iter extends Iterable<[string, string]> {}
734+
function luaIter(): Iter {
725735
let i = 0;
726736
/** @tupleReturn */
727737
function iter() { return arr[i] && [i.toString(), arr[i++]] || []; }
728738
return iter as any;
729739
}
730-
/** @luaIterator */
731-
/** @tupleReturn */
732-
function forward(): Iterable<[string, string]> {
733-
return luaIter();
740+
function forward() {
741+
const iter = luaIter();
742+
return iter;
734743
}
735744
let result = "";
736745
for (let [a, b] of forward()) { result += a + b; }

0 commit comments

Comments
 (0)