Skip to content

Commit 21c0a7d

Browse files
authored
refactor!: Use IVariableMap instead of VariableMap (#8401)
* refactor: use IVariableMap in place of VariableMap. * refactor!: move variable deletion prompting out of VariableMap. * chore: Remove unused imports.
1 parent 294ef74 commit 21c0a7d

File tree

5 files changed

+161
-102
lines changed

5 files changed

+161
-102
lines changed

core/names.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
// Former goog.module ID: Blockly.Names
1313

1414
import {Msg} from './msg.js';
15-
// import * as Procedures from './procedures.js';
16-
import type {VariableMap} from './variable_map.js';
15+
import type {IVariableMap} from './interfaces/i_variable_map.js';
16+
import type {
17+
IVariableModel,
18+
IVariableState,
19+
} from './interfaces/i_variable_model.js';
1720
import * as Variables from './variables.js';
1821
import type {Workspace} from './workspace.js';
1922

@@ -39,7 +42,8 @@ export class Names {
3942
/**
4043
* The variable map from the workspace, containing Blockly variable models.
4144
*/
42-
private variableMap: VariableMap | null = null;
45+
private variableMap: IVariableMap<IVariableModel<IVariableState>> | null =
46+
null;
4347

4448
/**
4549
* @param reservedWordsList A comma-separated string of words that are illegal
@@ -70,7 +74,7 @@ export class Names {
7074
*
7175
* @param map The map to track.
7276
*/
73-
setVariableMap(map: VariableMap) {
77+
setVariableMap(map: IVariableMap<IVariableModel<IVariableState>>) {
7478
this.variableMap = map;
7579
}
7680

core/variable_map.ts

Lines changed: 39 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import './events/events_var_delete.js';
1717
import './events/events_var_rename.js';
1818

1919
import type {Block} from './block.js';
20-
import * as dialog from './dialog.js';
20+
import * as deprecation from './utils/deprecation.js';
2121
import * as eventUtils from './events/utils.js';
2222
import * as registry from './registry.js';
23-
import {Msg} from './msg.js';
23+
import * as Variables from './variables.js';
2424
import {Names} from './names.js';
2525
import * as idGenerator from './utils/idgenerator.js';
2626
import {IVariableModel, IVariableState} from './interfaces/i_variable_model.js';
@@ -247,7 +247,6 @@ export class VariableMap
247247
this.variableMap.set(type, variables);
248248
}
249249
eventUtils.fire(new (eventUtils.get(eventUtils.VAR_CREATE))(variable));
250-
251250
return variable;
252251
}
253252

@@ -269,90 +268,51 @@ export class VariableMap
269268

270269
/* Begin functions for variable deletion. */
271270
/**
272-
* Delete a variable.
271+
* Delete a variable and all of its uses without confirmation.
273272
*
274273
* @param variable Variable to delete.
275274
*/
276275
deleteVariable(variable: IVariableModel<IVariableState>) {
277-
const variables = this.variableMap.get(variable.getType());
278-
if (!variables || !variables.has(variable.getId())) return;
279-
variables.delete(variable.getId());
280-
eventUtils.fire(new (eventUtils.get(eventUtils.VAR_DELETE))(variable));
281-
if (variables.size === 0) {
282-
this.variableMap.delete(variable.getType());
276+
const uses = this.getVariableUsesById(variable.getId());
277+
const existingGroup = eventUtils.getGroup();
278+
if (!existingGroup) {
279+
eventUtils.setGroup(true);
280+
}
281+
try {
282+
for (let i = 0; i < uses.length; i++) {
283+
uses[i].dispose(true);
284+
}
285+
const variables = this.variableMap.get(variable.getType());
286+
if (!variables || !variables.has(variable.getId())) return;
287+
variables.delete(variable.getId());
288+
eventUtils.fire(new (eventUtils.get(eventUtils.VAR_DELETE))(variable));
289+
if (variables.size === 0) {
290+
this.variableMap.delete(variable.getType());
291+
}
292+
} finally {
293+
eventUtils.setGroup(existingGroup);
283294
}
284295
}
285296

286297
/**
287-
* Delete a variables by the passed in ID and all of its uses from this
288-
* workspace. May prompt the user for confirmation.
298+
* @deprecated v12 - Delete a variables by the passed in ID and all of its
299+
* uses from this workspace. May prompt the user for confirmation.
289300
*
290301
* @param id ID of variable to delete.
291302
*/
292303
deleteVariableById(id: string) {
304+
deprecation.warn(
305+
'VariableMap.deleteVariableById',
306+
'v12',
307+
'v13',
308+
'Blockly.Variables.deleteVariable',
309+
);
293310
const variable = this.getVariableById(id);
294311
if (variable) {
295-
// Check whether this variable is a function parameter before deleting.
296-
const variableName = variable.getName();
297-
const uses = this.getVariableUsesById(id);
298-
for (let i = 0, block; (block = uses[i]); i++) {
299-
if (
300-
block.type === 'procedures_defnoreturn' ||
301-
block.type === 'procedures_defreturn'
302-
) {
303-
const procedureName = String(block.getFieldValue('NAME'));
304-
const deleteText = Msg['CANNOT_DELETE_VARIABLE_PROCEDURE']
305-
.replace('%1', variableName)
306-
.replace('%2', procedureName);
307-
dialog.alert(deleteText);
308-
return;
309-
}
310-
}
311-
312-
if (uses.length > 1) {
313-
// Confirm before deleting multiple blocks.
314-
const confirmText = Msg['DELETE_VARIABLE_CONFIRMATION']
315-
.replace('%1', String(uses.length))
316-
.replace('%2', variableName);
317-
dialog.confirm(confirmText, (ok) => {
318-
if (ok && variable) {
319-
this.deleteVariableInternal(variable, uses);
320-
}
321-
});
322-
} else {
323-
// No confirmation necessary for a single block.
324-
this.deleteVariableInternal(variable, uses);
325-
}
326-
} else {
327-
console.warn("Can't delete non-existent variable: " + id);
312+
Variables.deleteVariable(this.workspace, variable);
328313
}
329314
}
330315

331-
/**
332-
* Deletes a variable and all of its uses from this workspace without asking
333-
* the user for confirmation.
334-
*
335-
* @param variable Variable to delete.
336-
* @param uses An array of uses of the variable.
337-
* @internal
338-
*/
339-
deleteVariableInternal(
340-
variable: IVariableModel<IVariableState>,
341-
uses: Block[],
342-
) {
343-
const existingGroup = eventUtils.getGroup();
344-
if (!existingGroup) {
345-
eventUtils.setGroup(true);
346-
}
347-
try {
348-
for (let i = 0; i < uses.length; i++) {
349-
uses[i].dispose(true);
350-
}
351-
this.deleteVariable(variable);
352-
} finally {
353-
eventUtils.setGroup(existingGroup);
354-
}
355-
}
356316
/* End functions for variable deletion. */
357317
/**
358318
* Find the variable by the given name and type and return it. Return null if
@@ -431,7 +391,7 @@ export class VariableMap
431391
getVariableTypes(ws: Workspace | null): string[] {
432392
const variableTypes = new Set<string>(this.variableMap.keys());
433393
if (ws && ws.getPotentialVariableMap()) {
434-
for (const key of ws.getPotentialVariableMap()!.variableMap.keys()) {
394+
for (const key of ws.getPotentialVariableMap()!.getTypes()) {
435395
variableTypes.add(key);
436396
}
437397
}
@@ -470,26 +430,19 @@ export class VariableMap
470430
}
471431

472432
/**
473-
* Find all the uses of a named variable.
433+
* @deprecated v12 - Find all the uses of a named variable.
474434
*
475435
* @param id ID of the variable to find.
476436
* @returns Array of block usages.
477437
*/
478438
getVariableUsesById(id: string): Block[] {
479-
const uses = [];
480-
const blocks = this.workspace.getAllBlocks(false);
481-
// Iterate through every block and check the name.
482-
for (let i = 0; i < blocks.length; i++) {
483-
const blockVariables = blocks[i].getVarModels();
484-
if (blockVariables) {
485-
for (let j = 0; j < blockVariables.length; j++) {
486-
if (blockVariables[j].getId() === id) {
487-
uses.push(blocks[i]);
488-
}
489-
}
490-
}
491-
}
492-
return uses;
439+
deprecation.warn(
440+
'VariableMap.getVariableUsesById',
441+
'v12',
442+
'v13',
443+
'Blockly.Variables.getVariableUsesById',
444+
);
445+
return Variables.getVariableUsesById(this.workspace, id);
493446
}
494447
}
495448

core/variables.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
// Former goog.module ID: Blockly.Variables
88

9+
import type {Block} from './block.js';
910
import {Blocks} from './blocks.js';
1011
import * as dialog from './dialog.js';
1112
import {isVariableBackedParameterModel} from './interfaces/i_variable_backed_parameter_model.js';
@@ -683,6 +684,74 @@ export function compareByName(
683684
.localeCompare(var2.getName(), undefined, {sensitivity: 'base'});
684685
}
685686

687+
/**
688+
* Find all the uses of a named variable.
689+
*
690+
* @param workspace The workspace to search for the variable.
691+
* @param id ID of the variable to find.
692+
* @returns Array of block usages.
693+
*/
694+
export function getVariableUsesById(workspace: Workspace, id: string): Block[] {
695+
const uses = [];
696+
const blocks = workspace.getAllBlocks(false);
697+
// Iterate through every block and check the name.
698+
for (let i = 0; i < blocks.length; i++) {
699+
const blockVariables = blocks[i].getVarModels();
700+
if (blockVariables) {
701+
for (let j = 0; j < blockVariables.length; j++) {
702+
if (blockVariables[j].getId() === id) {
703+
uses.push(blocks[i]);
704+
}
705+
}
706+
}
707+
}
708+
return uses;
709+
}
710+
711+
/**
712+
* Delete a variable and all of its uses from the given workspace. May prompt
713+
* the user for confirmation.
714+
*
715+
* @param workspace The workspace from which to delete the variable.
716+
* @param variable The variable to delete.
717+
*/
718+
export function deleteVariable(
719+
workspace: Workspace,
720+
variable: IVariableModel<IVariableState>,
721+
) {
722+
// Check whether this variable is a function parameter before deleting.
723+
const variableName = variable.getName();
724+
const uses = getVariableUsesById(workspace, variable.getId());
725+
for (let i = 0, block; (block = uses[i]); i++) {
726+
if (
727+
block.type === 'procedures_defnoreturn' ||
728+
block.type === 'procedures_defreturn'
729+
) {
730+
const procedureName = String(block.getFieldValue('NAME'));
731+
const deleteText = Msg['CANNOT_DELETE_VARIABLE_PROCEDURE']
732+
.replace('%1', variableName)
733+
.replace('%2', procedureName);
734+
dialog.alert(deleteText);
735+
return;
736+
}
737+
}
738+
739+
if (uses.length > 1) {
740+
// Confirm before deleting multiple blocks.
741+
const confirmText = Msg['DELETE_VARIABLE_CONFIRMATION']
742+
.replace('%1', String(uses.length))
743+
.replace('%2', variableName);
744+
dialog.confirm(confirmText, (ok) => {
745+
if (ok && variable) {
746+
workspace.getVariableMap().deleteVariable(variable);
747+
}
748+
});
749+
} else {
750+
// No confirmation necessary for a single block.
751+
workspace.getVariableMap().deleteVariable(variable);
752+
}
753+
}
754+
686755
export const TEST_ONLY = {
687756
generateUniqueNameInternal,
688757
};

0 commit comments

Comments
 (0)