@flowgram-vue/variable-core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/dist/index.cjs +2630 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2293 -0
- package/dist/index.js +2592 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/src/ast/ast-node.ts +374 -0
- package/src/ast/ast-registers.ts +129 -0
- package/src/ast/common/data-node.ts +63 -0
- package/src/ast/common/index.ts +8 -0
- package/src/ast/common/list-node.ts +70 -0
- package/src/ast/common/map-node.ts +89 -0
- package/src/ast/declaration/base-variable-field.ts +184 -0
- package/src/ast/declaration/index.ts +13 -0
- package/src/ast/declaration/property.ts +19 -0
- package/src/ast/declaration/variable-declaration-list.ts +112 -0
- package/src/ast/declaration/variable-declaration.ts +78 -0
- package/src/ast/expression/base-expression.ts +117 -0
- package/src/ast/expression/enumerate-expression.ts +77 -0
- package/src/ast/expression/index.ts +10 -0
- package/src/ast/expression/keypath-expression.ts +157 -0
- package/src/ast/expression/legacy-keypath-expression.ts +119 -0
- package/src/ast/expression/wrap-array-expression.ts +96 -0
- package/src/ast/factory.ts +163 -0
- package/src/ast/flags.ts +50 -0
- package/src/ast/index.ts +26 -0
- package/src/ast/match.ts +146 -0
- package/src/ast/type/array.ts +109 -0
- package/src/ast/type/base-type.ts +49 -0
- package/src/ast/type/boolean.ts +26 -0
- package/src/ast/type/custom-type.ts +70 -0
- package/src/ast/type/index.ts +19 -0
- package/src/ast/type/integer.ts +29 -0
- package/src/ast/type/map.ts +96 -0
- package/src/ast/type/number.ts +26 -0
- package/src/ast/type/object.ts +185 -0
- package/src/ast/type/string.ts +55 -0
- package/src/ast/type/union.ts +13 -0
- package/src/ast/types.ts +188 -0
- package/src/ast/utils/expression.ts +61 -0
- package/src/ast/utils/helpers.ts +73 -0
- package/src/ast/utils/inversify.ts +42 -0
- package/src/ast/utils/observable.ts +5 -0
- package/src/ast/utils/variable-field.ts +25 -0
- package/src/composables/index.ts +9 -0
- package/src/composables/scope-provider.ts +78 -0
- package/src/composables/use-available-variables.ts +39 -0
- package/src/composables/use-output-variables.ts +36 -0
- package/src/composables/use-scope-available.ts +32 -0
- package/src/index.ts +14 -0
- package/src/providers.ts +22 -0
- package/src/scope/datas/index.ts +8 -0
- package/src/scope/datas/scope-available-data.ts +234 -0
- package/src/scope/datas/scope-event-data.ts +67 -0
- package/src/scope/datas/scope-output-data.ts +151 -0
- package/src/scope/index.ts +9 -0
- package/src/scope/scope-chain.ts +69 -0
- package/src/scope/scope.ts +200 -0
- package/src/scope/types.ts +102 -0
- package/src/scope/variable-table.ts +203 -0
- package/src/services/index.ts +6 -0
- package/src/services/variable-field-key-rename-service.ts +131 -0
- package/src/utils/memo.ts +38 -0
- package/src/utils/toDisposable.ts +16 -0
- package/src/variable-container-module.ts +28 -0
- package/src/variable-engine.ts +197 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { updateChildNodeHelper } from '../utils/helpers';
|
|
7
|
+
import { ASTKind, ASTNodeJSON } from '../types';
|
|
8
|
+
import { ASTNode } from '../ast-node';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ASTNodeJSON representation of `MapNode`
|
|
12
|
+
*/
|
|
13
|
+
export interface MapNodeJSON {
|
|
14
|
+
/**
|
|
15
|
+
* The map of nodes.
|
|
16
|
+
*/
|
|
17
|
+
map: [string, ASTNodeJSON][];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Represents a map of nodes.
|
|
22
|
+
*/
|
|
23
|
+
export class MapNode extends ASTNode<MapNodeJSON> {
|
|
24
|
+
static kind: string = ASTKind.MapNode;
|
|
25
|
+
|
|
26
|
+
protected map: Map<string, ASTNode> = new Map<string, ASTNode>();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Deserializes the `MapNodeJSON` to the `MapNode`.
|
|
30
|
+
* @param json The `MapNodeJSON` to deserialize.
|
|
31
|
+
*/
|
|
32
|
+
fromJSON({ map }: MapNodeJSON): void {
|
|
33
|
+
const removedKeys = new Set(this.map.keys());
|
|
34
|
+
|
|
35
|
+
for (const [key, item] of map || []) {
|
|
36
|
+
removedKeys.delete(key);
|
|
37
|
+
this.set(key, item);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const removeKey of Array.from(removedKeys)) {
|
|
41
|
+
this.remove(removeKey);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Serialize the `MapNode` to `MapNodeJSON`.
|
|
47
|
+
* @returns The JSON representation of `MapNode`.
|
|
48
|
+
*/
|
|
49
|
+
toJSON() {
|
|
50
|
+
return {
|
|
51
|
+
kind: ASTKind.MapNode,
|
|
52
|
+
map: Array.from(this.map.entries()),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Set a node in the map.
|
|
58
|
+
* @param key The key of the node.
|
|
59
|
+
* @param nextJSON The JSON representation of the node.
|
|
60
|
+
* @returns The node instance.
|
|
61
|
+
*/
|
|
62
|
+
set<Node extends ASTNode = ASTNode>(key: string, nextJSON: ASTNodeJSON): Node {
|
|
63
|
+
return this.withBatchUpdate(updateChildNodeHelper).call(this, {
|
|
64
|
+
getChildNode: () => this.get(key),
|
|
65
|
+
removeChildNode: () => this.map.delete(key),
|
|
66
|
+
updateChildNode: (nextNode) => this.map.set(key, nextNode),
|
|
67
|
+
nextJSON,
|
|
68
|
+
}) as Node;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Remove a node from the map.
|
|
73
|
+
* @param key The key of the node.
|
|
74
|
+
*/
|
|
75
|
+
remove(key: string) {
|
|
76
|
+
this.get(key)?.dispose();
|
|
77
|
+
this.map.delete(key);
|
|
78
|
+
this.fireChange();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get a node from the map.
|
|
83
|
+
* @param key The key of the node.
|
|
84
|
+
* @returns The node instance if found, otherwise `undefined`.
|
|
85
|
+
*/
|
|
86
|
+
get<Node extends ASTNode = ASTNode>(key: string): Node | undefined {
|
|
87
|
+
return this.map.get(key) as Node | undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { shallowEqual } from 'fast-equals';
|
|
7
|
+
|
|
8
|
+
import { getParentFields } from '../utils/variable-field';
|
|
9
|
+
import { ASTNodeJSON, ASTNodeJSONOrKind, Identifier } from '../types';
|
|
10
|
+
import { type BaseType } from '../type';
|
|
11
|
+
import { ASTNodeFlags } from '../flags';
|
|
12
|
+
import { type BaseExpression } from '../expression';
|
|
13
|
+
import { ASTNode } from '../ast-node';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* ASTNodeJSON representation of `BaseVariableField`
|
|
17
|
+
*/
|
|
18
|
+
export interface BaseVariableFieldJSON<VariableMeta = any> extends ASTNodeJSON {
|
|
19
|
+
/**
|
|
20
|
+
* key of the variable field
|
|
21
|
+
* - For `VariableDeclaration`, the key should be global unique.
|
|
22
|
+
* - For `Property`, the key is the property name.
|
|
23
|
+
*/
|
|
24
|
+
key: Identifier;
|
|
25
|
+
/**
|
|
26
|
+
* type of the variable field, similar to js code:
|
|
27
|
+
* `const v: string`
|
|
28
|
+
*/
|
|
29
|
+
type?: ASTNodeJSONOrKind;
|
|
30
|
+
/**
|
|
31
|
+
* initializer of the variable field, similar to js code:
|
|
32
|
+
* `const v = 'hello'`
|
|
33
|
+
*
|
|
34
|
+
* with initializer, the type of field will be inferred from the initializer.
|
|
35
|
+
*/
|
|
36
|
+
initializer?: ASTNodeJSON;
|
|
37
|
+
/**
|
|
38
|
+
* meta data of the variable field, you cans store information like `title`, `icon`, etc.
|
|
39
|
+
*/
|
|
40
|
+
meta?: VariableMeta;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Variable Field abstract class, which is the base class for `VariableDeclaration` and `Property`
|
|
45
|
+
*
|
|
46
|
+
* - `VariableDeclaration` is used to declare a variable in a block scope.
|
|
47
|
+
* - `Property` is used to declare a property in an object.
|
|
48
|
+
*/
|
|
49
|
+
export abstract class BaseVariableField<VariableMeta = any> extends ASTNode<
|
|
50
|
+
BaseVariableFieldJSON<VariableMeta>
|
|
51
|
+
> {
|
|
52
|
+
public flags: ASTNodeFlags = ASTNodeFlags.VariableField;
|
|
53
|
+
|
|
54
|
+
protected _type?: BaseType;
|
|
55
|
+
|
|
56
|
+
protected _meta: VariableMeta = {} as any;
|
|
57
|
+
|
|
58
|
+
protected _initializer?: BaseExpression;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Parent variable fields, sorted from closest to farthest
|
|
62
|
+
*/
|
|
63
|
+
get parentFields(): BaseVariableField[] {
|
|
64
|
+
return getParentFields(this);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* KeyPath of the variable field, sorted from farthest to closest
|
|
69
|
+
*/
|
|
70
|
+
get keyPath(): string[] {
|
|
71
|
+
return [...this.parentFields.reverse().map((_field) => _field.key), this.key];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Metadata of the variable field, you cans store information like `title`, `icon`, etc.
|
|
76
|
+
*/
|
|
77
|
+
get meta(): VariableMeta {
|
|
78
|
+
return this._meta;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Type of the variable field, similar to js code:
|
|
83
|
+
* `const v: string`
|
|
84
|
+
*/
|
|
85
|
+
get type(): BaseType {
|
|
86
|
+
return (this._initializer?.returnType || this._type)!;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Initializer of the variable field, similar to js code:
|
|
91
|
+
* `const v = 'hello'`
|
|
92
|
+
*
|
|
93
|
+
* with initializer, the type of field will be inferred from the initializer.
|
|
94
|
+
*/
|
|
95
|
+
get initializer(): BaseExpression | undefined {
|
|
96
|
+
return this._initializer;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The global unique hash of the field, and will be changed when the field is updated.
|
|
101
|
+
*/
|
|
102
|
+
get hash(): string {
|
|
103
|
+
return `[${this._version}]${this.keyPath.join('.')}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Deserialize the `BaseVariableFieldJSON` to the `BaseVariableField`.
|
|
108
|
+
* @param json ASTJSON representation of `BaseVariableField`
|
|
109
|
+
*/
|
|
110
|
+
fromJSON({ type, initializer, meta }: Omit<BaseVariableFieldJSON<VariableMeta>, 'key'>): void {
|
|
111
|
+
// 类型变化
|
|
112
|
+
this.updateType(type);
|
|
113
|
+
|
|
114
|
+
// 表达式更新
|
|
115
|
+
this.updateInitializer(initializer);
|
|
116
|
+
|
|
117
|
+
// Extra 更新
|
|
118
|
+
this.updateMeta(meta!);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update the type of the variable field
|
|
123
|
+
* @param type type ASTJSON representation of Type
|
|
124
|
+
*/
|
|
125
|
+
updateType(type: BaseVariableFieldJSON['type']) {
|
|
126
|
+
const nextTypeJson = typeof type === 'string' ? { kind: type } : type;
|
|
127
|
+
this.updateChildNodeByKey('_type', nextTypeJson);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Update the initializer of the variable field
|
|
132
|
+
* @param nextInitializer initializer ASTJSON representation of Expression
|
|
133
|
+
*/
|
|
134
|
+
updateInitializer(nextInitializer?: BaseVariableFieldJSON['initializer']) {
|
|
135
|
+
this.updateChildNodeByKey('_initializer', nextInitializer);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Update the meta data of the variable field
|
|
140
|
+
* @param nextMeta meta data of the variable field
|
|
141
|
+
*/
|
|
142
|
+
updateMeta(nextMeta: VariableMeta) {
|
|
143
|
+
if (!shallowEqual(nextMeta, this._meta)) {
|
|
144
|
+
this._meta = nextMeta;
|
|
145
|
+
this.fireChange();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get the variable field by keyPath, similar to js code:
|
|
151
|
+
* `v.a.b`
|
|
152
|
+
* @param keyPath
|
|
153
|
+
* @returns
|
|
154
|
+
*/
|
|
155
|
+
getByKeyPath(keyPath: string[]): BaseVariableField | undefined {
|
|
156
|
+
if (this.type?.flags & ASTNodeFlags.DrilldownType) {
|
|
157
|
+
return this.type.getByKeyPath(keyPath) as BaseVariableField | undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Subscribe to type change of the variable field
|
|
165
|
+
* @param observer
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
onTypeChange(observer: (type: ASTNode | undefined) => void) {
|
|
169
|
+
return this.subscribe(observer, { selector: (curr) => curr.type });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Serialize the variable field to JSON
|
|
174
|
+
* @returns ASTNodeJSON representation of `BaseVariableField`
|
|
175
|
+
*/
|
|
176
|
+
toJSON(): BaseVariableFieldJSON<VariableMeta> {
|
|
177
|
+
return {
|
|
178
|
+
key: this.key,
|
|
179
|
+
type: this.type?.toJSON(),
|
|
180
|
+
initializer: this.initializer?.toJSON(),
|
|
181
|
+
meta: this._meta,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { VariableDeclaration, type VariableDeclarationJSON } from './variable-declaration';
|
|
7
|
+
export {
|
|
8
|
+
VariableDeclarationList,
|
|
9
|
+
type VariableDeclarationListJSON,
|
|
10
|
+
type VariableDeclarationListChangeAction,
|
|
11
|
+
} from './variable-declaration-list';
|
|
12
|
+
export { type PropertyJSON, Property } from './property';
|
|
13
|
+
export { BaseVariableField } from './base-variable-field';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ASTKind } from '../types';
|
|
7
|
+
import { BaseVariableField, BaseVariableFieldJSON } from './base-variable-field';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* ASTNodeJSON representation of the `Property`.
|
|
11
|
+
*/
|
|
12
|
+
export type PropertyJSON<VariableMeta = any> = BaseVariableFieldJSON<VariableMeta>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `Property` is a variable field that represents a property of a `ObjectType`.
|
|
16
|
+
*/
|
|
17
|
+
export class Property<VariableMeta = any> extends BaseVariableField<VariableMeta> {
|
|
18
|
+
static kind: string = ASTKind.Property;
|
|
19
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ASTKind } from '../types';
|
|
7
|
+
import { GlobalEventActionType } from '../types';
|
|
8
|
+
import { ASTNode } from '../ast-node';
|
|
9
|
+
import { type VariableDeclarationJSON, VariableDeclaration } from './variable-declaration';
|
|
10
|
+
|
|
11
|
+
export interface VariableDeclarationListJSON<VariableMeta = any> {
|
|
12
|
+
/**
|
|
13
|
+
* `declarations` must be of type `VariableDeclaration`, so the business can omit the `kind` field.
|
|
14
|
+
*/
|
|
15
|
+
declarations?: VariableDeclarationJSON<VariableMeta>[];
|
|
16
|
+
/**
|
|
17
|
+
* The starting order number for variables.
|
|
18
|
+
*/
|
|
19
|
+
startOrder?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type VariableDeclarationListChangeAction = GlobalEventActionType<
|
|
23
|
+
'VariableListChange',
|
|
24
|
+
{
|
|
25
|
+
prev: VariableDeclaration[];
|
|
26
|
+
next: VariableDeclaration[];
|
|
27
|
+
},
|
|
28
|
+
VariableDeclarationList
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
export class VariableDeclarationList extends ASTNode<VariableDeclarationListJSON> {
|
|
32
|
+
static kind: string = ASTKind.VariableDeclarationList;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Map of variable declarations, keyed by variable name.
|
|
36
|
+
*/
|
|
37
|
+
declarationTable: Map<string, VariableDeclaration> = new Map();
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Variable declarations, sorted by `order`.
|
|
41
|
+
*/
|
|
42
|
+
declarations: VariableDeclaration[];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Deserialize the `VariableDeclarationListJSON` to the `VariableDeclarationList`.
|
|
46
|
+
* - VariableDeclarationListChangeAction will be dispatched after deserialization.
|
|
47
|
+
*
|
|
48
|
+
* @param declarations Variable declarations.
|
|
49
|
+
* @param startOrder The starting order number for variables. Default is 0.
|
|
50
|
+
*/
|
|
51
|
+
fromJSON({ declarations, startOrder }: VariableDeclarationListJSON): void {
|
|
52
|
+
const removedKeys = new Set(this.declarationTable.keys());
|
|
53
|
+
const prev = [...(this.declarations || [])];
|
|
54
|
+
|
|
55
|
+
// Iterate over the new properties.
|
|
56
|
+
this.declarations = (declarations || []).map(
|
|
57
|
+
(declaration: VariableDeclarationJSON, idx: number) => {
|
|
58
|
+
const order = (startOrder || 0) + idx;
|
|
59
|
+
|
|
60
|
+
// If the key is not set, reuse the previous key.
|
|
61
|
+
const declarationKey = declaration.key || this.declarations?.[idx]?.key;
|
|
62
|
+
const existDeclaration = this.declarationTable.get(declarationKey);
|
|
63
|
+
if (declarationKey) {
|
|
64
|
+
removedKeys.delete(declarationKey);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (existDeclaration) {
|
|
68
|
+
existDeclaration.fromJSON({ order, ...declaration });
|
|
69
|
+
|
|
70
|
+
return existDeclaration;
|
|
71
|
+
} else {
|
|
72
|
+
const newDeclaration = this.createChildNode({
|
|
73
|
+
order,
|
|
74
|
+
...declaration,
|
|
75
|
+
kind: ASTKind.VariableDeclaration,
|
|
76
|
+
}) as VariableDeclaration;
|
|
77
|
+
this.fireChange();
|
|
78
|
+
|
|
79
|
+
this.declarationTable.set(newDeclaration.key, newDeclaration);
|
|
80
|
+
|
|
81
|
+
return newDeclaration;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Delete variables that no longer exist.
|
|
87
|
+
removedKeys.forEach((key) => {
|
|
88
|
+
const declaration = this.declarationTable.get(key);
|
|
89
|
+
declaration?.dispose();
|
|
90
|
+
this.declarationTable.delete(key);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
this.dispatchGlobalEvent<VariableDeclarationListChangeAction>({
|
|
94
|
+
type: 'VariableListChange',
|
|
95
|
+
payload: {
|
|
96
|
+
prev,
|
|
97
|
+
next: [...this.declarations],
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Serialize the `VariableDeclarationList` to the `VariableDeclarationListJSON`.
|
|
104
|
+
* @returns ASTJSON representation of `VariableDeclarationList`
|
|
105
|
+
*/
|
|
106
|
+
toJSON() {
|
|
107
|
+
return {
|
|
108
|
+
kind: ASTKind.VariableDeclarationList,
|
|
109
|
+
declarations: this.declarations.map((_declaration) => _declaration.toJSON()),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ASTKind, GlobalEventActionType, type CreateASTParams } from '../types';
|
|
7
|
+
import { BaseVariableField, BaseVariableFieldJSON } from './base-variable-field';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* ASTNodeJSON representation of the `VariableDeclaration`.
|
|
11
|
+
*/
|
|
12
|
+
export type VariableDeclarationJSON<VariableMeta = any> = BaseVariableFieldJSON<VariableMeta> & {
|
|
13
|
+
/**
|
|
14
|
+
* Variable sorting order, which is used to sort variables in `scope.outputs.variables`
|
|
15
|
+
*/
|
|
16
|
+
order?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Action type for re-sorting variable declarations.
|
|
21
|
+
*/
|
|
22
|
+
export type ReSortVariableDeclarationsAction = GlobalEventActionType<'ReSortVariableDeclarations'>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* `VariableDeclaration` is a variable field that represents a variable declaration.
|
|
26
|
+
*/
|
|
27
|
+
export class VariableDeclaration<VariableMeta = any> extends BaseVariableField<VariableMeta> {
|
|
28
|
+
static kind: string = ASTKind.VariableDeclaration;
|
|
29
|
+
|
|
30
|
+
protected _order: number = 0;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Variable sorting order, which is used to sort variables in `scope.outputs.variables`
|
|
34
|
+
*/
|
|
35
|
+
get order(): number {
|
|
36
|
+
return this._order;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
constructor(params: CreateASTParams) {
|
|
40
|
+
super(params);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Deserialize the `VariableDeclarationJSON` to the `VariableDeclaration`.
|
|
45
|
+
*/
|
|
46
|
+
fromJSON({ order, ...rest }: Omit<VariableDeclarationJSON<VariableMeta>, 'key'>): void {
|
|
47
|
+
// Update order.
|
|
48
|
+
this.updateOrder(order);
|
|
49
|
+
|
|
50
|
+
// Update other information.
|
|
51
|
+
super.fromJSON(rest as BaseVariableFieldJSON<VariableMeta>);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Update the sorting order of the variable declaration.
|
|
56
|
+
* @param order Variable sorting order. Default is 0.
|
|
57
|
+
*/
|
|
58
|
+
updateOrder(order: number = 0): void {
|
|
59
|
+
if (order !== this._order) {
|
|
60
|
+
this._order = order;
|
|
61
|
+
this.dispatchGlobalEvent<ReSortVariableDeclarationsAction>({
|
|
62
|
+
type: 'ReSortVariableDeclarations',
|
|
63
|
+
});
|
|
64
|
+
this.fireChange();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Serialize the `VariableDeclaration` to `VariableDeclarationJSON`.
|
|
70
|
+
* @returns The JSON representation of `VariableDeclaration`.
|
|
71
|
+
*/
|
|
72
|
+
toJSON(): VariableDeclarationJSON<VariableMeta> {
|
|
73
|
+
return {
|
|
74
|
+
...super.toJSON(),
|
|
75
|
+
order: this.order,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type Observable,
|
|
8
|
+
distinctUntilChanged,
|
|
9
|
+
map,
|
|
10
|
+
switchMap,
|
|
11
|
+
combineLatest,
|
|
12
|
+
of,
|
|
13
|
+
Subject,
|
|
14
|
+
share,
|
|
15
|
+
} from 'rxjs';
|
|
16
|
+
import { shallowEqual } from 'fast-equals';
|
|
17
|
+
|
|
18
|
+
import { getParentFields } from '../utils/variable-field';
|
|
19
|
+
import { ASTNodeJSON, type CreateASTParams } from '../types';
|
|
20
|
+
import { type BaseType } from '../type';
|
|
21
|
+
import { ASTNodeFlags } from '../flags';
|
|
22
|
+
import { type BaseVariableField } from '../declaration';
|
|
23
|
+
import { ASTNode } from '../ast-node';
|
|
24
|
+
import { subsToDisposable } from '../../utils/toDisposable';
|
|
25
|
+
import { IVariableTable } from '../../scope/types';
|
|
26
|
+
|
|
27
|
+
type ExpressionRefs = (BaseVariableField | undefined)[];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Base class for all expressions.
|
|
31
|
+
*
|
|
32
|
+
* All other expressions should extend this class.
|
|
33
|
+
*/
|
|
34
|
+
export abstract class BaseExpression<JSON extends ASTNodeJSON = any> extends ASTNode<JSON> {
|
|
35
|
+
public flags: ASTNodeFlags = ASTNodeFlags.Expression;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the global variable table, which is used to access referenced variables.
|
|
39
|
+
*/
|
|
40
|
+
get globalVariableTable(): IVariableTable {
|
|
41
|
+
return this.scope.variableEngine.globalVariableTable;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parent variable fields, sorted from closest to farthest.
|
|
46
|
+
*/
|
|
47
|
+
get parentFields(): BaseVariableField[] {
|
|
48
|
+
return getParentFields(this);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the variable fields referenced by the expression.
|
|
53
|
+
*
|
|
54
|
+
* This method should be implemented by subclasses.
|
|
55
|
+
* @returns An array of referenced variable fields.
|
|
56
|
+
*/
|
|
57
|
+
abstract getRefFields(): ExpressionRefs;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The return type of the expression.
|
|
61
|
+
*/
|
|
62
|
+
abstract returnType: BaseType | undefined;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The variable fields referenced by the expression.
|
|
66
|
+
*/
|
|
67
|
+
protected _refs: ExpressionRefs = [];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The variable fields referenced by the expression.
|
|
71
|
+
*/
|
|
72
|
+
get refs(): ExpressionRefs {
|
|
73
|
+
return this._refs;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected refreshRefs$: Subject<void> = new Subject();
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Refresh the variable references.
|
|
80
|
+
*/
|
|
81
|
+
refreshRefs() {
|
|
82
|
+
this.refreshRefs$.next();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* An observable that emits the referenced variable fields when they change.
|
|
87
|
+
*/
|
|
88
|
+
refs$: Observable<ExpressionRefs> = this.refreshRefs$.pipe(
|
|
89
|
+
map(() => this.getRefFields()),
|
|
90
|
+
distinctUntilChanged<ExpressionRefs>(shallowEqual),
|
|
91
|
+
switchMap((refs) =>
|
|
92
|
+
!refs?.length
|
|
93
|
+
? of([])
|
|
94
|
+
: combineLatest(
|
|
95
|
+
refs.map((ref) =>
|
|
96
|
+
ref
|
|
97
|
+
? (ref.value$ as unknown as Observable<BaseVariableField | undefined>)
|
|
98
|
+
: of(undefined)
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
),
|
|
102
|
+
share()
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
constructor(params: CreateASTParams, opts?: any) {
|
|
106
|
+
super(params, opts);
|
|
107
|
+
|
|
108
|
+
this.toDispose.push(
|
|
109
|
+
subsToDisposable(
|
|
110
|
+
this.refs$.subscribe((_refs: ExpressionRefs) => {
|
|
111
|
+
this._refs = _refs;
|
|
112
|
+
this.fireChange();
|
|
113
|
+
})
|
|
114
|
+
)
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ASTKind, ASTNodeJSON } from '../types';
|
|
7
|
+
import { ArrayType } from '../type/array';
|
|
8
|
+
import { BaseType } from '../type';
|
|
9
|
+
import { BaseExpression } from './base-expression';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ASTNodeJSON representation of `EnumerateExpression`
|
|
13
|
+
*/
|
|
14
|
+
export interface EnumerateExpressionJSON {
|
|
15
|
+
/**
|
|
16
|
+
* The expression to be enumerated.
|
|
17
|
+
*/
|
|
18
|
+
enumerateFor: ASTNodeJSON;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Represents an enumeration expression, which iterates over a list and returns the type of the enumerated variable.
|
|
23
|
+
*/
|
|
24
|
+
export class EnumerateExpression extends BaseExpression<EnumerateExpressionJSON> {
|
|
25
|
+
static kind: string = ASTKind.EnumerateExpression;
|
|
26
|
+
|
|
27
|
+
protected _enumerateFor: BaseExpression | undefined;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The expression to be enumerated.
|
|
31
|
+
*/
|
|
32
|
+
get enumerateFor() {
|
|
33
|
+
return this._enumerateFor;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The return type of the expression.
|
|
38
|
+
*/
|
|
39
|
+
get returnType(): BaseType | undefined {
|
|
40
|
+
// The return value of the enumerated expression.
|
|
41
|
+
const childReturnType = this.enumerateFor?.returnType;
|
|
42
|
+
|
|
43
|
+
if (childReturnType?.kind === ASTKind.Array) {
|
|
44
|
+
// Get the item type of the array.
|
|
45
|
+
return (childReturnType as ArrayType).items;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the variable fields referenced by the expression.
|
|
53
|
+
* @returns An empty array, as this expression does not reference any variables.
|
|
54
|
+
*/
|
|
55
|
+
getRefFields(): [] {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Deserializes the `EnumerateExpressionJSON` to the `EnumerateExpression`.
|
|
61
|
+
* @param json The `EnumerateExpressionJSON` to deserialize.
|
|
62
|
+
*/
|
|
63
|
+
fromJSON({ enumerateFor: expression }: EnumerateExpressionJSON): void {
|
|
64
|
+
this.updateChildNodeByKey('_enumerateFor', expression);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Serialize the `EnumerateExpression` to `EnumerateExpressionJSON`.
|
|
69
|
+
* @returns The JSON representation of `EnumerateExpression`.
|
|
70
|
+
*/
|
|
71
|
+
toJSON() {
|
|
72
|
+
return {
|
|
73
|
+
kind: ASTKind.EnumerateExpression,
|
|
74
|
+
enumerateFor: this.enumerateFor?.toJSON(),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { BaseExpression } from './base-expression';
|
|
7
|
+
export { EnumerateExpression, type EnumerateExpressionJSON } from './enumerate-expression';
|
|
8
|
+
export { KeyPathExpression, type KeyPathExpressionJSON } from './keypath-expression';
|
|
9
|
+
export { LegacyKeyPathExpression } from './legacy-keypath-expression';
|
|
10
|
+
export { WrapArrayExpression, type WrapArrayExpressionJSON } from './wrap-array-expression';
|