Skip to content

Commit 71fb85e

Browse files
authored
Fix methods with non-null operator not being detected as methods (#1280)
* Fix methods with non-null operator not being detected as methods * Fix other occurrences of PropertyAccessCall
1 parent da506ac commit 71fb85e

File tree

12 files changed

+149
-129
lines changed

12 files changed

+149
-129
lines changed

src/transformation/builtins/array.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import * as lua from "../../LuaAST";
33
import { TransformationContext } from "../context";
44
import { unsupportedProperty } from "../utils/diagnostics";
55
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
6-
import { PropertyCallExpression, transformArguments, transformCallAndArguments } from "../visitors/call";
6+
import { transformArguments, transformCallAndArguments } from "../visitors/call";
77
import { isStringType, isNumberType, findFirstNonOuterParent } from "../utils/typescript";
88
import { moveToPrecedingTemp } from "../visitors/expression-list";
99
import { isUnpackCall, wrapInTable } from "../utils/lua-ast";
1010

1111
export function transformArrayConstructorCall(
1212
context: TransformationContext,
13-
node: PropertyCallExpression
13+
node: ts.CallExpression,
14+
calledMethod: ts.PropertyAccessExpression
1415
): lua.Expression | undefined {
15-
const expression = node.expression;
1616
const signature = context.checker.getResolvedSignature(node);
1717
const params = transformArguments(context, node.arguments, signature);
1818

19-
const expressionName = expression.name.text;
19+
const expressionName = calledMethod.name.text;
2020
switch (expressionName) {
2121
case "from":
2222
return transformLuaLibFunction(context, LuaLibFeature.ArrayFrom, node, ...params);
@@ -25,7 +25,7 @@ export function transformArrayConstructorCall(
2525
case "of":
2626
return wrapInTable(...params);
2727
default:
28-
context.diagnostics.push(unsupportedProperty(expression.name, "Array", expressionName));
28+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "Array", expressionName));
2929
}
3030
}
3131

@@ -37,7 +37,7 @@ export function transformArrayConstructorCall(
3737
*/
3838
function transformSingleElementArrayPush(
3939
context: TransformationContext,
40-
node: PropertyCallExpression,
40+
node: ts.CallExpression,
4141
caller: lua.Expression,
4242
param: lua.Expression
4343
): lua.Expression {
@@ -68,13 +68,13 @@ function transformSingleElementArrayPush(
6868

6969
export function transformArrayPrototypeCall(
7070
context: TransformationContext,
71-
node: PropertyCallExpression
71+
node: ts.CallExpression,
72+
calledMethod: ts.PropertyAccessExpression
7273
): lua.Expression | undefined {
73-
const expression = node.expression;
7474
const signature = context.checker.getResolvedSignature(node);
75-
const [caller, params] = transformCallAndArguments(context, expression.expression, node.arguments, signature);
75+
const [caller, params] = transformCallAndArguments(context, calledMethod.expression, node.arguments, signature);
7676

77-
const expressionName = expression.name.text;
77+
const expressionName = calledMethod.name.text;
7878
switch (expressionName) {
7979
case "concat":
8080
return transformLuaLibFunction(context, LuaLibFeature.ArrayConcat, node, caller, ...params);
@@ -143,7 +143,7 @@ export function transformArrayPrototypeCall(
143143
case "splice":
144144
return transformLuaLibFunction(context, LuaLibFeature.ArraySplice, node, caller, ...params);
145145
case "join":
146-
const callerType = context.checker.getTypeAtLocation(expression.expression);
146+
const callerType = context.checker.getTypeAtLocation(calledMethod.expression);
147147
const elementType = context.checker.getElementTypeOfArrayType(callerType);
148148
if (elementType && (isStringType(context, elementType) || isNumberType(context, elementType))) {
149149
const defaultSeparatorLiteral = lua.createStringLiteral(",");
@@ -170,7 +170,7 @@ export function transformArrayPrototypeCall(
170170
case "flatMap":
171171
return transformLuaLibFunction(context, LuaLibFeature.ArrayFlatMap, node, caller, ...params);
172172
default:
173-
context.diagnostics.push(unsupportedProperty(expression.name, "array", expressionName));
173+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "array", expressionName));
174174
}
175175
}
176176

src/transformation/builtins/console.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@ import * as ts from "typescript";
22
import * as lua from "../../LuaAST";
33
import { TransformationContext } from "../context";
44
import { unsupportedProperty } from "../utils/diagnostics";
5-
import { PropertyCallExpression, transformArguments } from "../visitors/call";
5+
import { transformArguments } from "../visitors/call";
66

77
const isStringFormatTemplate = (node: ts.Expression) => ts.isStringLiteral(node) && node.text.includes("%");
88

99
export function transformConsoleCall(
1010
context: TransformationContext,
11-
expression: PropertyCallExpression
11+
node: ts.CallExpression,
12+
calledMethod: ts.PropertyAccessExpression
1213
): lua.Expression | undefined {
13-
const method = expression.expression;
14-
const methodName = method.name.text;
15-
const signature = context.checker.getResolvedSignature(expression);
16-
const parameters = transformArguments(context, expression.arguments, signature);
14+
const methodName = calledMethod.name.text;
15+
const signature = context.checker.getResolvedSignature(node);
16+
const parameters = transformArguments(context, node.arguments, signature);
1717

1818
switch (methodName) {
1919
case "error":
2020
case "info":
2121
case "log":
2222
case "warn":
23-
if (expression.arguments.length > 0 && isStringFormatTemplate(expression.arguments[0])) {
23+
if (node.arguments.length > 0 && isStringFormatTemplate(node.arguments[0])) {
2424
// print(string.format([arguments]))
2525
const stringFormatCall = lua.createCallExpression(
2626
lua.createTableIndexExpression(lua.createIdentifier("string"), lua.createStringLiteral("format")),
@@ -31,7 +31,7 @@ export function transformConsoleCall(
3131
// print([arguments])
3232
return lua.createCallExpression(lua.createIdentifier("print"), parameters);
3333
case "assert":
34-
if (expression.arguments.length > 1 && isStringFormatTemplate(expression.arguments[1])) {
34+
if (node.arguments.length > 1 && isStringFormatTemplate(node.arguments[1])) {
3535
// assert([condition], string.format([arguments]))
3636
const stringFormatCall = lua.createCallExpression(
3737
lua.createTableIndexExpression(lua.createIdentifier("string"), lua.createStringLiteral("format")),
@@ -42,7 +42,7 @@ export function transformConsoleCall(
4242
// assert()
4343
return lua.createCallExpression(lua.createIdentifier("assert"), parameters);
4444
case "trace":
45-
if (expression.arguments.length > 0 && isStringFormatTemplate(expression.arguments[0])) {
45+
if (node.arguments.length > 0 && isStringFormatTemplate(node.arguments[0])) {
4646
// print(debug.traceback(string.format([arguments])))
4747
const stringFormatCall = lua.createCallExpression(
4848
lua.createTableIndexExpression(lua.createIdentifier("string"), lua.createStringLiteral("format")),
@@ -61,6 +61,6 @@ export function transformConsoleCall(
6161
);
6262
return lua.createCallExpression(lua.createIdentifier("print"), [debugTracebackCall]);
6363
default:
64-
context.diagnostics.push(unsupportedProperty(method.name, "console", methodName));
64+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "console", methodName));
6565
}
6666
}

src/transformation/builtins/function.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ import { unsupportedForTarget, unsupportedProperty, unsupportedSelfFunctionConve
66
import { ContextType, getFunctionContextType } from "../utils/function-context";
77
import { createUnpackCall } from "../utils/lua-ast";
88
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
9-
import { PropertyCallExpression, transformCallAndArguments } from "../visitors/call";
9+
import { transformCallAndArguments } from "../visitors/call";
1010

1111
export function transformFunctionPrototypeCall(
1212
context: TransformationContext,
13-
node: PropertyCallExpression
13+
node: ts.CallExpression,
14+
calledMethod: ts.PropertyAccessExpression
1415
): lua.CallExpression | undefined {
15-
const expression = node.expression;
16-
const callerType = context.checker.getTypeAtLocation(expression.expression);
16+
const callerType = context.checker.getTypeAtLocation(calledMethod.expression);
1717
if (getFunctionContextType(context, callerType) === ContextType.Void) {
1818
context.diagnostics.push(unsupportedSelfFunctionConversion(node));
1919
}
2020

2121
const signature = context.checker.getResolvedSignature(node);
22-
const [caller, params] = transformCallAndArguments(context, expression.expression, node.arguments, signature);
23-
const expressionName = expression.name.text;
22+
const [caller, params] = transformCallAndArguments(context, calledMethod.expression, node.arguments, signature);
23+
const expressionName = calledMethod.name.text;
2424
switch (expressionName) {
2525
case "apply":
2626
const nonContextArgs = params.length > 1 ? [createUnpackCall(context, params[1], node.arguments[1])] : [];
@@ -30,7 +30,7 @@ export function transformFunctionPrototypeCall(
3030
case "call":
3131
return lua.createCallExpression(caller, params, node);
3232
case "toString":
33-
context.diagnostics.push(unsupportedProperty(expression.name, "function", expressionName));
33+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "function", expressionName));
3434
}
3535
}
3636

src/transformation/builtins/index.ts

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as ts from "typescript";
22
import * as lua from "../../LuaAST";
3-
import { assume } from "../../utils";
43
import { TransformationContext } from "../context";
54
import { createNaN } from "../utils/lua-ast";
65
import { importLuaLibFeature, LuaLibFeature } from "../utils/lualib";
@@ -14,7 +13,7 @@ import {
1413
isStandardLibraryType,
1514
isStringType,
1615
} from "../utils/typescript";
17-
import { PropertyCallExpression } from "../visitors/call";
16+
import { getCalledExpression } from "../visitors/call";
1817
import { transformArrayConstructorCall, transformArrayProperty, transformArrayPrototypeCall } from "./array";
1918
import { transformConsoleCall } from "./console";
2019
import { transformFunctionPrototypeCall, transformFunctionProperty } from "./function";
@@ -74,79 +73,78 @@ export function transformBuiltinCallExpression(
7473
}
7574
}
7675

77-
const expression = ts.getOriginalNode(node.expression);
78-
if (!ts.isPropertyAccessExpression(expression)) {
76+
const calledMethod = ts.getOriginalNode(getCalledExpression(node));
77+
if (!ts.isPropertyAccessExpression(calledMethod)) {
7978
return;
8079
}
8180

82-
const isOptionalAccess = expression.questionDotToken;
83-
assume<PropertyCallExpression>(node);
81+
const isOptionalAccess = calledMethod.questionDotToken;
8482
// If the function being called is of type owner.func, get the type of owner
85-
const ownerType = context.checker.getTypeAtLocation(expression.expression);
83+
const ownerType = context.checker.getTypeAtLocation(calledMethod.expression);
8684

8785
if (isStandardLibraryType(context, ownerType, undefined)) {
8886
const symbol = ownerType.getSymbol();
8987
switch (symbol?.name) {
9088
case "ArrayConstructor":
9189
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
92-
return transformArrayConstructorCall(context, node);
90+
return transformArrayConstructorCall(context, node, calledMethod);
9391
case "Console":
9492
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
95-
return transformConsoleCall(context, node);
93+
return transformConsoleCall(context, node, calledMethod);
9694
case "Math":
9795
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
98-
return transformMathCall(context, node);
96+
return transformMathCall(context, node, calledMethod);
9997
case "StringConstructor":
10098
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
101-
return transformStringConstructorCall(context, node);
99+
return transformStringConstructorCall(context, node, calledMethod);
102100
case "ObjectConstructor":
103101
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
104-
return transformObjectConstructorCall(context, node);
102+
return transformObjectConstructorCall(context, node, calledMethod);
105103
case "SymbolConstructor":
106104
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
107-
return transformSymbolConstructorCall(context, node);
105+
return transformSymbolConstructorCall(context, node, calledMethod);
108106
case "NumberConstructor":
109107
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
110-
return transformNumberConstructorCall(context, node);
108+
return transformNumberConstructorCall(context, node, calledMethod);
111109
case "PromiseConstructor":
112110
if (isOptionalCall || isOptionalAccess) return unsupportedOptionalCall();
113-
return transformPromiseConstructorCall(context, node);
111+
return transformPromiseConstructorCall(context, node, calledMethod);
114112
}
115113
}
116114

117115
const isStringFunction =
118116
isStringType(context, ownerType) ||
119-
(expression.questionDotToken && isNullableType(context, ownerType, isStringType));
117+
(calledMethod.questionDotToken && isNullableType(context, ownerType, isStringType));
120118
if (isStringFunction && hasStandardLibrarySignature(context, node)) {
121119
if (isOptionalCall) return unsupportedOptionalCall();
122-
return transformStringPrototypeCall(context, node);
120+
return transformStringPrototypeCall(context, node, calledMethod);
123121
}
124122

125123
const isNumberFunction =
126124
isNumberType(context, ownerType) ||
127-
(expression.questionDotToken && isNullableType(context, ownerType, isNumberType));
125+
(calledMethod.questionDotToken && isNullableType(context, ownerType, isNumberType));
128126
if (isNumberFunction && hasStandardLibrarySignature(context, node)) {
129127
if (isOptionalCall) return unsupportedOptionalCall();
130-
return transformNumberPrototypeCall(context, node);
128+
return transformNumberPrototypeCall(context, node, calledMethod);
131129
}
132130

133131
const isArrayFunction =
134132
isArrayType(context, ownerType) ||
135-
(expression.questionDotToken && isNullableType(context, ownerType, isArrayType));
133+
(calledMethod.questionDotToken && isNullableType(context, ownerType, isArrayType));
136134
if (isArrayFunction && hasStandardLibrarySignature(context, node)) {
137135
if (isOptionalCall) return unsupportedOptionalCall();
138-
return transformArrayPrototypeCall(context, node);
136+
return transformArrayPrototypeCall(context, node, calledMethod);
139137
}
140138

141139
const isFunctionFunction =
142140
isFunctionType(ownerType) ||
143-
(expression.questionDotToken && isNullableType(context, ownerType, (_, t) => isFunctionType(t)));
141+
(calledMethod.questionDotToken && isNullableType(context, ownerType, (_, t) => isFunctionType(t)));
144142
if (isFunctionFunction && hasStandardLibrarySignature(context, node)) {
145143
if (isOptionalCall) return unsupportedOptionalCall();
146-
return transformFunctionPrototypeCall(context, node);
144+
return transformFunctionPrototypeCall(context, node, calledMethod);
147145
}
148146

149-
const objectResult = transformObjectPrototypeCall(context, node, expression);
147+
const objectResult = transformObjectPrototypeCall(context, node, calledMethod);
150148
if (objectResult) {
151149
if (isOptionalCall) return unsupportedOptionalCall();
152150
return objectResult;

src/transformation/builtins/math.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as lua from "../../LuaAST";
44
import { TransformationContext } from "../context";
55
import { unsupportedProperty } from "../utils/diagnostics";
66
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
7-
import { PropertyCallExpression, transformArguments } from "../visitors/call";
7+
import { transformArguments } from "../visitors/call";
88

99
export function transformMathProperty(
1010
context: TransformationContext,
@@ -33,14 +33,14 @@ export function transformMathProperty(
3333

3434
export function transformMathCall(
3535
context: TransformationContext,
36-
node: PropertyCallExpression
36+
node: ts.CallExpression,
37+
calledMethod: ts.PropertyAccessExpression
3738
): lua.Expression | undefined {
38-
const expression = node.expression;
3939
const signature = context.checker.getResolvedSignature(node);
4040
const params = transformArguments(context, node.arguments, signature);
4141
const math = lua.createIdentifier("math");
4242

43-
const expressionName = expression.name.text;
43+
const expressionName = calledMethod.name.text;
4444
switch (expressionName) {
4545
// Lua 5.3: math.atan(y, x)
4646
// Otherwise: math.atan2(y, x)
@@ -107,6 +107,6 @@ export function transformMathCall(
107107
}
108108

109109
default:
110-
context.diagnostics.push(unsupportedProperty(expression.name, "Math", expressionName));
110+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "Math", expressionName));
111111
}
112112
}
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
1+
import ts = require("typescript");
12
import * as lua from "../../LuaAST";
23
import { TransformationContext } from "../context";
34
import { unsupportedProperty } from "../utils/diagnostics";
45
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
5-
import { PropertyCallExpression, transformArguments } from "../visitors/call";
6+
import { transformArguments } from "../visitors/call";
67

78
export function transformNumberPrototypeCall(
89
context: TransformationContext,
9-
node: PropertyCallExpression
10+
node: ts.CallExpression,
11+
calledMethod: ts.PropertyAccessExpression
1012
): lua.Expression | undefined {
11-
const expression = node.expression;
1213
const signature = context.checker.getResolvedSignature(node);
1314
const params = transformArguments(context, node.arguments, signature);
14-
const caller = context.transformExpression(expression.expression);
15+
const caller = context.transformExpression(calledMethod.expression);
1516

16-
const expressionName = expression.name.text;
17+
const expressionName = calledMethod.name.text;
1718
switch (expressionName) {
1819
case "toString":
1920
return params.length === 0
2021
? lua.createCallExpression(lua.createIdentifier("tostring"), [caller], node)
2122
: transformLuaLibFunction(context, LuaLibFeature.NumberToString, node, caller, ...params);
2223
default:
23-
context.diagnostics.push(unsupportedProperty(expression.name, "number", expressionName));
24+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "number", expressionName));
2425
}
2526
}
2627

2728
export function transformNumberConstructorCall(
2829
context: TransformationContext,
29-
expression: PropertyCallExpression
30+
node: ts.CallExpression,
31+
calledMethod: ts.PropertyAccessExpression
3032
): lua.CallExpression | undefined {
31-
const method = expression.expression;
32-
const parameters = transformArguments(context, expression.arguments);
33-
const methodName = method.name.text;
33+
const parameters = transformArguments(context, node.arguments);
34+
const methodName = calledMethod.name.text;
3435
switch (methodName) {
3536
case "isNaN":
36-
return transformLuaLibFunction(context, LuaLibFeature.NumberIsNaN, expression, ...parameters);
37+
return transformLuaLibFunction(context, LuaLibFeature.NumberIsNaN, node, ...parameters);
3738
case "isFinite":
38-
return transformLuaLibFunction(context, LuaLibFeature.NumberIsFinite, expression, ...parameters);
39+
return transformLuaLibFunction(context, LuaLibFeature.NumberIsFinite, node, ...parameters);
3940
default:
40-
context.diagnostics.push(unsupportedProperty(method.name, "Number", methodName));
41+
context.diagnostics.push(unsupportedProperty(calledMethod.name, "Number", methodName));
4142
}
4243
}

0 commit comments

Comments
 (0)