From 7c619a1dba4e22e7d26562dddac28a7ca16867cb Mon Sep 17 00:00:00 2001 From: Noah Glaser Date: Mon, 7 Jan 2019 12:44:01 -0800 Subject: [PATCH] Prevent duplicate parameters in functions (#2177) Prevents the coder from using duplicate parameters names in functions. In the validator function check for parameter names that have been used. If it finds a block with a name that matches return null so that it will revert the change. Also change the name each time a new parameter is created to try to prevent duplicate name. --- blocks/procedures.js | 91 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/blocks/procedures.js b/blocks/procedures.js index 7f6e0965f..a8b15604b 100644 --- a/blocks/procedures.js +++ b/blocks/procedures.js @@ -80,26 +80,11 @@ Blockly.Blocks['procedures_defnoreturn'] = { }, /** * Update the display of parameters for this procedure definition block. - * Display a warning if there are duplicately named parameters. * @private * @this Blockly.Block */ updateParams_: function() { - // Check for duplicated arguments. - var badArg = false; - var hash = {}; - for (var i = 0; i < this.arguments_.length; i++) { - if (hash['arg_' + this.arguments_[i].toLowerCase()]) { - badArg = true; - break; - } - hash['arg_' + this.arguments_[i].toLowerCase()] = true; - } - if (badArg) { - this.setWarningText(Blockly.Msg['PROCEDURES_DEF_DUPLICATE_WARNING']); - } else { - this.setWarningText(null); - } + // Merge the arguments into a human-readable list. var paramString = ''; if (this.arguments_.length) { @@ -474,9 +459,72 @@ Blockly.Blocks['procedures_mutatorcontainer'] = { this.setColour(Blockly.Msg['PROCEDURES_HUE']); this.setTooltip(Blockly.Msg['PROCEDURES_MUTATORCONTAINER_TOOLTIP']); this.contextMenu = false; + }, + /** + * This will create & delete variables and in dialogs workspace to ensure + * that when a new block is dragged out it will have a unique parameter name. + * @param {!Blockly.Events.Abstract} event Change event. + * @this Blockly.Block + */ + onchange: function(event) { + if (!this.workspace || this.workspace.isFlyout || + (event.type != Blockly.Events.BLOCK_DELETE && event.type != Blockly.Events.BLOCK_CREATE)) { + return; + } + var blocks = this.workspace.getAllBlocks(); + var allVariables = this.workspace.getAllVariables(); + if (event.type == Blockly.Events.BLOCK_DELETE) { + var variableNamesToKeep = []; + for (var i = 0; i < blocks.length; i += 1) { + if (blocks[i].getFieldValue('NAME')) { + variableNamesToKeep.push(blocks[i].getFieldValue('NAME')); + } + } + for (var k = 0; k < allVariables.length; k += 1) { + if (variableNamesToKeep.indexOf(allVariables[k].name) == -1) { + this.workspace.deleteVariableById(allVariables[k].getId()); + } + } + return; + } + + if (event.type != Blockly.Events.BLOCK_CREATE) { + return; + } + + var block = this.workspace.getBlockById(event.blockId); + // This is to handle the one none variable block + // Happens when all the blocks are regenerated + if (!block.getField('NAME')) { + return; + } + var varName = block.getFieldValue('NAME'); + var variable = this.workspace.getVariable(varName); + + if (!variable) { + // This means the parameter name is not in use and we can create the variable. + variable = this.workspace.createVariable(varName); + } + // If the blocks are connected we don't have to check duplicate variables + // This only happens if the dialog box is open + if (block.previousConnection.isConnected() || block.nextConnection.isConnected()) { + return; + } + + for (var j = 0; j < blocks.length; j += 1) { + // filter block that was created + if (block.id != blocks[j].id && blocks[j].getFieldValue('NAME') == variable.name) { + // generate new name and set name field + varName = Blockly.Variables.generateUniqueName(this.workspace); + variable = this.workspace.createVariable(varName); + block.setFieldValue(variable.name, 'NAME'); + return; + } + } } }; + Blockly.Blocks['procedures_mutatorarg'] = { /** * Mutator block for procedure argument. @@ -510,6 +558,7 @@ Blockly.Blocks['procedures_mutatorarg'] = { field.createdVariables_ = []; field.onFinishEditing_('x'); }, + /** * Obtain a valid name for the procedure argument. Create a variable if * necessary. @@ -526,6 +575,16 @@ Blockly.Blocks['procedures_mutatorarg'] = { if (!varName) { return null; } + // Prevents duplicate parameter names in functions + var blocks = this.sourceBlock_.workspace.getAllBlocks(); + for (var i = 0; i < blocks.length; i += 1) { + if (blocks[i].id == this.sourceBlock_.id) { + continue; + } + if (blocks[i].getFieldValue('NAME') == varName) { + return null; + } + } var model = outerWs.getVariable(varName, ''); if (model && model.name != varName) { // Rename the variable (case change)