@hadss/turbo-trans-json-plugin 1.0.0-rc.0 → 1.0.0-rc.2
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/README.md +1 -1
- package/dist/core/Types.d.ts +7 -0
- package/dist/core/Types.js +7 -1
- package/dist/core/analyzers/ClassAnalyzer.d.ts +15 -0
- package/dist/core/analyzers/ClassAnalyzer.js +200 -120
- package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +3 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.js +65 -60
- package/dist/core/constants/DecoratorConstants.d.ts +1 -0
- package/dist/core/constants/DecoratorConstants.js +3 -1
- package/dist/core/handlers/CustomClassHandler.js +0 -1
- package/dist/core/import-rewrite/services/BuildProfileUpdater.js +1 -1
- package/dist/core/import-rewrite/services/ImportRewriteService.js +1 -1
- package/dist/core/interfaces/index.d.ts +2 -2
- package/dist/core/services/CodeAnalysisService.js +2 -1
- package/dist/core/services/CodeGenerationService/CodeGenerationService.js +1 -1
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +0 -1
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +0 -20
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +4 -4
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +26 -45
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +22 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +194 -129
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +20 -15
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +2 -1
- package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +2 -2
- package/dist/core/template/HandlebarsTemplateEngine.d.ts +2 -0
- package/dist/core/template/HandlebarsTemplateEngine.js +24 -2
- package/dist/core/utils/DeepCopyUtil.js +4 -2
- package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +1 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.js +27 -1
- package/dist/core/utils/SerializationPathUtil.d.ts +1 -1
- package/dist/core/utils/TsMorphUtil.js +6 -1
- package/dist/json-plugin/JSONExecuteController.d.ts +4 -0
- package/dist/json-plugin/JSONExecuteController.js +46 -36
- package/dist/json-plugin/interfaces/impl/TargetContext.js +4 -2
- package/dist/json-plugin/tasks/BaseTask.d.ts +2 -2
- package/dist/json-plugin/tasks/WatchTask.js +2 -1
- package/package.json +1 -1
- package/src/core/Types.ts +97 -89
- package/src/core/analyzers/ClassAnalyzer.ts +358 -197
- package/src/core/analyzers/CustomTypeAnalyzer.ts +145 -74
- package/src/core/constants/DecoratorConstants.ts +7 -5
- package/src/core/constants/PathConstants.ts +7 -7
- package/src/core/constants/StringConstants.ts +95 -97
- package/src/core/handlers/BaseTypeHandler.ts +11 -2
- package/src/core/handlers/CustomClassHandler.ts +4 -7
- package/src/core/handlers/DateHandler.ts +54 -46
- package/src/core/handlers/DecimalHandler.ts +53 -45
- package/src/core/handlers/EnumHandler.ts +2 -1
- package/src/core/handlers/GenericContainerHandler.ts +3 -1
- package/src/core/handlers/TupleHandler.ts +2 -1
- package/src/core/handlers/TypeHandlerRegistry.ts +3 -2
- package/src/core/handlers/UnionTypeHandler.ts +8 -7
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +7 -5
- package/src/core/import-rewrite/services/ImportRewriteService.ts +1 -3
- package/src/core/import-rewrite/services/ImportTransformService.ts +2 -2
- package/src/core/import-rewrite/types/ImportRewriteTypes.ts +3 -3
- package/src/core/index.ts +4 -4
- package/src/core/interfaces/ITask.ts +6 -5
- package/src/core/interfaces/ITaskContext.ts +9 -9
- package/src/core/interfaces/index.ts +2 -2
- package/src/core/logger/Logger.ts +28 -28
- package/src/core/services/CodeAnalysisService.ts +3 -2
- package/src/core/services/CodeGenerationEngine.ts +42 -42
- package/src/core/services/CodeGenerationService/CodeGenerationService.ts +1 -2
- package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +0 -29
- package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +31 -64
- package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +261 -170
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +26 -19
- package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +5 -3
- package/src/core/services/CodeGenerationService/shared/ImportManager.ts +8 -8
- package/src/core/template/HandlebarsTemplateEngine.ts +43 -10
- package/src/core/utils/ConfigManager.ts +2 -1
- package/src/core/utils/DeepCopyUtil.ts +4 -2
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +45 -2
- package/src/core/utils/SerializationPathUtil.ts +7 -6
- package/src/core/utils/TsMorphUtil.ts +9 -2
- package/src/index.ts +2 -2
- package/src/json-plugin/JSONExecuteController.ts +51 -38
- package/src/json-plugin/interfaces/IModuleContext.ts +8 -8
- package/src/json-plugin/interfaces/ITargetContext.ts +6 -6
- package/src/json-plugin/interfaces/impl/ModuleContext.ts +10 -10
- package/src/json-plugin/interfaces/impl/TargetContext.ts +63 -58
- package/src/json-plugin/tasks/BaseTask.ts +5 -4
- package/src/json-plugin/tasks/CleanTask.ts +7 -7
- package/src/json-plugin/tasks/WatchTask.ts +20 -18
- package/template/SerializerPerformanceTemplate.hbs +14 -4
- package/template/SerializerStrictTemplate.hbs +9 -1
- package/template/SerializerTemplate.hbs +71 -46
|
@@ -13,8 +13,13 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
|
|
16
|
+
import {
|
|
17
|
+
ClassDeclaration, ConstructorDeclaration, Decorator, Identifier, ImportDeclaration, ParameterDeclaration,
|
|
18
|
+
PropertyDeclaration, SourceFile
|
|
19
|
+
} from 'ts-morph';
|
|
20
|
+
import {
|
|
21
|
+
ClassAnalysis, ClassDetails, Logger, PropertyAnalysis, PropertyKind, TypeDependency, TypeKind, TypeStructure
|
|
22
|
+
} from '../../..';
|
|
18
23
|
import { ImportManager } from '../shared/ImportManager';
|
|
19
24
|
import { ClassAnalyzer } from '../../../analyzers/ClassAnalyzer';
|
|
20
25
|
import { TypeHandlerRegistry } from '../../../handlers';
|
|
@@ -64,7 +69,8 @@ export class SendableClassGenerator {
|
|
|
64
69
|
|
|
65
70
|
private getOriginClassDeclaration(result: ClassAnalysis): ClassDeclaration {
|
|
66
71
|
const originalContent = result.originalClass?.getFullText();
|
|
67
|
-
const copiedSourceFile = TsMorphUtil.getProject()
|
|
72
|
+
const copiedSourceFile = TsMorphUtil.getProject()
|
|
73
|
+
.createSourceFile('copied-file.ts', originalContent, { overwrite: true });
|
|
68
74
|
return copiedSourceFile.getClassOrThrow(result.className);
|
|
69
75
|
}
|
|
70
76
|
|
|
@@ -90,77 +96,93 @@ export class SendableClassGenerator {
|
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
private removeAllDecorators(classDecl: ClassDeclaration): void {
|
|
93
|
-
|
|
99
|
+
this.removeClassDecorators(classDecl);
|
|
100
|
+
this.removePropertyDecorators(classDecl);
|
|
101
|
+
this.removeMethodDecorators(classDecl);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private removeClassDecorators(classDecl: ClassDeclaration): void {
|
|
94
105
|
classDecl.getDecorators().forEach((decorator) => {
|
|
95
|
-
|
|
96
|
-
`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`
|
|
97
|
-
);
|
|
98
|
-
decorator.remove();
|
|
106
|
+
this.logAndRemoveDecorator(decorator);
|
|
99
107
|
});
|
|
108
|
+
}
|
|
100
109
|
|
|
101
|
-
|
|
110
|
+
private removePropertyDecorators(classDecl: ClassDeclaration): void {
|
|
102
111
|
classDecl.getProperties().forEach((property) => {
|
|
103
|
-
property.getDecorators().forEach((decorator) =>
|
|
104
|
-
Logger.warn(
|
|
105
|
-
`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`
|
|
106
|
-
);
|
|
107
|
-
decorator.remove();
|
|
108
|
-
});
|
|
112
|
+
property.getDecorators().forEach((decorator) => this.logAndRemoveDecorator(decorator));
|
|
109
113
|
});
|
|
114
|
+
}
|
|
110
115
|
|
|
111
|
-
|
|
116
|
+
private removeMethodDecorators(classDecl: ClassDeclaration): void {
|
|
112
117
|
classDecl.getMethods().forEach((method) => {
|
|
113
|
-
method.getDecorators().forEach((decorator) =>
|
|
114
|
-
Logger.warn(
|
|
115
|
-
`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`
|
|
116
|
-
);
|
|
117
|
-
decorator.remove();
|
|
118
|
-
});
|
|
118
|
+
method.getDecorators().forEach((decorator) => this.logAndRemoveDecorator(decorator));
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
private logAndRemoveDecorator(decorator: Decorator): void {
|
|
123
|
+
Logger.warn(
|
|
124
|
+
`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`
|
|
125
|
+
);
|
|
126
|
+
decorator.remove();
|
|
127
|
+
}
|
|
128
|
+
|
|
122
129
|
private convertPropertyTypesToSendable(classDecl: ClassDeclaration, result: ClassAnalysis): void {
|
|
123
130
|
const properties = classDecl.getProperties();
|
|
124
|
-
|
|
125
131
|
properties.forEach((property) => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Logger.debug(`Converting property ${propertyName} to sendable`);
|
|
129
|
-
|
|
130
|
-
// 从分析结果中找到对应的属性信息
|
|
131
|
-
const propertyAnalysis = result.properties.find((p) => p.name === propertyName);
|
|
132
|
-
if (!propertyAnalysis) {
|
|
133
|
-
Logger.warn(`未找到属性 ${propertyName} 的分析信息`);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
Logger.debug(
|
|
138
|
-
`Found property ${propertyName} analysis info: ${propertyAnalysis.name} ${propertyAnalysis.type.sourceText}`
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
// 转换类型为Sendable兼容类型
|
|
142
|
-
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
143
|
-
|
|
144
|
-
Logger.debug(`Converted type ${propertyAnalysis.type.sourceText} to ${sendableType}`);
|
|
145
|
-
|
|
146
|
-
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
147
|
-
property.setType(sendableType);
|
|
148
|
-
Logger.debug(`属性 ${propertyName} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// 处理默认值中的构造函数调用
|
|
152
|
-
const initializer = property.getInitializer();
|
|
153
|
-
if (initializer) {
|
|
154
|
-
const initializerText = initializer.getText();
|
|
155
|
-
const convertedInitializer = this.convertInitializerToSendable(initializerText);
|
|
156
|
-
if (convertedInitializer !== initializerText) {
|
|
157
|
-
property.setInitializer(convertedInitializer);
|
|
158
|
-
Logger.debug(`属性 ${propertyName} 默认值从 ${initializerText} 转换为 ${convertedInitializer}`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
132
|
+
this.convertSinglePropertyToSendable(property, result);
|
|
161
133
|
});
|
|
162
134
|
}
|
|
163
135
|
|
|
136
|
+
private convertSinglePropertyToSendable(
|
|
137
|
+
property: PropertyDeclaration,
|
|
138
|
+
result: ClassAnalysis
|
|
139
|
+
): void {
|
|
140
|
+
const propertyName = property.getName();
|
|
141
|
+
Logger.debug(`Converting property ${propertyName} to sendable`);
|
|
142
|
+
|
|
143
|
+
const propertyAnalysis = result.properties.find((p) => p.name === propertyName);
|
|
144
|
+
if (!propertyAnalysis) {
|
|
145
|
+
Logger.warn(`未找到属性 ${propertyName} 的分析信息`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
Logger.debug(
|
|
150
|
+
`Found property ${propertyName} analysis info: ${propertyAnalysis.name} ${propertyAnalysis.type.sourceText}`
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
this.updatePropertyType(property, propertyAnalysis);
|
|
154
|
+
this.updatePropertyInitializer(property, propertyAnalysis.name);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private updatePropertyType(
|
|
158
|
+
property: PropertyDeclaration,
|
|
159
|
+
propertyAnalysis: PropertyAnalysis
|
|
160
|
+
): void {
|
|
161
|
+
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
162
|
+
Logger.debug(`Converted type ${propertyAnalysis.type.sourceText} to ${sendableType}`);
|
|
163
|
+
|
|
164
|
+
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
165
|
+
property.setType(sendableType);
|
|
166
|
+
Logger.debug(`属性 ${propertyAnalysis.name} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private updatePropertyInitializer(
|
|
171
|
+
property: PropertyDeclaration,
|
|
172
|
+
propertyName: string
|
|
173
|
+
): void {
|
|
174
|
+
const initializer = property.getInitializer();
|
|
175
|
+
if (!initializer) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const initializerText = initializer.getText();
|
|
179
|
+
const convertedInitializer = this.convertInitializerToSendable(initializerText);
|
|
180
|
+
if (convertedInitializer !== initializerText) {
|
|
181
|
+
property.setInitializer(convertedInitializer);
|
|
182
|
+
Logger.debug(`属性 ${propertyName} 默认值从 ${initializerText} 转换为 ${convertedInitializer}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
164
186
|
private addSendableConstraints(classDecl: ClassDeclaration): void {
|
|
165
187
|
// 添加@Sendable装饰器
|
|
166
188
|
classDecl.addDecorator({ name: 'Sendable' });
|
|
@@ -187,7 +209,29 @@ export class SendableClassGenerator {
|
|
|
187
209
|
|
|
188
210
|
private generatedToOriginMethodBody(result: ClassAnalysis, returnType: string): string {
|
|
189
211
|
const statements: string[] = [];
|
|
190
|
-
|
|
212
|
+
const constructorCall = this.getConstructorCall(result, returnType);
|
|
213
|
+
statements.push(`const origin = ${constructorCall};`);
|
|
214
|
+
|
|
215
|
+
const assignmentProps = result.properties.filter((p) => {
|
|
216
|
+
return result.constructorParams.every((cp) => cp.name !== p.name);
|
|
217
|
+
});
|
|
218
|
+
// 生成属性赋值语句
|
|
219
|
+
if (assignmentProps.length > 0) {
|
|
220
|
+
statements.push('');
|
|
221
|
+
statements.push('// 非构造函数属性赋值');
|
|
222
|
+
assignmentProps.forEach((prop) => {
|
|
223
|
+
const assignment = this.generatePropertyConversion(prop, 'this.');
|
|
224
|
+
statements.push(`origin.${prop.name} = ${assignment};`);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
statements.push('');
|
|
229
|
+
statements.push('return origin;');
|
|
230
|
+
|
|
231
|
+
return statements.join('\n');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private getConstructorCall(result: ClassAnalysis, returnType: string): string {
|
|
191
235
|
if (result.constructorParams.length > 0) {
|
|
192
236
|
const constructorProps: PropertyAnalysis[] = [];
|
|
193
237
|
result.properties.forEach((p) => {
|
|
@@ -209,29 +253,10 @@ export class SendableClassGenerator {
|
|
|
209
253
|
})
|
|
210
254
|
.join(', ');
|
|
211
255
|
|
|
212
|
-
|
|
256
|
+
return `new ${returnType}(${args})`;
|
|
213
257
|
} else {
|
|
214
|
-
|
|
258
|
+
return `new ${returnType}()`;
|
|
215
259
|
}
|
|
216
|
-
statements.push(`const origin = ${constructorCall};`);
|
|
217
|
-
|
|
218
|
-
const assignmentProps = result.properties.filter((p) => {
|
|
219
|
-
return result.constructorParams.every((cp) => cp.name !== p.name);
|
|
220
|
-
});
|
|
221
|
-
// 生成属性赋值语句
|
|
222
|
-
if (assignmentProps.length > 0) {
|
|
223
|
-
statements.push('');
|
|
224
|
-
statements.push('// 非构造函数属性赋值');
|
|
225
|
-
assignmentProps.forEach((prop) => {
|
|
226
|
-
const assignment = this.generatePropertyConversion(prop, 'this.');
|
|
227
|
-
statements.push(`origin.${prop.name} = ${assignment};`);
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
statements.push('');
|
|
232
|
-
statements.push('return origin;');
|
|
233
|
-
|
|
234
|
-
return statements.join('\n');
|
|
235
260
|
}
|
|
236
261
|
|
|
237
262
|
private generatePropertyConversion(prop: PropertyAnalysis, prefix: string): string {
|
|
@@ -257,84 +282,141 @@ export class SendableClassGenerator {
|
|
|
257
282
|
}
|
|
258
283
|
|
|
259
284
|
private addNecessaryImports(result: ClassAnalysis, importManager: ImportManager): void {
|
|
260
|
-
|
|
285
|
+
this.processPropertyDependencyImports(result, importManager);
|
|
286
|
+
this.processBaseClassImport(result, importManager);
|
|
287
|
+
this.processCollectionsImport(result, importManager);
|
|
288
|
+
this.copySourceFileImports(result, importManager);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private processPropertyDependencyImports(result: ClassAnalysis, importManager: ImportManager): void {
|
|
261
292
|
result.properties.forEach((property) => {
|
|
262
293
|
property.type.dependencies.forEach((dependency) => {
|
|
263
|
-
|
|
264
|
-
const classAnalysis = ClassAnalyzer.analyzeClass((dependency.details as ClassDetails).classDecl);
|
|
265
|
-
if (classAnalysis.decorators.serializable?.generateSendable) {
|
|
266
|
-
importManager.registerCustomImport('./Sendable' + dependency.typeName, 'Sendable' + dependency.typeName);
|
|
267
|
-
} else {
|
|
268
|
-
importManager.registerCustomTypeImport(dependency.source.sourceFilePath!, dependency.typeName);
|
|
269
|
-
}
|
|
270
|
-
} else {
|
|
271
|
-
importManager.registerCustomTypeImport(dependency.source.sourceFilePath!, dependency.typeName);
|
|
272
|
-
}
|
|
294
|
+
this.registerDependencyImport(dependency, importManager);
|
|
273
295
|
});
|
|
274
296
|
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private registerDependencyImport(
|
|
300
|
+
dependency: TypeDependency,
|
|
301
|
+
importManager: ImportManager
|
|
302
|
+
): void {
|
|
303
|
+
if (dependency.typeKind !== TypeKind.CLASS) {
|
|
304
|
+
importManager.registerCustomTypeImport(dependency.source.sourceFilePath!, dependency.typeName);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const classAnalysis = ClassAnalyzer.analyzeClass((dependency.details as ClassDetails).classDecl);
|
|
308
|
+
if (classAnalysis.decorators.serializable?.generateSendable) {
|
|
309
|
+
importManager.registerCustomImport('./Sendable' + dependency.typeName, 'Sendable' + dependency.typeName);
|
|
310
|
+
} else {
|
|
311
|
+
importManager.registerCustomTypeImport(dependency.source.sourceFilePath!, dependency.typeName);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
275
314
|
|
|
315
|
+
private processBaseClassImport(result: ClassAnalysis, importManager: ImportManager): void {
|
|
276
316
|
const baseClass = result.inheritance.baseClassAnalysis;
|
|
277
|
-
if (baseClass) {
|
|
278
|
-
|
|
317
|
+
if (!baseClass) {
|
|
318
|
+
return;
|
|
279
319
|
}
|
|
280
|
-
|
|
320
|
+
importManager.registerCustomImport('./Sendable' + baseClass.className, 'Sendable' + baseClass.className);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private processCollectionsImport(result: ClassAnalysis, importManager: ImportManager): void {
|
|
281
324
|
const needsCollections = this.needsCollectionsImport(result);
|
|
282
|
-
if (needsCollections) {
|
|
283
|
-
|
|
325
|
+
if (!needsCollections) {
|
|
326
|
+
return;
|
|
284
327
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
328
|
+
importManager.registerArkTSImports(['collections']);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private copySourceFileImports(result: ClassAnalysis, importManager: ImportManager): void {
|
|
332
|
+
const importDeclarations = result.originalClass?.getSourceFile().getImportDeclarations();
|
|
333
|
+
if (!importDeclarations) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
importDeclarations.forEach((importDecl) => {
|
|
337
|
+
this.processSingleImportDeclaration(importDecl, result, importManager);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
private processSingleImportDeclaration(
|
|
342
|
+
importDecl: ImportDeclaration,
|
|
343
|
+
result: ClassAnalysis,
|
|
344
|
+
importManager: ImportManager
|
|
345
|
+
): void {
|
|
346
|
+
const specifier = importDecl.getModuleSpecifierValue();
|
|
347
|
+
const names = importDecl.getNamedImports().map((n) => n.getName());
|
|
348
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
349
|
+
const originalDir = SerializationPathUtil.dirname(result.sourceFilePath);
|
|
350
|
+
const importOriginAbs = SerializationPathUtil.pathResolve(originalDir, specifier);
|
|
351
|
+
|
|
352
|
+
if (SerializationPathUtil.exist(importOriginAbs + '.ets')) {
|
|
353
|
+
this.registerModuleImports(importOriginAbs + '.ets', names, defaultImport, importManager);
|
|
354
|
+
} else {
|
|
355
|
+
this.registerPackageImports(specifier, names, defaultImport, importManager);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private registerModuleImports(
|
|
360
|
+
absPath: string,
|
|
361
|
+
names: string[],
|
|
362
|
+
defaultImport: Identifier | undefined,
|
|
363
|
+
importManager: ImportManager
|
|
364
|
+
): void {
|
|
365
|
+
names.forEach((name) => {
|
|
366
|
+
importManager.registerCustomTypeImport(absPath, name);
|
|
367
|
+
});
|
|
368
|
+
if (defaultImport) {
|
|
369
|
+
importManager.registerDefaultImport(absPath, defaultImport.getText());
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private registerPackageImports(
|
|
374
|
+
specifier: string,
|
|
375
|
+
names: string[],
|
|
376
|
+
defaultImport: Identifier | undefined,
|
|
377
|
+
importManager: ImportManager
|
|
378
|
+
): void {
|
|
379
|
+
names.forEach((name) => {
|
|
380
|
+
importManager.registerCustomImport(specifier, name);
|
|
311
381
|
});
|
|
382
|
+
if (defaultImport) {
|
|
383
|
+
importManager.registerDefaultImport(specifier, defaultImport.getText());
|
|
384
|
+
}
|
|
312
385
|
}
|
|
313
386
|
|
|
314
387
|
private convertConstructorParameterTypes(classDecl: ClassDeclaration, result: ClassAnalysis): void {
|
|
315
388
|
const constructors = classDecl.getConstructors();
|
|
316
|
-
|
|
317
389
|
constructors.forEach((constructor) => {
|
|
318
|
-
|
|
390
|
+
this.convertSingleConstructorParameters(constructor, result);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
319
393
|
|
|
320
|
-
|
|
321
|
-
|
|
394
|
+
private convertSingleConstructorParameters(
|
|
395
|
+
constructor: ConstructorDeclaration,
|
|
396
|
+
result: ClassAnalysis
|
|
397
|
+
): void {
|
|
398
|
+
const parameters = constructor.getParameters();
|
|
399
|
+
parameters.forEach((parameter) => {
|
|
400
|
+
this.convertSingleParameter(parameter, result);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
322
403
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
404
|
+
private convertSingleParameter(
|
|
405
|
+
parameter: ParameterDeclaration,
|
|
406
|
+
result: ClassAnalysis
|
|
407
|
+
): void {
|
|
408
|
+
const paramName = parameter.getName();
|
|
409
|
+
const propertyAnalysis = result.properties.find((p) => p.name === paramName);
|
|
410
|
+
if (!propertyAnalysis) {
|
|
411
|
+
Logger.warn(`未找到构造函数参数 ${paramName} 的分析信息`);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
329
414
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
});
|
|
415
|
+
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
416
|
+
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
417
|
+
parameter.setType(sendableType);
|
|
418
|
+
Logger.debug(`构造函数参数 ${paramName} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
419
|
+
}
|
|
338
420
|
}
|
|
339
421
|
|
|
340
422
|
private isObjectType(typeName: string): boolean {
|
|
@@ -371,41 +453,50 @@ export class SendableClassGenerator {
|
|
|
371
453
|
}
|
|
372
454
|
|
|
373
455
|
private convertInitializerToSendable(initializerText: string): string {
|
|
374
|
-
let convertedText = initializerText;
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (convertedText === '[]') {
|
|
378
|
-
convertedText = 'new collections.Array()';
|
|
379
|
-
} else if (convertedText.startsWith('[') && convertedText.endsWith(']')) {
|
|
380
|
-
// 处理 [1, 2, 3] 这种情况
|
|
381
|
-
const arrayContent = convertedText.slice(1, -1);
|
|
382
|
-
if (arrayContent.trim()) {
|
|
383
|
-
convertedText = `new collections.Array(${arrayContent})`;
|
|
384
|
-
} else {
|
|
385
|
-
convertedText = 'new collections.Array()';
|
|
386
|
-
}
|
|
387
|
-
}
|
|
456
|
+
let convertedText = this.convertArrayLiteralToSendable(initializerText);
|
|
457
|
+
convertedText = this.replaceCollectionTypes(convertedText);
|
|
458
|
+
convertedText = this.replaceObjectConstructors(convertedText);
|
|
388
459
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
convertedText = convertedText.replace(/new\s+Array\s*\(/g, 'new collections.Array(');
|
|
460
|
+
Logger.debug(`初始化器转换: ${initializerText} -> ${convertedText}`);
|
|
461
|
+
return convertedText;
|
|
462
|
+
}
|
|
393
463
|
|
|
394
|
-
|
|
464
|
+
private convertArrayLiteralToSendable(text: string): string {
|
|
465
|
+
if (text === '[]') {
|
|
466
|
+
return 'new collections.Array()';
|
|
467
|
+
}
|
|
468
|
+
if (!text.startsWith('[') || !text.endsWith(']')) {
|
|
469
|
+
return text;
|
|
470
|
+
}
|
|
471
|
+
const arrayContent = text.slice(1, -1);
|
|
472
|
+
if (arrayContent.trim()) {
|
|
473
|
+
return `new collections.Array(${arrayContent})`;
|
|
474
|
+
}
|
|
475
|
+
return 'new collections.Array()';
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
private replaceObjectConstructors(text: string): string {
|
|
395
479
|
const objectConstructorPattern = /new\s+(\w+)\s*\(/g;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
if (className === 'collections' || match.includes('collections.')) {
|
|
399
|
-
return match;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (this.isObjectType(className)) {
|
|
403
|
-
return match.replace(className, `Sendable${className}`);
|
|
404
|
-
}
|
|
405
|
-
return match;
|
|
480
|
+
return text.replace(objectConstructorPattern, (match, className) => {
|
|
481
|
+
return this.replaceObjectConstructorMatch(match, className);
|
|
406
482
|
});
|
|
483
|
+
}
|
|
407
484
|
|
|
408
|
-
|
|
485
|
+
private replaceObjectConstructorMatch(match: string, className: string): string {
|
|
486
|
+
if (className === 'collections' || match.includes('collections.')) {
|
|
487
|
+
return match;
|
|
488
|
+
}
|
|
489
|
+
if (this.isObjectType(className)) {
|
|
490
|
+
return match.replace(className, `Sendable${className}`);
|
|
491
|
+
}
|
|
492
|
+
return match;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
private replaceCollectionTypes(text: string): string {
|
|
496
|
+
let convertedText = text;
|
|
497
|
+
convertedText = convertedText.replace(/new\s+Set\s*\(/g, 'new collections.Set(');
|
|
498
|
+
convertedText = convertedText.replace(/new\s+Map\s*\(/g, 'new collections.Map(');
|
|
499
|
+
convertedText = convertedText.replace(/new\s+Array\s*\(/g, 'new collections.Array(');
|
|
409
500
|
return convertedText;
|
|
410
501
|
}
|
|
411
502
|
|
|
@@ -50,12 +50,14 @@ export class SerializerGenerator {
|
|
|
50
50
|
this.templateEngine = new HandlebarsTemplateEngine();
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
generate(sourceFile: SourceFile, result: ClassAnalysis | InterfaceAnalysis,
|
|
53
|
+
generate(sourceFile: SourceFile, result: ClassAnalysis | InterfaceAnalysis,
|
|
54
|
+
context: ITaskContext): GenerationContext | string {
|
|
54
55
|
// 检查是否使用自定义序列化器
|
|
55
56
|
if (result.decorators?.serializable?.with) {
|
|
56
|
-
sourceFile.addStatements(
|
|
57
|
+
sourceFile.addStatements(
|
|
58
|
+
this.generateBuiltinSerializerRegistrationForSupplementary(context, result as ClassAnalysis));
|
|
57
59
|
// 使用自定义序列化器,仅生成注册语句
|
|
58
|
-
return this.generateCustomSerializerRegistration(
|
|
60
|
+
return this.generateCustomSerializerRegistration(result as ClassAnalysis);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
// 1. 注册必要的导入
|
|
@@ -103,7 +105,8 @@ export class SerializerGenerator {
|
|
|
103
105
|
// 基础导入 + 动态内置序列化器导入
|
|
104
106
|
this.importManager.registerCoreImports([
|
|
105
107
|
'Serializer', 'SerialDescriptor', 'buildClassSerialDescriptor',
|
|
106
|
-
'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', '
|
|
108
|
+
'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', 'ObjectUtils',
|
|
109
|
+
'registerAutoGeneratedSerializerEntryProviderForSupplementary', 'lazy',
|
|
107
110
|
...requiredBuiltinSerializers
|
|
108
111
|
]);
|
|
109
112
|
|
|
@@ -201,17 +204,17 @@ export class SerializerGenerator {
|
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
// 注册属性相关的序列化器导入
|
|
204
|
-
this.execPropertyImports(property.type.dependencies);
|
|
207
|
+
this.execPropertyImports(property.type.dependencies, !!property.decorators?.with);
|
|
205
208
|
}
|
|
206
209
|
}
|
|
207
210
|
|
|
208
|
-
private execPropertyImports(dependencies: TypeDependency[]): void {
|
|
211
|
+
private execPropertyImports(dependencies: TypeDependency[], hasWithParam: boolean): void {
|
|
209
212
|
dependencies.forEach((dependency: TypeDependency) => {
|
|
210
|
-
this.processDependency(dependency);
|
|
213
|
+
this.processDependency(dependency, hasWithParam);
|
|
211
214
|
});
|
|
212
215
|
}
|
|
213
216
|
|
|
214
|
-
private processDependency(dependency: TypeDependency): void {
|
|
217
|
+
private processDependency(dependency: TypeDependency, hasWithParam: boolean): void {
|
|
215
218
|
const source = dependency.source;
|
|
216
219
|
|
|
217
220
|
// 提前返回,减少嵌套
|
|
@@ -226,16 +229,16 @@ export class SerializerGenerator {
|
|
|
226
229
|
// 根据类型种类分别处理
|
|
227
230
|
switch (dependency.typeKind) {
|
|
228
231
|
case TypeKind.CLASS:
|
|
229
|
-
this.processClassDependency(dependency, source);
|
|
232
|
+
this.processClassDependency(dependency, source, hasWithParam);
|
|
230
233
|
break;
|
|
231
234
|
|
|
232
235
|
case TypeKind.INTERFACE:
|
|
233
|
-
this.processInterfaceDependency(dependency);
|
|
236
|
+
this.processInterfaceDependency(dependency, hasWithParam);
|
|
234
237
|
break;
|
|
235
238
|
}
|
|
236
239
|
}
|
|
237
240
|
|
|
238
|
-
private processClassDependency(dependency: TypeDependency, source: DependencySource): void {
|
|
241
|
+
private processClassDependency(dependency: TypeDependency, source: DependencySource, hasWithParam: boolean): void {
|
|
239
242
|
const classDetails = dependency.details as ClassDetails;
|
|
240
243
|
const tempClassAnalysis = ClassAnalyzer.analyzeClass(classDetails.classDecl);
|
|
241
244
|
|
|
@@ -249,6 +252,10 @@ export class SerializerGenerator {
|
|
|
249
252
|
if (tempClassAnalysis.decorators.serializable) {
|
|
250
253
|
this.handleSerializableClass(dependency, source, serializerName);
|
|
251
254
|
} else {
|
|
255
|
+
if (hasWithParam) {
|
|
256
|
+
// 有自定义序列化器,无需关注这个导入了
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
252
259
|
// 从 tempSerializer 目录(index.ets)导入
|
|
253
260
|
this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
|
|
254
261
|
}
|
|
@@ -263,7 +270,11 @@ export class SerializerGenerator {
|
|
|
263
270
|
}
|
|
264
271
|
}
|
|
265
272
|
|
|
266
|
-
private processInterfaceDependency(dependency: TypeDependency): void {
|
|
273
|
+
private processInterfaceDependency(dependency: TypeDependency, hasWithParam: boolean): void {
|
|
274
|
+
if (hasWithParam) {
|
|
275
|
+
// 有自定义序列化器,无需关注这个导入了
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
267
278
|
const interfaceDetails = dependency.details as InterfaceDetails;
|
|
268
279
|
const tempClassAnalysis = ClassAnalyzer.analyzeInterface(interfaceDetails.interfaceDecl);
|
|
269
280
|
TempSerializerGenerator.getInstance().generateSerializer(tempClassAnalysis);
|
|
@@ -275,13 +286,11 @@ export class SerializerGenerator {
|
|
|
275
286
|
this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
|
|
276
287
|
}
|
|
277
288
|
|
|
278
|
-
private generateCustomSerializerRegistration(
|
|
289
|
+
private generateCustomSerializerRegistration(result: ClassAnalysis): string {
|
|
279
290
|
this.importManager.registerCoreImports(['registerAutoGeneratedSerializerEntry']);
|
|
280
291
|
|
|
281
292
|
const customSerializer = result.decorators.serializable!.with;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return registrationCode;
|
|
293
|
+
return `registerAutoGeneratedSerializerEntry(${result.className}, ${customSerializer});`;
|
|
285
294
|
}
|
|
286
295
|
|
|
287
296
|
private generateBuiltinSerializerRegistrationForSupplementary(context: ITaskContext, result: ClassAnalysis): string {
|
|
@@ -289,10 +298,8 @@ export class SerializerGenerator {
|
|
|
289
298
|
const serialNameConstant = this.generateSerialNameConstant(result, context);
|
|
290
299
|
|
|
291
300
|
const customSerializer = result.decorators.serializable!.with;
|
|
292
|
-
|
|
301
|
+
return `const ${result.className}_SERIAL_NAME = '${serialNameConstant}';\n
|
|
293
302
|
registerAutoGeneratedSerializerEntryProviderForSupplementary(${result.className}_SERIAL_NAME, () => [${result.className}, ${customSerializer}]);`;
|
|
294
|
-
|
|
295
|
-
return registrationCode;
|
|
296
303
|
}
|
|
297
304
|
|
|
298
305
|
private getAllRequiredSerializers(properties: PropertyAnalysis[]): string[] {
|
|
@@ -38,7 +38,8 @@ export class TempSerializerGenerator {
|
|
|
38
38
|
private context: ITaskContext | null = null;
|
|
39
39
|
private serializerFiles: Map<string, SerializerFileInfo> = new Map();
|
|
40
40
|
|
|
41
|
-
private constructor() {
|
|
41
|
+
private constructor() {
|
|
42
|
+
}
|
|
42
43
|
|
|
43
44
|
static getInstance(): TempSerializerGenerator {
|
|
44
45
|
return this.INSTANCE;
|
|
@@ -102,7 +103,7 @@ export class TempSerializerGenerator {
|
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
private registerImports(classAnalysis: ClassAnalysis | InterfaceAnalysis, importManager: ImportManager) {
|
|
106
|
+
private registerImports(classAnalysis: ClassAnalysis | InterfaceAnalysis, importManager: ImportManager): void {
|
|
106
107
|
// 注册源文件导入
|
|
107
108
|
importManager.registerCustomTypeImport(classAnalysis.sourceFilePath, classAnalysis.className);
|
|
108
109
|
// 拷贝源文件导入
|
|
@@ -174,7 +175,8 @@ export class TempSerializerGenerator {
|
|
|
174
175
|
// 检测类名冲突
|
|
175
176
|
const classNameMap = new Map<string, SerializerFileInfo[]>();
|
|
176
177
|
for (const [_, fileInfo] of this.serializerFiles) {
|
|
177
|
-
const serializerName = `${fileInfo.className}${fileInfo.isGeneric ? StringConstants.SERIALIZER_FACTORY :
|
|
178
|
+
const serializerName = `${fileInfo.className}${fileInfo.isGeneric ? StringConstants.SERIALIZER_FACTORY :
|
|
179
|
+
StringConstants.SERIALIZER}`;
|
|
178
180
|
if (!classNameMap.has(serializerName)) {
|
|
179
181
|
classNameMap.set(serializerName, []);
|
|
180
182
|
}
|