Skip to content

Commit b8b406b

Browse files
CopilotDaanV2
andcommitted
Add type validation for variable molang parameters
Co-authored-by: DaanV2 <[email protected]>
1 parent 58cf113 commit b8b406b

File tree

4 files changed

+205
-22
lines changed

4 files changed

+205
-22
lines changed

packages/bedrock-diagnoser/src/diagnostics/molang/expressions.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
FunctionCallNode,
66
MolangData,
77
MolangFunction,
8+
MolangParameter,
89
MolangSet,
910
MolangSyntaxError,
1011
NodeType,
@@ -233,6 +234,34 @@ export function diagnose_molang_function(fn: FunctionCallNode, diagnoser: Diagno
233234
'molang.function.arguments',
234235
);
235236
}
237+
238+
// Validate parameter types
239+
for (let i = 0; i < fn.arguments.length; i++) {
240+
const arg = fn.arguments[i];
241+
let expectedParam: MolangParameter | undefined;
242+
243+
// Determine which parameter definition to use
244+
if (i < fnData.parameters.length) {
245+
// Use the fixed parameter definition
246+
expectedParam = fnData.parameters[i];
247+
} else if (fnData.repeatableParam) {
248+
// Use the repeatable parameter definition for additional args
249+
expectedParam = fnData.repeatableParam;
250+
}
251+
252+
// Validate type if specified
253+
if (expectedParam?.type) {
254+
const actualType = getArgumentType(arg);
255+
if (actualType && actualType !== expectedParam.type) {
256+
diagnoser.add(
257+
OffsetWord.create(`${fn.scope}.${fn.names.join('.')}`, fn.position),
258+
`wrong argument type at position ${i + 1}, expected ${expectedParam.type} but got ${actualType}`,
259+
DiagnosticSeverity.error,
260+
'molang.function.arguments.type',
261+
);
262+
}
263+
}
264+
}
236265
} else {
237266
// Check for exact parameter count
238267
if (fnData.parameters.length != fn.arguments.length) {
@@ -242,7 +271,45 @@ export function diagnose_molang_function(fn: FunctionCallNode, diagnoser: Diagno
242271
DiagnosticSeverity.error,
243272
'molang.function.arguments',
244273
);
274+
} else {
275+
// Validate parameter types for exact match case
276+
for (let i = 0; i < fn.arguments.length; i++) {
277+
const arg = fn.arguments[i];
278+
const expectedParam = fnData.parameters[i];
279+
280+
if (expectedParam?.type) {
281+
const actualType = getArgumentType(arg);
282+
if (actualType && actualType !== expectedParam.type) {
283+
diagnoser.add(
284+
OffsetWord.create(`${fn.scope}.${fn.names.join('.')}`, fn.position),
285+
`wrong argument type at position ${i + 1}, expected ${expectedParam.type} but got ${actualType}`,
286+
DiagnosticSeverity.error,
287+
'molang.function.arguments.type',
288+
);
289+
}
290+
}
291+
}
245292
}
246293
}
247294
}
248295
}
296+
297+
/**
298+
* Helper function to determine the type of an argument node
299+
*/
300+
function getArgumentType(arg: ExpressionNode): 'string' | 'float' | 'boolean' | undefined {
301+
switch (arg.type) {
302+
case NodeType.StringLiteral:
303+
return 'string';
304+
case NodeType.Literal:
305+
// Check if it's a boolean literal (true/false) or numeric
306+
const value = (arg as any).value?.toLowerCase();
307+
if (value === 'true' || value === 'false') {
308+
return 'boolean';
309+
}
310+
return 'float';
311+
default:
312+
// For complex expressions, we can't determine the type statically
313+
return undefined;
314+
}
315+
}

packages/bedrock-diagnoser/test/lib/diagnostics/molang/syntax.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,18 @@ describe("Molang Syntax", () => {
9393
name: "Variable parameters: block_has_all_tags with 3 args (needs at least 4)",
9494
data: "q.block_has_all_tags(0, 0, 0)",
9595
},
96+
{
97+
name: "Type validation: block_has_all_tags with wrong type for tag (number instead of string)",
98+
data: "q.block_has_all_tags(0, 0, 0, 2, 1)",
99+
},
100+
{
101+
name: "Type validation: equipped_item_all_tags with wrong type for tag (number instead of string)",
102+
data: "q.equipped_item_all_tags('slot.weapon.mainhand', 123)",
103+
},
104+
{
105+
name: "Type validation: is_name_any with wrong type (number instead of string)",
106+
data: "q.is_name_any(123)",
107+
},
96108
];
97109

98110
for (const test of error_tests) {

0 commit comments

Comments
 (0)