@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,149 @@
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 { HvigorLogger } from '@ohos/hvigor'
17
+
18
+ const PREFIX = '[TSerialization]'
19
+
20
+ /**
21
+ * TSerialization 日志工具类
22
+ * 自动添加项目前缀和模块信息,简化日志输出
23
+ */
24
+ export class Logger {
25
+ /** 当前模块上下文 */
26
+ private static currentModule: string = ''
27
+
28
+ /**
29
+ * 设置当前模块上下文
30
+ * @param moduleName 模块名称
31
+ */
32
+ static setModuleContext(moduleName: string): void {
33
+ this.currentModule = moduleName
34
+ }
35
+
36
+ /**
37
+ * 清除当前模块上下文
38
+ */
39
+ static clearModuleContext(): void {
40
+ this.currentModule = ''
41
+ }
42
+
43
+ /**
44
+ * 获取当前模块上下文
45
+ */
46
+ static getCurrentModule(): string {
47
+ return this.currentModule
48
+ }
49
+
50
+ /**
51
+ * 格式化日志消息
52
+ * @param msg 原始消息
53
+ * @returns 格式化后的消息
54
+ */
55
+ private static formatMessage(msg: string): string {
56
+ const modulePrefix = this.currentModule ? `[${this.currentModule}]` : ''
57
+ return `${PREFIX}${modulePrefix} ${msg}`
58
+ }
59
+
60
+ /**
61
+ * 输出错误日志
62
+ * @param msg 错误消息
63
+ * @param args 额外参数
64
+ */
65
+ static error(msg: string, ...args: unknown[]): void {
66
+ const formattedMsg = this.formatMessage(msg)
67
+ if (args.length > 0) {
68
+ HvigorLogger.getLogger().error(formattedMsg, ...args)
69
+ } else {
70
+ HvigorLogger.getLogger().error(formattedMsg)
71
+ }
72
+ }
73
+
74
+ /**
75
+ * 输出信息日志
76
+ * @param msg 信息消息
77
+ * @param args 额外参数
78
+ */
79
+ static info(msg: string, ...args: unknown[]): void {
80
+ const formattedMsg = this.formatMessage(msg)
81
+ if (args.length > 0) {
82
+ HvigorLogger.getLogger().info(formattedMsg, ...args)
83
+ } else {
84
+ HvigorLogger.getLogger().info(formattedMsg)
85
+ }
86
+ }
87
+
88
+ /**
89
+ * 输出警告日志
90
+ * @param msg 警告消息
91
+ * @param args 额外参数
92
+ */
93
+ static warn(msg: string, ...args: unknown[]): void {
94
+ const formattedMsg = this.formatMessage(msg)
95
+ if (args.length > 0) {
96
+ HvigorLogger.getLogger().warn(formattedMsg, ...args)
97
+ } else {
98
+ HvigorLogger.getLogger().warn(formattedMsg)
99
+ }
100
+ }
101
+
102
+ /**
103
+ * 输出调试日志
104
+ * @param msg 调试消息
105
+ * @param args 额外参数
106
+ */
107
+ static debug(msg: string, ...args: unknown[]): void {
108
+ const formattedMsg = this.formatMessage(msg)
109
+ if (args.length > 0) {
110
+ HvigorLogger.getLogger().debug(formattedMsg, ...args)
111
+ } else {
112
+ HvigorLogger.getLogger().debug(formattedMsg)
113
+ }
114
+ }
115
+
116
+ /**
117
+ * 在指定模块上下文中执行函数,执行完毕后自动清理上下文
118
+ * @param moduleName 模块名称
119
+ * @param fn 要执行的函数
120
+ * @returns 函数执行结果
121
+ */
122
+ static withModuleContext<T>(moduleName: string, fn: () => T): T {
123
+ const previousModule = this.currentModule
124
+ try {
125
+ this.setModuleContext(moduleName)
126
+ return fn()
127
+ } finally {
128
+ // 恢复之前的模块上下文
129
+ this.currentModule = previousModule
130
+ }
131
+ }
132
+
133
+ /**
134
+ * 在指定模块上下文中执行异步函数,执行完毕后自动清理上下文
135
+ * @param moduleName 模块名称
136
+ * @param fn 要执行的异步函数
137
+ * @returns Promise
138
+ */
139
+ static async withModuleContextAsync<T>(moduleName: string, fn: () => Promise<T>): Promise<T> {
140
+ const previousModule = this.currentModule
141
+ try {
142
+ this.setModuleContext(moduleName)
143
+ return await fn()
144
+ } finally {
145
+ // 恢复之前的模块上下文
146
+ this.currentModule = previousModule
147
+ }
148
+ }
149
+ }
@@ -0,0 +1,67 @@
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, ModuleKind, Project, ScriptTarget } from 'ts-morph';
17
+ import { ClassAnalysis, DecoratorConstants, Logger } from '..';
18
+ import { ClassAnalyzer } from '../analyzers/ClassAnalyzer';
19
+ import { TsMorphUtil } from '../utils/TsMorphUtil';
20
+
21
+ export class CodeAnalysisService {
22
+ constructor() { }
23
+
24
+ analyzeFile(filePath: string): ClassAnalysis[] {
25
+ Logger.debug(`开始分析文件: ${filePath}`);
26
+
27
+ const sourceFile = TsMorphUtil.getProject().addSourceFileAtPath(filePath);
28
+ const classes = sourceFile.getClasses();
29
+ const results: ClassAnalysis[] = [];
30
+
31
+ for (const cls of classes) {
32
+ const classAnalysis = this.analyzeClass(cls);
33
+ if (classAnalysis) {
34
+ results.push(classAnalysis);
35
+ } else {
36
+ Logger.debug(`${cls.getName()}无@Serializable装饰器,跳过分析`);
37
+ }
38
+ }
39
+
40
+ Logger.debug(`文件分析完成: ${filePath}, 发现 ${results.length} 个@Serializable类`);
41
+
42
+ return results;
43
+ }
44
+
45
+ private analyzeClass(cls: ClassDeclaration): ClassAnalysis | null {
46
+ const decorators = cls.getDecorators();
47
+
48
+ for (const decorator of decorators) {
49
+ if (decorator.getName() === DecoratorConstants.SERIALIZABLE) {
50
+ // 找到@Serializable装饰器,开始分析
51
+ return ClassAnalyzer.analyzeClass(cls);
52
+ }
53
+ }
54
+
55
+ // 没有@Serializable装饰器,跳过
56
+ return null;
57
+ }
58
+
59
+ dispose(): void {
60
+ // 清理项目资源
61
+ const sourceFiles = TsMorphUtil.getProject().getSourceFiles();
62
+ Logger.info(`code analysis Clearing ${sourceFiles.length} source files...`);
63
+ sourceFiles.forEach((sourceFile) => {
64
+ TsMorphUtil.getProject().removeSourceFile(sourceFile);
65
+ });
66
+ }
67
+ }
@@ -0,0 +1,181 @@
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 { ClassAnalysis, IGeneratedFile, IGenerationResult, Logger, ITaskContext, GeneratedFileInfo } from '..';
17
+ import { CodeAnalysisService } from './CodeAnalysisService';
18
+ import { CodeGenerationService } from './CodeGenerationService';
19
+ import { SendableMergeabilityRegistry } from '../analyzers/SendableMergeabilityRegistry';
20
+ import { SendableMergeChecker } from '../analyzers/SendableMergeChecker';
21
+ import { CustomTypeAnalyzer } from '../analyzers/CustomTypeAnalyzer';
22
+
23
+ export class CodeGenerationEngine {
24
+ private readonly analysisService: CodeAnalysisService
25
+ private readonly generationService: CodeGenerationService
26
+
27
+ // 保存分析结果供导入重写使用
28
+ private allClassAnalysis: ClassAnalysis[] = []
29
+
30
+ constructor() {
31
+ this.analysisService = new CodeAnalysisService()
32
+ this.generationService = new CodeGenerationService()
33
+ }
34
+
35
+ /**
36
+ * @param scanFiles 待处理的源文件路径列表
37
+ * @param context 任务上下文
38
+ * @returns 生成结果详情
39
+ */
40
+ processFilesUnified(scanFiles: string[], context: ITaskContext): IGenerationResult {
41
+ if (!scanFiles || scanFiles.length === 0) {
42
+ Logger.info('没有待处理的源文件')
43
+ return {
44
+ generatedFiles: [],
45
+ skippedFiles: []
46
+ }
47
+ }
48
+
49
+ const generatedFiles: IGeneratedFile[] = []
50
+ const skippedFiles: string[] = []
51
+
52
+ // 重置分析结果和合并性注册表
53
+ this.allClassAnalysis = []
54
+ SendableMergeabilityRegistry.clear()
55
+
56
+ Logger.info(`开始处理 ${scanFiles.length} 个源文件`)
57
+
58
+ // ========== 阶段1:分析所有文件并检查合并性 ==========
59
+ Logger.debug(`[阶段1] 开始分析所有文件`)
60
+ const fileAnalysisMap = new Map<string, ClassAnalysis[]>()
61
+
62
+ // 步骤1.1:分析所有文件的基本信息
63
+ for (const filePath of scanFiles) {
64
+ const classAnalysis = this.analysisService.analyzeFile(filePath)
65
+
66
+ if (classAnalysis.length === 0) {
67
+ skippedFiles.push(filePath)
68
+ Logger.debug(`跳过文件(无@Serializable类): ${filePath}`)
69
+ continue
70
+ }
71
+
72
+ // 保存分析结果
73
+ fileAnalysisMap.set(filePath, classAnalysis)
74
+ this.allClassAnalysis.push(...classAnalysis)
75
+ }
76
+
77
+ Logger.debug(`[阶段1.1] 完成基本分析,共 ${this.allClassAnalysis.length} 个类`)
78
+
79
+ // 步骤1.2:检查所有类的合并性并注册到全局注册表
80
+ Logger.debug(`[阶段1.2] 开始检查合并性并注册`)
81
+ for (const analysis of this.allClassAnalysis) {
82
+ // 仅对启用 generateSendable 的类检查合并性
83
+ if (analysis.decorators.serializable?.generateSendable) {
84
+ analysis.canMerge = SendableMergeChecker.check(analysis)
85
+ SendableMergeabilityRegistry.register(analysis.className, analysis.canMerge)
86
+ } else {
87
+ // 未启用 generateSendable 的类,注册为不可合并
88
+ SendableMergeabilityRegistry.register(analysis.className, false)
89
+ }
90
+ }
91
+
92
+ // ========== 阶段2:生成所有文件 ==========
93
+ Logger.debug(`[阶段2] 开始生成所有文件`)
94
+
95
+ for (const [filePath, classAnalysis] of fileAnalysisMap.entries()) {
96
+ const generatedFile = this.generationService.generateForSourceFile(filePath, classAnalysis, context)
97
+ if (generatedFile) {
98
+ generatedFiles.push(generatedFile)
99
+ Logger.debug(`成功处理文件: ${filePath}`)
100
+ } else {
101
+ Logger.warn(`文件生成失败: ${filePath}`)
102
+ }
103
+ }
104
+
105
+ Logger.info(`处理完成,成功 ${generatedFiles.length} 个,跳过 ${skippedFiles.length} 个`)
106
+
107
+ return { generatedFiles, skippedFiles }
108
+ }
109
+
110
+ /**
111
+ * @param filePath 源文件路径
112
+ * @param context 任务上下文
113
+ * @returns 生成的文件信息,如果无需生成则返回null
114
+ */
115
+ processFileUnified(filePath: string, context: ITaskContext): IGeneratedFile | null {
116
+ const classAnalysis = this.analysisService.analyzeFile(filePath)
117
+
118
+ // 如果没有@Serializable类,跳过生成
119
+ if (classAnalysis.length === 0) {
120
+ Logger.debug(`源文件 ${filePath} 无@Serializable类,跳过生成`)
121
+ return null
122
+ }
123
+
124
+ // 保存分析结果供导入重写使用
125
+ this.allClassAnalysis.push(...classAnalysis)
126
+
127
+ // 生成对应文件
128
+ return this.generationService.generateForSourceFile(filePath, classAnalysis, context)
129
+ }
130
+
131
+
132
+ /**
133
+ * 收集所有生成的文件信息
134
+ * 供导入重写功能使用
135
+ * @param context 任务上下文
136
+ * @returns 生成文件信息列表
137
+ */
138
+ collectGeneratedFileInfos(context: ITaskContext): GeneratedFileInfo[] {
139
+ // 按源文件路径分组收集类名
140
+ const fileInfoMap = new Map<string, GeneratedFileInfo>();
141
+
142
+ for (const analysisResult of this.allClassAnalysis) {
143
+ const sourceFilePath = analysisResult.sourceFilePath;
144
+
145
+ if (!fileInfoMap.has(sourceFilePath)) {
146
+ // 为新文件创建 GeneratedFileInfo
147
+ const generatedFilePath = context.mapToOutputPath(sourceFilePath);
148
+ fileInfoMap.set(sourceFilePath, {
149
+ sourceFilePath,
150
+ generatedFilePath,
151
+ classNames: new Set<string>()
152
+ });
153
+ }
154
+
155
+ // 添加类名到对应文件的集合中
156
+ const fileInfo = fileInfoMap.get(sourceFilePath)!;
157
+ fileInfo.classNames.add(analysisResult.className);
158
+ }
159
+
160
+ return Array.from(fileInfoMap.values());
161
+ }
162
+
163
+ /**
164
+ * 获取所有分析结果
165
+ * 供外部使用(如调试)
166
+ */
167
+ getAllAnalysisResults(): ClassAnalysis[] {
168
+ return [...this.allClassAnalysis]
169
+ }
170
+
171
+ /**
172
+ * 清理资源
173
+ * 注意:这个方法应该在整个流程(包括导入重写)完成后调用
174
+ */
175
+ cleanup(): void {
176
+ this.analysisService.dispose()
177
+ this.allClassAnalysis = []
178
+ CustomTypeAnalyzer.getInstance().clearCache()
179
+ SendableMergeabilityRegistry.clear()
180
+ }
181
+ }
@@ -0,0 +1,159 @@
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 { IndentationText, Project, QuoteKind } from 'ts-morph';
17
+ import { OriginalClassGenerator } from './generators/OriginalClassGenerator';
18
+ import { SendableClassGenerator } from './generators/SendableClassGenerator';
19
+ import { SerializerGenerator } from './generators/SerializerGenerator';
20
+ import { ImportManager } from './shared/ImportManager';
21
+ import { ClassAnalysis, IGeneratedFile, Logger, ITaskContext, GenerationContext } from '../..';
22
+ import SerializationPathUtil from '../../utils/SerializationPathUtil';
23
+ import { CustomError, ErrorCodes } from '../../utils/CustomError';
24
+ import { TsMorphUtil } from '../../utils/TsMorphUtil';
25
+
26
+ export class CodeGenerationService {
27
+ private readonly importManger: ImportManager;
28
+ private readonly originalClassGenerator: OriginalClassGenerator;
29
+ private readonly serializerGenerator: SerializerGenerator;
30
+ private readonly sendableGenerator: SendableClassGenerator;
31
+
32
+ constructor() {
33
+ this.importManger = new ImportManager();
34
+
35
+ this.originalClassGenerator = new OriginalClassGenerator(this.importManger);
36
+ this.serializerGenerator = new SerializerGenerator(this.importManger);
37
+ this.sendableGenerator = new SendableClassGenerator();
38
+ }
39
+
40
+ generateForSourceFile(sourcePath: string, results: ClassAnalysis[], context: ITaskContext): IGeneratedFile | null {
41
+ Logger.debug(`开始为 ${sourcePath} 文件生成代码: ${results.length} 个类`);
42
+ this.importManger.setContext(context);
43
+ // 1. 生成Sendable文件(sendableModel目录)- 包含Sendable类
44
+ this.generateSendableModelFiles(results, context);
45
+ // 2. 生成主文件(model目录)- 包含原始类、序列化器、toSendable方法
46
+ return this.generateMainModelFile(sourcePath, results, context);
47
+ }
48
+
49
+ private generateMainModelFile(
50
+ sourceFileAbs: string,
51
+ results: ClassAnalysis[],
52
+ context: ITaskContext
53
+ ): IGeneratedFile | null {
54
+ const originalSourceFile = TsMorphUtil.getProject().addSourceFileAtPath(sourceFileAbs);
55
+ // 计算输出路径
56
+ const outputPath = context.mapToOutputPath(sourceFileAbs);
57
+ // 确保输出目录存在
58
+ context.ensureOutputDirectory(outputPath);
59
+ // 验证输出路径有效性
60
+ if (!context.isValidOutputPath(outputPath)) {
61
+ throw new CustomError(`输出路径无效: ${outputPath}`, ErrorCodes.INVALID_OUTPUT_FAIL);
62
+ }
63
+ // 创建输出文件
64
+ const outputSourceFile = TsMorphUtil.getProject().createSourceFile(outputPath, '', { overwrite: true });
65
+
66
+ const serializableGeneratorContext: (GenerationContext | string)[] = [];
67
+ for (const classAnalysis of results) {
68
+ serializableGeneratorContext.push(this.serializerGenerator.generate(outputSourceFile, classAnalysis, context));
69
+ }
70
+
71
+ // 生成原始类结构
72
+ this.originalClassGenerator.generate(outputSourceFile, originalSourceFile, results, context);
73
+
74
+ for (const content of serializableGeneratorContext) {
75
+ this.serializerGenerator.generateRegistration(outputSourceFile, content);
76
+ }
77
+
78
+ // 添加导入语句
79
+ this.importManger.getImportDeclarations().forEach((importDeclaration) => {
80
+ outputSourceFile.addImportDeclaration({
81
+ moduleSpecifier: importDeclaration.specifier,
82
+ namedImports: [...new Set(importDeclaration.names)]
83
+ });
84
+ });
85
+ this.importManger.getDefaultImport().forEach((importDeclaration) => {
86
+ outputSourceFile.addImportDeclaration({
87
+ moduleSpecifier: importDeclaration.specifier,
88
+ defaultImport: importDeclaration.name
89
+ });
90
+ });
91
+ // 格式化代码
92
+ outputSourceFile.formatText();
93
+ // 保存文件
94
+ outputSourceFile.saveSync();
95
+ // 返回生成结果
96
+ this.cleanup();
97
+ return {
98
+ sourcePath: sourceFileAbs,
99
+ outputPath,
100
+ contentLength: outputSourceFile.getFullText().length,
101
+ serializerCount: results.length,
102
+ generatedAt: Date.now()
103
+ };
104
+ }
105
+
106
+ private generateSendableModelFiles(results: ClassAnalysis[], context: ITaskContext): void {
107
+ for (const classAnalysis of results) {
108
+ // 跳过可合并的类(它们已经在主文件中生成为Sendable类)
109
+ if (classAnalysis.canMerge) {
110
+ Logger.debug(`类 ${classAnalysis.className} 采用合并策略,跳过独立Sendable文件生成`);
111
+ continue;
112
+ }
113
+
114
+ // 双版本策略:生成独立的Sendable文件
115
+ if (this.sendableGenerator.canHandle(classAnalysis)) {
116
+ this.generateSendableFile(classAnalysis, context);
117
+ }
118
+ }
119
+ }
120
+
121
+ private generateSendableFile(result: ClassAnalysis, context: ITaskContext): void {
122
+ Logger.debug(`类 ${result.className} 采用独立Sendable文件生成`);
123
+ const sendableOutputPath = SerializationPathUtil.mapToSendableOutputPath(result.className, context);
124
+ context.ensureOutputDirectory(sendableOutputPath);
125
+ const sendableImportManager = new ImportManager();
126
+ sendableImportManager.setContext(context);
127
+ sendableImportManager.registerArkTSImports(['lang']);
128
+ const sendableSourceFile = TsMorphUtil.getProject().createSourceFile(sendableOutputPath, '', { overwrite: true });
129
+ this.sendableGenerator.generate(sendableSourceFile, result, sendableImportManager);
130
+ if (this.sendableGenerator.needsCollectionsImport(result)) {
131
+ this.importManger.registerArkTSImports(['collections']);
132
+ }
133
+ this.importManger.registerCustomTypeImport(sendableOutputPath, `Sendable${result.className}`);
134
+ sendableImportManager.getImportDeclarations().forEach((importDeclaration) => {
135
+ sendableSourceFile.addImportDeclaration({
136
+ moduleSpecifier: importDeclaration.specifier,
137
+ namedImports: [...new Set(importDeclaration.names)]
138
+ });
139
+ });
140
+ sendableImportManager.getDefaultImport().forEach((importDeclaration) => {
141
+ sendableSourceFile.addImportDeclaration({
142
+ moduleSpecifier: importDeclaration.specifier,
143
+ defaultImport: importDeclaration.name
144
+ });
145
+ });
146
+ sendableSourceFile.formatText();
147
+ sendableSourceFile.saveSync();
148
+ }
149
+
150
+ // ============= 验证和清理 =============
151
+
152
+ private cleanup(): void {
153
+ // 注意import是共享的,所以每个文件生成结束以后需要清空
154
+ this.importManger.clear();
155
+
156
+ // 清理项目缓存
157
+ // 注意:不要完全dispose project,因为它可能被重复使用
158
+ }
159
+ }