make compiler throw if a function call includes an unexpected parameter

This commit is contained in:
undergroundwires
2021-02-05 13:27:40 +01:00
parent f1e21babbf
commit 15353d0e25
2 changed files with 34 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ export class ScriptCompiler implements IScriptCompiler {
calls.forEach((currentCall, currentCallIndex) => { calls.forEach((currentCall, currentCallIndex) => {
ensureValidCall(currentCall, script.name); ensureValidCall(currentCall, script.name);
const commonFunction = this.getFunctionByName(currentCall.function); const commonFunction = this.getFunctionByName(currentCall.function);
ensureExpectedParameters(commonFunction, currentCall);
let functionCode = compileCode(commonFunction, currentCall.parameters); let functionCode = compileCode(commonFunction, currentCall.parameters);
if (currentCallIndex !== calls.length - 1) { if (currentCallIndex !== calls.length - 1) {
functionCode = appendLine(functionCode); functionCode = appendLine(functionCode);
@@ -57,6 +58,18 @@ export class ScriptCompiler implements IScriptCompiler {
} }
} }
function ensureExpectedParameters(func: FunctionData, call: FunctionCallData) {
if (!func.parameters && !call.parameters) {
return;
}
const unexpectedParameters = Object.keys(call.parameters || {})
.filter((callParam) => !func.parameters.includes(callParam));
if (unexpectedParameters.length) {
throw new Error(
`function "${func.name}" has unexpected parameter(s) provided: "${unexpectedParameters.join('", "')}"`);
}
}
function getDuplicates(texts: readonly string[]): string[] { function getDuplicates(texts: readonly string[]): string[] {
return texts.filter((item, index) => texts.indexOf(item) !== index); return texts.filter((item, index) => texts.indexOf(item) !== index);
} }

View File

@@ -206,6 +206,26 @@ describe('ScriptCompiler', () => {
expect(act).to.throw(expectedError); expect(act).to.throw(expectedError);
}); });
}); });
it('throws if provided parameters does not match given ones', () => {
// arrange
const unexpectedParameterName = 'unexpected-parameter-name';
const functionName = 'test-function-name';
const expectedError = `function "${functionName}" has unexpected parameter(s) provided: "${unexpectedParameterName}"`;
const sut = new ScriptCompilerBuilder()
.withFunctions(
new FunctionDataStub()
.withName(functionName)
.withParameters('another-parameter'))
.build();
const params: FunctionCallParametersData = {};
params[unexpectedParameterName] = 'unexpected-parameter-value';
const call: ScriptFunctionCallData = { function: functionName, parameters: params };
const script = ScriptDataStub.createWithCall(call);
// act
const act = () => sut.compile(script);
// assert
expect(act).to.throw(expectedError);
});
}); });
describe('builds code as expected', () => { describe('builds code as expected', () => {
it('creates code with expected syntax', () => { // test through script validation logic it('creates code with expected syntax', () => { // test through script validation logic
@@ -304,7 +324,7 @@ describe('ScriptCompiler', () => {
expect(actual).to.deep.equal(expected); expect(actual).to.deep.equal(expected);
}); });
}); });
it('throws when parameters is undefined', () => { it('throws when parameters are undefined', () => {
// arrange // arrange
const env = new TestEnvironment({ const env = new TestEnvironment({
code: '{{ $parameter }} {{ $parameter }}!', code: '{{ $parameter }} {{ $parameter }}!',