Skip to content

Commit 32f8e24

Browse files
authored
refactor: update the variable interfaces. (#8388)
1 parent 9fa4b2c commit 32f8e24

File tree

5 files changed

+97
-49
lines changed

5 files changed

+97
-49
lines changed

core/interfaces/i_variable_map.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {IVariableModel} from './i_variable_model.js';
8-
import {State} from '../serialization/variables.js';
7+
import type {IVariableModel, IVariableState} from './i_variable_model.js';
98

109
/**
1110
* Variable maps are container objects responsible for storing and managing the
@@ -14,7 +13,7 @@ import {State} from '../serialization/variables.js';
1413
* Any of these methods may define invariants about which names and types are
1514
* legal, and throw if they are not met.
1615
*/
17-
export interface IVariableMap<T extends IVariableModel, U extends State> {
16+
export interface IVariableMap<T extends IVariableModel<IVariableState>> {
1817
/* Returns the variable corresponding to the given ID, or null if none. */
1918
getVariableById(id: string): T | null;
2019

@@ -46,6 +45,9 @@ export interface IVariableMap<T extends IVariableModel, U extends State> {
4645
*/
4746
createVariable(name: string, id?: string, type?: string | null): T;
4847

48+
/* Adds a variable to this variable map. */
49+
addVariable(variable: T): void;
50+
4951
/**
5052
* Changes the name of the given variable to the name provided and returns the
5153
* renamed variable.
@@ -60,13 +62,4 @@ export interface IVariableMap<T extends IVariableModel, U extends State> {
6062

6163
/* Removes all variables from this variable map. */
6264
clear(): void;
63-
64-
/* Returns an object representing the serialized state of the variable. */
65-
saveVariable(variable: T): U;
66-
67-
/**
68-
* Creates a variable in this variable map corresponding to the given state
69-
* (produced by a call to `saveVariable`).
70-
*/
71-
loadVariable(state: U): T;
7265
}

core/interfaces/i_variable_model.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
import type {Workspace} from '../workspace.js';
8+
79
/* Representation of a variable. */
8-
export interface IVariableModel {
10+
export interface IVariableModel<T extends IVariableState> {
911
/* Returns the unique ID of this variable. */
1012
getId(): string;
1113

@@ -23,4 +25,33 @@ export interface IVariableModel {
2325

2426
/* Sets the type of this variable. */
2527
setType(type: string): this;
28+
29+
getWorkspace(): Workspace;
30+
31+
/* Serializes this variable */
32+
save(): T;
33+
}
34+
35+
export interface IVariableModelStatic<T extends IVariableState> {
36+
new (
37+
workspace: Workspace,
38+
name: string,
39+
type?: string,
40+
id?: string,
41+
): IVariableModel<T>;
42+
43+
/**
44+
* Creates a new IVariableModel corresponding to the given state on the
45+
* specified workspace. This method must be static in your implementation.
46+
*/
47+
load(state: T, workspace: Workspace): IVariableModel<T>;
48+
}
49+
50+
/**
51+
* Represents the state of a given variable.
52+
*/
53+
export interface IVariableState {
54+
name: string;
55+
id: string;
56+
type?: string;
2657
}

core/registry.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ import type {IPaster} from './interfaces/i_paster.js';
2424
import type {ICopyData, ICopyable} from './interfaces/i_copyable.js';
2525
import type {IConnectionPreviewer} from './interfaces/i_connection_previewer.js';
2626
import type {IDragger} from './interfaces/i_dragger.js';
27+
import type {
28+
IVariableModel,
29+
IVariableModelStatic,
30+
IVariableState,
31+
} from './interfaces/i_variable_model.js';
32+
import type {IVariableMap} from './interfaces/i_variable_map.js';
2733

2834
/**
2935
* A map of maps. With the keys being the type and name of the class we are
@@ -109,6 +115,14 @@ export class Type<_T> {
109115

110116
/** @internal */
111117
static PASTER = new Type<IPaster<ICopyData, ICopyable<ICopyData>>>('paster');
118+
119+
static VARIABLE_MODEL = new Type<IVariableModelStatic<IVariableState>>(
120+
'variableModel',
121+
);
122+
123+
static VARIABLE_MAP = new Type<IVariableMap<IVariableModel<IVariableState>>>(
124+
'variableMap',
125+
);
112126
}
113127

114128
/**

core/serialization/variables.ts

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,13 @@
77
// Former goog.module ID: Blockly.serialization.variables
88

99
import type {ISerializer} from '../interfaces/i_serializer.js';
10+
import type {IVariableState} from '../interfaces/i_variable_model.js';
1011
import type {Workspace} from '../workspace.js';
1112

1213
import * as priorities from './priorities.js';
14+
import * as registry from '../registry.js';
1315
import * as serializationRegistry from './registry.js';
1416

15-
/**
16-
* Represents the state of a given variable.
17-
*/
18-
export interface State {
19-
name: string;
20-
id: string;
21-
type: string | undefined;
22-
}
23-
2417
/**
2518
* Serializer for saving and loading variable state.
2619
*/
@@ -40,23 +33,9 @@ export class VariableSerializer implements ISerializer {
4033
* @returns The state of the workspace's variables, or null if there are no
4134
* variables.
4235
*/
43-
save(workspace: Workspace): State[] | null {
44-
const variableStates = [];
45-
for (const variable of workspace.getAllVariables()) {
46-
const state = {
47-
'name': variable.name,
48-
'id': variable.getId(),
49-
};
50-
if (variable.type) {
51-
(state as AnyDuringMigration)['type'] = variable.type;
52-
}
53-
variableStates.push(state);
54-
}
55-
// AnyDuringMigration because: Type '{ name: string; id: string; }[] |
56-
// null' is not assignable to type 'State[] | null'.
57-
return (
58-
variableStates.length ? variableStates : null
59-
) as AnyDuringMigration;
36+
save(workspace: Workspace): IVariableState[] | null {
37+
const variableStates = workspace.getAllVariables().map((v) => v.save());
38+
return variableStates.length ? variableStates : null;
6039
}
6140

6241
/**
@@ -66,14 +45,14 @@ export class VariableSerializer implements ISerializer {
6645
* @param state The state of the variables to deserialize.
6746
* @param workspace The workspace to deserialize into.
6847
*/
69-
load(state: State[], workspace: Workspace) {
70-
for (const varState of state) {
71-
workspace.createVariable(
72-
varState['name'],
73-
varState['type'],
74-
varState['id'],
75-
);
76-
}
48+
load(state: IVariableState[], workspace: Workspace) {
49+
const VariableModel = registry.getObject(
50+
registry.Type.VARIABLE_MODEL,
51+
registry.DEFAULT,
52+
);
53+
state.forEach((s) => {
54+
VariableModel?.load(s, workspace);
55+
});
7756
}
7857

7958
/**

core/variable_model.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@
1515
import './events/events_var_create.js';
1616

1717
import * as idGenerator from './utils/idgenerator.js';
18+
import * as registry from './registry.js';
1819
import type {Workspace} from './workspace.js';
19-
import {IVariableModel} from './interfaces/i_variable_model.js';
20+
import {IVariableModel, IVariableState} from './interfaces/i_variable_model.js';
2021

2122
/**
2223
* Class for a variable model.
2324
* Holds information for the variable including name, ID, and type.
2425
*
2526
* @see {Blockly.FieldVariable}
2627
*/
27-
export class VariableModel implements IVariableModel {
28+
export class VariableModel implements IVariableModel<IVariableState> {
2829
type: string;
2930
private readonly id_: string;
3031

@@ -95,6 +96,30 @@ export class VariableModel implements IVariableModel {
9596
return this;
9697
}
9798

99+
getWorkspace(): Workspace {
100+
return this.workspace;
101+
}
102+
103+
save(): IVariableState {
104+
const state: IVariableState = {
105+
'name': this.getName(),
106+
'id': this.getId(),
107+
};
108+
const type = this.getType();
109+
if (type) {
110+
state['type'] = type;
111+
}
112+
113+
return state;
114+
}
115+
116+
static load(state: IVariableState, workspace: Workspace) {
117+
// TODO(adodson): Once VariableMap implements IVariableMap, directly
118+
// construct a variable, retrieve the variable map from the workspace,
119+
// add the variable to that variable map, and fire a VAR_CREATE event.
120+
workspace.createVariable(state['name'], state['type'], state['id']);
121+
}
122+
98123
/**
99124
* A custom compare function for the VariableModel objects.
100125
*
@@ -108,3 +133,9 @@ export class VariableModel implements IVariableModel {
108133
return var1.name.localeCompare(var2.name, undefined, {sensitivity: 'base'});
109134
}
110135
}
136+
137+
registry.register(
138+
registry.Type.VARIABLE_MODEL,
139+
registry.DEFAULT,
140+
VariableModel,
141+
);

0 commit comments

Comments
 (0)