Skip to content

Commit 5fab147

Browse files
authored
Fix call language extensions diagnostic trying to use them incorrectly (#1334)
* Fix broken diagnostic when trying to directly use call extensions * prettier * Update snapshot * prettier
1 parent 61d0738 commit 5fab147

File tree

5 files changed

+98
-3
lines changed

5 files changed

+98
-3
lines changed

src/transformation/visitors/access.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ import * as lua from "../../LuaAST";
33
import { transformBuiltinPropertyAccessExpression } from "../builtins";
44
import { FunctionVisitor, TransformationContext } from "../context";
55
import { AnnotationKind, getTypeAnnotations } from "../utils/annotations";
6-
import { invalidMultiReturnAccess, unsupportedOptionalCompileMembersOnly } from "../utils/diagnostics";
6+
import {
7+
invalidCallExtensionUse,
8+
invalidMultiReturnAccess,
9+
unsupportedOptionalCompileMembersOnly,
10+
} from "../utils/diagnostics";
11+
import { getExtensionKindForNode } from "../utils/language-extensions";
712
import { addToNumericExpression } from "../utils/lua-ast";
813
import { LuaLibFeature, transformLuaLibFunction } from "../utils/lualib";
914
import { isArrayType, isNumberType, isStringType } from "../utils/typescript";
1015
import { tryGetConstEnumValue } from "./enum";
1116
import { transformOrderedExpressions } from "./expression-list";
17+
import { callExtensions } from "./language-extensions/call-extension";
1218
import { isMultiReturnCall, returnsMultiType } from "./language-extensions/multi";
1319
import {
1420
transformOptionalChainWithCapture,
@@ -143,6 +149,18 @@ export function transformPropertyAccessExpressionWithCapture(
143149
return { expression: builtinResult };
144150
}
145151

152+
if (
153+
ts.isIdentifier(node.expression) &&
154+
node.parent &&
155+
(!ts.isCallExpression(node.parent) || node.parent.expression !== node)
156+
) {
157+
// Check if this is a method call extension that is not used as a call
158+
const extensionType = getExtensionKindForNode(context, node);
159+
if (extensionType && callExtensions.has(extensionType)) {
160+
context.diagnostics.push(invalidCallExtensionUse(node));
161+
}
162+
}
163+
146164
const table = context.transformExpression(node.expression);
147165

148166
if (thisValueCapture) {

src/transformation/visitors/identifier.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ function transformNonValueIdentifier(
3131

3232
if (extensionKind) {
3333
if (callExtensions.has(extensionKind)) {
34-
context.diagnostics.push(invalidCallExtensionUse(identifier));
34+
// Avoid putting duplicate diagnostic on the name of a variable declaration, due to the inferred type
35+
if (!(ts.isVariableDeclaration(identifier.parent) && identifier.parent.name === identifier)) {
36+
context.diagnostics.push(invalidCallExtensionUse(identifier));
37+
}
3538
// fall through
3639
} else if (isIdentifierExtensionValue(symbol, extensionKind)) {
3740
reportInvalidExtensionValue(context, identifier, extensionKind);

test/setup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ expect.extend({
3737
const message = this.isNot
3838
? diagnosticMessages
3939
: expected
40-
? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnostics.map(diag => diag.code).join("\n")}\n`
40+
? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnostics
41+
.map(diag => diag.code)
42+
.join("\n")}\n\n${diagnosticMessages}\n`
4143
: `Received: ${this.utils.printReceived([])}\n`;
4244

4345
return matcherHint + "\n\n" + message;

test/unit/language-extensions/__snapshots__/table.spec.ts.snap

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,51 @@ exports[`LuaTableHas extension invalid use ("const foo: unknown = tableHas;"): d
8585
exports[`LuaTableHas extension invalid use ("declare function foo(tableHas: LuaTableHas<{}, string>): void; foo(tableHas);"): code 1`] = `"foo(_G, tableHas)"`;
8686

8787
exports[`LuaTableHas extension invalid use ("declare function foo(tableHas: LuaTableHas<{}, string>): void; foo(tableHas);"): diagnostics 1`] = `"main.ts(3,80): error TSTL: This function must be called directly and cannot be referred to."`;
88+
89+
exports[`LuaTableHas extension invalid use method assignment ("LuaMap<string, number>"): code 1`] = `
90+
"____table = {}
91+
has = ____table.has"
92+
`;
93+
94+
exports[`LuaTableHas extension invalid use method assignment ("LuaMap<string, number>"): diagnostics 1`] = `"main.ts(3,29): error TSTL: This function must be called directly and cannot be referred to."`;
95+
96+
exports[`LuaTableHas extension invalid use method assignment ("LuaSet<string>"): code 1`] = `
97+
"____table = {}
98+
has = ____table.has"
99+
`;
100+
101+
exports[`LuaTableHas extension invalid use method assignment ("LuaSet<string>"): diagnostics 1`] = `"main.ts(3,29): error TSTL: This function must be called directly and cannot be referred to."`;
102+
103+
exports[`LuaTableHas extension invalid use method assignment ("LuaTable<string, number>"): code 1`] = `
104+
"____table = {}
105+
has = ____table.has"
106+
`;
107+
108+
exports[`LuaTableHas extension invalid use method assignment ("LuaTable<string, number>"): diagnostics 1`] = `"main.ts(3,29): error TSTL: This function must be called directly and cannot be referred to."`;
109+
110+
exports[`LuaTableHas extension invalid use method expression ("LuaMap<string, number>"): code 1`] = `
111+
"local ____lualib = require(\\"lualib_bundle\\")
112+
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
113+
____table = {}
114+
__TS__ArrayMap({\\"a\\", \\"b\\", \\"c\\"}, ____table.has)"
115+
`;
116+
117+
exports[`LuaTableHas extension invalid use method expression ("LuaMap<string, number>"): diagnostics 1`] = `"main.ts(3,37): error TSTL: This function must be called directly and cannot be referred to."`;
118+
119+
exports[`LuaTableHas extension invalid use method expression ("LuaSet<string>"): code 1`] = `
120+
"local ____lualib = require(\\"lualib_bundle\\")
121+
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
122+
____table = {}
123+
__TS__ArrayMap({\\"a\\", \\"b\\", \\"c\\"}, ____table.has)"
124+
`;
125+
126+
exports[`LuaTableHas extension invalid use method expression ("LuaSet<string>"): diagnostics 1`] = `"main.ts(3,37): error TSTL: This function must be called directly and cannot be referred to."`;
127+
128+
exports[`LuaTableHas extension invalid use method expression ("LuaTable<string, number>"): code 1`] = `
129+
"local ____lualib = require(\\"lualib_bundle\\")
130+
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
131+
____table = {}
132+
__TS__ArrayMap({\\"a\\", \\"b\\", \\"c\\"}, ____table.has)"
133+
`;
134+
135+
exports[`LuaTableHas extension invalid use method expression ("LuaTable<string, number>"): diagnostics 1`] = `"main.ts(3,37): error TSTL: This function must be called directly and cannot be referred to."`;

test/unit/language-extensions/table.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,30 @@ describe("LuaTableHas extension", () => {
170170
.withLanguageExtensions()
171171
.expectDiagnosticsToMatchSnapshot([invalidCallExtensionUse.code]);
172172
});
173+
174+
test.each(["LuaTable<string, number>", "LuaMap<string, number>", "LuaSet<string>"])(
175+
"invalid use method assignment (%p)",
176+
type => {
177+
util.testModule`
178+
const table = new ${type}();
179+
const has = table.has;
180+
`
181+
.withLanguageExtensions()
182+
.expectDiagnosticsToMatchSnapshot([invalidCallExtensionUse.code]);
183+
}
184+
);
185+
186+
test.each(["LuaTable<string, number>", "LuaMap<string, number>", "LuaSet<string>"])(
187+
"invalid use method expression (%p)",
188+
type => {
189+
util.testModule`
190+
const table = new ${type}();
191+
["a", "b", "c"].map(table.has);
192+
`
193+
.withLanguageExtensions()
194+
.expectDiagnosticsToMatchSnapshot([invalidCallExtensionUse.code]);
195+
}
196+
);
173197
});
174198

175199
describe("LuaTableDelete extension", () => {

0 commit comments

Comments
 (0)