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
16 changes: 14 additions & 2 deletions src/LuaTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1882,16 +1882,28 @@ export class LuaTransformer {
tstl.isIdentifier)
: tstl.createAnonymousIdentifier(statement.name);

// Don't unpack TupleReturn decorated functions
if (statement.initializer) {
if (tsHelper.isTupleReturnCall(statement.initializer, this.checker)) {
// Don't unpack TupleReturn decorated functions
statements.push(
...this.createLocalOrExportedOrGlobalDeclaration(
vars,
this.transformExpression(statement.initializer),
statement
)
);
} else if (ts.isArrayLiteralExpression(statement.initializer)) {
// Don't unpack array literals
const values = statement.initializer.elements.length > 0
? statement.initializer.elements.map(e => this.transformExpression(e))
: tstl.createNilLiteral();
statements.push(
...this.createLocalOrExportedOrGlobalDeclaration(
vars,
values,
statement
)
);
} else {
// local vars = this.transpileDestructingAssignmentValue(node.initializer);
const initializer = this.createUnpackCall(
Expand Down Expand Up @@ -4873,7 +4885,7 @@ export class LuaTransformer {

protected createLocalOrExportedOrGlobalDeclaration(
lhs: tstl.Identifier | tstl.Identifier[],
rhs?: tstl.Expression,
rhs?: tstl.Expression | tstl.Expression[],
tsOriginal?: ts.Node,
parent?: tstl.Node
): tstl.Statement[]
Expand Down
22 changes: 20 additions & 2 deletions src/TSHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,18 @@ export class TSHelper {
public static isInTupleReturnFunction(node: ts.Node, checker: ts.TypeChecker): boolean {
const declaration = TSHelper.findFirstNodeAbove(node, ts.isFunctionLike);
if (declaration) {
let functionType: ts.Type;
let functionType: ts.Type | undefined;
if (ts.isFunctionExpression(declaration) || ts.isArrowFunction(declaration)) {
functionType = TSHelper.inferAssignedType(declaration, checker);
} else {
} else if (ts.isMethodDeclaration(declaration) && ts.isObjectLiteralExpression(declaration.parent)) {
// Manually lookup type for object literal properties declared with method syntax
const interfaceType = TSHelper.inferAssignedType(declaration.parent, checker);
const propertySymbol = interfaceType.getProperty(declaration.name.getText());
if (propertySymbol) {
functionType = checker.getTypeOfSymbolAtLocation(propertySymbol, declaration);
}
}
if (functionType === undefined) {
functionType = checker.getTypeAtLocation(declaration);
}

Expand Down Expand Up @@ -304,6 +312,16 @@ export class TSHelper {
{
const directivesMap = new Map<DecoratorKind, Decorator>();
TSHelper.collectCustomDecorators(signature, checker, directivesMap);

// Function properties on interfaces have the JSDoc tags on the parent PropertySignature
const declaration = signature.getDeclaration();
if (declaration && declaration.parent && ts.isPropertySignature(declaration.parent)) {
const symbol = checker.getSymbolAtLocation(declaration.parent.name);
if (symbol) {
TSHelper.collectCustomDecorators(symbol, checker, directivesMap);
}
}

return directivesMap;
}

Expand Down
171 changes: 151 additions & 20 deletions test/unit/tuples.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,30 @@ test("Tuple Destruct", () => {
expect(result).toBe(5);
});

test("Tuple Destruct Array Literal", () => {
const code = `
const [a,b,c] = [3,5,1];
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Destruct Array Literal Extra Values", () => {
const code = `
let result = "";
const set = () => { result = "bar"; };
const [a] = ["foo", set()];
return a + result;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe("foobar");
});

test("Tuple length", () => {
const result = util.transpileAndExecute(
`const tuple: [number, number, number] = [3,5,1];
Expand All @@ -74,62 +98,169 @@ test("Tuple length", () => {
});

test("Tuple Return Access", () => {
const result = util.transpileAndExecute(
`/** @tupleReturn */
const code = `
/** @tupleReturn */
function tuple(): [number, number, number] { return [3,5,1]; }
return tuple()[2];`,
);
return tuple()[2];`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(1);
});

test("Tuple Return Destruct Declaration", () => {
const result = util.transpileAndExecute(
`/** @tupleReturn */
const code = `
/** @tupleReturn */
function tuple(): [number, number, number] { return [3,5,1]; }
const [a,b,c] = tuple();
return b;`,
);
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Return Destruct Assignment", () => {
const result = util.transpileAndExecute(
`/** @tupleReturn */
const code = `
/** @tupleReturn */
function tuple(): [number, number] { return [3,6]; }
let [a,b] = [1,2];
[b,a] = tuple();
return a - b;`,
);
return a - b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(3);
});

test("Tuple Static Method Return Destruct", () => {
const result = util.transpileAndExecute(
`class Test {
const code = `
class Test {
/** @tupleReturn */
static tuple(): [number, number, number] { return [3,5,1]; }
}
const [a,b,c] = Test.tuple();
return b;`,
);
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Static Function Property Return Destruct", () => {
const code = `
class Test {
/** @tupleReturn */
static tuple: () => [number, number, number] = () => [3,5,1];
}
const [a,b,c] = Test.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Non-Static Method Return Destruct", () => {
const result = util.transpileAndExecute(
`class Test {
const code = `
class Test {
/** @tupleReturn */
tuple(): [number, number, number] { return [3,5,1]; }
}
const t = new Test();
const [a,b,c] = t.tuple();
return b;`,
);
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Non-Static Function Property Return Destruct", () => {
const code = `
class Test {
/** @tupleReturn */
tuple: () => [number, number, number] = () => [3,5,1];
}
const t = new Test();
const [a,b,c] = t.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Interface Method Return Destruct", () => {
const code = `
interface Test {
/** @tupleReturn */
tuple(): [number, number, number];
}
const t: Test = {
tuple() { return [3,5,1]; }
};
const [a,b,c] = t.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Interface Function Property Return Destruct", () => {
const code = `
interface Test {
/** @tupleReturn */
tuple: () => [number, number, number];
}
const t: Test = {
tuple: () => [3,5,1]
};
const [a,b,c] = t.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Object Literal Method Return Destruct", () => {
const code = `
const t = {
/** @tupleReturn */
tuple() { return [3,5,1]; }
};
const [a,b,c] = t.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

test("Tuple Object Literal Function Property Return Destruct", () => {
const code = `
const t = {
/** @tupleReturn */
tuple: () => [3,5,1]
};
const [a,b,c] = t.tuple();
return b;`;

const lua = util.transpileString(code);
expect(lua).not.toContain("unpack");
const result = util.executeLua(lua);
expect(result).toBe(5);
});

Expand Down