mirror of
https://github.com/google/blockly.git
synced 2025-12-16 06:10:12 +01:00
feat!: Throw errors on missing inputs (#7969)
Previously generators could generate code from inputs that didn't exist and get back the empty string. This silent failure was causing problems for diagnosing issues. This PR changes the behaviour so that an error is thrown. This will break generators which rely on the previous behaviour. Several of our demo blocks needed editing to accomodate this change. Resolves #7665
This commit is contained in:
@@ -313,6 +313,9 @@ export class CodeGenerator {
|
|||||||
throw TypeError('Expecting valid order from block: ' + block.type);
|
throw TypeError('Expecting valid order from block: ' + block.type);
|
||||||
}
|
}
|
||||||
const targetBlock = block.getInputTargetBlock(name);
|
const targetBlock = block.getInputTargetBlock(name);
|
||||||
|
if (!targetBlock && !block.getInput(name)) {
|
||||||
|
throw ReferenceError(`Input "${name}" doesn't exist on "${block.type}"`);
|
||||||
|
}
|
||||||
if (!targetBlock) {
|
if (!targetBlock) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -391,6 +394,9 @@ export class CodeGenerator {
|
|||||||
*/
|
*/
|
||||||
statementToCode(block: Block, name: string): string {
|
statementToCode(block: Block, name: string): string {
|
||||||
const targetBlock = block.getInputTargetBlock(name);
|
const targetBlock = block.getInputTargetBlock(name);
|
||||||
|
if (!targetBlock && !block.getInput(name)) {
|
||||||
|
throw ReferenceError(`Input "${name}" doesn't exist on "${block.type}"`);
|
||||||
|
}
|
||||||
let code = this.blockToCode(targetBlock);
|
let code = this.blockToCode(targetBlock);
|
||||||
// Value blocks must return code and order of operations info.
|
// Value blocks must return code and order of operations info.
|
||||||
// Statement blocks must only return code.
|
// Statement blocks must only return code.
|
||||||
|
|||||||
@@ -35,8 +35,17 @@ export function procedures_defreturn(block: Block, generator: DartGenerator) {
|
|||||||
generator.INDENT,
|
generator.INDENT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const branch = generator.statementToCode(block, 'STACK');
|
let branch = '';
|
||||||
let returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
if (block.getInput('STACK')) {
|
||||||
|
// The 'procedures_defreturn' block might not have a STACK input.
|
||||||
|
branch = generator.statementToCode(block, 'STACK');
|
||||||
|
}
|
||||||
|
let returnValue = '';
|
||||||
|
if (block.getInput('RETURN')) {
|
||||||
|
// The 'procedures_defnoreturn' block (which shares this code)
|
||||||
|
// does not have a RETURN input.
|
||||||
|
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
||||||
|
}
|
||||||
let xfix2 = '';
|
let xfix2 = '';
|
||||||
if (branch && returnValue) {
|
if (branch && returnValue) {
|
||||||
// After executing the function body, revisit this block for the return.
|
// After executing the function body, revisit this block for the return.
|
||||||
|
|||||||
@@ -128,10 +128,12 @@ export function text_charAt(
|
|||||||
return [code, Order.UNARY_POSTFIX];
|
return [code, Order.UNARY_POSTFIX];
|
||||||
}
|
}
|
||||||
case 'LAST':
|
case 'LAST':
|
||||||
at = 1;
|
|
||||||
// Fall through.
|
|
||||||
case 'FROM_END': {
|
case 'FROM_END': {
|
||||||
at = generator.getAdjusted(block, 'AT', 1);
|
if (where === 'LAST') {
|
||||||
|
at = 1;
|
||||||
|
} else {
|
||||||
|
at = generator.getAdjusted(block, 'AT', 1);
|
||||||
|
}
|
||||||
const functionName = generator.provideFunction_(
|
const functionName = generator.provideFunction_(
|
||||||
'text_get_from_end',
|
'text_get_from_end',
|
||||||
`
|
`
|
||||||
@@ -140,7 +142,7 @@ String ${generator.FUNCTION_NAME_PLACEHOLDER_}(String text, num x) {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
);
|
);
|
||||||
const code = functionName + '(' + text + ', ' + at + ')';
|
const code = `${functionName}(${text}, ${at})`;
|
||||||
return [code, Order.UNARY_POSTFIX];
|
return [code, Order.UNARY_POSTFIX];
|
||||||
}
|
}
|
||||||
case 'RANDOM': {
|
case 'RANDOM': {
|
||||||
|
|||||||
@@ -38,8 +38,17 @@ export function procedures_defreturn(
|
|||||||
generator.INDENT,
|
generator.INDENT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const branch = generator.statementToCode(block, 'STACK');
|
let branch = '';
|
||||||
let returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
if (block.getInput('STACK')) {
|
||||||
|
// The 'procedures_defreturn' block might not have a STACK input.
|
||||||
|
branch = generator.statementToCode(block, 'STACK');
|
||||||
|
}
|
||||||
|
let returnValue = '';
|
||||||
|
if (block.getInput('RETURN')) {
|
||||||
|
// The 'procedures_defnoreturn' block (which shares this code)
|
||||||
|
// does not have a RETURN input.
|
||||||
|
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
||||||
|
}
|
||||||
let xfix2 = '';
|
let xfix2 = '';
|
||||||
if (branch && returnValue) {
|
if (branch && returnValue) {
|
||||||
// After executing the function body, revisit this block for the return.
|
// After executing the function body, revisit this block for the return.
|
||||||
|
|||||||
@@ -38,8 +38,17 @@ export function procedures_defreturn(
|
|||||||
generator.INDENT,
|
generator.INDENT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let branch = generator.statementToCode(block, 'STACK');
|
let branch = '';
|
||||||
let returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
if (block.getInput('STACK')) {
|
||||||
|
// The 'procedures_defreturn' block might not have a STACK input.
|
||||||
|
branch = generator.statementToCode(block, 'STACK');
|
||||||
|
}
|
||||||
|
let returnValue = '';
|
||||||
|
if (block.getInput('RETURN')) {
|
||||||
|
// The 'procedures_defnoreturn' block (which shares this code)
|
||||||
|
// does not have a RETURN input.
|
||||||
|
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
||||||
|
}
|
||||||
let xfix2 = '';
|
let xfix2 = '';
|
||||||
if (branch && returnValue) {
|
if (branch && returnValue) {
|
||||||
// After executing the function body, revisit this block for the return.
|
// After executing the function body, revisit this block for the return.
|
||||||
|
|||||||
@@ -132,8 +132,6 @@ export function text_charAt(
|
|||||||
// Get letter at index.
|
// Get letter at index.
|
||||||
// Note: Until January 2013 this block did not have the WHERE input.
|
// Note: Until January 2013 this block did not have the WHERE input.
|
||||||
const where = block.getFieldValue('WHERE') || 'FROM_START';
|
const where = block.getFieldValue('WHERE') || 'FROM_START';
|
||||||
const atOrder = where === 'FROM_END' ? Order.UNARY : Order.NONE;
|
|
||||||
const at = generator.valueToCode(block, 'AT', atOrder) || '1';
|
|
||||||
const text = generator.valueToCode(block, 'VALUE', Order.NONE) || "''";
|
const text = generator.valueToCode(block, 'VALUE', Order.NONE) || "''";
|
||||||
let code;
|
let code;
|
||||||
if (where === 'RANDOM') {
|
if (where === 'RANDOM') {
|
||||||
@@ -154,6 +152,8 @@ end
|
|||||||
} else if (where === 'LAST') {
|
} else if (where === 'LAST') {
|
||||||
start = '-1';
|
start = '-1';
|
||||||
} else {
|
} else {
|
||||||
|
const atOrder = where === 'FROM_END' ? Order.UNARY : Order.NONE;
|
||||||
|
const at = generator.valueToCode(block, 'AT', atOrder) || '1';
|
||||||
if (where === 'FROM_START') {
|
if (where === 'FROM_START') {
|
||||||
start = at;
|
start = at;
|
||||||
} else if (where === 'FROM_END') {
|
} else if (where === 'FROM_END') {
|
||||||
|
|||||||
@@ -60,8 +60,17 @@ export function procedures_defreturn(block: Block, generator: PhpGenerator) {
|
|||||||
generator.INDENT,
|
generator.INDENT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const branch = generator.statementToCode(block, 'STACK');
|
let branch = '';
|
||||||
let returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
if (block.getInput('STACK')) {
|
||||||
|
// The 'procedures_defreturn' block might not have a STACK input.
|
||||||
|
branch = generator.statementToCode(block, 'STACK');
|
||||||
|
}
|
||||||
|
let returnValue = '';
|
||||||
|
if (block.getInput('RETURN')) {
|
||||||
|
// The 'procedures_defnoreturn' block (which shares this code)
|
||||||
|
// does not have a RETURN input.
|
||||||
|
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
||||||
|
}
|
||||||
let xfix2 = '';
|
let xfix2 = '';
|
||||||
if (branch && returnValue) {
|
if (branch && returnValue) {
|
||||||
// After executing the function body, revisit this block for the return.
|
// After executing the function body, revisit this block for the return.
|
||||||
|
|||||||
@@ -60,8 +60,17 @@ export function procedures_defreturn(block: Block, generator: PythonGenerator) {
|
|||||||
generator.INDENT,
|
generator.INDENT,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let branch = generator.statementToCode(block, 'STACK');
|
let branch = '';
|
||||||
let returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
if (block.getInput('STACK')) {
|
||||||
|
// The 'procedures_defreturn' block might not have a STACK input.
|
||||||
|
branch = generator.statementToCode(block, 'STACK');
|
||||||
|
}
|
||||||
|
let returnValue = '';
|
||||||
|
if (block.getInput('RETURN')) {
|
||||||
|
// The 'procedures_defnoreturn' block (which shares this code)
|
||||||
|
// does not have a RETURN input.
|
||||||
|
returnValue = generator.valueToCode(block, 'RETURN', Order.NONE) || '';
|
||||||
|
}
|
||||||
let xfix2 = '';
|
let xfix2 = '';
|
||||||
if (branch && returnValue) {
|
if (branch && returnValue) {
|
||||||
// After executing the function body, revisit this block for the return.
|
// After executing the function body, revisit this block for the return.
|
||||||
|
|||||||
Reference in New Issue
Block a user