@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,621 @@
|
|
|
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, ArrayTypeNode, TypeReferenceNode } 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
|
+
import { Logger } from '../logger/Logger';
|
|
22
|
+
|
|
23
|
+
abstract class GenericContainerHandler extends BaseTypeHandler implements ITypeHandler {
|
|
24
|
+
abstract readonly name: string;
|
|
25
|
+
abstract readonly kind: PropertyKind;
|
|
26
|
+
abstract readonly typeNames: string[]; // 支持的类型名称,如 ['Array'], ['Map'], ['collections.Array']
|
|
27
|
+
abstract readonly argsCount: 1 | 2; // 泛型参数数量
|
|
28
|
+
|
|
29
|
+
readonly priority = 90; // 泛型容器优先级
|
|
30
|
+
|
|
31
|
+
// ==================== 阶段1: 类型识别 ====================
|
|
32
|
+
|
|
33
|
+
matches(typeNode: TypeNode): boolean {
|
|
34
|
+
const syntaxKind = typeNode.getKind();
|
|
35
|
+
|
|
36
|
+
// 支持数组字面量语法: T[]
|
|
37
|
+
if (syntaxKind === SyntaxKind.ArrayType) {
|
|
38
|
+
return this.kind === PropertyKind.ARRAY;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 支持泛型语法: Array<T>, Map<K,V>, collections.Array<T>
|
|
42
|
+
if (syntaxKind === SyntaxKind.TypeReference) {
|
|
43
|
+
const typeRef = typeNode as TypeReferenceNode;
|
|
44
|
+
const refName = typeRef.getTypeName().getText();
|
|
45
|
+
return this.typeNames.includes(refName);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ==================== 阶段2: 类型解析 ====================
|
|
52
|
+
|
|
53
|
+
parse(typeNode: TypeNode, context: TypeContext): TypeStructure {
|
|
54
|
+
const syntaxKind = typeNode.getKind();
|
|
55
|
+
|
|
56
|
+
// 处理数组字面量: T[]
|
|
57
|
+
if (syntaxKind === SyntaxKind.ArrayType) {
|
|
58
|
+
return this.parseArrayLiteral(typeNode as ArrayTypeNode, context);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 处理泛型语法: Array<T>, Map<K,V>
|
|
62
|
+
if (syntaxKind === SyntaxKind.TypeReference) {
|
|
63
|
+
return this.parseGenericType(typeNode as TypeReferenceNode, context);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
throw new CustomError(`Unexpected syntax kind for ${this.name}: ${syntaxKind}`, ErrorCodes.UNEXPECTED_GENERIC);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 解析数组字面量: T[]
|
|
71
|
+
*/
|
|
72
|
+
private parseArrayLiteral(typeNode: ArrayTypeNode, context: TypeContext): TypeStructure {
|
|
73
|
+
const elementTypeNode = typeNode.getElementTypeNode();
|
|
74
|
+
|
|
75
|
+
Logger.debug('GenericHandler.parseArrayLiteral', typeNode.getText(), elementTypeNode.getText(), elementTypeNode.getKind());
|
|
76
|
+
|
|
77
|
+
// 递归解析元素类型
|
|
78
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
79
|
+
const elementType = TypeHandlerRegistry.getInstance().parseType(elementTypeNode, {
|
|
80
|
+
...context,
|
|
81
|
+
depth: context.depth + 1
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
kind: this.kind,
|
|
86
|
+
depth: context.depth,
|
|
87
|
+
sourceText: typeNode.getText(),
|
|
88
|
+
args: [elementType], // 使用args数组存储泛型参数
|
|
89
|
+
dependencies: elementType.dependencies
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 解析泛型类型: Array<T>, Map<K,V>
|
|
95
|
+
*/
|
|
96
|
+
private parseGenericType(typeNode: TypeReferenceNode, context: TypeContext): TypeStructure {
|
|
97
|
+
const typeArgs = typeNode.getTypeArguments();
|
|
98
|
+
|
|
99
|
+
if (typeArgs.length !== this.argsCount) {
|
|
100
|
+
throw new CustomError(
|
|
101
|
+
`${this.name} expects ${this.argsCount} type argument(s), got ${typeArgs.length}`,
|
|
102
|
+
ErrorCodes.GENERIC_NOT_MATCH
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 收集所有依赖
|
|
107
|
+
const allDependencies: TypeDependency[] = [];
|
|
108
|
+
|
|
109
|
+
// 解析所有泛型参数
|
|
110
|
+
const parsedArgs: TypeStructure[] = typeArgs.map((argNode) => {
|
|
111
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
112
|
+
Logger.debug(`[GenericContainerHandler] parse: ${typeNode.getText()} -> ${typeNode.getKind()}`);
|
|
113
|
+
const argStructure = TypeHandlerRegistry.getInstance().parseType(argNode, {
|
|
114
|
+
...context,
|
|
115
|
+
depth: context.depth + 1
|
|
116
|
+
});
|
|
117
|
+
allDependencies.push(...argStructure.dependencies);
|
|
118
|
+
return argStructure;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
kind: this.kind,
|
|
123
|
+
depth: context.depth,
|
|
124
|
+
sourceText: typeNode.getText(),
|
|
125
|
+
args: parsedArgs, // 使用args数组存储所有泛型参数
|
|
126
|
+
dependencies: allDependencies
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ==================== 阶段3: 序列化器配置 ====================
|
|
131
|
+
|
|
132
|
+
getSerializerMetadata(structure: TypeStructure, withParam?: string): SerializerMetadata {
|
|
133
|
+
const serializerName = this.getSerializerName();
|
|
134
|
+
const defaultInstantiation = this.generateInstantiation(structure);
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
name: serializerName,
|
|
138
|
+
typeDeclaration: this.generateTypeDeclaration(structure),
|
|
139
|
+
instantiationTemplate: this.applyWithParam(withParam, defaultInstantiation, structure),
|
|
140
|
+
encodeMethod: 'encodeSerializableElement',
|
|
141
|
+
decodeMethod: 'deserialize',
|
|
142
|
+
decoderType: `${structure.sourceText} | undefined`,
|
|
143
|
+
needsTypeAssertion: false
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ==================== 阶段4: 代码生成 ====================
|
|
148
|
+
|
|
149
|
+
generateInstantiation(structure: TypeStructure): string {
|
|
150
|
+
if (!structure.args || structure.args.length !== this.argsCount) {
|
|
151
|
+
throw new CustomError(
|
|
152
|
+
`${this.name}: expected ${this.argsCount} type argument(s), got ${structure.args?.length || 0}`,
|
|
153
|
+
ErrorCodes.GENERIC_NOT_MATCH
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (this.argsCount === 1) {
|
|
158
|
+
return this.generateSingleArgInstantiation(structure);
|
|
159
|
+
} else {
|
|
160
|
+
return this.generateDoubleArgInstantiation(structure);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
generateTypeDeclaration(structure: TypeStructure): string {
|
|
165
|
+
if (!structure.args || structure.args.length !== this.argsCount) {
|
|
166
|
+
throw new CustomError(
|
|
167
|
+
`${this.name}: expected ${this.argsCount} type argument(s), got ${structure.args?.length || 0}`,
|
|
168
|
+
ErrorCodes.GENERIC_NOT_MATCH
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (this.argsCount === 1) {
|
|
173
|
+
return this.generateSingleArgTypeDeclaration(structure);
|
|
174
|
+
} else {
|
|
175
|
+
return this.generateDoubleArgTypeDeclaration(structure);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
generateTypeKey(): string {
|
|
180
|
+
return this.getTypeKeyString();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ==================== Protected 抽象方法 - 子类必须实现 ====================
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* 生成类型键字符串(如 'array', 'set', 'map')
|
|
187
|
+
* 子类实现具体的类型键
|
|
188
|
+
*/
|
|
189
|
+
protected abstract getTypeKeyString(): string;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 获取Sendable容器名称(如 'collections.Array', 'collections.Map')
|
|
193
|
+
* 子类可覆盖自定义Sendable容器名称
|
|
194
|
+
*/
|
|
195
|
+
protected abstract getSendableContainerName(): string;
|
|
196
|
+
|
|
197
|
+
// ==================== Protected 工具方法 - 子类可复用 ====================
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 生成单参数容器的实例化代码
|
|
201
|
+
* Array<T>, Set<T>, collections.Array<T>
|
|
202
|
+
*/
|
|
203
|
+
protected generateSingleArgInstantiation(structure: TypeStructure): string {
|
|
204
|
+
Logger.info(
|
|
205
|
+
'generateSingleArgInstantiation: sourceText: %s, kind: %s, args: sourceText %s, kind: %s',
|
|
206
|
+
structure.sourceText,
|
|
207
|
+
structure.kind,
|
|
208
|
+
structure.args.map((arg) => arg.sourceText).join(','),
|
|
209
|
+
structure.args.map((arg) => arg.kind).join(',')
|
|
210
|
+
);
|
|
211
|
+
const serializerName = this.getSerializerName();
|
|
212
|
+
const elementType = structure.args[0];
|
|
213
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
214
|
+
const elementHandler = TypeHandlerRegistry.getInstance().getHandlerForKind(elementType.kind);
|
|
215
|
+
const elementSerializer = elementHandler.generateInstantiation(elementType);
|
|
216
|
+
|
|
217
|
+
return `new ${serializerName}<${elementType.sourceText}>(${elementSerializer})`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 生成双参数容器的实例化代码
|
|
222
|
+
* Map<K,V>, Record<K,V>, collections.Map<K,V>
|
|
223
|
+
*/
|
|
224
|
+
protected generateDoubleArgInstantiation(structure: TypeStructure): string {
|
|
225
|
+
Logger.info('generateDoubleArgInstantiation:', structure.sourceText, structure.kind, structure.args.join(','));
|
|
226
|
+
const serializerName = this.getSerializerName();
|
|
227
|
+
const keyType = structure.args[0];
|
|
228
|
+
const valueType = structure.args[1];
|
|
229
|
+
const { TypeHandlerRegistry } = require('./TypeHandlerRegistry');
|
|
230
|
+
const keyHandler = TypeHandlerRegistry.getInstance().getHandlerForKind(keyType.kind);
|
|
231
|
+
const valueHandler = TypeHandlerRegistry.getInstance().getHandlerForKind(valueType.kind);
|
|
232
|
+
const keySerializer = keyHandler.generateInstantiation(keyType);
|
|
233
|
+
const valueSerializer = valueHandler.generateInstantiation(valueType);
|
|
234
|
+
|
|
235
|
+
return `new ${serializerName}<${keyType.sourceText}, ${valueType.sourceText}>(${keySerializer}, ${valueSerializer})`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 生成单参数容器的类型声明
|
|
240
|
+
* Array<T>, Set<T>, collections.Array<T>
|
|
241
|
+
*/
|
|
242
|
+
protected generateSingleArgTypeDeclaration(structure: TypeStructure): string {
|
|
243
|
+
const elementType = structure.args[0];
|
|
244
|
+
const serializerName = this.getSerializerName();
|
|
245
|
+
|
|
246
|
+
return `${serializerName}<${elementType.sourceText}>`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 生成双参数容器的类型声明
|
|
251
|
+
* Map<K,V>, Record<K,V>, collections.Map<K,V>
|
|
252
|
+
*/
|
|
253
|
+
protected generateDoubleArgTypeDeclaration(structure: TypeStructure): string {
|
|
254
|
+
const keyType = structure.args[0];
|
|
255
|
+
const valueType = structure.args[1];
|
|
256
|
+
const serializerName = this.getSerializerName();
|
|
257
|
+
|
|
258
|
+
return `${serializerName}<${keyType.sourceText}, ${valueType.sourceText}>`;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ==================== Sendable转换 ====================
|
|
262
|
+
|
|
263
|
+
generateSendableTypeDeclaration(structure: TypeStructure): string {
|
|
264
|
+
if (!structure.args || structure.args.length !== this.argsCount) {
|
|
265
|
+
throw new CustomError(
|
|
266
|
+
`${this.name}: expected ${this.argsCount} type argument(s), got ${structure.args?.length || 0}`,
|
|
267
|
+
ErrorCodes.GENERIC_NOT_MATCH
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 递归获取TypeHandlerRegistry(通过全局单例)
|
|
272
|
+
const registry = require('./TypeHandlerRegistry').TypeHandlerRegistry.getInstance();
|
|
273
|
+
|
|
274
|
+
if (this.argsCount === 1) {
|
|
275
|
+
// 单参数容器:Array<T> -> collections.Array<SendableT>
|
|
276
|
+
const elementType = structure.args[0];
|
|
277
|
+
const elementHandler = registry.getHandlerForKind(elementType.kind);
|
|
278
|
+
const sendableElementType = elementHandler.generateSendableTypeDeclaration(elementType);
|
|
279
|
+
return `${this.getSendableContainerName()}<${sendableElementType}>`;
|
|
280
|
+
} else {
|
|
281
|
+
// 双参数容器:Map<K,V> -> collections.Map<SendableK, SendableV>
|
|
282
|
+
const keyType = structure.args[0];
|
|
283
|
+
const valueType = structure.args[1];
|
|
284
|
+
|
|
285
|
+
const keyHandler = registry.getHandlerForKind(keyType.kind);
|
|
286
|
+
const valueHandler = registry.getHandlerForKind(valueType.kind);
|
|
287
|
+
|
|
288
|
+
const sendableKeyType = keyHandler.generateSendableTypeDeclaration(keyType);
|
|
289
|
+
const sendableValueType = valueHandler.generateSendableTypeDeclaration(valueType);
|
|
290
|
+
|
|
291
|
+
return `${this.getSendableContainerName()}<${sendableKeyType}, ${sendableValueType}>`;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
generatePropertyConversion(_structure: TypeStructure, sourceValue: string, direction: ConversionDirection): string {
|
|
296
|
+
if (direction === ConversionDirection.TO_SENDABLE) {
|
|
297
|
+
// 普通容器 -> Sendable容器
|
|
298
|
+
return this.generateToSendableConversion(sourceValue);
|
|
299
|
+
} else {
|
|
300
|
+
// Sendable容器 -> 普通容器
|
|
301
|
+
return this.generateToOriginConversion(sourceValue);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 生成 TO_SENDABLE 转换代码
|
|
307
|
+
* 子类可覆盖自定义转换逻辑
|
|
308
|
+
*/
|
|
309
|
+
protected generateToSendableConversion(sourceValue: string): string {
|
|
310
|
+
const sendableContainer = this.getSendableContainerName();
|
|
311
|
+
|
|
312
|
+
if (this.argsCount === 1) {
|
|
313
|
+
// Array/Set: new collections.Array(...this.items)
|
|
314
|
+
return `new ${sendableContainer}(...${sourceValue})`;
|
|
315
|
+
} else {
|
|
316
|
+
// Map: new collections.Map(this.data.entries())
|
|
317
|
+
return `new ${sendableContainer}(${sourceValue}.entries())`;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 生成 TO_ORIGIN 转换代码
|
|
323
|
+
* 子类可覆盖自定义转换逻辑
|
|
324
|
+
*/
|
|
325
|
+
protected generateToOriginConversion(sourceValue: string): string {
|
|
326
|
+
const originContainer = this.getOriginContainerName();
|
|
327
|
+
|
|
328
|
+
if (this.argsCount === 1) {
|
|
329
|
+
// collections.Array/Set -> Array/Set: new Array(...this.items)
|
|
330
|
+
return `new ${originContainer}(...${sourceValue})`;
|
|
331
|
+
} else {
|
|
332
|
+
// collections.Map -> Map: new Map(this.data.entries())
|
|
333
|
+
return `new ${originContainer}(${sourceValue}.entries())`;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 获取原始容器名称(如 'Array', 'Map', 'Set')
|
|
339
|
+
* 子类可覆盖自定义原始容器名称
|
|
340
|
+
*/
|
|
341
|
+
protected abstract getOriginContainerName(): string;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ArrayHandler
|
|
345
|
+
class ArrayHandler extends GenericContainerHandler {
|
|
346
|
+
readonly name = 'ArrayHandler';
|
|
347
|
+
readonly kind = PropertyKind.ARRAY;
|
|
348
|
+
readonly typeNames = ['Array'];
|
|
349
|
+
readonly argsCount = 1 as const;
|
|
350
|
+
|
|
351
|
+
protected getTypeKeyString(): string {
|
|
352
|
+
return `'array'`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
protected getSerializerName(): string {
|
|
356
|
+
return 'ArraySerializer';
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
protected getSendableContainerName(): string {
|
|
360
|
+
return 'collections.Array';
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
protected getOriginContainerName(): string {
|
|
364
|
+
return 'Array';
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// MapHandler
|
|
369
|
+
class MapHandler extends GenericContainerHandler {
|
|
370
|
+
readonly name = 'MapHandler';
|
|
371
|
+
readonly kind = PropertyKind.MAP;
|
|
372
|
+
readonly typeNames = ['Map'];
|
|
373
|
+
readonly argsCount = 2 as const;
|
|
374
|
+
|
|
375
|
+
protected getTypeKeyString(): string {
|
|
376
|
+
return `'map'`;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
protected getSerializerName(): string {
|
|
380
|
+
return 'MapSerializer';
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
protected getSendableContainerName(): string {
|
|
384
|
+
return 'collections.Map';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
protected getOriginContainerName(): string {
|
|
388
|
+
return 'Map';
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// SetHandler
|
|
393
|
+
class SetHandler extends GenericContainerHandler {
|
|
394
|
+
readonly name = 'SetHandler';
|
|
395
|
+
readonly kind = PropertyKind.SET;
|
|
396
|
+
readonly typeNames = ['Set'];
|
|
397
|
+
readonly argsCount = 1 as const;
|
|
398
|
+
|
|
399
|
+
protected getTypeKeyString(): string {
|
|
400
|
+
return `'set'`;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
protected getSerializerName(): string {
|
|
404
|
+
return 'SetSerializer';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
protected getSendableContainerName(): string {
|
|
408
|
+
return 'collections.Set';
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
protected getOriginContainerName(): string {
|
|
412
|
+
return 'Set';
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// RecordHandler
|
|
417
|
+
class RecordHandler extends GenericContainerHandler {
|
|
418
|
+
readonly name = 'RecordHandler';
|
|
419
|
+
readonly kind = PropertyKind.RECORD;
|
|
420
|
+
readonly typeNames = ['Record'];
|
|
421
|
+
readonly argsCount = 2 as const;
|
|
422
|
+
|
|
423
|
+
protected getTypeKeyString(): string {
|
|
424
|
+
return `'map'`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
protected getSerializerName(): string {
|
|
428
|
+
return 'RecordSerializer';
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
protected getSendableContainerName(): string {
|
|
432
|
+
return 'collections.Map';
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
protected getOriginContainerName(): string {
|
|
436
|
+
return 'Map';
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// CollectionsArrayHandler
|
|
441
|
+
class CollectionsArrayHandler extends GenericContainerHandler {
|
|
442
|
+
readonly name = 'CollectionsArrayHandler';
|
|
443
|
+
readonly kind = PropertyKind.COLLECTIONS_ARRAY;
|
|
444
|
+
readonly typeNames = ['collections.Array'];
|
|
445
|
+
readonly argsCount = 1 as const;
|
|
446
|
+
|
|
447
|
+
protected getTypeKeyString(): string {
|
|
448
|
+
return `'array'`;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
protected getSerializerName(): string {
|
|
452
|
+
return 'CollectionsArraySerializer';
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
protected getSendableContainerName(): string {
|
|
456
|
+
return 'collections.Array';
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
protected getOriginContainerName(): string {
|
|
460
|
+
return 'Array';
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// CollectionsSetHandler
|
|
465
|
+
class CollectionsSetHandler extends GenericContainerHandler {
|
|
466
|
+
readonly name = 'CollectionsSetHandler';
|
|
467
|
+
readonly kind = PropertyKind.COLLECTIONS_SET;
|
|
468
|
+
readonly typeNames = ['collections.Set'];
|
|
469
|
+
readonly argsCount = 1 as const;
|
|
470
|
+
|
|
471
|
+
protected getTypeKeyString(): string {
|
|
472
|
+
return `'set'`;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
protected getSerializerName(): string {
|
|
476
|
+
return 'CollectionsSetSerializer';
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
protected getSendableContainerName(): string {
|
|
480
|
+
return 'collections.Set';
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
protected getOriginContainerName(): string {
|
|
484
|
+
return 'Set';
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// CollectionsMapHandler
|
|
489
|
+
class CollectionsMapHandler extends GenericContainerHandler {
|
|
490
|
+
readonly name = 'CollectionsMapHandler';
|
|
491
|
+
readonly kind = PropertyKind.COLLECTIONS_MAP;
|
|
492
|
+
readonly typeNames = ['collections.Map'];
|
|
493
|
+
readonly argsCount = 2 as const;
|
|
494
|
+
|
|
495
|
+
protected getTypeKeyString(): string {
|
|
496
|
+
return `'map'`;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
protected getSerializerName(): string {
|
|
500
|
+
return 'CollectionsMapSerializer';
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
protected getSendableContainerName(): string {
|
|
504
|
+
return 'collections.Map';
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
protected getOriginContainerName(): string {
|
|
508
|
+
return 'Map';
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
class ArrayListHandler extends GenericContainerHandler {
|
|
513
|
+
readonly name = 'ArrayListHandler';
|
|
514
|
+
readonly kind = PropertyKind.ARRAY_LIST;
|
|
515
|
+
readonly typeNames = ['ArrayList'];
|
|
516
|
+
readonly argsCount = 1 as const;
|
|
517
|
+
|
|
518
|
+
protected getTypeKeyString(): string {
|
|
519
|
+
return `'ArrayList'`;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
protected getSerializerName(): string {
|
|
523
|
+
return 'ArrayListSerializer';
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
protected getSendableContainerName(): string {
|
|
527
|
+
throw new CustomError('toSendable ArrayList type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
protected getOriginContainerName(): string {
|
|
531
|
+
throw new CustomError('toOrgin ArrayList type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
class HashMapHandler extends GenericContainerHandler {
|
|
536
|
+
readonly name = 'HashMapHandler';
|
|
537
|
+
readonly kind = PropertyKind.HASH_MAP;
|
|
538
|
+
readonly typeNames = ['HashMap'];
|
|
539
|
+
readonly argsCount = 2 as const;
|
|
540
|
+
|
|
541
|
+
protected getTypeKeyString(): string {
|
|
542
|
+
return `'HashMap'`;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
protected getSerializerName(): string {
|
|
546
|
+
return 'HashMapSerializer';
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
protected getSendableContainerName(): string {
|
|
550
|
+
throw new CustomError('toSendable HashMap type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
protected getOriginContainerName(): string {
|
|
554
|
+
throw new CustomError('toOrgin HashMap type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
class HashSetHandler extends GenericContainerHandler {
|
|
559
|
+
readonly name = 'HashSetHandler';
|
|
560
|
+
readonly kind = PropertyKind.HASH_SET;
|
|
561
|
+
readonly typeNames = ['HashSet'];
|
|
562
|
+
readonly argsCount = 1 as const;
|
|
563
|
+
|
|
564
|
+
protected getTypeKeyString(): string {
|
|
565
|
+
return `'HashSet'`;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
protected getSerializerName(): string {
|
|
569
|
+
return 'HashSetSerializer';
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
protected getSendableContainerName(): string {
|
|
573
|
+
throw new CustomError('toSendable HashSet type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
574
|
+
}
|
|
575
|
+
protected getOriginContainerName(): string {
|
|
576
|
+
throw new CustomError('toOrgin HashSet type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
class ListHandler extends GenericContainerHandler {
|
|
581
|
+
readonly name = 'ListHandler';
|
|
582
|
+
readonly kind = PropertyKind.LIST;
|
|
583
|
+
readonly typeNames = ['List'];
|
|
584
|
+
readonly argsCount = 1 as const;
|
|
585
|
+
|
|
586
|
+
protected getTypeKeyString(): string {
|
|
587
|
+
return `'List'`;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
protected getSerializerName(): string {
|
|
591
|
+
return 'ListSerializer';
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
protected getSendableContainerName(): string {
|
|
595
|
+
throw new CustomError('toSendable List type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
protected getOriginContainerName(): string {
|
|
599
|
+
throw new CustomError('toOrgin List type is not supported.', ErrorCodes.TYPE_NOT_SUPPORT);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* 工厂函数:创建所有泛型容器Handler
|
|
605
|
+
* @returns 7个泛型容器Handler实例
|
|
606
|
+
*/
|
|
607
|
+
export function createGenericContainerHandlers(): ITypeHandler[] {
|
|
608
|
+
return [
|
|
609
|
+
new ArrayHandler(),
|
|
610
|
+
new SetHandler(),
|
|
611
|
+
new MapHandler(),
|
|
612
|
+
new RecordHandler(),
|
|
613
|
+
new CollectionsArrayHandler(),
|
|
614
|
+
new CollectionsSetHandler(),
|
|
615
|
+
new CollectionsMapHandler(),
|
|
616
|
+
new ArrayListHandler(),
|
|
617
|
+
new HashMapHandler(),
|
|
618
|
+
new HashSetHandler(),
|
|
619
|
+
new ListHandler()
|
|
620
|
+
];
|
|
621
|
+
}
|