@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.
Files changed (195) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +253 -0
  3. package/dist/core/Types.d.ts +196 -0
  4. package/dist/core/Types.js +47 -0
  5. package/dist/core/analyzers/ClassAnalyzer.d.ts +23 -0
  6. package/dist/core/analyzers/ClassAnalyzer.js +480 -0
  7. package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +21 -0
  8. package/dist/core/analyzers/CustomTypeAnalyzer.js +243 -0
  9. package/dist/core/analyzers/SendableMergeChecker.d.ts +9 -0
  10. package/dist/core/analyzers/SendableMergeChecker.js +100 -0
  11. package/dist/core/analyzers/SendableMergeabilityRegistry.d.ts +7 -0
  12. package/dist/core/analyzers/SendableMergeabilityRegistry.js +23 -0
  13. package/dist/core/constants/DecoratorConstants.d.ts +7 -0
  14. package/dist/core/constants/DecoratorConstants.js +13 -0
  15. package/dist/core/constants/PathConstants.d.ts +6 -0
  16. package/dist/core/constants/PathConstants.js +10 -0
  17. package/dist/core/constants/StringConstants.d.ts +83 -0
  18. package/dist/core/constants/StringConstants.js +87 -0
  19. package/dist/core/constants/index.d.ts +3 -0
  20. package/dist/core/constants/index.js +19 -0
  21. package/dist/core/handlers/BaseTypeHandler.d.ts +23 -0
  22. package/dist/core/handlers/BaseTypeHandler.js +57 -0
  23. package/dist/core/handlers/CustomClassHandler.d.ts +21 -0
  24. package/dist/core/handlers/CustomClassHandler.js +191 -0
  25. package/dist/core/handlers/DateHandler.d.ts +2 -0
  26. package/dist/core/handlers/DateHandler.js +60 -0
  27. package/dist/core/handlers/DecimalHandler.d.ts +2 -0
  28. package/dist/core/handlers/DecimalHandler.js +60 -0
  29. package/dist/core/handlers/EnumHandler.d.ts +2 -0
  30. package/dist/core/handlers/EnumHandler.js +89 -0
  31. package/dist/core/handlers/GenericContainerHandler.d.ts +2 -0
  32. package/dist/core/handlers/GenericContainerHandler.js +440 -0
  33. package/dist/core/handlers/GenericHandler.d.ts +18 -0
  34. package/dist/core/handlers/GenericHandler.js +92 -0
  35. package/dist/core/handlers/HandlerBootstrap.d.ts +2 -0
  36. package/dist/core/handlers/HandlerBootstrap.js +28 -0
  37. package/dist/core/handlers/ITypeHandler.d.ts +23 -0
  38. package/dist/core/handlers/ITypeHandler.js +8 -0
  39. package/dist/core/handlers/PrimitiveHandler.d.ts +2 -0
  40. package/dist/core/handlers/PrimitiveHandler.js +127 -0
  41. package/dist/core/handlers/TupleHandler.d.ts +2 -0
  42. package/dist/core/handlers/TupleHandler.js +98 -0
  43. package/dist/core/handlers/TypeHandlerRegistry.d.ts +20 -0
  44. package/dist/core/handlers/TypeHandlerRegistry.js +113 -0
  45. package/dist/core/handlers/UnionTypeHandler.d.ts +2 -0
  46. package/dist/core/handlers/UnionTypeHandler.js +263 -0
  47. package/dist/core/handlers/index.d.ts +2 -0
  48. package/dist/core/handlers/index.js +5 -0
  49. package/dist/core/import-rewrite/services/BuildProfileUpdater.d.ts +8 -0
  50. package/dist/core/import-rewrite/services/BuildProfileUpdater.js +92 -0
  51. package/dist/core/import-rewrite/services/ImportRewriteService.d.ts +9 -0
  52. package/dist/core/import-rewrite/services/ImportRewriteService.js +61 -0
  53. package/dist/core/import-rewrite/services/ImportTransformService.d.ts +15 -0
  54. package/dist/core/import-rewrite/services/ImportTransformService.js +109 -0
  55. package/dist/core/import-rewrite/strategies/ImportScanStrategy.d.ts +17 -0
  56. package/dist/core/import-rewrite/strategies/ImportScanStrategy.js +137 -0
  57. package/dist/core/import-rewrite/types/ImportRewriteTypes.d.ts +17 -0
  58. package/dist/core/import-rewrite/types/ImportRewriteTypes.js +2 -0
  59. package/dist/core/index.d.ts +9 -0
  60. package/dist/core/index.js +27 -0
  61. package/dist/core/interfaces/ITask.d.ts +7 -0
  62. package/dist/core/interfaces/ITask.js +2 -0
  63. package/dist/core/interfaces/ITaskContext.d.ts +11 -0
  64. package/dist/core/interfaces/ITaskContext.js +2 -0
  65. package/dist/core/interfaces/index.d.ts +2 -0
  66. package/dist/core/interfaces/index.js +2 -0
  67. package/dist/core/logger/Logger.d.ts +13 -0
  68. package/dist/core/logger/Logger.js +78 -0
  69. package/dist/core/services/CodeAnalysisService.d.ts +7 -0
  70. package/dist/core/services/CodeAnalysisService.js +43 -0
  71. package/dist/core/services/CodeGenerationEngine.d.ts +12 -0
  72. package/dist/core/services/CodeGenerationEngine.js +102 -0
  73. package/dist/core/services/CodeGenerationService/CodeGenerationService.d.ts +13 -0
  74. package/dist/core/services/CodeGenerationService/CodeGenerationService.js +110 -0
  75. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +13 -0
  76. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +119 -0
  77. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +21 -0
  78. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +224 -0
  79. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +24 -0
  80. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +307 -0
  81. package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.d.ts +28 -0
  82. package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +259 -0
  83. package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.d.ts +19 -0
  84. package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +178 -0
  85. package/dist/core/services/CodeGenerationService/index.d.ts +1 -0
  86. package/dist/core/services/CodeGenerationService/index.js +5 -0
  87. package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +27 -0
  88. package/dist/core/services/CodeGenerationService/shared/ImportManager.js +127 -0
  89. package/dist/core/template/HandlebarsTemplateEngine.d.ts +26 -0
  90. package/dist/core/template/HandlebarsTemplateEngine.js +226 -0
  91. package/dist/core/utils/ConfigManager.d.ts +10 -0
  92. package/dist/core/utils/ConfigManager.js +32 -0
  93. package/dist/core/utils/CustomError.d.ts +30 -0
  94. package/dist/core/utils/CustomError.js +37 -0
  95. package/dist/core/utils/DeepCopyUtil.d.ts +15 -0
  96. package/dist/core/utils/DeepCopyUtil.js +138 -0
  97. package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +9 -0
  98. package/dist/core/utils/GenericTypeSubstitutionUtil.js +68 -0
  99. package/dist/core/utils/SerializationPathUtil.d.ts +18 -0
  100. package/dist/core/utils/SerializationPathUtil.js +107 -0
  101. package/dist/core/utils/TsMorphUtil.d.ts +8 -0
  102. package/dist/core/utils/TsMorphUtil.js +34 -0
  103. package/dist/index.d.ts +4 -0
  104. package/dist/index.js +57 -0
  105. package/dist/json-plugin/JSONExecuteController.d.ts +13 -0
  106. package/dist/json-plugin/JSONExecuteController.js +103 -0
  107. package/dist/json-plugin/constants/TaskConstants.d.ts +7 -0
  108. package/dist/json-plugin/constants/TaskConstants.js +11 -0
  109. package/dist/json-plugin/interfaces/IModuleContext.d.ts +10 -0
  110. package/dist/json-plugin/interfaces/IModuleContext.js +2 -0
  111. package/dist/json-plugin/interfaces/ITargetContext.d.ts +8 -0
  112. package/dist/json-plugin/interfaces/ITargetContext.js +2 -0
  113. package/dist/json-plugin/interfaces/impl/ModuleContext.d.ts +12 -0
  114. package/dist/json-plugin/interfaces/impl/ModuleContext.js +24 -0
  115. package/dist/json-plugin/interfaces/impl/TargetContext.d.ts +23 -0
  116. package/dist/json-plugin/interfaces/impl/TargetContext.js +113 -0
  117. package/dist/json-plugin/tasks/BaseTask.d.ts +14 -0
  118. package/dist/json-plugin/tasks/BaseTask.js +53 -0
  119. package/dist/json-plugin/tasks/CleanTask.d.ts +8 -0
  120. package/dist/json-plugin/tasks/CleanTask.js +25 -0
  121. package/dist/json-plugin/tasks/CodeProcessingTask.d.ts +8 -0
  122. package/dist/json-plugin/tasks/CodeProcessingTask.js +26 -0
  123. package/dist/json-plugin/tasks/SyncTask.d.ts +8 -0
  124. package/dist/json-plugin/tasks/SyncTask.js +21 -0
  125. package/dist/json-plugin/tasks/WatchTask.d.ts +11 -0
  126. package/dist/json-plugin/tasks/WatchTask.js +102 -0
  127. package/package.json +46 -0
  128. package/src/core/Types.ts +356 -0
  129. package/src/core/analyzers/ClassAnalyzer.ts +824 -0
  130. package/src/core/analyzers/CustomTypeAnalyzer.ts +337 -0
  131. package/src/core/analyzers/SendableMergeChecker.ts +195 -0
  132. package/src/core/analyzers/SendableMergeabilityRegistry.ts +72 -0
  133. package/src/core/constants/DecoratorConstants.ts +27 -0
  134. package/src/core/constants/PathConstants.ts +31 -0
  135. package/src/core/constants/StringConstants.ts +152 -0
  136. package/src/core/constants/index.ts +21 -0
  137. package/src/core/handlers/BaseTypeHandler.ts +121 -0
  138. package/src/core/handlers/CustomClassHandler.ts +278 -0
  139. package/src/core/handlers/DateHandler.ts +75 -0
  140. package/src/core/handlers/DecimalHandler.ts +75 -0
  141. package/src/core/handlers/EnumHandler.ts +142 -0
  142. package/src/core/handlers/GenericContainerHandler.ts +621 -0
  143. package/src/core/handlers/GenericHandler.ts +130 -0
  144. package/src/core/handlers/HandlerBootstrap.ts +64 -0
  145. package/src/core/handlers/ITypeHandler.ts +133 -0
  146. package/src/core/handlers/PrimitiveHandler.ts +159 -0
  147. package/src/core/handlers/TupleHandler.ts +145 -0
  148. package/src/core/handlers/TypeHandlerRegistry.ts +236 -0
  149. package/src/core/handlers/UnionTypeHandler.ts +400 -0
  150. package/src/core/handlers/index.ts +18 -0
  151. package/src/core/import-rewrite/services/BuildProfileUpdater.ts +145 -0
  152. package/src/core/import-rewrite/services/ImportRewriteService.ts +129 -0
  153. package/src/core/import-rewrite/services/ImportTransformService.ts +200 -0
  154. package/src/core/import-rewrite/strategies/ImportScanStrategy.ts +303 -0
  155. package/src/core/import-rewrite/types/ImportRewriteTypes.ts +100 -0
  156. package/src/core/index.ts +31 -0
  157. package/src/core/interfaces/ITask.ts +23 -0
  158. package/src/core/interfaces/ITaskContext.ts +94 -0
  159. package/src/core/interfaces/index.ts +17 -0
  160. package/src/core/logger/Logger.ts +149 -0
  161. package/src/core/services/CodeAnalysisService.ts +67 -0
  162. package/src/core/services/CodeGenerationEngine.ts +181 -0
  163. package/src/core/services/CodeGenerationService/CodeGenerationService.ts +159 -0
  164. package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +189 -0
  165. package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +314 -0
  166. package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +421 -0
  167. package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +392 -0
  168. package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +277 -0
  169. package/src/core/services/CodeGenerationService/index.ts +16 -0
  170. package/src/core/services/CodeGenerationService/shared/ImportManager.ts +191 -0
  171. package/src/core/template/HandlebarsTemplateEngine.ts +282 -0
  172. package/src/core/utils/ConfigManager.ts +49 -0
  173. package/src/core/utils/CustomError.ts +51 -0
  174. package/src/core/utils/DeepCopyUtil.ts +185 -0
  175. package/src/core/utils/GenericTypeSubstitutionUtil.ts +136 -0
  176. package/src/core/utils/SerializationPathUtil.ts +142 -0
  177. package/src/core/utils/TsMorphUtil.ts +50 -0
  178. package/src/index.ts +81 -0
  179. package/src/json-plugin/JSONExecuteController.ts +134 -0
  180. package/src/json-plugin/constants/TaskConstants.ts +22 -0
  181. package/src/json-plugin/interfaces/IModuleContext.ts +27 -0
  182. package/src/json-plugin/interfaces/ITargetContext.ts +25 -0
  183. package/src/json-plugin/interfaces/impl/ModuleContext.ts +45 -0
  184. package/src/json-plugin/interfaces/impl/TargetContext.ts +196 -0
  185. package/src/json-plugin/tasks/BaseTask.ts +94 -0
  186. package/src/json-plugin/tasks/CleanTask.ts +36 -0
  187. package/src/json-plugin/tasks/CodeProcessingTask.ts +41 -0
  188. package/src/json-plugin/tasks/SyncTask.ts +33 -0
  189. package/src/json-plugin/tasks/WatchTask.ts +99 -0
  190. package/template/SerializerPerformanceTemplate.hbs +35 -0
  191. package/template/SerializerRegisterTemplate.hbs +10 -0
  192. package/template/SerializerStrictTemplate.hbs +89 -0
  193. package/template/SerializerTemplate.hbs +176 -0
  194. package/tsconfig.json +17 -0
  195. package/tslint.json +3 -0
@@ -0,0 +1,189 @@
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 { ClassDeclaration } from 'ts-morph';
17
+ import { ClassAnalysis, Logger } from '../../..';
18
+ import { DecoratorConstants } from '../../../constants';
19
+
20
+ /**
21
+ * 合并版Sendable类生成器
22
+ *
23
+ * 当满足合并条件时,将原始类直接转换为Sendable类:
24
+ * - 移除所有TurboTrans装饰器 (@Serializable, @SerialName, @Required, @Transient)
25
+ * - 添加 @Sendable 装饰器
26
+ * - 类名保持不变
27
+ * - 添加 ITSerializable 接口和相关方法
28
+ */
29
+ export class MergedSendableClassGenerator {
30
+ // TurboTrans装饰器集合
31
+ private static readonly TURBO_TRANS_DECORATORS = new Set(DecoratorConstants.SERIAL_DECORATORS);
32
+
33
+ generate(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
34
+ // 1. 移除TurboTrans装饰器
35
+ this.removeTurboTransDecorators(classDecl);
36
+
37
+ // 2. 添加@Sendable装饰器
38
+ this.addSendableDecorator(classDecl);
39
+
40
+ // 3. 添加ITSerializable接口
41
+ this.addITSerializableInterface(classDecl);
42
+
43
+ // 4. 生成三个核心方法
44
+ this.generateConvertToSendableMethod(classDecl, classAnalysis); // 返回自身
45
+ this.generateToOriginMethod(classDecl, classAnalysis);
46
+ this.generateToJsonMethod(classDecl, classAnalysis);
47
+
48
+ Logger.debug(`成功生成合并版Sendable类: ${classAnalysis.className}`);
49
+ }
50
+
51
+ private removeTurboTransDecorators(classDecl: ClassDeclaration): void {
52
+ // 移除类级别的TurboTrans装饰器
53
+ const classDecorators = classDecl.getDecorators();
54
+ classDecorators.forEach(decorator => {
55
+ const decoratorName = decorator.getName();
56
+ if (MergedSendableClassGenerator.TURBO_TRANS_DECORATORS.has(decoratorName)) {
57
+ decorator.remove();
58
+ Logger.debug(`移除类 ${classDecl.getName()} 的装饰器: @${decoratorName}`);
59
+ }
60
+ });
61
+
62
+ // 移除属性级别的TurboTrans装饰器
63
+ const properties = classDecl.getProperties();
64
+ properties.forEach(property => {
65
+ const propDecorators = property.getDecorators();
66
+ propDecorators.forEach(decorator => {
67
+ const decoratorName = decorator.getName();
68
+ if (MergedSendableClassGenerator.TURBO_TRANS_DECORATORS.has(decoratorName)) {
69
+ decorator.remove();
70
+ Logger.debug(`移除属性 ${property.getName()} 的装饰器: @${decoratorName}`);
71
+ }
72
+ });
73
+ });
74
+ }
75
+
76
+ private addSendableDecorator(classDecl: ClassDeclaration): void {
77
+ classDecl.addDecorator({ name: 'Sendable' });
78
+ }
79
+
80
+ private addITSerializableInterface(classDecl: ClassDeclaration): void {
81
+ // 检查是否已经实现了接口
82
+ const existingImplements = classDecl.getImplements().map(impl => impl.getText());
83
+ if (existingImplements.some(impl => impl.includes('ITSerializable'))) {
84
+ Logger.warn(`类 ${classDecl.getName()} 已经实现了ITSerializable接口, 跳过接口添加`);
85
+ return;
86
+ }
87
+
88
+ // 添加接口实现
89
+ classDecl.addImplements(['ITSerializable', 'lang.ISendable']);
90
+ }
91
+
92
+ private generateGetTypeMethod(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
93
+ // 检查是否已存在该方法
94
+ if (classDecl.getMethod('getType')) {
95
+ Logger.warn(`类 ${classAnalysis.className} 已存在getType方法,跳过生成`);
96
+ return;
97
+ }
98
+
99
+ const methodBody = `return ${classAnalysis.className};`;
100
+
101
+ classDecl.addMethod({
102
+ name: 'getType',
103
+ returnType: 'Function',
104
+ statements: [methodBody]
105
+ });
106
+ }
107
+
108
+ /**
109
+ * 生成toSendable方法
110
+ * 对于合并版Sendable类,直接返回自身(因为类本身已经是Sendable)
111
+ */
112
+ private generateConvertToSendableMethod(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
113
+ // 检查是否已存在该方法
114
+ if (classDecl.getMethod('toSendable')) {
115
+ Logger.warn(`类 ${classAnalysis.className} 已存在toSendable方法,跳过生成`);
116
+ return;
117
+ }
118
+
119
+ // 合并版Sendable类的toSendable方法返回自身
120
+ let returnType = classAnalysis.className;
121
+ if (classAnalysis.generics.parameters.length > 0) {
122
+ returnType += `<${classAnalysis.generics.parameters.join(', ')}>`;
123
+ }
124
+
125
+ classDecl.addMethod({
126
+ name: 'toSendable',
127
+ returnType: returnType,
128
+ statements: ['return this;'] // 直接返回自身
129
+ });
130
+
131
+ Logger.debug(`为合并版Sendable类 ${classAnalysis.className} 生成toSendable方法(返回自身)`);
132
+ }
133
+
134
+ private generateToOriginMethod(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
135
+ // 检查是否已存在该方法
136
+ if (classDecl.getMethod('toOrigin')) {
137
+ Logger.warn(`类 ${classAnalysis.className} 已存在toOrigin方法,跳过生成`);
138
+ return;
139
+ }
140
+
141
+ // 合并版Sendable类的toSendable方法返回自身
142
+ let returnType = classAnalysis.className;
143
+ if (classAnalysis.generics.parameters.length > 0) {
144
+ returnType += `<${classAnalysis.generics.parameters.join(', ')}>`;
145
+ }
146
+
147
+ classDecl.addMethod({
148
+ name: 'toOrigin',
149
+ returnType: returnType,
150
+ statements: ['return this;'] // 直接返回自身
151
+ });
152
+
153
+ Logger.debug(`为合并版Sendable类 ${classAnalysis.className} 生成toOrigin方法(返回自身)`);
154
+ }
155
+
156
+ private generateToJsonMethod(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
157
+ // 检查是否已存在该方法
158
+ if (classDecl.getMethod('toJson')) {
159
+ Logger.warn(`类 ${classAnalysis.className} 已存在toJson方法,跳过生成`);
160
+ return;
161
+ }
162
+
163
+ const methodBody = 'return TJSON.toString(this, typeKey)';
164
+
165
+ // 获取类的泛型参数
166
+ const genericParameters = classAnalysis.generics.parameters;
167
+
168
+ // 构建完整的类型名(包含泛型参数)
169
+ let fullTypeName: string;
170
+ if (genericParameters.length > 0) {
171
+ // 对于泛型类:ClassName<T, U>
172
+ fullTypeName = `${classDecl.getNameOrThrow()}<${genericParameters.join(', ')}>`;
173
+ } else {
174
+ // 对于非泛型类:ClassName
175
+ fullTypeName = classDecl.getNameOrThrow();
176
+ }
177
+
178
+ classDecl.addMethod({
179
+ name: 'toJson',
180
+ returnType: 'string',
181
+ parameters: [{
182
+ name: 'typeKey',
183
+ type: 'TypeKey',
184
+ hasQuestionToken: true
185
+ }],
186
+ statements: [methodBody]
187
+ });
188
+ }
189
+ }
@@ -0,0 +1,314 @@
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 { ClassDeclaration, Project, SourceFile } from 'ts-morph';
17
+ import { ClassAnalysis, PropertyAnalysis, Logger, PropertyKind, ITaskContext } from '../../..';
18
+ import { ImportManager } from '../shared/ImportManager';
19
+ import SerializationPathUtil from '../../../utils/SerializationPathUtil';
20
+ import { ConversionDirection } from '../../../handlers/ITypeHandler';
21
+ import { TypeHandlerRegistry } from '../../../handlers';
22
+ import { MergedSendableClassGenerator } from './MergedSendableClassGenerator';
23
+ import { CustomError, ErrorCodes } from '../../../utils/CustomError';
24
+ import { TsMorphUtil } from '../../../utils/TsMorphUtil';
25
+
26
+ export class OriginalClassGenerator {
27
+ private readonly importManager: ImportManager;
28
+ private readonly mergedSendableGenerator: MergedSendableClassGenerator;
29
+
30
+ constructor(importManager: ImportManager) {
31
+ this.importManager = importManager;
32
+ this.mergedSendableGenerator = new MergedSendableClassGenerator();
33
+ }
34
+
35
+ generate(outputSourceFile: SourceFile, originalSourceFile: SourceFile, results: ClassAnalysis[], context: ITaskContext): void {
36
+ this.registerImports();
37
+
38
+ // 1. 获取原始源文件的完整内容并移除原始import语句
39
+ const contentWithoutImports = this.copySourceFileContentWithoutImports(originalSourceFile);
40
+
41
+ // 2. 创建临时源文件进行AST操作
42
+ const tempSourceFile = TsMorphUtil.getProject().createSourceFile('temp.ts', contentWithoutImports, {
43
+ overwrite: true
44
+ });
45
+
46
+ for (const result of results) {
47
+ const className = result.className;
48
+ // 3. 找到目标类
49
+ const targetClass = tempSourceFile.getClassOrThrow(className);
50
+
51
+ if (result.canMerge && result.decorators.serializable?.generateSendable) {
52
+ this.importManager.registerArkTSImports(['lang']);
53
+ this.mergedSendableGenerator.generate(targetClass, result);
54
+ } else {
55
+ this.addITSerializableInterface(targetClass);
56
+ this.addStaticSerialName(targetClass, result, context);
57
+ this.generateConvertToSendableMethod(targetClass, result);
58
+ this.generateToJsonMethod(targetClass, result);
59
+ }
60
+ }
61
+
62
+ // 8. 将修改后的内容写入目标文件
63
+ outputSourceFile.addStatements(tempSourceFile.getFullText());
64
+ }
65
+
66
+ private copySourceFileContentWithoutImports(originalSourceFile: SourceFile): string {
67
+ const originalFilePath = originalSourceFile.getFilePath();
68
+ const originalDir = SerializationPathUtil.dirname(originalFilePath);
69
+
70
+ // 创建临时源文件用于AST操作
71
+ const tempSourceFile = TsMorphUtil.getProject().createSourceFile(
72
+ 'temp-original.ts',
73
+ originalSourceFile.getFullText(),
74
+ {
75
+ overwrite: true
76
+ }
77
+ );
78
+
79
+ // 移除所有import声明
80
+ const importDeclarations = tempSourceFile.getImportDeclarations();
81
+ importDeclarations.forEach((importDecl) => {
82
+ const specifier = importDecl.getModuleSpecifierValue();
83
+ const names = importDecl.getNamedImports().map((names) => names.getName());
84
+ const defaultImport = importDecl.getDefaultImport();
85
+
86
+ const importOriginAbs = SerializationPathUtil.pathResolve(originalDir, specifier);
87
+ if (SerializationPathUtil.exist(importOriginAbs + '.ets')) {
88
+ // 路径存在,使用模块化路径计算
89
+ const importOriginAbsWithExt = importOriginAbs + '.ets';
90
+ names.forEach((name) => {
91
+ this.importManager.registerCustomTypeImport(importOriginAbsWithExt, name);
92
+ });
93
+ if (defaultImport) {
94
+ this.importManager.registerDefaultImport(importOriginAbsWithExt, defaultImport.getText());
95
+ }
96
+ } else {
97
+ // 不存在该路径,说明可能为包名,暂时不动
98
+ names.forEach((name) => {
99
+ this.importManager.registerCustomImport(specifier, name);
100
+ });
101
+ if (defaultImport) {
102
+ this.importManager.registerDefaultImport(specifier, defaultImport.getText());
103
+ }
104
+ }
105
+ // 先删除源文件导入,统一注册到importManger中处理
106
+ importDecl.remove();
107
+ });
108
+
109
+ const contentWithoutImports = tempSourceFile.getFullText();
110
+
111
+ if (!contentWithoutImports || contentWithoutImports.trim().length === 0) {
112
+ throw new CustomError(`Source file content is empty for ${originalFilePath}`, ErrorCodes.INVALID_FILE_CONTENT);
113
+ }
114
+
115
+ Logger.debug(`成功拷贝 ${originalFilePath} 文件内容并替换import语句`);
116
+ return contentWithoutImports;
117
+ }
118
+
119
+ private addITSerializableInterface(classDecl: ClassDeclaration): void {
120
+ // 检查是否已经实现了接口
121
+ const existingImplements = classDecl.getImplements().map((impl) => impl.getText());
122
+ if (existingImplements.some((impl) => impl.includes('ITSerializable'))) {
123
+ Logger.warn(`类 ${classDecl.getName()} 已经实现了ITSerializable接口, 跳过接口添加`);
124
+ return;
125
+ }
126
+
127
+ // 添加接口实现
128
+ classDecl.addImplements('ITSerializable');
129
+ Logger.debug(`为类 ${classDecl.getName()} 添加ITSerializable接口实现`);
130
+ }
131
+
132
+ private generateSerialNameConstant(result: ClassAnalysis, context: ITaskContext): string {
133
+ const relativePath = context.calculateSourceRootToModuleRoot(result.sourceFilePath);
134
+ const serialName = SerializationPathUtil.join(context.getPackageName(), relativePath, result.className + '.class')
135
+ .replaceAll(SerializationPathUtil.sep, '/');
136
+ return result.decorators.serialName || serialName;
137
+ }
138
+
139
+ private addStaticSerialName(classDecl: ClassDeclaration, result: ClassAnalysis, context: ITaskContext): void {
140
+ // 添加静态属性
141
+ classDecl.addProperty({
142
+ name: 'SERIAL_NAME',
143
+ type: 'string',
144
+ initializer: `${result.className}_SERIAL_NAME`,
145
+ isStatic: true,
146
+ isReadonly: true,
147
+ });
148
+ Logger.debug(`为类 ${classDecl.getName()} 添加静态属性 serialName`);
149
+ }
150
+
151
+ private generateGetTypeMethod(classDecl: ClassDeclaration, result: ClassAnalysis): void {
152
+ // 检查是否已存在该方法
153
+ if (classDecl.getMethod('getType')) {
154
+ Logger.warn(`类 ${result.className} 已存在getType方法,跳过生成`);
155
+ return;
156
+ }
157
+
158
+ const methodBody = `return ${result.className};`;
159
+
160
+ classDecl.addMethod({
161
+ name: 'getType',
162
+ returnType: 'Function',
163
+ statements: [methodBody]
164
+ });
165
+ }
166
+
167
+ private generateConvertToSendableMethod(classDecl: ClassDeclaration, result: ClassAnalysis): void {
168
+ // 检查是否已存在该方法
169
+ if (classDecl.getMethod('toSendable')) {
170
+ Logger.warn(`类 ${result.className} 已存在toSendable方法,跳过生成`);
171
+ return;
172
+ }
173
+
174
+ const isSendable = result.decorators.serializable?.generateSendable;
175
+
176
+ if (!isSendable) {
177
+ // 如果不需要生成Sendable类,返回undefined
178
+ classDecl.addMethod({
179
+ name: 'toSendable',
180
+ returnType: 'undefined',
181
+ statements: ['return undefined']
182
+ });
183
+ return;
184
+ }
185
+
186
+ let returnType = `Sendable${result.className}`;
187
+ if (result.generics.parameters.length > 0) {
188
+ returnType += `<${result.generics.parameters.join(', ')}>`;
189
+ }
190
+ // 生成方法体
191
+ const methodBody = this.generateConvertToSendableMethodBody(result, returnType);
192
+ classDecl.addMethod({
193
+ name: 'toSendable',
194
+ returnType: returnType,
195
+ statements: [methodBody]
196
+ });
197
+ }
198
+
199
+ private generateToJsonMethod(classDecl: ClassDeclaration, result: ClassAnalysis): void {
200
+ // 检查是否已存在该方法
201
+ if (classDecl.getMethod('toJson')) {
202
+ Logger.warn(`类 ${result.className} 已存在toJson方法,跳过生成`);
203
+ return;
204
+ }
205
+
206
+ const methodBody = 'return TJSON.toString(this, typeKey)';
207
+
208
+ // 获取类的泛型参数
209
+ const genericParameters = result.generics.parameters;
210
+
211
+ // 构建完整的类型名(包含泛型参数)
212
+ let fullTypeName: string;
213
+ if (genericParameters.length > 0) {
214
+ // 对于泛型类:ClassName<T, U>
215
+ fullTypeName = `${classDecl.getNameOrThrow()}<${genericParameters.join(', ')}>`;
216
+ } else {
217
+ // 对于非泛型类:ClassName
218
+ fullTypeName = classDecl.getNameOrThrow();
219
+ }
220
+
221
+ classDecl.addMethod({
222
+ name: 'toJson',
223
+ returnType: 'string',
224
+ parameters: [{
225
+ name: 'typeKey',
226
+ type: 'TypeKey',
227
+ hasQuestionToken: true
228
+ }],
229
+ statements: [methodBody]
230
+ });
231
+ }
232
+
233
+ private registerImports(): void {
234
+ this.importManager.registerJsonImports(['ITSerializable', 'TJSON']);
235
+
236
+ this.importManager.registerCoreImports(['TypeKey', 'Serializable']);
237
+ }
238
+
239
+ // ============= toSendable方法生成 =============
240
+
241
+ private generateConvertToSendableMethodBody(classAnalysis: ClassAnalysis, returnType: string): string {
242
+ const constructorProps: PropertyAnalysis[] = [];
243
+ // 遍历 constructorParams 按顺序处理
244
+ classAnalysis.constructorParams.forEach((cp) => {
245
+ // 查找 classAnalysis.properties 中是否存在该属性
246
+ const matchingProperty = classAnalysis.properties.find((p) => p.name === cp.name);
247
+
248
+ // 如果找到匹配的属性,按顺序添加到 constructorProps
249
+ if (matchingProperty) {
250
+ constructorProps.push({
251
+ ...matchingProperty,
252
+ type: {
253
+ ...matchingProperty.type,
254
+ // 使用 constructorParam 中的 isOptional
255
+ isOptional: cp.isOptional,
256
+ }
257
+ });
258
+ }
259
+ });
260
+
261
+ const assignmentProps = classAnalysis.properties.filter((p) => {
262
+ return classAnalysis.constructorParams.every((cp) => cp.name !== p.name);
263
+ });
264
+ const statements: string[] = [];
265
+
266
+ // 生成构造函数调用
267
+ const constructorCall = this.generateConstructorCall(constructorProps, returnType);
268
+ statements.push(`const sendable = ${constructorCall};`);
269
+
270
+ // 生成属性赋值语句
271
+ if (assignmentProps.length > 0) {
272
+ statements.push('');
273
+ statements.push('// 非构造函数属性赋值');
274
+ assignmentProps.forEach((prop) => {
275
+ const assignment = this.generatePropertyAssignment(prop);
276
+ statements.push(`sendable.${prop.name} = ${assignment};`);
277
+ });
278
+ }
279
+
280
+ statements.push('');
281
+ statements.push('return sendable;');
282
+
283
+ return statements.join('\n');
284
+ }
285
+
286
+ private generateConstructorCall(constructorProps: PropertyAnalysis[], returnType: string): string {
287
+ if (constructorProps.length === 0) {
288
+ return `new ${returnType}()`;
289
+ }
290
+
291
+ const args = constructorProps.map(prop => {
292
+ return this.generatePropertyConversion(prop, 'this.');
293
+ }).join(', ');
294
+
295
+ return `new ${returnType}(${args})`;
296
+ }
297
+
298
+ private generatePropertyAssignment(prop: PropertyAnalysis): string {
299
+ return this.generatePropertyConversion(prop, 'this.');
300
+ }
301
+
302
+ private generatePropertyConversion(prop: PropertyAnalysis, prefix: string): string {
303
+ const sourceValue = `${prefix}${prop.name}`;
304
+ if (prop.type.kind === PropertyKind.UNKNOWN) {
305
+ // UNKNOWN只接跳过
306
+ return sourceValue;
307
+ }
308
+ const registry = TypeHandlerRegistry.getInstance();
309
+ const handler = registry.getHandlerForKind(prop.type.kind);
310
+
311
+ // TO_SENDABLE: 普通对象 -> Sendable对象
312
+ return handler.generatePropertyConversion(prop.type, sourceValue, ConversionDirection.TO_SENDABLE);
313
+ }
314
+ }