@hadss/turbo-trans-json-plugin 1.0.0-rc.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 +177 -0
- package/README.md +253 -0
- package/dist/core/Types.d.ts +196 -0
- package/dist/core/Types.js +47 -0
- package/dist/core/analyzers/ClassAnalyzer.d.ts +23 -0
- package/dist/core/analyzers/ClassAnalyzer.js +480 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +21 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.js +243 -0
- package/dist/core/analyzers/SendableMergeChecker.d.ts +9 -0
- package/dist/core/analyzers/SendableMergeChecker.js +100 -0
- package/dist/core/analyzers/SendableMergeabilityRegistry.d.ts +7 -0
- package/dist/core/analyzers/SendableMergeabilityRegistry.js +23 -0
- package/dist/core/constants/DecoratorConstants.d.ts +7 -0
- package/dist/core/constants/DecoratorConstants.js +13 -0
- package/dist/core/constants/PathConstants.d.ts +6 -0
- package/dist/core/constants/PathConstants.js +10 -0
- package/dist/core/constants/StringConstants.d.ts +83 -0
- package/dist/core/constants/StringConstants.js +87 -0
- package/dist/core/constants/index.d.ts +3 -0
- package/dist/core/constants/index.js +19 -0
- package/dist/core/handlers/BaseTypeHandler.d.ts +23 -0
- package/dist/core/handlers/BaseTypeHandler.js +57 -0
- package/dist/core/handlers/CustomClassHandler.d.ts +21 -0
- package/dist/core/handlers/CustomClassHandler.js +191 -0
- package/dist/core/handlers/DateHandler.d.ts +2 -0
- package/dist/core/handlers/DateHandler.js +60 -0
- package/dist/core/handlers/DecimalHandler.d.ts +2 -0
- package/dist/core/handlers/DecimalHandler.js +60 -0
- package/dist/core/handlers/EnumHandler.d.ts +2 -0
- package/dist/core/handlers/EnumHandler.js +89 -0
- package/dist/core/handlers/GenericContainerHandler.d.ts +2 -0
- package/dist/core/handlers/GenericContainerHandler.js +440 -0
- package/dist/core/handlers/GenericHandler.d.ts +18 -0
- package/dist/core/handlers/GenericHandler.js +92 -0
- package/dist/core/handlers/HandlerBootstrap.d.ts +2 -0
- package/dist/core/handlers/HandlerBootstrap.js +28 -0
- package/dist/core/handlers/ITypeHandler.d.ts +23 -0
- package/dist/core/handlers/ITypeHandler.js +8 -0
- package/dist/core/handlers/PrimitiveHandler.d.ts +2 -0
- package/dist/core/handlers/PrimitiveHandler.js +127 -0
- package/dist/core/handlers/TupleHandler.d.ts +2 -0
- package/dist/core/handlers/TupleHandler.js +98 -0
- package/dist/core/handlers/TypeHandlerRegistry.d.ts +20 -0
- package/dist/core/handlers/TypeHandlerRegistry.js +113 -0
- package/dist/core/handlers/UnionTypeHandler.d.ts +2 -0
- package/dist/core/handlers/UnionTypeHandler.js +263 -0
- package/dist/core/handlers/index.d.ts +2 -0
- package/dist/core/handlers/index.js +5 -0
- package/dist/core/import-rewrite/services/BuildProfileUpdater.d.ts +8 -0
- package/dist/core/import-rewrite/services/BuildProfileUpdater.js +92 -0
- package/dist/core/import-rewrite/services/ImportRewriteService.d.ts +9 -0
- package/dist/core/import-rewrite/services/ImportRewriteService.js +61 -0
- package/dist/core/import-rewrite/services/ImportTransformService.d.ts +15 -0
- package/dist/core/import-rewrite/services/ImportTransformService.js +109 -0
- package/dist/core/import-rewrite/strategies/ImportScanStrategy.d.ts +17 -0
- package/dist/core/import-rewrite/strategies/ImportScanStrategy.js +137 -0
- package/dist/core/import-rewrite/types/ImportRewriteTypes.d.ts +17 -0
- package/dist/core/import-rewrite/types/ImportRewriteTypes.js +2 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +27 -0
- package/dist/core/interfaces/ITask.d.ts +7 -0
- package/dist/core/interfaces/ITask.js +2 -0
- package/dist/core/interfaces/ITaskContext.d.ts +11 -0
- package/dist/core/interfaces/ITaskContext.js +2 -0
- package/dist/core/interfaces/index.d.ts +2 -0
- package/dist/core/interfaces/index.js +2 -0
- package/dist/core/logger/Logger.d.ts +13 -0
- package/dist/core/logger/Logger.js +78 -0
- package/dist/core/services/CodeAnalysisService.d.ts +7 -0
- package/dist/core/services/CodeAnalysisService.js +43 -0
- package/dist/core/services/CodeGenerationEngine.d.ts +12 -0
- package/dist/core/services/CodeGenerationEngine.js +102 -0
- package/dist/core/services/CodeGenerationService/CodeGenerationService.d.ts +13 -0
- package/dist/core/services/CodeGenerationService/CodeGenerationService.js +110 -0
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +13 -0
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +119 -0
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +21 -0
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +224 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +24 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +307 -0
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.d.ts +28 -0
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +259 -0
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.d.ts +19 -0
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +178 -0
- package/dist/core/services/CodeGenerationService/index.d.ts +1 -0
- package/dist/core/services/CodeGenerationService/index.js +5 -0
- package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +27 -0
- package/dist/core/services/CodeGenerationService/shared/ImportManager.js +127 -0
- package/dist/core/template/HandlebarsTemplateEngine.d.ts +26 -0
- package/dist/core/template/HandlebarsTemplateEngine.js +226 -0
- package/dist/core/utils/ConfigManager.d.ts +10 -0
- package/dist/core/utils/ConfigManager.js +32 -0
- package/dist/core/utils/CustomError.d.ts +30 -0
- package/dist/core/utils/CustomError.js +37 -0
- package/dist/core/utils/DeepCopyUtil.d.ts +15 -0
- package/dist/core/utils/DeepCopyUtil.js +138 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +9 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.js +68 -0
- package/dist/core/utils/SerializationPathUtil.d.ts +18 -0
- package/dist/core/utils/SerializationPathUtil.js +107 -0
- package/dist/core/utils/TsMorphUtil.d.ts +8 -0
- package/dist/core/utils/TsMorphUtil.js +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +57 -0
- package/dist/json-plugin/JSONExecuteController.d.ts +13 -0
- package/dist/json-plugin/JSONExecuteController.js +103 -0
- package/dist/json-plugin/constants/TaskConstants.d.ts +7 -0
- package/dist/json-plugin/constants/TaskConstants.js +11 -0
- package/dist/json-plugin/interfaces/IModuleContext.d.ts +10 -0
- package/dist/json-plugin/interfaces/IModuleContext.js +2 -0
- package/dist/json-plugin/interfaces/ITargetContext.d.ts +8 -0
- package/dist/json-plugin/interfaces/ITargetContext.js +2 -0
- package/dist/json-plugin/interfaces/impl/ModuleContext.d.ts +12 -0
- package/dist/json-plugin/interfaces/impl/ModuleContext.js +24 -0
- package/dist/json-plugin/interfaces/impl/TargetContext.d.ts +23 -0
- package/dist/json-plugin/interfaces/impl/TargetContext.js +113 -0
- package/dist/json-plugin/tasks/BaseTask.d.ts +14 -0
- package/dist/json-plugin/tasks/BaseTask.js +53 -0
- package/dist/json-plugin/tasks/CleanTask.d.ts +8 -0
- package/dist/json-plugin/tasks/CleanTask.js +25 -0
- package/dist/json-plugin/tasks/CodeProcessingTask.d.ts +8 -0
- package/dist/json-plugin/tasks/CodeProcessingTask.js +26 -0
- package/dist/json-plugin/tasks/SyncTask.d.ts +8 -0
- package/dist/json-plugin/tasks/SyncTask.js +21 -0
- package/dist/json-plugin/tasks/WatchTask.d.ts +11 -0
- package/dist/json-plugin/tasks/WatchTask.js +102 -0
- package/package.json +46 -0
- package/src/core/Types.ts +356 -0
- package/src/core/analyzers/ClassAnalyzer.ts +824 -0
- package/src/core/analyzers/CustomTypeAnalyzer.ts +337 -0
- package/src/core/analyzers/SendableMergeChecker.ts +195 -0
- package/src/core/analyzers/SendableMergeabilityRegistry.ts +72 -0
- package/src/core/constants/DecoratorConstants.ts +27 -0
- package/src/core/constants/PathConstants.ts +31 -0
- package/src/core/constants/StringConstants.ts +152 -0
- package/src/core/constants/index.ts +21 -0
- package/src/core/handlers/BaseTypeHandler.ts +121 -0
- package/src/core/handlers/CustomClassHandler.ts +278 -0
- package/src/core/handlers/DateHandler.ts +75 -0
- package/src/core/handlers/DecimalHandler.ts +75 -0
- package/src/core/handlers/EnumHandler.ts +142 -0
- package/src/core/handlers/GenericContainerHandler.ts +621 -0
- package/src/core/handlers/GenericHandler.ts +130 -0
- package/src/core/handlers/HandlerBootstrap.ts +64 -0
- package/src/core/handlers/ITypeHandler.ts +133 -0
- package/src/core/handlers/PrimitiveHandler.ts +159 -0
- package/src/core/handlers/TupleHandler.ts +145 -0
- package/src/core/handlers/TypeHandlerRegistry.ts +236 -0
- package/src/core/handlers/UnionTypeHandler.ts +400 -0
- package/src/core/handlers/index.ts +18 -0
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +145 -0
- package/src/core/import-rewrite/services/ImportRewriteService.ts +129 -0
- package/src/core/import-rewrite/services/ImportTransformService.ts +200 -0
- package/src/core/import-rewrite/strategies/ImportScanStrategy.ts +303 -0
- package/src/core/import-rewrite/types/ImportRewriteTypes.ts +100 -0
- package/src/core/index.ts +31 -0
- package/src/core/interfaces/ITask.ts +23 -0
- package/src/core/interfaces/ITaskContext.ts +94 -0
- package/src/core/interfaces/index.ts +17 -0
- package/src/core/logger/Logger.ts +149 -0
- package/src/core/services/CodeAnalysisService.ts +67 -0
- package/src/core/services/CodeGenerationEngine.ts +181 -0
- package/src/core/services/CodeGenerationService/CodeGenerationService.ts +159 -0
- package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +189 -0
- package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +314 -0
- package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +421 -0
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +392 -0
- package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +277 -0
- package/src/core/services/CodeGenerationService/index.ts +16 -0
- package/src/core/services/CodeGenerationService/shared/ImportManager.ts +191 -0
- package/src/core/template/HandlebarsTemplateEngine.ts +282 -0
- package/src/core/utils/ConfigManager.ts +49 -0
- package/src/core/utils/CustomError.ts +51 -0
- package/src/core/utils/DeepCopyUtil.ts +185 -0
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +136 -0
- package/src/core/utils/SerializationPathUtil.ts +142 -0
- package/src/core/utils/TsMorphUtil.ts +50 -0
- package/src/index.ts +81 -0
- package/src/json-plugin/JSONExecuteController.ts +134 -0
- package/src/json-plugin/constants/TaskConstants.ts +22 -0
- package/src/json-plugin/interfaces/IModuleContext.ts +27 -0
- package/src/json-plugin/interfaces/ITargetContext.ts +25 -0
- package/src/json-plugin/interfaces/impl/ModuleContext.ts +45 -0
- package/src/json-plugin/interfaces/impl/TargetContext.ts +196 -0
- package/src/json-plugin/tasks/BaseTask.ts +94 -0
- package/src/json-plugin/tasks/CleanTask.ts +36 -0
- package/src/json-plugin/tasks/CodeProcessingTask.ts +41 -0
- package/src/json-plugin/tasks/SyncTask.ts +33 -0
- package/src/json-plugin/tasks/WatchTask.ts +99 -0
- package/template/SerializerPerformanceTemplate.hbs +35 -0
- package/template/SerializerRegisterTemplate.hbs +10 -0
- package/template/SerializerStrictTemplate.hbs +89 -0
- package/template/SerializerTemplate.hbs +176 -0
- package/tsconfig.json +17 -0
- package/tslint.json +3 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { TypeNode, SyntaxKind, InferTypeNode } from 'ts-morph';
|
|
17
|
+
import { ITypeHandler, TypeContext } from './ITypeHandler';
|
|
18
|
+
import { PropertyKind, TypeStructure, Logger } from '..';
|
|
19
|
+
import { CustomError, ErrorCodes } from '../utils/CustomError';
|
|
20
|
+
|
|
21
|
+
export class TypeHandlerRegistry {
|
|
22
|
+
private static instance: TypeHandlerRegistry;
|
|
23
|
+
|
|
24
|
+
/** 所有已注册的处理器(按注册顺序) */
|
|
25
|
+
private handlers: ITypeHandler[] = [];
|
|
26
|
+
|
|
27
|
+
/** Kind到Handler的快速查找表 */
|
|
28
|
+
private kindMap: Map<PropertyKind, ITypeHandler> = new Map();
|
|
29
|
+
|
|
30
|
+
/** 类型名称到Handler的快速查找表(支持多个候选) */
|
|
31
|
+
private nameMap: Map<string, ITypeHandler[]> = new Map();
|
|
32
|
+
|
|
33
|
+
private constructor() { }
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 获取单例实例
|
|
37
|
+
*/
|
|
38
|
+
static getInstance(): TypeHandlerRegistry {
|
|
39
|
+
if (!TypeHandlerRegistry.instance) {
|
|
40
|
+
TypeHandlerRegistry.instance = new TypeHandlerRegistry();
|
|
41
|
+
}
|
|
42
|
+
return TypeHandlerRegistry.instance;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ==================== 注册管理 ====================
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 注册类型处理器
|
|
49
|
+
* @param handler 类型处理器实例
|
|
50
|
+
*/
|
|
51
|
+
register(handler: ITypeHandler): void {
|
|
52
|
+
// 添加到列表
|
|
53
|
+
this.handlers.push(handler);
|
|
54
|
+
|
|
55
|
+
// 按优先级排序(优先级高的在前)
|
|
56
|
+
this.handlers.sort((a, b) => b.priority - a.priority);
|
|
57
|
+
|
|
58
|
+
// 更新Kind映射(只保留最高优先级)
|
|
59
|
+
const existingHandler = this.kindMap.get(handler.kind);
|
|
60
|
+
if (!existingHandler || handler.priority > existingHandler.priority) {
|
|
61
|
+
this.kindMap.set(handler.kind, handler);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 更新类型名称映射(支持多个候选)
|
|
65
|
+
const typeName = this.extractTypeName(handler.kind);
|
|
66
|
+
const candidates = this.nameMap.get(typeName) || [];
|
|
67
|
+
candidates.push(handler);
|
|
68
|
+
candidates.sort((a, b) => b.priority - a.priority);
|
|
69
|
+
this.nameMap.set(typeName, candidates);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 批量注册处理器
|
|
74
|
+
* @param handlers 处理器数组
|
|
75
|
+
*/
|
|
76
|
+
registerAll(handlers: ITypeHandler[]): void {
|
|
77
|
+
handlers.forEach((handler) => this.register(handler));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ==================== 处理器查找 ====================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 根据PropertyKind查找处理器
|
|
84
|
+
* @param kind PropertyKind
|
|
85
|
+
* @returns 对应的处理器,如果不存在返回undefined
|
|
86
|
+
*/
|
|
87
|
+
getHandlerForKind(kind: PropertyKind): ITypeHandler {
|
|
88
|
+
const handler = this.kindMap.get(kind);
|
|
89
|
+
if (!handler) {
|
|
90
|
+
// 理论上走不到这里来
|
|
91
|
+
throw new CustomError(`No handler for kind: ${kind}`, ErrorCodes.HANDLER_NOT_FOUND);
|
|
92
|
+
}
|
|
93
|
+
return handler;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 根据类型节点查找匹配的处理器
|
|
98
|
+
* @param typeNode AST类型节点
|
|
99
|
+
* @param context 上下文
|
|
100
|
+
* @returns 匹配的处理器,如果没有匹配返回undefined
|
|
101
|
+
*/
|
|
102
|
+
findHandler(typeNode: TypeNode, context: TypeContext): ITypeHandler | undefined {
|
|
103
|
+
const typeName = typeNode.getText();
|
|
104
|
+
|
|
105
|
+
// 策略1: 先尝试类型名称精确匹配
|
|
106
|
+
const candidates = this.nameMap.get(this.normalizeTypeName(typeName));
|
|
107
|
+
if (candidates && candidates.length > 0) {
|
|
108
|
+
for (const handler of candidates) {
|
|
109
|
+
if (handler.matches(typeNode, context)) {
|
|
110
|
+
return handler;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 策略2: 遍历所有处理器(按优先级顺序)
|
|
116
|
+
for (const handler of this.handlers) {
|
|
117
|
+
if (handler.matches(typeNode, context)) {
|
|
118
|
+
return handler;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Logger.warn(`No handler found for type: ${typeName}`);
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ==================== 类型解析入口 ====================
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 解析类型节点为类型结构
|
|
130
|
+
* @param typeNode AST类型节点
|
|
131
|
+
* @param context 类型上下文
|
|
132
|
+
* @returns 类型结构
|
|
133
|
+
*/
|
|
134
|
+
parseType(typeNode: TypeNode, context: TypeContext): TypeStructure {
|
|
135
|
+
|
|
136
|
+
// 字面量类型检测:除了 null 和 undefined,其他字面量类型都不支持
|
|
137
|
+
if (typeNode.getKind() === SyntaxKind.LiteralType) {
|
|
138
|
+
const literal = typeNode.asKindOrThrow(SyntaxKind.LiteralType);
|
|
139
|
+
const literalValue = literal.getLiteral();
|
|
140
|
+
const literalKind = literalValue.getKind();
|
|
141
|
+
|
|
142
|
+
// 允许 null 和 undefined 字面量
|
|
143
|
+
if (literalKind !== SyntaxKind.NullKeyword && literalKind !== SyntaxKind.UndefinedKeyword) {
|
|
144
|
+
throw new CustomError(
|
|
145
|
+
`不支持字面量类型 '${typeNode.getText()}'(无论出现在何处)。\n` +
|
|
146
|
+
`不支持的字面量类型包括:字符串字面量(如 'admin')、数字字面量(如 123)、布尔字面量(如 true)。\n` +
|
|
147
|
+
`即使在联合类型、Type 别名、泛型参数中使用字面量也不支持。\n` +
|
|
148
|
+
`请使用基础类型:string、number、boolean 替代字面量类型。`,
|
|
149
|
+
ErrorCodes.LITERAL_NOT_SOPPORT);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 处理 ParenthesizedType (括号类型)例如 (string|number)
|
|
154
|
+
if (typeNode.getKind() === SyntaxKind.ParenthesizedType) {
|
|
155
|
+
// 对于括号类型,我们解析其内部的类型
|
|
156
|
+
const parenthesizedType = typeNode.asKindOrThrow(SyntaxKind.ParenthesizedType);
|
|
157
|
+
const innerTypeNode = parenthesizedType.getTypeNode();
|
|
158
|
+
|
|
159
|
+
// 递归解析括号内的类型
|
|
160
|
+
return this.parseType(innerTypeNode, context);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const handler = this.findHandler(typeNode, context);
|
|
164
|
+
if (!handler) {
|
|
165
|
+
// 容错机制:找不到处理器时返回 UNKNOWN 类型
|
|
166
|
+
// ClassAnalyzer 会检查是否有 @Transient 注解来决定如何处理
|
|
167
|
+
const typeName = typeNode.getText();
|
|
168
|
+
Logger.warn(`No handler found for type: ${typeName}, marking as UNKNOWN`);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
kind: PropertyKind.UNKNOWN,
|
|
172
|
+
depth: 0,
|
|
173
|
+
sourceText: typeName,
|
|
174
|
+
args: [],
|
|
175
|
+
dependencies: []
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return handler.parse(typeNode, context);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ==================== 代码生成入口 ====================
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 生成序列化器实例化代码
|
|
186
|
+
* @param structure 类型结构
|
|
187
|
+
* @returns 实例化代码字符串
|
|
188
|
+
*/
|
|
189
|
+
generateInstantiation(structure: TypeStructure): string {
|
|
190
|
+
const handler = this.getHandlerForKind(structure.kind);
|
|
191
|
+
|
|
192
|
+
return handler.generateInstantiation(structure);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
generateTypeKey(structure: TypeStructure): string {
|
|
196
|
+
const handler = this.getHandlerForKind(structure.kind);
|
|
197
|
+
|
|
198
|
+
return handler.generateTypeKey(structure);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ==================== 辅助方法 ====================
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 从PropertyKind提取类型名称
|
|
205
|
+
* @param kind PropertyKind
|
|
206
|
+
* @returns 类型名称
|
|
207
|
+
* @example 'string' -> 'string', 'array' -> 'Array', 'collections.Array' -> 'Array'
|
|
208
|
+
*/
|
|
209
|
+
private extractTypeName(kind: PropertyKind): string {
|
|
210
|
+
// 处理collections.*类型
|
|
211
|
+
if (kind.startsWith('collections.')) {
|
|
212
|
+
return kind.split('.')[1];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 基础类型直接返回
|
|
216
|
+
return kind;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 规范化类型名称(用于查找)
|
|
221
|
+
* @param typeName 原始类型名称
|
|
222
|
+
* @returns 规范化后的名称
|
|
223
|
+
* @example 'Array<string>' -> 'Array', 'collections.Array<T>' -> 'Array'
|
|
224
|
+
*/
|
|
225
|
+
private normalizeTypeName(typeName: string): string {
|
|
226
|
+
// 移除泛型参数
|
|
227
|
+
const withoutGenerics = typeName.split('<')[0].trim();
|
|
228
|
+
|
|
229
|
+
// 处理collections.*
|
|
230
|
+
if (withoutGenerics.startsWith('collections.')) {
|
|
231
|
+
return withoutGenerics.split('.')[1];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return withoutGenerics;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { TypeNode, SyntaxKind, UnionTypeNode } from 'ts-morph';
|
|
17
|
+
import { PropertyKind, TypeStructure, SerializerMetadata, TypeDependency } from '../Types';
|
|
18
|
+
import { ITypeHandler, TypeContext, ConversionDirection } from './ITypeHandler';
|
|
19
|
+
import { BaseTypeHandler } from './BaseTypeHandler';
|
|
20
|
+
import { CustomError, ErrorCodes } from '../utils/CustomError';
|
|
21
|
+
|
|
22
|
+
type UnionPattern = 'optional' | 'nullable' | 'union' | 'optionalNullable';
|
|
23
|
+
|
|
24
|
+
abstract class UnionTypeHandler extends BaseTypeHandler implements ITypeHandler {
|
|
25
|
+
abstract readonly name: string;
|
|
26
|
+
abstract readonly kind: PropertyKind;
|
|
27
|
+
abstract readonly priority: number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 子类指定支持的联合类型模式
|
|
31
|
+
*/
|
|
32
|
+
protected abstract readonly supportedPattern: UnionPattern;
|
|
33
|
+
|
|
34
|
+
// ==================== 阶段1: 类型识别 ====================
|
|
35
|
+
|
|
36
|
+
matches(typeNode: TypeNode): boolean {
|
|
37
|
+
// 必须是UnionType
|
|
38
|
+
if (typeNode.getKind() !== SyntaxKind.UnionType) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const unionType = typeNode as UnionTypeNode;
|
|
43
|
+
const memberTypes = unionType.getTypeNodes();
|
|
44
|
+
|
|
45
|
+
// 辅助函数:检查是否为 null 类型节点
|
|
46
|
+
const isNullType = (t: TypeNode): boolean => {
|
|
47
|
+
return t.getKind() === SyntaxKind.LiteralType && t.getText() === 'null';
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// 辅助函数:检查是否为 undefined 类型节点
|
|
51
|
+
const isUndefinedType = (t: TypeNode): boolean => {
|
|
52
|
+
return t.getKind() === SyntaxKind.UndefinedKeyword;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// 根据supportedPattern匹配不同的联合类型模式
|
|
56
|
+
switch (this.supportedPattern) {
|
|
57
|
+
case 'optional':
|
|
58
|
+
// T | undefined (必须是2个成员,其中一个是undefined,另一个不是null)
|
|
59
|
+
if (memberTypes.length !== 2) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const hasUndefined = memberTypes.some(isUndefinedType);
|
|
63
|
+
const hasNull = memberTypes.some(isNullType);
|
|
64
|
+
// 确保有undefined,但另一个成员不是null
|
|
65
|
+
return hasUndefined && !hasNull;
|
|
66
|
+
|
|
67
|
+
case 'nullable':
|
|
68
|
+
// T | null (必须是2个成员,其中一个是null,另一个不是undefined)
|
|
69
|
+
if (memberTypes.length !== 2) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const hasNullable = memberTypes.some(isNullType);
|
|
73
|
+
const hasUndefinedNullable = memberTypes.some(isUndefinedType);
|
|
74
|
+
// 确保有null,但另一个成员不是undefined
|
|
75
|
+
return hasNullable && !hasUndefinedNullable;
|
|
76
|
+
|
|
77
|
+
case 'optionalNullable':
|
|
78
|
+
// T | null | undefined (必须是3个成员,包含null和undefined,还有一个其他类型)
|
|
79
|
+
return memberTypes.length === 3 &&
|
|
80
|
+
memberTypes.some(isNullType) &&
|
|
81
|
+
memberTypes.some(isUndefinedType);
|
|
82
|
+
|
|
83
|
+
case 'union':
|
|
84
|
+
// 普通联合类型(其他所有联合类型)
|
|
85
|
+
return true;
|
|
86
|
+
|
|
87
|
+
default:
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ==================== 阶段2: 类型解析 ====================
|
|
93
|
+
|
|
94
|
+
parse(typeNode: TypeNode, context: TypeContext): TypeStructure {
|
|
95
|
+
const unionType = typeNode as UnionTypeNode;
|
|
96
|
+
|
|
97
|
+
// 统一解析所有成员类型
|
|
98
|
+
const members = this.parseUnionMembers(unionType, context);
|
|
99
|
+
|
|
100
|
+
// 收集所有依赖
|
|
101
|
+
const allDependencies: TypeDependency[] = [];
|
|
102
|
+
let maxDepth = 0;
|
|
103
|
+
members.forEach(member => {
|
|
104
|
+
allDependencies.push(...member.dependencies);
|
|
105
|
+
maxDepth = Math.max(maxDepth, member.depth);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
kind: this.kind,
|
|
110
|
+
depth: this.supportedPattern === 'union' ? 0 : maxDepth + 1,
|
|
111
|
+
sourceText: typeNode.getText(),
|
|
112
|
+
args: [],
|
|
113
|
+
dependencies: allDependencies,
|
|
114
|
+
unionDetails: members
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ==================== 阶段3: 序列化器配置 ====================
|
|
119
|
+
|
|
120
|
+
getSerializerMetadata(structure: TypeStructure, withParam?: string): SerializerMetadata {
|
|
121
|
+
const serializerName = this.getSerializerName();
|
|
122
|
+
const defaultInstantiation = this.generateInstantiation(structure);
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
name: serializerName,
|
|
126
|
+
typeDeclaration: this.generateTypeDeclaration(structure),
|
|
127
|
+
instantiationTemplate: this.applyWithParam(withParam, defaultInstantiation, structure),
|
|
128
|
+
encodeMethod: 'encodeSerializableElement',
|
|
129
|
+
decodeMethod: 'deserialize',
|
|
130
|
+
decoderType: `${structure.sourceText} | undefined`,
|
|
131
|
+
needsTypeAssertion: false
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ==================== 阶段4: 代码生成 ====================
|
|
136
|
+
|
|
137
|
+
generateInstantiation(structure: TypeStructure): string {
|
|
138
|
+
if (!structure.unionDetails || structure.unionDetails.length === 0) {
|
|
139
|
+
throw new CustomError(`${this.name}: missing unionDetails`, ErrorCodes.UNION_STRUCTURE_NOT_FOUND);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const serializerName = this.getSerializerName();
|
|
143
|
+
|
|
144
|
+
// 处理Optional/Nullable/OptionalNullable模式
|
|
145
|
+
if (this.isOptionalOrNullablePattern()) {
|
|
146
|
+
return this.generateOptionalNullableInstantiation(structure);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Union: 所有成员类型
|
|
150
|
+
const primitiveTypes = ['undefined', 'null', 'boolean', 'number', 'string', 'bigint'];
|
|
151
|
+
const unionTypes = structure.unionDetails.map(member => {
|
|
152
|
+
return primitiveTypes.includes(member.sourceText)
|
|
153
|
+
? `'${member.sourceText}'`
|
|
154
|
+
: member.sourceText;
|
|
155
|
+
}).join(', ');
|
|
156
|
+
|
|
157
|
+
const typeDeclaration = structure.unionDetails.map(member => member.sourceText).join(' | ');
|
|
158
|
+
return `new ${serializerName}<${typeDeclaration}>([${unionTypes}])`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
generateTypeDeclaration(structure: TypeStructure): string {
|
|
162
|
+
if (!structure.unionDetails || structure.unionDetails.length === 0) {
|
|
163
|
+
throw new CustomError(`${this.name}: missing unionDetails`, ErrorCodes.UNION_STRUCTURE_NOT_FOUND);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const serializerName = this.getSerializerName();
|
|
167
|
+
|
|
168
|
+
// 处理Optional/Nullable/OptionalNullable模式
|
|
169
|
+
if (this.isOptionalOrNullablePattern()) {
|
|
170
|
+
const innerMember = this.getInnerMember(structure);
|
|
171
|
+
if (!innerMember) {
|
|
172
|
+
throw new CustomError(`${this.name}: cannot find inner member`, ErrorCodes.UNION_INNER_NOT_FOUND);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return `${serializerName}<${innerMember.sourceText}>`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Union: 所有成员类型
|
|
179
|
+
const typeDeclaration = structure.unionDetails.map(member => member.sourceText).join(' | ');
|
|
180
|
+
return `${serializerName}<${typeDeclaration}>`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
generateTypeKey(structure: TypeStructure): string {
|
|
184
|
+
if (!structure.unionDetails || structure.unionDetails.length === 0) {
|
|
185
|
+
throw new CustomError(`${this.name}: missing unionDetails`, ErrorCodes.UNION_STRUCTURE_NOT_FOUND);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 处理Optional/Nullable/OptionalNullable模式
|
|
189
|
+
if (this.isOptionalOrNullablePattern()) {
|
|
190
|
+
return this.generateOptionalNullableTypeKey(structure);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Union: 所有成员typeKey的数组
|
|
194
|
+
const memberTypeKeys = structure.unionDetails.map(member => {
|
|
195
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
196
|
+
const handler = TypeHandlerRegistry.getInstance().getHandlerForKind(member.kind);
|
|
197
|
+
return handler.generateTypeKey(member);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return `[${memberTypeKeys.join(', ')}]`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ==================== Protected 工具方法 ====================
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 检查是否为Optional、Nullable或OptionalNullable模式
|
|
207
|
+
*/
|
|
208
|
+
protected isOptionalOrNullablePattern(): boolean {
|
|
209
|
+
return this.supportedPattern === 'optional' ||
|
|
210
|
+
this.supportedPattern === 'nullable' ||
|
|
211
|
+
this.supportedPattern === 'optionalNullable';
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 获取Optional/Nullable/OptionalNullable模式的内部成员类型
|
|
216
|
+
*/
|
|
217
|
+
protected getInnerMember(structure: TypeStructure): TypeStructure | undefined {
|
|
218
|
+
switch (this.supportedPattern) {
|
|
219
|
+
case 'optional':
|
|
220
|
+
return structure.unionDetails?.find(m => m.kind !== PropertyKind.UNDEFINED);
|
|
221
|
+
case 'nullable':
|
|
222
|
+
return structure.unionDetails?.find(m => m.kind !== PropertyKind.NULL);
|
|
223
|
+
case 'optionalNullable':
|
|
224
|
+
return structure.unionDetails?.find(m =>
|
|
225
|
+
m.kind !== PropertyKind.NULL && m.kind !== PropertyKind.UNDEFINED
|
|
226
|
+
);
|
|
227
|
+
default:
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* 生成Optional/Nullable/OptionalNullable模式的实例化代码
|
|
234
|
+
*/
|
|
235
|
+
protected generateOptionalNullableInstantiation(structure: TypeStructure): string {
|
|
236
|
+
if (this.supportedPattern === 'optionalNullable' && structure.unionDetails?.length !== 3) {
|
|
237
|
+
throw new CustomError(`${this.name}: expected 3 union members`, ErrorCodes.UNION_EXPEDTED_THREE);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (this.supportedPattern !== 'optionalNullable' && structure.unionDetails?.length !== 2) {
|
|
241
|
+
throw new CustomError(`${this.name}: expected 2 union members`, ErrorCodes.UNION_EXPEDTED_TWO);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const innerMember = this.getInnerMember(structure);
|
|
245
|
+
if (!innerMember) {
|
|
246
|
+
throw new CustomError(`${this.name}: cannot find inner member`, ErrorCodes.UNION_INNER_NOT_FOUND);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const innerType = innerMember.sourceText;
|
|
250
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
251
|
+
const innerHandler = TypeHandlerRegistry.getInstance().getHandlerForKind(innerMember.kind);
|
|
252
|
+
|
|
253
|
+
const innerSerializer = innerHandler.generateInstantiation(innerMember);
|
|
254
|
+
const serializerName = this.getSerializerName();
|
|
255
|
+
return `new ${serializerName}<${innerType}>(${innerSerializer})`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* 生成Optional/Nullable/OptionalNullable模式的类型键
|
|
260
|
+
*/
|
|
261
|
+
protected generateOptionalNullableTypeKey(structure: TypeStructure): string {
|
|
262
|
+
const innerMember = this.getInnerMember(structure);
|
|
263
|
+
if (!innerMember) {
|
|
264
|
+
throw new CustomError(`${this.name}: cannot find inner member`, ErrorCodes.UNION_INNER_NOT_FOUND);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
268
|
+
const innerHandler = TypeHandlerRegistry.getInstance().getHandlerForKind(innerMember.kind);
|
|
269
|
+
const innerTypeKey = innerHandler.generateTypeKey(innerMember);
|
|
270
|
+
|
|
271
|
+
switch (this.supportedPattern) {
|
|
272
|
+
case 'optional':
|
|
273
|
+
return `[${innerTypeKey}, "'undefined'"]`;
|
|
274
|
+
case 'nullable':
|
|
275
|
+
return `[${innerTypeKey}, "'null'"]`;
|
|
276
|
+
case 'optionalNullable':
|
|
277
|
+
return `[${innerTypeKey}, "'null'", "'undefined'"]`;
|
|
278
|
+
default:
|
|
279
|
+
throw new CustomError(`${this.name}: unsupported pattern`, ErrorCodes.UNION_UNSUPPORTED_PATTERN);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* 解析联合类型的所有成员
|
|
285
|
+
*/
|
|
286
|
+
protected parseUnionMembers(typeNode: UnionTypeNode, context: TypeContext): TypeStructure[] {
|
|
287
|
+
const memberTypes = typeNode.getTypeNodes();
|
|
288
|
+
const members: TypeStructure[] = [];
|
|
289
|
+
|
|
290
|
+
for (const memberType of memberTypes) {
|
|
291
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
292
|
+
const memberStructure = TypeHandlerRegistry.getInstance().parseType(memberType, {
|
|
293
|
+
...context,
|
|
294
|
+
depth: context.depth + 1
|
|
295
|
+
});
|
|
296
|
+
members.push(memberStructure);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return members;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ==================== Sendable转换 ====================
|
|
303
|
+
|
|
304
|
+
generateSendableTypeDeclaration(structure: TypeStructure): string {
|
|
305
|
+
if (!structure.unionDetails || structure.unionDetails.length === 0) {
|
|
306
|
+
throw new CustomError(`${this.name}: missing unionDetails for Sendable type declaration`, ErrorCodes.UNION_STRUCTURE_NOT_FOUND);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// 递归获取TypeHandlerRegistry
|
|
310
|
+
const registry = require('./TypeHandlerRegistry').TypeHandlerRegistry.getInstance();
|
|
311
|
+
|
|
312
|
+
// 递归转换每个成员类型为Sendable类型
|
|
313
|
+
const sendableMemberTypes = structure.unionDetails.map(member => {
|
|
314
|
+
const handler = registry.getHandlerForKind(member.kind);
|
|
315
|
+
if (!handler) {
|
|
316
|
+
throw new CustomError(`${this.name}: no handler for member type: ${member.kind}`, ErrorCodes.HANDLER_NOT_FOUND);
|
|
317
|
+
}
|
|
318
|
+
return handler.generateSendableTypeDeclaration(member);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// 联合所有Sendable成员类型
|
|
322
|
+
return sendableMemberTypes.join(' | ');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
generatePropertyConversion(structure: TypeStructure, sourceValue: string, direction: ConversionDirection): string {
|
|
326
|
+
// 联合类型的转换无法在编译时确定具体类型,直接传递
|
|
327
|
+
// 实际转换由运行时的具体类型决定
|
|
328
|
+
// 注意:这可能需要在运行时检查类型并调用相应的转换方法
|
|
329
|
+
return sourceValue;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
class NullableHandler extends UnionTypeHandler {
|
|
334
|
+
readonly name = 'NullableHandler';
|
|
335
|
+
readonly kind = PropertyKind.NULLABLE;
|
|
336
|
+
readonly priority = 95; // 高于普通UnionHandler
|
|
337
|
+
protected readonly supportedPattern = 'nullable' as const;
|
|
338
|
+
|
|
339
|
+
protected getSerializerName(): string {
|
|
340
|
+
return 'NullableSerializer';
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
class OptionalHandler extends UnionTypeHandler {
|
|
345
|
+
readonly name = 'OptionalHandler';
|
|
346
|
+
readonly kind = PropertyKind.OPTIONAL;
|
|
347
|
+
readonly priority = 95; // 高于普通UnionHandler
|
|
348
|
+
protected readonly supportedPattern = 'optional' as const;
|
|
349
|
+
|
|
350
|
+
protected getSerializerName(): string {
|
|
351
|
+
return 'OptionalSerializer';
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
class OptionalNullableHandler extends UnionTypeHandler {
|
|
356
|
+
readonly name = 'OptionalNullableHandler';
|
|
357
|
+
readonly kind = PropertyKind.OPTIONAL_NULLABLE;
|
|
358
|
+
readonly priority = 95; // 高于普通UnionHandler
|
|
359
|
+
protected readonly supportedPattern = 'optionalNullable' as const;
|
|
360
|
+
|
|
361
|
+
protected getSerializerName(): string {
|
|
362
|
+
return 'OptionalNullableSerializer';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
class UnionHandler extends UnionTypeHandler {
|
|
367
|
+
readonly name = 'UnionHandler';
|
|
368
|
+
readonly kind = PropertyKind.UNION;
|
|
369
|
+
readonly priority = 85; // 低于Optional和Nullable,作为fallback
|
|
370
|
+
protected readonly supportedPattern = 'union' as const;
|
|
371
|
+
|
|
372
|
+
protected getSerializerName(): string {
|
|
373
|
+
return 'UnionTypeSerializer';
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* 工厂函数:创建所有联合类型Handler
|
|
379
|
+
* @returns 4个联合类型Handler实例
|
|
380
|
+
*
|
|
381
|
+
* 优先级顺序(从高到低):
|
|
382
|
+
* 1. OptionalHandler (95) - T | undefined (T不为null)
|
|
383
|
+
* 2. NullableHandler (95) - T | null (T不为undefined)
|
|
384
|
+
* 3. OptionalNullableHandler (95) - T | null | undefined (T为其他类型)
|
|
385
|
+
* 4. UnionHandler (85) - 其他所有联合类型 (包括 null | undefined)
|
|
386
|
+
*
|
|
387
|
+
* 特殊情况说明:
|
|
388
|
+
* - `null | undefined` 会被 UnionHandler 处理,生成 UnionTypeSerializer<null | undefined>
|
|
389
|
+
* - `T | undefined` (T非null) 会被 OptionalHandler 处理,生成 OptionalSerializer<T>
|
|
390
|
+
* - `T | null` (T非undefined) 会被 NullableHandler 处理,生成 NullableSerializer<T>
|
|
391
|
+
* - `T | null | undefined` 会被 OptionalNullableHandler 处理,生成 OptionalNullableSerializer<T>
|
|
392
|
+
*/
|
|
393
|
+
export function createUnionTypeHandlers(): ITypeHandler[] {
|
|
394
|
+
return [
|
|
395
|
+
new OptionalHandler(),
|
|
396
|
+
new NullableHandler(),
|
|
397
|
+
new OptionalNullableHandler(),
|
|
398
|
+
new UnionHandler()
|
|
399
|
+
];
|
|
400
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export type { ITypeHandler, TypeContext } from './ITypeHandler';
|
|
17
|
+
|
|
18
|
+
export { TypeHandlerRegistry } from './TypeHandlerRegistry';
|