Skip to content

Commit 4dcffa0

Browse files
authored
fix: Don't create intermediate variables when renaming a procedure argument. (#8723)
1 parent 151d21e commit 4dcffa0

1 file changed

Lines changed: 48 additions & 56 deletions

File tree

blocks/procedures.ts

Lines changed: 48 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -629,30 +629,49 @@ type ArgumentBlock = Block & ArgumentMixin;
629629
interface ArgumentMixin extends ArgumentMixinType {}
630630
type ArgumentMixinType = typeof PROCEDURES_MUTATORARGUMENT;
631631

632-
// TODO(#6920): This is kludgy.
633-
type FieldTextInputForArgument = FieldTextInput & {
634-
oldShowEditorFn_(_e?: Event, quietInput?: boolean): void;
635-
createdVariables_: IVariableModel<IVariableState>[];
636-
};
632+
/**
633+
* Field responsible for editing procedure argument names.
634+
*/
635+
class ProcedureArgumentField extends FieldTextInput {
636+
/**
637+
* Whether or not this field is currently being edited interactively.
638+
*/
639+
editingInteractively = false;
640+
641+
/**
642+
* The procedure argument variable whose name is being interactively edited.
643+
*/
644+
editingVariable?: IVariableModel<IVariableState>;
645+
646+
/**
647+
* Displays the field editor.
648+
*
649+
* @param e The event that triggered display of the field editor.
650+
*/
651+
protected override showEditor_(e?: Event) {
652+
super.showEditor_(e);
653+
this.editingInteractively = true;
654+
this.editingVariable = undefined;
655+
}
656+
657+
/**
658+
* Handles cleanup when the field editor is dismissed.
659+
*/
660+
override onFinishEditing_(value: string) {
661+
super.onFinishEditing_(value);
662+
this.editingInteractively = false;
663+
}
664+
}
637665

638666
const PROCEDURES_MUTATORARGUMENT = {
639667
/**
640668
* Mutator block for procedure argument.
641669
*/
642670
init: function (this: ArgumentBlock) {
643-
const field = fieldRegistry.fromJson({
644-
type: 'field_input',
645-
text: Procedures.DEFAULT_ARG,
646-
}) as FieldTextInputForArgument;
647-
field.setValidator(this.validator_);
648-
// Hack: override showEditor to do just a little bit more work.
649-
// We don't have a good place to hook into the start of a text edit.
650-
field.oldShowEditorFn_ = (field as AnyDuringMigration).showEditor_;
651-
const newShowEditorFn = function (this: typeof field) {
652-
this.createdVariables_ = [];
653-
this.oldShowEditorFn_();
654-
};
655-
(field as AnyDuringMigration).showEditor_ = newShowEditorFn;
671+
const field = new ProcedureArgumentField(
672+
Procedures.DEFAULT_ARG,
673+
this.validator_,
674+
);
656675

657676
this.appendDummyInput()
658677
.appendField(Msg['PROCEDURES_MUTATORARG_TITLE'])
@@ -662,14 +681,6 @@ const PROCEDURES_MUTATORARGUMENT = {
662681
this.setStyle('procedure_blocks');
663682
this.setTooltip(Msg['PROCEDURES_MUTATORARG_TOOLTIP']);
664683
this.contextMenu = false;
665-
666-
// Create the default variable when we drag the block in from the flyout.
667-
// Have to do this after installing the field on the block.
668-
field.onFinishEditing_ = this.deleteIntermediateVars_;
669-
// Create an empty list so onFinishEditing_ has something to look at, even
670-
// though the editor was never opened.
671-
field.createdVariables_ = [];
672-
field.onFinishEditing_('x');
673684
},
674685

675686
/**
@@ -683,11 +694,11 @@ const PROCEDURES_MUTATORARGUMENT = {
683694
* @returns Valid name, or null if a name was not specified.
684695
*/
685696
validator_: function (
686-
this: FieldTextInputForArgument,
697+
this: ProcedureArgumentField,
687698
varName: string,
688699
): string | null {
689700
const sourceBlock = this.getSourceBlock()!;
690-
const outerWs = sourceBlock!.workspace.getRootWorkspace()!;
701+
const outerWs = sourceBlock.workspace.getRootWorkspace()!;
691702
varName = varName.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
692703
if (!varName) {
693704
return null;
@@ -716,43 +727,24 @@ const PROCEDURES_MUTATORARGUMENT = {
716727
return varName;
717728
}
718729

719-
let model = outerWs.getVariable(varName, '');
730+
const model = outerWs.getVariable(varName, '');
720731
if (model && model.getName() !== varName) {
721732
// Rename the variable (case change)
722733
outerWs.renameVariableById(model.getId(), varName);
723734
}
724735
if (!model) {
725-
model = outerWs.createVariable(varName, '');
726-
if (model && this.createdVariables_) {
727-
this.createdVariables_.push(model);
736+
if (this.editingInteractively) {
737+
if (!this.editingVariable) {
738+
this.editingVariable = outerWs.createVariable(varName, '');
739+
} else {
740+
outerWs.renameVariableById(this.editingVariable.getId(), varName);
741+
}
742+
} else {
743+
outerWs.createVariable(varName, '');
728744
}
729745
}
730746
return varName;
731747
},
732-
733-
/**
734-
* Called when focusing away from the text field.
735-
* Deletes all variables that were created as the user typed their intended
736-
* variable name.
737-
*
738-
* @internal
739-
* @param newText The new variable name.
740-
*/
741-
deleteIntermediateVars_: function (
742-
this: FieldTextInputForArgument,
743-
newText: string,
744-
) {
745-
const outerWs = this.getSourceBlock()!.workspace.getRootWorkspace();
746-
if (!outerWs) {
747-
return;
748-
}
749-
for (let i = 0; i < this.createdVariables_.length; i++) {
750-
const model = this.createdVariables_[i];
751-
if (model.getName() !== newText) {
752-
outerWs.deleteVariableById(model.getId());
753-
}
754-
}
755-
},
756748
};
757749
blocks['procedures_mutatorarg'] = PROCEDURES_MUTATORARGUMENT;
758750

0 commit comments

Comments
 (0)