@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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/core/Types.d.ts +7 -0
  3. package/dist/core/Types.js +7 -1
  4. package/dist/core/analyzers/ClassAnalyzer.js +35 -4
  5. package/dist/core/constants/DecoratorConstants.d.ts +1 -0
  6. package/dist/core/constants/DecoratorConstants.js +2 -1
  7. package/dist/core/handlers/CustomClassHandler.js +0 -1
  8. package/dist/core/services/CodeGenerationService/CodeGenerationService.js +1 -1
  9. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +0 -1
  10. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +0 -20
  11. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +2 -4
  12. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +4 -30
  13. package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +20 -15
  14. package/dist/core/template/HandlebarsTemplateEngine.js +3 -0
  15. package/dist/core/utils/DeepCopyUtil.js +3 -1
  16. package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +1 -0
  17. package/dist/core/utils/GenericTypeSubstitutionUtil.js +27 -1
  18. package/dist/core/utils/TsMorphUtil.js +4 -0
  19. package/package.json +1 -1
  20. package/src/core/Types.ts +9 -1
  21. package/src/core/analyzers/ClassAnalyzer.ts +74 -18
  22. package/src/core/analyzers/CustomTypeAnalyzer.ts +0 -1
  23. package/src/core/constants/DecoratorConstants.ts +2 -1
  24. package/src/core/constants/StringConstants.ts +0 -2
  25. package/src/core/handlers/CustomClassHandler.ts +0 -3
  26. package/src/core/handlers/TypeHandlerRegistry.ts +1 -1
  27. package/src/core/import-rewrite/services/BuildProfileUpdater.ts +1 -1
  28. package/src/core/import-rewrite/services/ImportRewriteService.ts +0 -2
  29. package/src/core/services/CodeAnalysisService.ts +1 -1
  30. package/src/core/services/CodeGenerationService/CodeGenerationService.ts +1 -2
  31. package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +0 -29
  32. package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +6 -42
  33. package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +26 -19
  34. package/src/core/template/HandlebarsTemplateEngine.ts +5 -0
  35. package/src/core/utils/DeepCopyUtil.ts +3 -1
  36. package/src/core/utils/GenericTypeSubstitutionUtil.ts +51 -1
  37. package/src/core/utils/TsMorphUtil.ts +5 -1
  38. package/src/json-plugin/tasks/BaseTask.ts +0 -1
  39. package/template/SerializerPerformanceTemplate.hbs +14 -4
  40. package/template/SerializerStrictTemplate.hbs +8 -0
  41. package/template/SerializerTemplate.hbs +14 -6
@@ -17,6 +17,7 @@ import { TypeNode } from 'ts-morph';
17
17
  import { PropertyAnalysis, TypeStructure, PropertyKind, TypeDependency } from '..';
18
18
  import { TypeHandlerRegistry } from '../handlers';
19
19
  import { DeepCopyUtil } from './DeepCopyUtil';
20
+ import { Logger } from '../logger/Logger';
20
21
 
21
22
  export class GenericTypeSubstitutionUtil {
22
23
  /**
@@ -30,7 +31,9 @@ export class GenericTypeSubstitutionUtil {
30
31
 
31
32
  const length = Math.min(parentGenericParams.length, childTypeArguments.length);
32
33
 
34
+ Logger.debug(`[GenericMapping] Building mapping with ${length} parameters`);
33
35
  for (let i = 0; i < length; i++) {
36
+ Logger.debug(`[GenericMapping] ${parentGenericParams[i]} -> ${childTypeArguments[i].getText()}`);
34
37
  mapping.set(parentGenericParams[i], childTypeArguments[i]);
35
38
  }
36
39
 
@@ -71,12 +74,20 @@ export class GenericTypeSubstitutionUtil {
71
74
  if (typeStructure.kind === PropertyKind.GENERIC) {
72
75
  // 对于泛型类型,sourceText 就是泛型参数名(如 "T", "U", "TData")
73
76
  const genericTypeName = typeStructure.sourceText;
77
+ Logger.debug(`[GenericSubstitution] Processing generic type: ${genericTypeName}`);
78
+ Logger.debug(`[GenericSubstitution] Available mappings: ${Array.from(mapping.keys()).join(', ')}`);
79
+ Logger.debug(`[GenericSubstitution] Current class generic params: ${currentClassGenericParams.join(', ')}`);
80
+
74
81
  if (mapping.has(genericTypeName)) {
75
82
  const substitutedTypeNode = mapping.get(genericTypeName)!;
83
+ Logger.debug(`[GenericSubstitution] Found mapping for ${genericTypeName} -> ${substitutedTypeNode.getText()}`);
76
84
 
77
- return this.constructTypeStructureFromTypeName(substitutedTypeNode, currentClassGenericParams);
85
+ const result = this.constructTypeStructureFromTypeName(substitutedTypeNode, currentClassGenericParams);
86
+ Logger.debug(`[GenericSubstitution] Result kind: ${result.kind}, sourceText: ${result.sourceText}`);
87
+ return result;
78
88
  }
79
89
  // 如果没有找到对应的映射,保持原样
90
+ Logger.warn(`[GenericSubstitution] No mapping found for generic type: ${genericTypeName}, keeping as-is`);
80
91
  return typeStructure;
81
92
  }
82
93
 
@@ -95,8 +106,18 @@ export class GenericTypeSubstitutionUtil {
95
106
  newStructure.args = newStructure.args.map(
96
107
  arg => this.substituteTypeStructure(arg, mapping, currentClassGenericParams)
97
108
  );
109
+ // 重新生成 sourceText 以反映泛型参数替换
110
+ newStructure.sourceText = this.regenerateSourceText(newStructure);
98
111
  }
99
112
 
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
100
121
  // 重新计算依赖信息
101
122
  newStructure.dependencies = this.collectDependenciesFromChildren(newStructure);
102
123
 
@@ -113,6 +134,35 @@ export class GenericTypeSubstitutionUtil {
113
134
  })
114
135
  }
115
136
 
137
+ /**
138
+ * 根据替换后的 args 重新生成 sourceText
139
+ * 保持原始格式(数组字面量 T[] 或泛型形式 Container<T>)
140
+ * @param structure 类型结构
141
+ * @returns 重新生成的 sourceText
142
+ */
143
+ private static regenerateSourceText(structure: TypeStructure): string {
144
+ if (!structure.args || structure.args.length === 0) {
145
+ return structure.sourceText;
146
+ }
147
+
148
+ // 处理数组字面量形式: T[] -> NewT[]
149
+ if (structure.sourceText.endsWith('[]')) {
150
+ return `${structure.args[0].sourceText}[]`;
151
+ }
152
+
153
+ // 处理泛型形式: Container<T> 或 Container<K, V>
154
+ // 提取容器名称(在 < 之前的部分)
155
+ const genericStart = structure.sourceText.indexOf('<');
156
+ if (genericStart > 0) {
157
+ const containerName = structure.sourceText.substring(0, genericStart);
158
+ const argsText = structure.args.map(arg => arg.sourceText).join(', ');
159
+ return `${containerName}<${argsText}>`;
160
+ }
161
+
162
+ // 其他情况保持原样
163
+ return structure.sourceText;
164
+ }
165
+
116
166
  private static collectDependenciesFromChildren(children: TypeStructure): TypeDependency[] {
117
167
  const allDependencies: TypeDependency[] = [];
118
168
 
@@ -13,7 +13,7 @@
13
13
  * limitations under the License.
14
14
  */
15
15
 
16
- import { Project, ProjectOptions, TypeChecker } from 'ts-morph';
16
+ import { IndentationText, Project, ProjectOptions, QuoteKind, TypeChecker } from 'ts-morph';
17
17
  import { Logger } from '../logger/Logger';
18
18
 
19
19
  export class TsMorphUtil {
@@ -24,6 +24,10 @@ export class TsMorphUtil {
24
24
  Logger.info('创建ts-morph项目');
25
25
  this.project = new Project(
26
26
  options || {
27
+ manipulationSettings: {
28
+ indentationText: IndentationText.TwoSpaces,
29
+ quoteKind: QuoteKind.Single
30
+ },
27
31
  compilerOptions: {
28
32
  allowNonTsExtensions: true
29
33
  }
@@ -16,7 +16,6 @@
16
16
  import { ITask, Logger, ImportRewriteServiceImpl, ConfigManager, CodeGenerationEngine } from '../../core';
17
17
  import { BuildProfileUpdaterImpl } from '../../core/import-rewrite/services/BuildProfileUpdater';
18
18
  import { ITargetContext } from '../interfaces/ITargetContext';
19
- import {logger} from 'handlebars';
20
19
  import {TaskConstants} from '../constants/TaskConstants';
21
20
  import SerializationPathUtil from '../../core/utils/SerializationPathUtil';
22
21
 
@@ -7,13 +7,13 @@ deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.g
7
7
  const result = new {{class.className}}{{#if class.generics.isGeneric}}<{{genericParametersString class.generics.parameters}}>{{/if}}(
8
8
  {{#each (getCtorProperties class.constructorParams properties)}}
9
9
  {{#unless analysis.decorators.isTransient}}
10
- {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{#unless @last}},{{/unless}}
10
+ {{#if analysis.decorators.isPlainValue}}plain[keys[{{getPropertyIndex this ../properties}}]]{{else}}{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{/if}}{{#unless @last}},{{/unless}}
11
11
  {{/unless}}
12
12
  {{/each}});
13
13
  {{else}}
14
14
  const result: ESObject = {};
15
15
  {{/if}}
16
-
16
+
17
17
 
18
18
  {{! 可选属性赋值(构造函数外的属性)}}
19
19
  {{#each (postConstructorAssignments class.constructorParams properties)}}
@@ -21,12 +21,22 @@ deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.g
21
21
  const {{analysis.name}}PlainValue: ESObject = plain[keys[{{getPropertyIndex this ../properties}}]];
22
22
  {{#if analysis.defaultValue}}
23
23
  {{! 有默认值的属性 }}
24
+ {{#if (eq analysis.visibility "private")}}
25
+ ObjectUtils.setProp(result, '{{analysis.name}}', {{analysis.name}}PlainValue === undefined ? {{analysis.defaultValue}} :
26
+ {{#if analysis.decorators.isPlainValue}}plain[keys[{{getPropertyIndex this ../properties}}]]{{else}}{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{/if}});
27
+ {{else}}
24
28
  result.{{analysis.name}} = {{analysis.name}}PlainValue === undefined ? {{analysis.defaultValue}} :
25
- {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
29
+ {{#if analysis.decorators.isPlainValue}}plain[keys[{{getPropertyIndex this ../properties}}]]{{else}}{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{/if}};
30
+ {{/if}}
26
31
  {{else}}
27
32
  {{! 无默认值的属性 }}
33
+ {{#if (eq analysis.visibility "private")}}
34
+ ObjectUtils.setProp(result, '{{analysis.name}}', {{analysis.name}}PlainValue === undefined ? undefined :
35
+ {{#if analysis.decorators.isPlainValue}}plain[keys[{{getPropertyIndex this ../properties}}]]{{else}}{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{/if}});
36
+ {{else}}
28
37
  result.{{analysis.name}} = {{analysis.name}}PlainValue === undefined ? undefined :
29
- {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
38
+ {{#if analysis.decorators.isPlainValue}}plain[keys[{{getPropertyIndex this ../properties}}]]{{else}}{{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}decoder.{{serializer.decodeMethod}}(plain[keys[{{getPropertyIndex this ../properties}}]]){{else}}this.{{analysis.name}}Serializer.deserialize(decoder, plain[keys[{{getPropertyIndex this ../properties}}]]){{/if}}{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}}{{/if}};
39
+ {{/if}}
30
40
  {{/if}}
31
41
  {{/unless}}
32
42
  {{/each}}
@@ -27,11 +27,15 @@ deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.g
27
27
  {{#each properties}}
28
28
  case {{@index}}:
29
29
  {{analysis.name}}Seen = true;
30
+ {{#if analysis.decorators.isPlainValue}}
31
+ {{analysis.name}}Value = value;
32
+ {{else}}
30
33
  {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
31
34
  {{analysis.name}}Value = decoder.{{serializer.decodeMethod}}(value);
32
35
  {{else}}
33
36
  {{analysis.name}}Value = this.{{analysis.name}}Serializer.deserialize(decoder, value){{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
34
37
  {{/if}}
38
+ {{/if}}
35
39
  break;
36
40
  {{/each}}
37
41
  case DecodedElementIndex.UNKNOWN_NAME:
@@ -80,7 +84,11 @@ deserialize(decoder: Decoder, plain: ESObject): {{class.className}}{{#if class.g
80
84
  {{#each (postConstructorAssignments class.constructorParams properties)}}
81
85
  {{#unless analysis.decorators.isTransient}}
82
86
  if ({{analysis.name}}Seen) {
87
+ {{#if (eq analysis.visibility "private")}}
88
+ ObjectUtils.setProp(result, '{{analysis.name}}', {{analysis.name}}Value!{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}});
89
+ {{else}}
83
90
  result.{{analysis.name}} = {{analysis.name}}Value!{{#if serializer.needsTypeAssertion}} as {{analysis.type.sourceText}}{{/if}};
91
+ {{/if}}
84
92
  }
85
93
  {{/unless}}
86
94
  {{/each}}
@@ -121,21 +121,29 @@ export class {{class.className}}Serializer extends Serializer<{{class.className}
121
121
  {{/if}}
122
122
  }
123
123
 
124
- private innerSerialize(encoder: Encoder, value: {{#if class.generics.isGeneric}}{{class.className}}<{{genericParametersString class.generics.parameters}}>{{else}}{{class.className}}{{/if}}): ESObject {
124
+ private innerSerialize(encoder: Encoder, value: {{#if class.generics.isGeneric}}{{class.className}}<{{genericParametersString class.generics.parameters}}>{{else}}{{class.className}}{{/if}}): ESObject {
125
125
  const keys = this.serialDescriptor.elementNames;
126
126
  const result = encoder.newObject();
127
127
  {{#each properties}}
128
- {{! 根据类型选择编码方法 }}
129
- {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
130
- encoder.{{serializer.encodeMethod}}(result, keys[{{@index}}], value.{{analysis.name}});
128
+ {{! 根据类型选择编码方法 }}
129
+ {{#if (eq analysis.visibility "private")}}
130
+ {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
131
+ encoder.{{serializer.encodeMethod}}(result, keys[{{@index}}], ObjectUtils.getProp(value, '{{analysis.name}}'));
132
+ {{else}}
133
+ encoder.encodeSerializableElement(result, keys[{{@index}}], this.{{analysis.name}}Serializer, ObjectUtils.getProp(value, '{{analysis.name}}'));
134
+ {{/if}}
131
135
  {{else}}
132
- encoder.encodeSerializableElement(result, keys[{{@index}}], this.{{analysis.name}}Serializer, value.{{analysis.name}});
136
+ {{#if (and (eqPrimitiveType analysis.type.kind) (not (hasDecoratorWith analysis.decorators)))}}
137
+ encoder.{{serializer.encodeMethod}}(result, keys[{{@index}}], value.{{analysis.name}});
138
+ {{else}}
139
+ encoder.encodeSerializableElement(result, keys[{{@index}}], this.{{analysis.name}}Serializer, value.{{analysis.name}});
140
+ {{/if}}
133
141
  {{/if}}
134
142
  {{/each}}
135
143
 
136
144
  return result;
137
145
  }
138
-
146
+
139
147
  {{! 动态包含反序列化模板 - 使用从上下文传递的deserializeTemplate参数 }}
140
148
  {{> (lookup . "deserializeTemplate")}}
141
149
  }