@hadss/turbo-trans-json-plugin 1.0.0-rc.1 → 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/dist/core/analyzers/ClassAnalyzer.d.ts +15 -0
- package/dist/core/analyzers/ClassAnalyzer.js +193 -144
- package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +3 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.js +65 -60
- package/dist/core/constants/DecoratorConstants.js +2 -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/generators/OriginalClassGenerator.d.ts +2 -0
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +22 -15
- 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 +1 -1
- 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 +21 -2
- package/dist/core/utils/DeepCopyUtil.js +1 -1
- package/dist/core/utils/SerializationPathUtil.d.ts +1 -1
- package/dist/core/utils/TsMorphUtil.js +2 -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 +90 -90
- package/src/core/analyzers/ClassAnalyzer.ts +335 -230
- package/src/core/analyzers/CustomTypeAnalyzer.ts +145 -73
- package/src/core/constants/DecoratorConstants.ts +7 -6
- package/src/core/constants/PathConstants.ts +7 -7
- package/src/core/constants/StringConstants.ts +95 -95
- package/src/core/handlers/BaseTypeHandler.ts +11 -2
- package/src/core/handlers/CustomClassHandler.ts +4 -4
- 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 +2 -1
- package/src/core/handlers/UnionTypeHandler.ts +8 -7
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +6 -4
- package/src/core/import-rewrite/services/ImportRewriteService.ts +1 -1
- 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 +2 -1
- package/src/core/services/CodeGenerationEngine.ts +42 -42
- package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +25 -22
- package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +261 -170
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +1 -1
- 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 +39 -11
- package/src/core/utils/ConfigManager.ts +2 -1
- package/src/core/utils/DeepCopyUtil.ts +1 -1
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +1 -8
- package/src/core/utils/SerializationPathUtil.ts +7 -6
- package/src/core/utils/TsMorphUtil.ts +4 -1
- 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 -3
- package/src/json-plugin/tasks/CleanTask.ts +7 -7
- package/src/json-plugin/tasks/WatchTask.ts +20 -18
- package/template/SerializerPerformanceTemplate.hbs +5 -5
- package/template/SerializerStrictTemplate.hbs +1 -1
- package/template/SerializerTemplate.hbs +59 -42
|
@@ -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
|
|
|
@@ -106,7 +106,7 @@ export class SerializerGenerator {
|
|
|
106
106
|
this.importManager.registerCoreImports([
|
|
107
107
|
'Serializer', 'SerialDescriptor', 'buildClassSerialDescriptor',
|
|
108
108
|
'Encoder', 'Decoder', 'registerAutoGeneratedSerializerEntry', 'ObjectUtils',
|
|
109
|
-
'registerAutoGeneratedSerializerEntryProviderForSupplementary',
|
|
109
|
+
'registerAutoGeneratedSerializerEntryProviderForSupplementary', 'lazy',
|
|
110
110
|
...requiredBuiltinSerializers
|
|
111
111
|
]);
|
|
112
112
|
|
|
@@ -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
|
}
|
|
@@ -47,7 +47,7 @@ export class ImportManager {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
registerArkTSImports(names: string[]) {
|
|
50
|
+
registerArkTSImports(names: string[]): void {
|
|
51
51
|
const arkTSModule = '@kit.ArkTS';
|
|
52
52
|
|
|
53
53
|
for (const name of names) {
|
|
@@ -59,7 +59,7 @@ export class ImportManager {
|
|
|
59
59
|
// 智能去重:检查是否已有同名类型的更好路径
|
|
60
60
|
if (this.typeToModulePath.has(importedName)) {
|
|
61
61
|
const existingModulePath = this.typeToModulePath.get(importedName)!;
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
// 如果当前路径是模块化路径,而已存在的是相对路径,则替换
|
|
64
64
|
if (this.isModularPath(modulePath) && this.isRelativePath(existingModulePath)) {
|
|
65
65
|
// 移除旧的相对路径导入
|
|
@@ -106,10 +106,10 @@ export class ImportManager {
|
|
|
106
106
|
* 判断是否为模块化路径(不以 . 或 / 开头,不是 @开头的包名)
|
|
107
107
|
*/
|
|
108
108
|
private isModularPath(modulePath: string): boolean {
|
|
109
|
-
return !modulePath.startsWith('.') &&
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
return !modulePath.startsWith('.') &&
|
|
110
|
+
!modulePath.startsWith('/') &&
|
|
111
|
+
!modulePath.startsWith('@') &&
|
|
112
|
+
modulePath.includes('/');
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
private isRelativePath(modulePath: string): boolean {
|
|
@@ -120,7 +120,7 @@ export class ImportManager {
|
|
|
120
120
|
if (this.imports.has(modulePath)) {
|
|
121
121
|
const existingInfo = this.imports.get(modulePath)!;
|
|
122
122
|
const filteredNames = existingInfo.importedNames.filter(name => name !== importedName);
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
if (filteredNames.length === 0) {
|
|
125
125
|
// 如果该模块没有其他导入,则删除整个模块
|
|
126
126
|
this.imports.delete(modulePath);
|
|
@@ -134,7 +134,7 @@ export class ImportManager {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
getImportDeclarations() {
|
|
137
|
+
getImportDeclarations(): Array<{ specifier: string, names: string[] }> {
|
|
138
138
|
const imports: Array<{ specifier: string, names: string[] }> = [];
|
|
139
139
|
for (const [specifier, infos] of this.imports) {
|
|
140
140
|
imports.push({ specifier: specifier, names: infos.importedNames });
|