@hadss/turbo-trans-json-plugin 1.0.0-rc.0 → 1.0.0-rc.1
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.js +35 -4
- package/dist/core/constants/DecoratorConstants.d.ts +1 -0
- package/dist/core/constants/DecoratorConstants.js +2 -1
- package/dist/core/handlers/CustomClassHandler.js +0 -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 +2 -4
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +4 -30
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +20 -15
- package/dist/core/template/HandlebarsTemplateEngine.js +3 -0
- package/dist/core/utils/DeepCopyUtil.js +3 -1
- package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +1 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.js +27 -1
- package/dist/core/utils/TsMorphUtil.js +4 -0
- package/package.json +1 -1
- package/src/core/Types.ts +9 -1
- package/src/core/analyzers/ClassAnalyzer.ts +74 -18
- package/src/core/analyzers/CustomTypeAnalyzer.ts +0 -1
- package/src/core/constants/DecoratorConstants.ts +2 -1
- package/src/core/constants/StringConstants.ts +0 -2
- package/src/core/handlers/CustomClassHandler.ts +0 -3
- package/src/core/handlers/TypeHandlerRegistry.ts +1 -1
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +1 -1
- package/src/core/import-rewrite/services/ImportRewriteService.ts +0 -2
- package/src/core/services/CodeAnalysisService.ts +1 -1
- 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 +6 -42
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +26 -19
- package/src/core/template/HandlebarsTemplateEngine.ts +5 -0
- package/src/core/utils/DeepCopyUtil.ts +3 -1
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +51 -1
- package/src/core/utils/TsMorphUtil.ts +5 -1
- package/src/json-plugin/tasks/BaseTask.ts +0 -1
- package/template/SerializerPerformanceTemplate.hbs +14 -4
- package/template/SerializerStrictTemplate.hbs +8 -0
- package/template/SerializerTemplate.hbs +14 -6
|
@@ -26,15 +26,16 @@ import {
|
|
|
26
26
|
} from 'ts-morph';
|
|
27
27
|
import {
|
|
28
28
|
ClassAnalysis,
|
|
29
|
-
InterfaceAnalysis,
|
|
30
29
|
ClassDecorators,
|
|
31
30
|
ConstructorParam,
|
|
32
31
|
DeserializationMode,
|
|
33
32
|
GenericInfo,
|
|
34
33
|
InheritanceInfo,
|
|
34
|
+
InterfaceAnalysis,
|
|
35
35
|
PropertyAnalysis,
|
|
36
36
|
PropertyDecorators,
|
|
37
37
|
PropertyKind,
|
|
38
|
+
PropertyVisibility,
|
|
38
39
|
SerializableOptions,
|
|
39
40
|
TypeStructure
|
|
40
41
|
} from '../Types';
|
|
@@ -45,7 +46,6 @@ import { CustomTypeAnalyzer } from './CustomTypeAnalyzer';
|
|
|
45
46
|
import { CustomError, ErrorCodes } from '../utils/CustomError';
|
|
46
47
|
import { Logger } from '../logger/Logger';
|
|
47
48
|
import { TsMorphUtil } from '../utils/TsMorphUtil';
|
|
48
|
-
import { logger } from 'handlebars';
|
|
49
49
|
|
|
50
50
|
export class ClassAnalyzer {
|
|
51
51
|
/**
|
|
@@ -97,14 +97,15 @@ export class ClassAnalyzer {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
* 分析接口的完整结构,包括属性、继承关系等信息
|
|
101
|
+
* @param interfaceDecl 接口声明节点
|
|
102
|
+
* @returns 接口分析结果
|
|
103
|
+
*/
|
|
104
104
|
public static analyzeInterface(interfaceDecl: InterfaceDeclaration): InterfaceAnalysis {
|
|
105
105
|
const interfaceName = interfaceDecl.getName();
|
|
106
106
|
if (!interfaceName) {
|
|
107
|
-
throw new CustomError(`Interface name is undefined in ${interfaceDecl.getSourceFile().getFilePath()}`,
|
|
107
|
+
throw new CustomError(`Interface name is undefined in ${interfaceDecl.getSourceFile().getFilePath()}`,
|
|
108
|
+
ErrorCodes.CLASS_DECLARATION_NOT_FOUND);
|
|
108
109
|
}
|
|
109
110
|
const sourceFilePath = interfaceDecl.getSourceFile().getFilePath();
|
|
110
111
|
const generics: GenericInfo = {
|
|
@@ -141,7 +142,8 @@ export class ClassAnalyzer {
|
|
|
141
142
|
*/
|
|
142
143
|
private static analyzeInheritanceInfo(cls: ClassDeclaration | InterfaceDeclaration): InheritanceInfo {
|
|
143
144
|
const heritageClaus = cls.getHeritageClauses();
|
|
144
|
-
Logger.debug(
|
|
145
|
+
Logger.debug(
|
|
146
|
+
`分析类的继承信息: ${cls.getName()} ${heritageClaus.length} ${heritageClaus.map(c => c.getText()).join(',')}`);
|
|
145
147
|
for (const clause of heritageClaus) {
|
|
146
148
|
const token = clause.getToken();
|
|
147
149
|
// 接口实现
|
|
@@ -155,7 +157,8 @@ export class ClassAnalyzer {
|
|
|
155
157
|
Logger.debug(`继承信息: text: ${className} getTypeArguments: ${args.map(type => type.getText()).join(', ')}`);
|
|
156
158
|
const classDecl = CustomTypeAnalyzer.getInstance().findClassDeclFromClassName(className, cls.getSourceFile());
|
|
157
159
|
if (!classDecl) {
|
|
158
|
-
throw new CustomError(`class ${className} decl does not exist ${cls.getName} implement ${className}`,
|
|
160
|
+
throw new CustomError(`class ${className} decl does not exist ${cls.getName} implement ${className}`,
|
|
161
|
+
ErrorCodes.CLASS_DECLARATION_NOT_FOUND);
|
|
159
162
|
}
|
|
160
163
|
if (classDecl instanceof InterfaceDeclaration) {
|
|
161
164
|
const baseClassAnalysis = this.analyzeInterface(classDecl);
|
|
@@ -343,7 +346,7 @@ export class ClassAnalyzer {
|
|
|
343
346
|
} else {
|
|
344
347
|
// 未知类型且没有 @Transient 或自定义序列化器,抛出清晰错误
|
|
345
348
|
throw new CustomError(`不支持的类型 '${propertyAnalysis.type.sourceText}' 用于属性 '${propertyAnalysis.name
|
|
346
|
-
|
|
349
|
+
}' (接口: ${cls.getName()})`, ErrorCodes.TYPE_NOT_SUPPORT);
|
|
347
350
|
}
|
|
348
351
|
}
|
|
349
352
|
}
|
|
@@ -441,9 +444,33 @@ export class ClassAnalyzer {
|
|
|
441
444
|
|
|
442
445
|
// 3. 递归处理更上层祖先,传递泛型参数
|
|
443
446
|
if (classAnalysis.inheritance.isInherited && classAnalysis.inheritance.baseClassAnalysis) {
|
|
447
|
+
// 关键修复: 需要解析父类的泛型参数,将其中的泛型引用替换为当前映射的具体类型
|
|
448
|
+
const parentGenericTypeArgs = classAnalysis.inheritance.genericTypeArguments || [];
|
|
449
|
+
|
|
450
|
+
// 对父类的泛型参数进行替换,解决泛型参数引用问题
|
|
451
|
+
// 例如: CrudRepository<T> extends Repository<T, number>
|
|
452
|
+
// 这里的 T 需要替换为当前映射中的 UserEntity
|
|
453
|
+
const resolvedParentGenericArgs = parentGenericTypeArgs.map(typeArg => {
|
|
454
|
+
// 解析类型参数为 TypeStructure
|
|
455
|
+
const typeStructure = TypeHandlerRegistry.getInstance().parseType(typeArg, {
|
|
456
|
+
depth: 0,
|
|
457
|
+
genericParams: parentGenericParams // 使用父类的泛型参数上下文
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// 如果是泛型引用,进行替换
|
|
461
|
+
if (typeStructure.kind === PropertyKind.GENERIC && genericMapping.has(typeStructure.sourceText)) {
|
|
462
|
+
return genericMapping.get(typeStructure.sourceText)!;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// 否则保持原样
|
|
466
|
+
return typeArg;
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
Logger.debug(`[CollectAncestors] Resolved parent generic args: ${resolvedParentGenericArgs.map(a => a.getText()).join(', ')}`);
|
|
470
|
+
|
|
444
471
|
const ancestorProperties = this.collectAllAncestorProperties(
|
|
445
472
|
classAnalysis.inheritance.baseClassAnalysis,
|
|
446
|
-
|
|
473
|
+
resolvedParentGenericArgs, // 传递解析后的泛型参数
|
|
447
474
|
currentClassGenericParams // 保持传递当前类的泛型参数
|
|
448
475
|
);
|
|
449
476
|
allProperties.push(...ancestorProperties);
|
|
@@ -494,18 +521,25 @@ export class ClassAnalyzer {
|
|
|
494
521
|
throw new CustomError(`无法分析属性 '${name}' 的类型。请检查属性声明。`, ErrorCodes.TYPE_NOT_SUPPORT);
|
|
495
522
|
}
|
|
496
523
|
|
|
497
|
-
const defaultValue: string | undefined = prop instanceof PropertyDeclaration ?
|
|
524
|
+
const defaultValue: string | undefined = prop instanceof PropertyDeclaration ?
|
|
525
|
+
this.analyzeDefaultValue(prop, constructorParams) : undefined;
|
|
498
526
|
const decorators = prop instanceof PropertyDeclaration ? this.analyzePropertyDecorators(prop) : undefined;
|
|
499
527
|
const type = TypeHandlerRegistry.getInstance().parseType(typeNode, { genericParams: genericParameters, depth: 0 });
|
|
500
528
|
type.isOptional = prop.hasQuestionToken();
|
|
501
529
|
|
|
530
|
+
// 检测属性可见性修饰符
|
|
531
|
+
const visibility: PropertyVisibility =
|
|
532
|
+
prop.hasModifier(SyntaxKind.PrivateKeyword) ? PropertyVisibility.PRIVATE :
|
|
533
|
+
prop.hasModifier(SyntaxKind.ProtectedKeyword) ? PropertyVisibility.PROTECTED :
|
|
534
|
+
PropertyVisibility.PUBLIC;
|
|
535
|
+
|
|
502
536
|
const constructorParam = constructorParams.find((param) => param.name === name);
|
|
503
537
|
|
|
504
538
|
// 计算构造函数参数的可选性(用于后续验证)
|
|
505
539
|
const isParamOptional = constructorParam
|
|
506
540
|
? constructorParam.isOptional ||
|
|
507
|
-
|
|
508
|
-
|
|
541
|
+
constructorParam.defaultValue !== undefined ||
|
|
542
|
+
this.hasUndefinedInUnion(constructorParam.type)
|
|
509
543
|
: true;
|
|
510
544
|
|
|
511
545
|
let isMust: boolean;
|
|
@@ -539,7 +573,8 @@ export class ClassAnalyzer {
|
|
|
539
573
|
defaultValue,
|
|
540
574
|
decorators,
|
|
541
575
|
type,
|
|
542
|
-
isMust
|
|
576
|
+
isMust,
|
|
577
|
+
visibility
|
|
543
578
|
};
|
|
544
579
|
}
|
|
545
580
|
|
|
@@ -598,7 +633,8 @@ export class ClassAnalyzer {
|
|
|
598
633
|
return typeText;
|
|
599
634
|
}
|
|
600
635
|
|
|
601
|
-
private static getTypeFromInitializer(prop: PropertyDeclaration | PropertySignature,
|
|
636
|
+
private static getTypeFromInitializer(prop: PropertyDeclaration | PropertySignature,
|
|
637
|
+
propName: string): TypeNode | undefined {
|
|
602
638
|
const initializer = prop.getInitializer();
|
|
603
639
|
if (!initializer) {
|
|
604
640
|
return undefined;
|
|
@@ -626,7 +662,8 @@ export class ClassAnalyzer {
|
|
|
626
662
|
}
|
|
627
663
|
|
|
628
664
|
const exprText = expression.getText();
|
|
629
|
-
const supportedTypes = ['Map', 'Set', 'WeakMap', 'WeakSet', 'Array', 'Object', 'ArrayList', 'HashMap', 'HashSet',
|
|
665
|
+
const supportedTypes = ['Map', 'Set', 'WeakMap', 'WeakSet', 'Array', 'Object', 'ArrayList', 'HashMap', 'HashSet',
|
|
666
|
+
'LinkedList', 'Decimal', 'List'];
|
|
630
667
|
|
|
631
668
|
if (!supportedTypes.includes(exprText)) {
|
|
632
669
|
return undefined;
|
|
@@ -651,7 +688,8 @@ export class ClassAnalyzer {
|
|
|
651
688
|
* @param type 类型结构
|
|
652
689
|
* @returns 是否为可选属性
|
|
653
690
|
*/
|
|
654
|
-
private static isOptional(node: PropertyDeclaration | PropertySignature, defaultValue: string | undefined,
|
|
691
|
+
private static isOptional(node: PropertyDeclaration | PropertySignature, defaultValue: string | undefined,
|
|
692
|
+
type: TypeStructure): boolean {
|
|
655
693
|
// 1. 语法上带 ?(prop?: T, param?: T)
|
|
656
694
|
if (node.hasQuestionToken()) {
|
|
657
695
|
return true;
|
|
@@ -770,6 +808,7 @@ export class ClassAnalyzer {
|
|
|
770
808
|
const decorators = prop.getDecorators();
|
|
771
809
|
let isRequired: boolean = false;
|
|
772
810
|
let isTransient: boolean = false;
|
|
811
|
+
let isPlainValue: boolean = false;
|
|
773
812
|
let serialName: string | undefined;
|
|
774
813
|
let _with: string | undefined;
|
|
775
814
|
|
|
@@ -786,6 +825,9 @@ export class ClassAnalyzer {
|
|
|
786
825
|
case DecoratorConstants.TRANSIENT:
|
|
787
826
|
isTransient = true;
|
|
788
827
|
break;
|
|
828
|
+
case DecoratorConstants.PLAIN_VALUE:
|
|
829
|
+
isPlainValue = true;
|
|
830
|
+
break;
|
|
789
831
|
case DecoratorConstants.SERIALIZABLE:
|
|
790
832
|
_with = this.parseSerializableOptions(decorator)!.with;
|
|
791
833
|
}
|
|
@@ -803,6 +845,9 @@ export class ClassAnalyzer {
|
|
|
803
845
|
if (_with) {
|
|
804
846
|
conflictingDecorators.push('@Serializable');
|
|
805
847
|
}
|
|
848
|
+
if (isPlainValue) {
|
|
849
|
+
conflictingDecorators.push('@PlainValue');
|
|
850
|
+
}
|
|
806
851
|
|
|
807
852
|
if (conflictingDecorators.length > 0) {
|
|
808
853
|
throw new CustomError(
|
|
@@ -814,9 +859,20 @@ export class ClassAnalyzer {
|
|
|
814
859
|
}
|
|
815
860
|
}
|
|
816
861
|
|
|
862
|
+
// 注解互斥检查:@PlainValue 与自定义序列化器互斥
|
|
863
|
+
if (isPlainValue && _with) {
|
|
864
|
+
throw new CustomError(
|
|
865
|
+
`属性 '${prop.getName()}' 的注解冲突:@PlainValue 与 @Serializable(with:) 不能同时使用。\n` +
|
|
866
|
+
`@PlainValue 跳过类型转换直接使用原始值,与自定义序列化器冲突。\n` +
|
|
867
|
+
`请移除 @PlainValue 或移除自定义序列化器。`,
|
|
868
|
+
ErrorCodes.ANNOTATION_CONFLICT
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
817
872
|
return {
|
|
818
873
|
isRequired,
|
|
819
874
|
isTransient,
|
|
875
|
+
isPlainValue,
|
|
820
876
|
serialName,
|
|
821
877
|
with: _with
|
|
822
878
|
};
|
|
@@ -22,6 +22,7 @@ export class DecoratorConstants {
|
|
|
22
22
|
static readonly SERIAL_NAME = 'SerialName'
|
|
23
23
|
static readonly REQUIRED = 'Required'
|
|
24
24
|
static readonly TRANSIENT = 'Transient'
|
|
25
|
+
static readonly PLAIN_VALUE = 'PlainValue'
|
|
25
26
|
|
|
26
|
-
static readonly SERIAL_DECORATORS = [this.SERIALIZABLE, this.SERIAL_NAME, this.REQUIRED, this.TRANSIENT];
|
|
27
|
+
static readonly SERIAL_DECORATORS = [this.SERIALIZABLE, this.SERIAL_NAME, this.REQUIRED, this.TRANSIENT, this.PLAIN_VALUE];
|
|
27
28
|
}
|
|
@@ -240,9 +240,6 @@ export class CustomClassHandler extends BaseTypeHandler implements ITypeHandler
|
|
|
240
240
|
throw new CustomError(`Type ${classDetails.classDecl.getName()} is not sendable.
|
|
241
241
|
please add @Sendable or @Serializable({ generateSendable: true })`, ErrorCodes.NOT_SENDABLE);
|
|
242
242
|
}
|
|
243
|
-
|
|
244
|
-
// 未启用generateSendable,返回原类型
|
|
245
|
-
return structure.sourceText;
|
|
246
243
|
}
|
|
247
244
|
|
|
248
245
|
generatePropertyConversion(structure: TypeStructure, sourceValue: string, direction: ConversionDirection): string {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { TypeNode, SyntaxKind
|
|
16
|
+
import { TypeNode, SyntaxKind } from 'ts-morph';
|
|
17
17
|
import { ITypeHandler, TypeContext } from './ITypeHandler';
|
|
18
18
|
import { PropertyKind, TypeStructure, Logger } from '..';
|
|
19
19
|
import { CustomError, ErrorCodes } from '../utils/CustomError';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import { Logger } from '../..';
|
|
17
17
|
import { ITargetContext } from '../../../json-plugin/interfaces/ITargetContext';
|
|
18
18
|
import SerializationPathUtil from '../../utils/SerializationPathUtil';
|
|
19
19
|
|
|
@@ -17,8 +17,6 @@ import { ITaskContext, ImportRewriteOptions, Logger } from '../..';
|
|
|
17
17
|
import { GeneratedFileInfo, ImportRewriteService as IImportRewriteService } from '../types/ImportRewriteTypes';
|
|
18
18
|
import { ImportTransformServiceImpl } from './ImportTransformService';
|
|
19
19
|
import SerializationPathUtil from '../../utils/SerializationPathUtil';
|
|
20
|
-
import { BuildProfileUpdaterImpl } from './BuildProfileUpdater';
|
|
21
|
-
import { ITargetContext } from '../../../json-plugin/interfaces/ITargetContext';
|
|
22
20
|
|
|
23
21
|
/**
|
|
24
22
|
* 导入重写主服务实现
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { ClassDeclaration
|
|
16
|
+
import { ClassDeclaration } from 'ts-morph';
|
|
17
17
|
import { ClassAnalysis, DecoratorConstants, Logger } from '..';
|
|
18
18
|
import { ClassAnalyzer } from '../analyzers/ClassAnalyzer';
|
|
19
19
|
import { TsMorphUtil } from '../utils/TsMorphUtil';
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { IndentationText, Project, QuoteKind } from 'ts-morph';
|
|
17
16
|
import { OriginalClassGenerator } from './generators/OriginalClassGenerator';
|
|
18
17
|
import { SendableClassGenerator } from './generators/SendableClassGenerator';
|
|
19
18
|
import { SerializerGenerator } from './generators/SerializerGenerator';
|
|
@@ -69,7 +68,7 @@ export class CodeGenerationService {
|
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
// 生成原始类结构
|
|
72
|
-
this.originalClassGenerator.generate(outputSourceFile, originalSourceFile, results
|
|
71
|
+
this.originalClassGenerator.generate(outputSourceFile, originalSourceFile, results);
|
|
73
72
|
|
|
74
73
|
for (const content of serializableGeneratorContext) {
|
|
75
74
|
this.serializerGenerator.generateRegistration(outputSourceFile, content);
|
|
@@ -89,22 +89,6 @@ export class MergedSendableClassGenerator {
|
|
|
89
89
|
classDecl.addImplements(['ITSerializable', 'lang.ISendable']);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
private generateGetTypeMethod(classDecl: ClassDeclaration, classAnalysis: ClassAnalysis): void {
|
|
93
|
-
// 检查是否已存在该方法
|
|
94
|
-
if (classDecl.getMethod('getType')) {
|
|
95
|
-
Logger.warn(`类 ${classAnalysis.className} 已存在getType方法,跳过生成`);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const methodBody = `return ${classAnalysis.className};`;
|
|
100
|
-
|
|
101
|
-
classDecl.addMethod({
|
|
102
|
-
name: 'getType',
|
|
103
|
-
returnType: 'Function',
|
|
104
|
-
statements: [methodBody]
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
92
|
/**
|
|
109
93
|
* 生成toSendable方法
|
|
110
94
|
* 对于合并版Sendable类,直接返回自身(因为类本身已经是Sendable)
|
|
@@ -162,19 +146,6 @@ export class MergedSendableClassGenerator {
|
|
|
162
146
|
|
|
163
147
|
const methodBody = 'return TJSON.toString(this, typeKey)';
|
|
164
148
|
|
|
165
|
-
// 获取类的泛型参数
|
|
166
|
-
const genericParameters = classAnalysis.generics.parameters;
|
|
167
|
-
|
|
168
|
-
// 构建完整的类型名(包含泛型参数)
|
|
169
|
-
let fullTypeName: string;
|
|
170
|
-
if (genericParameters.length > 0) {
|
|
171
|
-
// 对于泛型类:ClassName<T, U>
|
|
172
|
-
fullTypeName = `${classDecl.getNameOrThrow()}<${genericParameters.join(', ')}>`;
|
|
173
|
-
} else {
|
|
174
|
-
// 对于非泛型类:ClassName
|
|
175
|
-
fullTypeName = classDecl.getNameOrThrow();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
149
|
classDecl.addMethod({
|
|
179
150
|
name: 'toJson',
|
|
180
151
|
returnType: 'string',
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { ClassDeclaration,
|
|
17
|
-
import { ClassAnalysis, PropertyAnalysis, Logger, PropertyKind
|
|
16
|
+
import { ClassDeclaration, SourceFile } from 'ts-morph';
|
|
17
|
+
import { ClassAnalysis, PropertyAnalysis, Logger, PropertyKind } from '../../..';
|
|
18
18
|
import { ImportManager } from '../shared/ImportManager';
|
|
19
19
|
import SerializationPathUtil from '../../../utils/SerializationPathUtil';
|
|
20
20
|
import { ConversionDirection } from '../../../handlers/ITypeHandler';
|
|
@@ -32,7 +32,7 @@ export class OriginalClassGenerator {
|
|
|
32
32
|
this.mergedSendableGenerator = new MergedSendableClassGenerator();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
generate(outputSourceFile: SourceFile, originalSourceFile: SourceFile, results: ClassAnalysis[]
|
|
35
|
+
generate(outputSourceFile: SourceFile, originalSourceFile: SourceFile, results: ClassAnalysis[]): void {
|
|
36
36
|
this.registerImports();
|
|
37
37
|
|
|
38
38
|
// 1. 获取原始源文件的完整内容并移除原始import语句
|
|
@@ -53,7 +53,7 @@ export class OriginalClassGenerator {
|
|
|
53
53
|
this.mergedSendableGenerator.generate(targetClass, result);
|
|
54
54
|
} else {
|
|
55
55
|
this.addITSerializableInterface(targetClass);
|
|
56
|
-
this.addStaticSerialName(targetClass, result
|
|
56
|
+
this.addStaticSerialName(targetClass, result);
|
|
57
57
|
this.generateConvertToSendableMethod(targetClass, result);
|
|
58
58
|
this.generateToJsonMethod(targetClass, result);
|
|
59
59
|
}
|
|
@@ -129,14 +129,7 @@ export class OriginalClassGenerator {
|
|
|
129
129
|
Logger.debug(`为类 ${classDecl.getName()} 添加ITSerializable接口实现`);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
private
|
|
133
|
-
const relativePath = context.calculateSourceRootToModuleRoot(result.sourceFilePath);
|
|
134
|
-
const serialName = SerializationPathUtil.join(context.getPackageName(), relativePath, result.className + '.class')
|
|
135
|
-
.replaceAll(SerializationPathUtil.sep, '/');
|
|
136
|
-
return result.decorators.serialName || serialName;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private addStaticSerialName(classDecl: ClassDeclaration, result: ClassAnalysis, context: ITaskContext): void {
|
|
132
|
+
private addStaticSerialName(classDecl: ClassDeclaration, result: ClassAnalysis): void {
|
|
140
133
|
// 添加静态属性
|
|
141
134
|
classDecl.addProperty({
|
|
142
135
|
name: 'SERIAL_NAME',
|
|
@@ -148,22 +141,6 @@ export class OriginalClassGenerator {
|
|
|
148
141
|
Logger.debug(`为类 ${classDecl.getName()} 添加静态属性 serialName`);
|
|
149
142
|
}
|
|
150
143
|
|
|
151
|
-
private generateGetTypeMethod(classDecl: ClassDeclaration, result: ClassAnalysis): void {
|
|
152
|
-
// 检查是否已存在该方法
|
|
153
|
-
if (classDecl.getMethod('getType')) {
|
|
154
|
-
Logger.warn(`类 ${result.className} 已存在getType方法,跳过生成`);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const methodBody = `return ${result.className};`;
|
|
159
|
-
|
|
160
|
-
classDecl.addMethod({
|
|
161
|
-
name: 'getType',
|
|
162
|
-
returnType: 'Function',
|
|
163
|
-
statements: [methodBody]
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
144
|
private generateConvertToSendableMethod(classDecl: ClassDeclaration, result: ClassAnalysis): void {
|
|
168
145
|
// 检查是否已存在该方法
|
|
169
146
|
if (classDecl.getMethod('toSendable')) {
|
|
@@ -205,19 +182,6 @@ export class OriginalClassGenerator {
|
|
|
205
182
|
|
|
206
183
|
const methodBody = 'return TJSON.toString(this, typeKey)';
|
|
207
184
|
|
|
208
|
-
// 获取类的泛型参数
|
|
209
|
-
const genericParameters = result.generics.parameters;
|
|
210
|
-
|
|
211
|
-
// 构建完整的类型名(包含泛型参数)
|
|
212
|
-
let fullTypeName: string;
|
|
213
|
-
if (genericParameters.length > 0) {
|
|
214
|
-
// 对于泛型类:ClassName<T, U>
|
|
215
|
-
fullTypeName = `${classDecl.getNameOrThrow()}<${genericParameters.join(', ')}>`;
|
|
216
|
-
} else {
|
|
217
|
-
// 对于非泛型类:ClassName
|
|
218
|
-
fullTypeName = classDecl.getNameOrThrow();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
185
|
classDecl.addMethod({
|
|
222
186
|
name: 'toJson',
|
|
223
187
|
returnType: 'string',
|
|
@@ -233,7 +197,7 @@ export class OriginalClassGenerator {
|
|
|
233
197
|
private registerImports(): void {
|
|
234
198
|
this.importManager.registerJsonImports(['ITSerializable', 'TJSON']);
|
|
235
199
|
|
|
236
|
-
this.importManager.registerCoreImports(['TypeKey', 'Serializable']);
|
|
200
|
+
this.importManager.registerCoreImports(['TypeKey', 'Serializable', 'Encoder', 'SerialDescriptor']);
|
|
237
201
|
}
|
|
238
202
|
|
|
239
203
|
// ============= toSendable方法生成 =============
|
|
@@ -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',
|
|
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[] {
|
|
@@ -230,6 +230,11 @@ export class HandlebarsTemplateEngine {
|
|
|
230
230
|
this.registerHelper('genericParametersESObjString', (parameters: string[]) => {
|
|
231
231
|
return parameters.map(() => 'ESObject').join(', ');
|
|
232
232
|
});
|
|
233
|
+
|
|
234
|
+
// 过滤出泛型类型的属性(用于生成静态方法的泛型序列化器参数)
|
|
235
|
+
this.registerHelper('filterGenericProperties', (properties: PropertyGenerationInfo[]) => {
|
|
236
|
+
return properties.filter(p => p.analysis.type.kind === PropertyKind.GENERIC && !p.analysis.decorators?.isTransient);
|
|
237
|
+
});
|
|
233
238
|
}
|
|
234
239
|
|
|
235
240
|
private registerPropertyAnalysisHelpers(): void {
|
|
@@ -25,7 +25,8 @@ export class DeepCopyUtil {
|
|
|
25
25
|
defaultValue: original.defaultValue,
|
|
26
26
|
decorators: this.copyPropertyDecorators(original.decorators),
|
|
27
27
|
isMust: original.isMust,
|
|
28
|
-
type: this.copyTypeStructure(original.type)
|
|
28
|
+
type: this.copyTypeStructure(original.type),
|
|
29
|
+
visibility: original.visibility
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
|
|
@@ -37,6 +38,7 @@ export class DeepCopyUtil {
|
|
|
37
38
|
serialName: original.serialName,
|
|
38
39
|
isRequired: original.isRequired,
|
|
39
40
|
isTransient: original.isTransient,
|
|
41
|
+
isPlainValue: original.isPlainValue,
|
|
40
42
|
with: original.with
|
|
41
43
|
};
|
|
42
44
|
}
|