@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
|
@@ -29,7 +29,8 @@ class SendableClassGenerator {
|
|
|
29
29
|
}
|
|
30
30
|
getOriginClassDeclaration(result) {
|
|
31
31
|
const originalContent = result.originalClass?.getFullText();
|
|
32
|
-
const copiedSourceFile = TsMorphUtil_1.TsMorphUtil.getProject()
|
|
32
|
+
const copiedSourceFile = TsMorphUtil_1.TsMorphUtil.getProject()
|
|
33
|
+
.createSourceFile('copied-file.ts', originalContent, { overwrite: true });
|
|
33
34
|
return copiedSourceFile.getClassOrThrow(result.className);
|
|
34
35
|
}
|
|
35
36
|
renameSendableClass(classDecl, result) {
|
|
@@ -51,51 +52,67 @@ class SendableClassGenerator {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
removeAllDecorators(classDecl) {
|
|
55
|
+
this.removeClassDecorators(classDecl);
|
|
56
|
+
this.removePropertyDecorators(classDecl);
|
|
57
|
+
this.removeMethodDecorators(classDecl);
|
|
58
|
+
}
|
|
59
|
+
removeClassDecorators(classDecl) {
|
|
54
60
|
classDecl.getDecorators().forEach((decorator) => {
|
|
55
|
-
|
|
56
|
-
decorator.remove();
|
|
61
|
+
this.logAndRemoveDecorator(decorator);
|
|
57
62
|
});
|
|
63
|
+
}
|
|
64
|
+
removePropertyDecorators(classDecl) {
|
|
58
65
|
classDecl.getProperties().forEach((property) => {
|
|
59
|
-
property.getDecorators().forEach((decorator) =>
|
|
60
|
-
__1.Logger.warn(`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`);
|
|
61
|
-
decorator.remove();
|
|
62
|
-
});
|
|
66
|
+
property.getDecorators().forEach((decorator) => this.logAndRemoveDecorator(decorator));
|
|
63
67
|
});
|
|
68
|
+
}
|
|
69
|
+
removeMethodDecorators(classDecl) {
|
|
64
70
|
classDecl.getMethods().forEach((method) => {
|
|
65
|
-
method.getDecorators().forEach((decorator) =>
|
|
66
|
-
__1.Logger.warn(`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`);
|
|
67
|
-
decorator.remove();
|
|
68
|
-
});
|
|
71
|
+
method.getDecorators().forEach((decorator) => this.logAndRemoveDecorator(decorator));
|
|
69
72
|
});
|
|
70
73
|
}
|
|
74
|
+
logAndRemoveDecorator(decorator) {
|
|
75
|
+
__1.Logger.warn(`Remove the decorator ${decorator.getName()}, because @Sendable cannot coexist with other decorators`);
|
|
76
|
+
decorator.remove();
|
|
77
|
+
}
|
|
71
78
|
convertPropertyTypesToSendable(classDecl, result) {
|
|
72
79
|
const properties = classDecl.getProperties();
|
|
73
80
|
properties.forEach((property) => {
|
|
74
|
-
|
|
75
|
-
__1.Logger.debug(`Converting property ${propertyName} to sendable`);
|
|
76
|
-
const propertyAnalysis = result.properties.find((p) => p.name === propertyName);
|
|
77
|
-
if (!propertyAnalysis) {
|
|
78
|
-
__1.Logger.warn(`未找到属性 ${propertyName} 的分析信息`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
__1.Logger.debug(`Found property ${propertyName} analysis info: ${propertyAnalysis.name} ${propertyAnalysis.type.sourceText}`);
|
|
82
|
-
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
83
|
-
__1.Logger.debug(`Converted type ${propertyAnalysis.type.sourceText} to ${sendableType}`);
|
|
84
|
-
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
85
|
-
property.setType(sendableType);
|
|
86
|
-
__1.Logger.debug(`属性 ${propertyName} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
87
|
-
}
|
|
88
|
-
const initializer = property.getInitializer();
|
|
89
|
-
if (initializer) {
|
|
90
|
-
const initializerText = initializer.getText();
|
|
91
|
-
const convertedInitializer = this.convertInitializerToSendable(initializerText);
|
|
92
|
-
if (convertedInitializer !== initializerText) {
|
|
93
|
-
property.setInitializer(convertedInitializer);
|
|
94
|
-
__1.Logger.debug(`属性 ${propertyName} 默认值从 ${initializerText} 转换为 ${convertedInitializer}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
81
|
+
this.convertSinglePropertyToSendable(property, result);
|
|
97
82
|
});
|
|
98
83
|
}
|
|
84
|
+
convertSinglePropertyToSendable(property, result) {
|
|
85
|
+
const propertyName = property.getName();
|
|
86
|
+
__1.Logger.debug(`Converting property ${propertyName} to sendable`);
|
|
87
|
+
const propertyAnalysis = result.properties.find((p) => p.name === propertyName);
|
|
88
|
+
if (!propertyAnalysis) {
|
|
89
|
+
__1.Logger.warn(`未找到属性 ${propertyName} 的分析信息`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
__1.Logger.debug(`Found property ${propertyName} analysis info: ${propertyAnalysis.name} ${propertyAnalysis.type.sourceText}`);
|
|
93
|
+
this.updatePropertyType(property, propertyAnalysis);
|
|
94
|
+
this.updatePropertyInitializer(property, propertyAnalysis.name);
|
|
95
|
+
}
|
|
96
|
+
updatePropertyType(property, propertyAnalysis) {
|
|
97
|
+
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
98
|
+
__1.Logger.debug(`Converted type ${propertyAnalysis.type.sourceText} to ${sendableType}`);
|
|
99
|
+
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
100
|
+
property.setType(sendableType);
|
|
101
|
+
__1.Logger.debug(`属性 ${propertyAnalysis.name} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
updatePropertyInitializer(property, propertyName) {
|
|
105
|
+
const initializer = property.getInitializer();
|
|
106
|
+
if (!initializer) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const initializerText = initializer.getText();
|
|
110
|
+
const convertedInitializer = this.convertInitializerToSendable(initializerText);
|
|
111
|
+
if (convertedInitializer !== initializerText) {
|
|
112
|
+
property.setInitializer(convertedInitializer);
|
|
113
|
+
__1.Logger.debug(`属性 ${propertyName} 默认值从 ${initializerText} 转换为 ${convertedInitializer}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
99
116
|
addSendableConstraints(classDecl) {
|
|
100
117
|
classDecl.addDecorator({ name: 'Sendable' });
|
|
101
118
|
classDecl.addImplements('lang.ISendable');
|
|
@@ -115,7 +132,24 @@ class SendableClassGenerator {
|
|
|
115
132
|
}
|
|
116
133
|
generatedToOriginMethodBody(result, returnType) {
|
|
117
134
|
const statements = [];
|
|
118
|
-
|
|
135
|
+
const constructorCall = this.getConstructorCall(result, returnType);
|
|
136
|
+
statements.push(`const origin = ${constructorCall};`);
|
|
137
|
+
const assignmentProps = result.properties.filter((p) => {
|
|
138
|
+
return result.constructorParams.every((cp) => cp.name !== p.name);
|
|
139
|
+
});
|
|
140
|
+
if (assignmentProps.length > 0) {
|
|
141
|
+
statements.push('');
|
|
142
|
+
statements.push('// 非构造函数属性赋值');
|
|
143
|
+
assignmentProps.forEach((prop) => {
|
|
144
|
+
const assignment = this.generatePropertyConversion(prop, 'this.');
|
|
145
|
+
statements.push(`origin.${prop.name} = ${assignment};`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
statements.push('');
|
|
149
|
+
statements.push('return origin;');
|
|
150
|
+
return statements.join('\n');
|
|
151
|
+
}
|
|
152
|
+
getConstructorCall(result, returnType) {
|
|
119
153
|
if (result.constructorParams.length > 0) {
|
|
120
154
|
const constructorProps = [];
|
|
121
155
|
result.properties.forEach((p) => {
|
|
@@ -135,26 +169,11 @@ class SendableClassGenerator {
|
|
|
135
169
|
return this.generatePropertyConversion(prop, 'this.');
|
|
136
170
|
})
|
|
137
171
|
.join(', ');
|
|
138
|
-
|
|
172
|
+
return `new ${returnType}(${args})`;
|
|
139
173
|
}
|
|
140
174
|
else {
|
|
141
|
-
|
|
175
|
+
return `new ${returnType}()`;
|
|
142
176
|
}
|
|
143
|
-
statements.push(`const origin = ${constructorCall};`);
|
|
144
|
-
const assignmentProps = result.properties.filter((p) => {
|
|
145
|
-
return result.constructorParams.every((cp) => cp.name !== p.name);
|
|
146
|
-
});
|
|
147
|
-
if (assignmentProps.length > 0) {
|
|
148
|
-
statements.push('');
|
|
149
|
-
statements.push('// 非构造函数属性赋值');
|
|
150
|
-
assignmentProps.forEach((prop) => {
|
|
151
|
-
const assignment = this.generatePropertyConversion(prop, 'this.');
|
|
152
|
-
statements.push(`origin.${prop.name} = ${assignment};`);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
statements.push('');
|
|
156
|
-
statements.push('return origin;');
|
|
157
|
-
return statements.join('\n');
|
|
158
177
|
}
|
|
159
178
|
generatePropertyConversion(prop, prefix) {
|
|
160
179
|
const sourceValue = `${prefix}${prop.name}`;
|
|
@@ -175,74 +194,108 @@ class SendableClassGenerator {
|
|
|
175
194
|
return `Sendable${result.className}`;
|
|
176
195
|
}
|
|
177
196
|
addNecessaryImports(result, importManager) {
|
|
197
|
+
this.processPropertyDependencyImports(result, importManager);
|
|
198
|
+
this.processBaseClassImport(result, importManager);
|
|
199
|
+
this.processCollectionsImport(result, importManager);
|
|
200
|
+
this.copySourceFileImports(result, importManager);
|
|
201
|
+
}
|
|
202
|
+
processPropertyDependencyImports(result, importManager) {
|
|
178
203
|
result.properties.forEach((property) => {
|
|
179
204
|
property.type.dependencies.forEach((dependency) => {
|
|
180
|
-
|
|
181
|
-
const classAnalysis = ClassAnalyzer_1.ClassAnalyzer.analyzeClass(dependency.details.classDecl);
|
|
182
|
-
if (classAnalysis.decorators.serializable?.generateSendable) {
|
|
183
|
-
importManager.registerCustomImport('./Sendable' + dependency.typeName, 'Sendable' + dependency.typeName);
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
importManager.registerCustomTypeImport(dependency.source.sourceFilePath, dependency.typeName);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
importManager.registerCustomTypeImport(dependency.source.sourceFilePath, dependency.typeName);
|
|
191
|
-
}
|
|
205
|
+
this.registerDependencyImport(dependency, importManager);
|
|
192
206
|
});
|
|
193
207
|
});
|
|
208
|
+
}
|
|
209
|
+
registerDependencyImport(dependency, importManager) {
|
|
210
|
+
if (dependency.typeKind !== __1.TypeKind.CLASS) {
|
|
211
|
+
importManager.registerCustomTypeImport(dependency.source.sourceFilePath, dependency.typeName);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const classAnalysis = ClassAnalyzer_1.ClassAnalyzer.analyzeClass(dependency.details.classDecl);
|
|
215
|
+
if (classAnalysis.decorators.serializable?.generateSendable) {
|
|
216
|
+
importManager.registerCustomImport('./Sendable' + dependency.typeName, 'Sendable' + dependency.typeName);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
importManager.registerCustomTypeImport(dependency.source.sourceFilePath, dependency.typeName);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
processBaseClassImport(result, importManager) {
|
|
194
223
|
const baseClass = result.inheritance.baseClassAnalysis;
|
|
195
|
-
if (baseClass) {
|
|
196
|
-
|
|
224
|
+
if (!baseClass) {
|
|
225
|
+
return;
|
|
197
226
|
}
|
|
227
|
+
importManager.registerCustomImport('./Sendable' + baseClass.className, 'Sendable' + baseClass.className);
|
|
228
|
+
}
|
|
229
|
+
processCollectionsImport(result, importManager) {
|
|
198
230
|
const needsCollections = this.needsCollectionsImport(result);
|
|
199
|
-
if (needsCollections) {
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
importManager.registerCustomTypeImport(importOriginAbsWithExt, name);
|
|
212
|
-
});
|
|
213
|
-
if (defaultImport) {
|
|
214
|
-
importManager.registerDefaultImport(importOriginAbsWithExt, defaultImport.getText());
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
names.forEach((name) => {
|
|
219
|
-
importManager.registerCustomImport(specifier, name);
|
|
220
|
-
});
|
|
221
|
-
if (defaultImport) {
|
|
222
|
-
importManager.registerDefaultImport(specifier, defaultImport.getText());
|
|
223
|
-
}
|
|
224
|
-
}
|
|
231
|
+
if (!needsCollections) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
importManager.registerArkTSImports(['collections']);
|
|
235
|
+
}
|
|
236
|
+
copySourceFileImports(result, importManager) {
|
|
237
|
+
const importDeclarations = result.originalClass?.getSourceFile().getImportDeclarations();
|
|
238
|
+
if (!importDeclarations) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
importDeclarations.forEach((importDecl) => {
|
|
242
|
+
this.processSingleImportDeclaration(importDecl, result, importManager);
|
|
225
243
|
});
|
|
226
244
|
}
|
|
245
|
+
processSingleImportDeclaration(importDecl, result, importManager) {
|
|
246
|
+
const specifier = importDecl.getModuleSpecifierValue();
|
|
247
|
+
const names = importDecl.getNamedImports().map((n) => n.getName());
|
|
248
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
249
|
+
const originalDir = SerializationPathUtil_1.default.dirname(result.sourceFilePath);
|
|
250
|
+
const importOriginAbs = SerializationPathUtil_1.default.pathResolve(originalDir, specifier);
|
|
251
|
+
if (SerializationPathUtil_1.default.exist(importOriginAbs + '.ets')) {
|
|
252
|
+
this.registerModuleImports(importOriginAbs + '.ets', names, defaultImport, importManager);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
this.registerPackageImports(specifier, names, defaultImport, importManager);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
registerModuleImports(absPath, names, defaultImport, importManager) {
|
|
259
|
+
names.forEach((name) => {
|
|
260
|
+
importManager.registerCustomTypeImport(absPath, name);
|
|
261
|
+
});
|
|
262
|
+
if (defaultImport) {
|
|
263
|
+
importManager.registerDefaultImport(absPath, defaultImport.getText());
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
registerPackageImports(specifier, names, defaultImport, importManager) {
|
|
267
|
+
names.forEach((name) => {
|
|
268
|
+
importManager.registerCustomImport(specifier, name);
|
|
269
|
+
});
|
|
270
|
+
if (defaultImport) {
|
|
271
|
+
importManager.registerDefaultImport(specifier, defaultImport.getText());
|
|
272
|
+
}
|
|
273
|
+
}
|
|
227
274
|
convertConstructorParameterTypes(classDecl, result) {
|
|
228
275
|
const constructors = classDecl.getConstructors();
|
|
229
276
|
constructors.forEach((constructor) => {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
239
|
-
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
240
|
-
parameter.setType(sendableType);
|
|
241
|
-
__1.Logger.debug(`构造函数参数 ${paramName} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
277
|
+
this.convertSingleConstructorParameters(constructor, result);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
convertSingleConstructorParameters(constructor, result) {
|
|
281
|
+
const parameters = constructor.getParameters();
|
|
282
|
+
parameters.forEach((parameter) => {
|
|
283
|
+
this.convertSingleParameter(parameter, result);
|
|
244
284
|
});
|
|
245
285
|
}
|
|
286
|
+
convertSingleParameter(parameter, result) {
|
|
287
|
+
const paramName = parameter.getName();
|
|
288
|
+
const propertyAnalysis = result.properties.find((p) => p.name === paramName);
|
|
289
|
+
if (!propertyAnalysis) {
|
|
290
|
+
__1.Logger.warn(`未找到构造函数参数 ${paramName} 的分析信息`);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const sendableType = this.convertToSendableType(propertyAnalysis.type);
|
|
294
|
+
if (sendableType !== propertyAnalysis.type.sourceText) {
|
|
295
|
+
parameter.setType(sendableType);
|
|
296
|
+
__1.Logger.debug(`构造函数参数 ${paramName} 类型从 ${propertyAnalysis.type.sourceText} 转换为 ${sendableType}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
246
299
|
isObjectType(typeName) {
|
|
247
300
|
const primitiveTypes = ['string', 'number', 'boolean', 'bigint', 'null', 'undefined'];
|
|
248
301
|
if (primitiveTypes.includes(typeName)) {
|
|
@@ -266,33 +319,45 @@ class SendableClassGenerator {
|
|
|
266
319
|
});
|
|
267
320
|
}
|
|
268
321
|
convertInitializerToSendable(initializerText) {
|
|
269
|
-
let convertedText = initializerText;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
322
|
+
let convertedText = this.convertArrayLiteralToSendable(initializerText);
|
|
323
|
+
convertedText = this.replaceCollectionTypes(convertedText);
|
|
324
|
+
convertedText = this.replaceObjectConstructors(convertedText);
|
|
325
|
+
__1.Logger.debug(`初始化器转换: ${initializerText} -> ${convertedText}`);
|
|
326
|
+
return convertedText;
|
|
327
|
+
}
|
|
328
|
+
convertArrayLiteralToSendable(text) {
|
|
329
|
+
if (text === '[]') {
|
|
330
|
+
return 'new collections.Array()';
|
|
331
|
+
}
|
|
332
|
+
if (!text.startsWith('[') || !text.endsWith(']')) {
|
|
333
|
+
return text;
|
|
334
|
+
}
|
|
335
|
+
const arrayContent = text.slice(1, -1);
|
|
336
|
+
if (arrayContent.trim()) {
|
|
337
|
+
return `new collections.Array(${arrayContent})`;
|
|
281
338
|
}
|
|
339
|
+
return 'new collections.Array()';
|
|
340
|
+
}
|
|
341
|
+
replaceObjectConstructors(text) {
|
|
342
|
+
const objectConstructorPattern = /new\s+(\w+)\s*\(/g;
|
|
343
|
+
return text.replace(objectConstructorPattern, (match, className) => {
|
|
344
|
+
return this.replaceObjectConstructorMatch(match, className);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
replaceObjectConstructorMatch(match, className) {
|
|
348
|
+
if (className === 'collections' || match.includes('collections.')) {
|
|
349
|
+
return match;
|
|
350
|
+
}
|
|
351
|
+
if (this.isObjectType(className)) {
|
|
352
|
+
return match.replace(className, `Sendable${className}`);
|
|
353
|
+
}
|
|
354
|
+
return match;
|
|
355
|
+
}
|
|
356
|
+
replaceCollectionTypes(text) {
|
|
357
|
+
let convertedText = text;
|
|
282
358
|
convertedText = convertedText.replace(/new\s+Set\s*\(/g, 'new collections.Set(');
|
|
283
359
|
convertedText = convertedText.replace(/new\s+Map\s*\(/g, 'new collections.Map(');
|
|
284
360
|
convertedText = convertedText.replace(/new\s+Array\s*\(/g, 'new collections.Array(');
|
|
285
|
-
const objectConstructorPattern = /new\s+(\w+)\s*\(/g;
|
|
286
|
-
convertedText = convertedText.replace(objectConstructorPattern, (match, className) => {
|
|
287
|
-
if (className === 'collections' || match.includes('collections.')) {
|
|
288
|
-
return match;
|
|
289
|
-
}
|
|
290
|
-
if (this.isObjectType(className)) {
|
|
291
|
-
return match.replace(className, `Sendable${className}`);
|
|
292
|
-
}
|
|
293
|
-
return match;
|
|
294
|
-
});
|
|
295
|
-
__1.Logger.debug(`初始化器转换: ${initializerText} -> ${convertedText}`);
|
|
296
361
|
return convertedText;
|
|
297
362
|
}
|
|
298
363
|
convertToSendableType(structure) {
|
|
@@ -20,7 +20,7 @@ class SerializerGenerator {
|
|
|
20
20
|
generate(sourceFile, result, context) {
|
|
21
21
|
if (result.decorators?.serializable?.with) {
|
|
22
22
|
sourceFile.addStatements(this.generateBuiltinSerializerRegistrationForSupplementary(context, result));
|
|
23
|
-
return this.generateCustomSerializerRegistration(
|
|
23
|
+
return this.generateCustomSerializerRegistration(result);
|
|
24
24
|
}
|
|
25
25
|
this.registerImports(result);
|
|
26
26
|
const templateContext = {
|
|
@@ -49,7 +49,8 @@ class SerializerGenerator {
|
|
|
49
49
|
const requiredBuiltinSerializers = this.getAllRequiredSerializers(result.properties);
|
|
50
50
|
this.importManager.registerCoreImports([
|
|
51
51
|
'Serializer', 'SerialDescriptor', 'buildClassSerialDescriptor',
|
|
52
|
-
'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', '
|
|
52
|
+
'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', 'ObjectUtils',
|
|
53
|
+
'registerAutoGeneratedSerializerEntryProviderForSupplementary', 'lazy',
|
|
53
54
|
...requiredBuiltinSerializers
|
|
54
55
|
]);
|
|
55
56
|
this.registerDecoratorsImports(result);
|
|
@@ -120,15 +121,15 @@ class SerializerGenerator {
|
|
|
120
121
|
this.importManager.registerCoreImports(['WithEntryContextualSerializer']);
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
|
-
this.execPropertyImports(property.type.dependencies);
|
|
124
|
+
this.execPropertyImports(property.type.dependencies, !!property.decorators?.with);
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
|
-
execPropertyImports(dependencies) {
|
|
127
|
+
execPropertyImports(dependencies, hasWithParam) {
|
|
127
128
|
dependencies.forEach((dependency) => {
|
|
128
|
-
this.processDependency(dependency);
|
|
129
|
+
this.processDependency(dependency, hasWithParam);
|
|
129
130
|
});
|
|
130
131
|
}
|
|
131
|
-
processDependency(dependency) {
|
|
132
|
+
processDependency(dependency, hasWithParam) {
|
|
132
133
|
const source = dependency.source;
|
|
133
134
|
if (source.type !== 'imported' && source.type !== 'local') {
|
|
134
135
|
return;
|
|
@@ -138,14 +139,14 @@ class SerializerGenerator {
|
|
|
138
139
|
}
|
|
139
140
|
switch (dependency.typeKind) {
|
|
140
141
|
case __1.TypeKind.CLASS:
|
|
141
|
-
this.processClassDependency(dependency, source);
|
|
142
|
+
this.processClassDependency(dependency, source, hasWithParam);
|
|
142
143
|
break;
|
|
143
144
|
case __1.TypeKind.INTERFACE:
|
|
144
|
-
this.processInterfaceDependency(dependency);
|
|
145
|
+
this.processInterfaceDependency(dependency, hasWithParam);
|
|
145
146
|
break;
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
|
-
processClassDependency(dependency, source) {
|
|
149
|
+
processClassDependency(dependency, source, hasWithParam) {
|
|
149
150
|
const classDetails = dependency.details;
|
|
150
151
|
const tempClassAnalysis = ClassAnalyzer_1.ClassAnalyzer.analyzeClass(classDetails.classDecl);
|
|
151
152
|
if (!tempClassAnalysis.decorators.serializable) {
|
|
@@ -157,6 +158,9 @@ class SerializerGenerator {
|
|
|
157
158
|
this.handleSerializableClass(dependency, source, serializerName);
|
|
158
159
|
}
|
|
159
160
|
else {
|
|
161
|
+
if (hasWithParam) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
160
164
|
this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
|
|
161
165
|
}
|
|
162
166
|
}
|
|
@@ -165,7 +169,10 @@ class SerializerGenerator {
|
|
|
165
169
|
this.importManager.registerCustomTypeImport(source.sourceFilePath, `${dependency.typeName}${serializerName}`);
|
|
166
170
|
}
|
|
167
171
|
}
|
|
168
|
-
processInterfaceDependency(dependency) {
|
|
172
|
+
processInterfaceDependency(dependency, hasWithParam) {
|
|
173
|
+
if (hasWithParam) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
169
176
|
const interfaceDetails = dependency.details;
|
|
170
177
|
const tempClassAnalysis = ClassAnalyzer_1.ClassAnalyzer.analyzeInterface(interfaceDetails.interfaceDecl);
|
|
171
178
|
TempSerializerGenerator_1.TempSerializerGenerator.getInstance().generateSerializer(tempClassAnalysis);
|
|
@@ -173,19 +180,17 @@ class SerializerGenerator {
|
|
|
173
180
|
__1.StringConstants.SERIALIZER;
|
|
174
181
|
this.importManager.registerTempSerializerImport(`${dependency.typeName}${serializerName}`);
|
|
175
182
|
}
|
|
176
|
-
generateCustomSerializerRegistration(
|
|
183
|
+
generateCustomSerializerRegistration(result) {
|
|
177
184
|
this.importManager.registerCoreImports(['registerAutoGeneratedSerializerEntry']);
|
|
178
185
|
const customSerializer = result.decorators.serializable.with;
|
|
179
|
-
|
|
180
|
-
return registrationCode;
|
|
186
|
+
return `registerAutoGeneratedSerializerEntry(${result.className}, ${customSerializer});`;
|
|
181
187
|
}
|
|
182
188
|
generateBuiltinSerializerRegistrationForSupplementary(context, result) {
|
|
183
189
|
this.importManager.registerCoreImports(['registerAutoGeneratedSerializerEntryProviderForSupplementary']);
|
|
184
190
|
const serialNameConstant = this.generateSerialNameConstant(result, context);
|
|
185
191
|
const customSerializer = result.decorators.serializable.with;
|
|
186
|
-
|
|
192
|
+
return `const ${result.className}_SERIAL_NAME = '${serialNameConstant}';\n
|
|
187
193
|
registerAutoGeneratedSerializerEntryProviderForSupplementary(${result.className}_SERIAL_NAME, () => [${result.className}, ${customSerializer}]);`;
|
|
188
|
-
return registrationCode;
|
|
189
194
|
}
|
|
190
195
|
getAllRequiredSerializers(properties) {
|
|
191
196
|
const requiredSerializers = new Set();
|
|
@@ -111,7 +111,8 @@ class TempSerializerGenerator {
|
|
|
111
111
|
const indexSourceFile = TsMorphUtil_1.TsMorphUtil.getProject().createSourceFile(indexFilePath, '', { overwrite: true });
|
|
112
112
|
const classNameMap = new Map();
|
|
113
113
|
for (const [_, fileInfo] of this.serializerFiles) {
|
|
114
|
-
const serializerName = `${fileInfo.className}${fileInfo.isGeneric ? __1.StringConstants.SERIALIZER_FACTORY :
|
|
114
|
+
const serializerName = `${fileInfo.className}${fileInfo.isGeneric ? __1.StringConstants.SERIALIZER_FACTORY :
|
|
115
|
+
__1.StringConstants.SERIALIZER}`;
|
|
115
116
|
if (!classNameMap.has(serializerName)) {
|
|
116
117
|
classNameMap.set(serializerName, []);
|
|
117
118
|
}
|
|
@@ -12,10 +12,10 @@ export declare class ImportManager {
|
|
|
12
12
|
private isModularPath;
|
|
13
13
|
private isRelativePath;
|
|
14
14
|
private removeImportFromModule;
|
|
15
|
-
getImportDeclarations(): {
|
|
15
|
+
getImportDeclarations(): Array<{
|
|
16
16
|
specifier: string;
|
|
17
17
|
names: string[];
|
|
18
|
-
}
|
|
18
|
+
}>;
|
|
19
19
|
getDefaultImport(): Array<{
|
|
20
20
|
specifier: string;
|
|
21
21
|
name: string;
|
|
@@ -14,6 +14,8 @@ export declare class HandlebarsTemplateEngine {
|
|
|
14
14
|
registerHelper(name: string, helper: Handlebars.HelperDelegate): void;
|
|
15
15
|
loadTemplateFromString(template: string): HandlebarsTemplateDelegate;
|
|
16
16
|
private registerBuiltinHelpers;
|
|
17
|
+
private isPrimitiveType;
|
|
18
|
+
private toUpperCase;
|
|
17
19
|
private registerComparisonHelpers;
|
|
18
20
|
private registerTypeCheckHelpers;
|
|
19
21
|
private hasNonSerializableClassDecorator;
|
|
@@ -93,13 +93,21 @@ class HandlebarsTemplateEngine {
|
|
|
93
93
|
this.registerConstructorHelpers();
|
|
94
94
|
this.registerLogicHelpers();
|
|
95
95
|
}
|
|
96
|
+
isPrimitiveType(kind) {
|
|
97
|
+
return ['string', 'number', 'boolean', 'bigint', 'undefined', 'null'].includes(kind);
|
|
98
|
+
}
|
|
99
|
+
toUpperCase(name) {
|
|
100
|
+
if (!name) {
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
return name.charAt(0).toUpperCase() + name.substring(1);
|
|
104
|
+
}
|
|
96
105
|
registerComparisonHelpers() {
|
|
97
106
|
this.registerHelper('eq', (arg1, arg2) => {
|
|
98
107
|
return (arg1 === arg2);
|
|
99
108
|
});
|
|
100
109
|
this.registerHelper('eqPrimitiveType', (kind) => {
|
|
101
|
-
|
|
102
|
-
return primitives.includes(kind);
|
|
110
|
+
return this.isPrimitiveType(kind);
|
|
103
111
|
});
|
|
104
112
|
this.registerHelper('eqEmptyType', (kind) => {
|
|
105
113
|
return ['null', 'undefined'].includes(kind);
|
|
@@ -182,12 +190,26 @@ class HandlebarsTemplateEngine {
|
|
|
182
190
|
this.registerHelper('toLowerCase', (str) => {
|
|
183
191
|
return str.toLowerCase();
|
|
184
192
|
});
|
|
193
|
+
this.registerHelper('toUpperCase', (str) => {
|
|
194
|
+
return this.toUpperCase(str);
|
|
195
|
+
});
|
|
196
|
+
this.registerHelper('getSerializer', (analysis) => {
|
|
197
|
+
if (this.isPrimitiveType(analysis.type.kind)) {
|
|
198
|
+
return `${analysis.name}Serializer`;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
return `get${this.toUpperCase(analysis.name)}Serializer()`;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
185
204
|
this.registerHelper('genericParametersString', (parameters) => {
|
|
186
205
|
return parameters.join(', ');
|
|
187
206
|
});
|
|
188
207
|
this.registerHelper('genericParametersESObjString', (parameters) => {
|
|
189
208
|
return parameters.map(() => 'ESObject').join(', ');
|
|
190
209
|
});
|
|
210
|
+
this.registerHelper('filterGenericProperties', (properties) => {
|
|
211
|
+
return properties.filter(p => p.analysis.type.kind === __1.PropertyKind.GENERIC && !p.analysis.decorators?.isTransient);
|
|
212
|
+
});
|
|
191
213
|
}
|
|
192
214
|
registerPropertyAnalysisHelpers() {
|
|
193
215
|
this.registerHelper('getPropertyIndex', (property, properties) => {
|
|
@@ -8,7 +8,8 @@ class DeepCopyUtil {
|
|
|
8
8
|
defaultValue: original.defaultValue,
|
|
9
9
|
decorators: this.copyPropertyDecorators(original.decorators),
|
|
10
10
|
isMust: original.isMust,
|
|
11
|
-
type: this.copyTypeStructure(original.type)
|
|
11
|
+
type: this.copyTypeStructure(original.type),
|
|
12
|
+
visibility: original.visibility
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
static copyPropertyDecorators(original) {
|
|
@@ -19,6 +20,7 @@ class DeepCopyUtil {
|
|
|
19
20
|
serialName: original.serialName,
|
|
20
21
|
isRequired: original.isRequired,
|
|
21
22
|
isTransient: original.isTransient,
|
|
23
|
+
isPlainValue: original.isPlainValue,
|
|
22
24
|
with: original.with
|
|
23
25
|
};
|
|
24
26
|
}
|
|
@@ -126,7 +128,7 @@ class DeepCopyUtil {
|
|
|
126
128
|
if (typeof obj === 'object') {
|
|
127
129
|
const copy = {};
|
|
128
130
|
for (const key in obj) {
|
|
129
|
-
if (
|
|
131
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
130
132
|
copy[key] = this.deepCopy(obj[key]);
|
|
131
133
|
}
|
|
132
134
|
}
|
|
@@ -5,5 +5,6 @@ export declare class GenericTypeSubstitutionUtil {
|
|
|
5
5
|
static substitutePropertyType(property: PropertyAnalysis, genericMapping: Map<string, TypeNode>, currentClassGenericParams?: string[]): PropertyAnalysis;
|
|
6
6
|
private static substituteTypeStructure;
|
|
7
7
|
private static constructTypeStructureFromTypeName;
|
|
8
|
+
private static regenerateSourceText;
|
|
8
9
|
private static collectDependenciesFromChildren;
|
|
9
10
|
}
|