@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.
Files changed (88) 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.d.ts +15 -0
  5. package/dist/core/analyzers/ClassAnalyzer.js +200 -120
  6. package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +3 -0
  7. package/dist/core/analyzers/CustomTypeAnalyzer.js +65 -60
  8. package/dist/core/constants/DecoratorConstants.d.ts +1 -0
  9. package/dist/core/constants/DecoratorConstants.js +3 -1
  10. package/dist/core/handlers/CustomClassHandler.js +0 -1
  11. package/dist/core/import-rewrite/services/BuildProfileUpdater.js +1 -1
  12. package/dist/core/import-rewrite/services/ImportRewriteService.js +1 -1
  13. package/dist/core/interfaces/index.d.ts +2 -2
  14. package/dist/core/services/CodeAnalysisService.js +2 -1
  15. package/dist/core/services/CodeGenerationService/CodeGenerationService.js +1 -1
  16. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +0 -1
  17. package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +0 -20
  18. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +4 -4
  19. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +26 -45
  20. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +22 -0
  21. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +194 -129
  22. package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +20 -15
  23. package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +2 -1
  24. package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +2 -2
  25. package/dist/core/template/HandlebarsTemplateEngine.d.ts +2 -0
  26. package/dist/core/template/HandlebarsTemplateEngine.js +24 -2
  27. package/dist/core/utils/DeepCopyUtil.js +4 -2
  28. package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +1 -0
  29. package/dist/core/utils/GenericTypeSubstitutionUtil.js +27 -1
  30. package/dist/core/utils/SerializationPathUtil.d.ts +1 -1
  31. package/dist/core/utils/TsMorphUtil.js +6 -1
  32. package/dist/json-plugin/JSONExecuteController.d.ts +4 -0
  33. package/dist/json-plugin/JSONExecuteController.js +46 -36
  34. package/dist/json-plugin/interfaces/impl/TargetContext.js +4 -2
  35. package/dist/json-plugin/tasks/BaseTask.d.ts +2 -2
  36. package/dist/json-plugin/tasks/WatchTask.js +2 -1
  37. package/package.json +1 -1
  38. package/src/core/Types.ts +97 -89
  39. package/src/core/analyzers/ClassAnalyzer.ts +358 -197
  40. package/src/core/analyzers/CustomTypeAnalyzer.ts +145 -74
  41. package/src/core/constants/DecoratorConstants.ts +7 -5
  42. package/src/core/constants/PathConstants.ts +7 -7
  43. package/src/core/constants/StringConstants.ts +95 -97
  44. package/src/core/handlers/BaseTypeHandler.ts +11 -2
  45. package/src/core/handlers/CustomClassHandler.ts +4 -7
  46. package/src/core/handlers/DateHandler.ts +54 -46
  47. package/src/core/handlers/DecimalHandler.ts +53 -45
  48. package/src/core/handlers/EnumHandler.ts +2 -1
  49. package/src/core/handlers/GenericContainerHandler.ts +3 -1
  50. package/src/core/handlers/TupleHandler.ts +2 -1
  51. package/src/core/handlers/TypeHandlerRegistry.ts +3 -2
  52. package/src/core/handlers/UnionTypeHandler.ts +8 -7
  53. package/src/core/import-rewrite/services/BuildProfileUpdater.ts +7 -5
  54. package/src/core/import-rewrite/services/ImportRewriteService.ts +1 -3
  55. package/src/core/import-rewrite/services/ImportTransformService.ts +2 -2
  56. package/src/core/import-rewrite/types/ImportRewriteTypes.ts +3 -3
  57. package/src/core/index.ts +4 -4
  58. package/src/core/interfaces/ITask.ts +6 -5
  59. package/src/core/interfaces/ITaskContext.ts +9 -9
  60. package/src/core/interfaces/index.ts +2 -2
  61. package/src/core/logger/Logger.ts +28 -28
  62. package/src/core/services/CodeAnalysisService.ts +3 -2
  63. package/src/core/services/CodeGenerationEngine.ts +42 -42
  64. package/src/core/services/CodeGenerationService/CodeGenerationService.ts +1 -2
  65. package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +0 -29
  66. package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +31 -64
  67. package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +261 -170
  68. package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +26 -19
  69. package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +5 -3
  70. package/src/core/services/CodeGenerationService/shared/ImportManager.ts +8 -8
  71. package/src/core/template/HandlebarsTemplateEngine.ts +43 -10
  72. package/src/core/utils/ConfigManager.ts +2 -1
  73. package/src/core/utils/DeepCopyUtil.ts +4 -2
  74. package/src/core/utils/GenericTypeSubstitutionUtil.ts +45 -2
  75. package/src/core/utils/SerializationPathUtil.ts +7 -6
  76. package/src/core/utils/TsMorphUtil.ts +9 -2
  77. package/src/index.ts +2 -2
  78. package/src/json-plugin/JSONExecuteController.ts +51 -38
  79. package/src/json-plugin/interfaces/IModuleContext.ts +8 -8
  80. package/src/json-plugin/interfaces/ITargetContext.ts +6 -6
  81. package/src/json-plugin/interfaces/impl/ModuleContext.ts +10 -10
  82. package/src/json-plugin/interfaces/impl/TargetContext.ts +63 -58
  83. package/src/json-plugin/tasks/BaseTask.ts +5 -4
  84. package/src/json-plugin/tasks/CleanTask.ts +7 -7
  85. package/src/json-plugin/tasks/WatchTask.ts +20 -18
  86. package/template/SerializerPerformanceTemplate.hbs +14 -4
  87. package/template/SerializerStrictTemplate.hbs +9 -1
  88. package/template/SerializerTemplate.hbs +71 -46
package/README.md CHANGED
@@ -23,7 +23,7 @@ TurboTransJSONPlugin 是一个基于 Hvigor 构建系统的编译时插件,专
23
23
  {
24
24
  "modelVersion": "6.0.0",
25
25
  "dependencies": {
26
- "@hadss/turbo-trans-json-plugin": "^1.0.0",
26
+ "@hadss/turbo-trans-json-plugin": "latest",
27
27
  // 使用npm仓版本号
28
28
  }
29
29
  // ...其余配置
@@ -90,11 +90,18 @@ export interface PropertyAnalysis {
90
90
  decorators?: PropertyDecorators;
91
91
  isMust: boolean;
92
92
  type: TypeStructure;
93
+ visibility: PropertyVisibility;
94
+ }
95
+ export declare enum PropertyVisibility {
96
+ PUBLIC = "public",
97
+ PRIVATE = "private",
98
+ PROTECTED = "protected"
93
99
  }
94
100
  export interface PropertyDecorators {
95
101
  serialName?: string;
96
102
  isRequired: boolean;
97
103
  isTransient: boolean;
104
+ isPlainValue: boolean;
98
105
  with?: string;
99
106
  }
100
107
  export interface TypeStructure {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TypeKind = exports.DeserializationMode = exports.PropertyKind = void 0;
3
+ exports.TypeKind = exports.PropertyVisibility = exports.DeserializationMode = exports.PropertyKind = void 0;
4
4
  var PropertyKind;
5
5
  (function (PropertyKind) {
6
6
  PropertyKind["STRING"] = "string";
@@ -38,6 +38,12 @@ var DeserializationMode;
38
38
  DeserializationMode["PERFORMANCE"] = "performance";
39
39
  DeserializationMode["STRICT"] = "strict";
40
40
  })(DeserializationMode || (exports.DeserializationMode = DeserializationMode = {}));
41
+ var PropertyVisibility;
42
+ (function (PropertyVisibility) {
43
+ PropertyVisibility["PUBLIC"] = "public";
44
+ PropertyVisibility["PRIVATE"] = "private";
45
+ PropertyVisibility["PROTECTED"] = "protected";
46
+ })(PropertyVisibility || (exports.PropertyVisibility = PropertyVisibility = {}));
41
47
  var TypeKind;
42
48
  (function (TypeKind) {
43
49
  TypeKind["CLASS"] = "class";
@@ -6,12 +6,25 @@ export declare class ClassAnalyzer {
6
6
  private static analyzeInheritanceInfo;
7
7
  private static analyzeConstructorParameters;
8
8
  private static parseSerializableOptions;
9
+ private static extractOptionsFromObjectLiteral;
10
+ private static extractSingleOption;
11
+ private static parseBooleanInitializer;
12
+ private static parseDeserializationMode;
9
13
  private static parseSerialNameOptions;
14
+ private static extractNameFromProperties;
10
15
  private static analyzeOwnProperties;
16
+ private static checkUnknownType;
11
17
  private static classifyProperties;
18
+ private static buildPropertyClassification;
12
19
  private static collectAllAncestorProperties;
20
+ private static collectAncestorPropertiesRecursively;
21
+ private static resolveGenericTypeArgs;
13
22
  private static extractConstructorParams;
14
23
  private static createPropertyAnalysis;
24
+ private static getTypeNode;
25
+ private static getPropertyVisibility;
26
+ private static calculateIsMust;
27
+ private static validateTransientConstructorParam;
15
28
  private static analyzePropertyType;
16
29
  private static simplifyImportType;
17
30
  private static getTypeFromInitializer;
@@ -20,4 +33,6 @@ export declare class ClassAnalyzer {
20
33
  private static hasUndefinedInUnion;
21
34
  private static splitUnionType;
22
35
  private static analyzePropertyDecorators;
36
+ private static checkTransientConflicts;
37
+ private static checkPlainValueConflicts;
23
38
  }
@@ -118,41 +118,54 @@ class ClassAnalyzer {
118
118
  return undefined;
119
119
  }
120
120
  const args = decorator.getArguments();
121
- let generateSendable;
122
- let _with;
123
- let deserializationMode;
124
121
  const firstArg = args[0];
125
- if (!firstArg) {
122
+ if (!firstArg || firstArg.getKind() !== ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
126
123
  return {};
127
124
  }
128
- if (firstArg.getKind() === ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
129
- const properties = firstArg.asKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression).getProperties();
130
- for (const prop of properties) {
131
- if (prop.getKind() === ts_morph_1.SyntaxKind.PropertyAssignment) {
132
- const propAssignment = prop.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAssignment);
133
- const propertyName = propAssignment.getName();
134
- const initializer = propAssignment.getInitializer();
135
- if (propertyName === 'generateSendable' && initializer) {
136
- if (initializer.getKind() === ts_morph_1.SyntaxKind.TrueKeyword) {
137
- generateSendable = true;
138
- }
139
- else if (initializer.getKind() === ts_morph_1.SyntaxKind.FalseKeyword) {
140
- generateSendable = false;
141
- }
142
- }
143
- else if (propertyName === 'with' && initializer) {
144
- _with = initializer.getText();
145
- }
146
- else if (propertyName === 'deserializationMode' && initializer) {
147
- const modeText = initializer.getText().replace(/['"]/g, '');
148
- if (modeText === Types_1.DeserializationMode.PERFORMANCE || modeText === Types_1.DeserializationMode.STRICT) {
149
- deserializationMode = modeText;
150
- }
151
- }
152
- }
125
+ return this.extractOptionsFromObjectLiteral(firstArg.asKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression));
126
+ }
127
+ static extractOptionsFromObjectLiteral(objectLiteral) {
128
+ const options = {};
129
+ const properties = objectLiteral.getProperties();
130
+ for (const prop of properties) {
131
+ if (prop.getKind() !== ts_morph_1.SyntaxKind.PropertyAssignment) {
132
+ continue;
133
+ }
134
+ const propAssignment = prop.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAssignment);
135
+ const initializer = propAssignment.getInitializer();
136
+ if (!initializer) {
137
+ continue;
153
138
  }
139
+ this.extractSingleOption(options, propAssignment.getName(), initializer);
140
+ }
141
+ return options;
142
+ }
143
+ static extractSingleOption(options, propertyName, initializer) {
144
+ if (propertyName === 'generateSendable') {
145
+ options.generateSendable = this.parseBooleanInitializer(initializer);
146
+ }
147
+ else if (propertyName === 'with') {
148
+ options.with = initializer.getText();
149
+ }
150
+ else if (propertyName === 'deserializationMode') {
151
+ this.parseDeserializationMode(options, initializer);
152
+ }
153
+ }
154
+ static parseBooleanInitializer(initializer) {
155
+ const kind = initializer.getKind();
156
+ if (kind === ts_morph_1.SyntaxKind.TrueKeyword) {
157
+ return true;
158
+ }
159
+ if (kind === ts_morph_1.SyntaxKind.FalseKeyword) {
160
+ return false;
161
+ }
162
+ return undefined;
163
+ }
164
+ static parseDeserializationMode(options, initializer) {
165
+ const modeText = initializer.getText().replace(/['"]/g, '');
166
+ if (modeText === Types_1.DeserializationMode.PERFORMANCE || modeText === Types_1.DeserializationMode.STRICT) {
167
+ options.deserializationMode = modeText;
154
168
  }
155
- return { with: _with, generateSendable, deserializationMode };
156
169
  }
157
170
  static parseSerialNameOptions(decorator) {
158
171
  if (!decorator) {
@@ -163,21 +176,26 @@ class ClassAnalyzer {
163
176
  return undefined;
164
177
  }
165
178
  const firstArg = args[0];
166
- if (firstArg.getKind() === ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
167
- const properties = firstArg.asKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression).getProperties();
168
- for (const prop of properties) {
169
- if (prop.getKind() === ts_morph_1.SyntaxKind.PropertyAssignment) {
170
- const propAssignment = prop.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAssignment);
171
- const name = propAssignment.getName();
172
- if (name === 'name') {
173
- const initializer = propAssignment.getInitializer();
174
- if (initializer && initializer.getKind() === ts_morph_1.SyntaxKind.StringLiteral) {
175
- const stringLiteral = initializer.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral);
176
- return stringLiteral.getLiteralValue();
177
- }
178
- }
179
- }
179
+ if (firstArg.getKind() !== ts_morph_1.SyntaxKind.ObjectLiteralExpression) {
180
+ return undefined;
181
+ }
182
+ const properties = firstArg.asKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression).getProperties();
183
+ return this.extractNameFromProperties(properties);
184
+ }
185
+ static extractNameFromProperties(properties) {
186
+ for (const prop of properties) {
187
+ if (prop.getKind() !== ts_morph_1.SyntaxKind.PropertyAssignment) {
188
+ continue;
180
189
  }
190
+ const propAssignment = prop.asKindOrThrow(ts_morph_1.SyntaxKind.PropertyAssignment);
191
+ if (propAssignment.getName() !== 'name') {
192
+ continue;
193
+ }
194
+ const initializer = propAssignment.getInitializer();
195
+ if (!initializer || initializer.getKind() !== ts_morph_1.SyntaxKind.StringLiteral) {
196
+ continue;
197
+ }
198
+ return initializer.asKindOrThrow(ts_morph_1.SyntaxKind.StringLiteral).getLiteralValue();
181
199
  }
182
200
  return undefined;
183
201
  }
@@ -186,29 +204,34 @@ class ClassAnalyzer {
186
204
  const props = cls.getProperties();
187
205
  for (const prop of props) {
188
206
  const propertyAnalysis = this.createPropertyAnalysis(prop, constructorParams, genericParameters);
189
- if (propertyAnalysis.type.kind === Types_1.PropertyKind.UNKNOWN) {
190
- const hasTransient = propertyAnalysis.decorators?.isTransient;
191
- const hasCustomSerializer = !!propertyAnalysis.decorators?.with;
192
- if (!hasTransient && !hasCustomSerializer) {
193
- if (prop instanceof ts_morph_1.PropertyDeclaration) {
194
- throw new CustomError_1.CustomError(`不支持的类型 '${propertyAnalysis.type.sourceText}' 用于属性 '${propertyAnalysis.name}' (类: ${cls.getName()})。\n` +
195
- `请选择以下任一解决方案:\n` +
196
- ` 1. 添加 @Transient() 跳过序列化(属性仍会参与 Sendable 转换和对象拷贝):\n` +
197
- ` @Transient()\n` +
198
- ` ${propertyAnalysis.name}: ${propertyAnalysis.type.sourceText};\n\n` +
199
- ` 2. 添加 @Serializable({with: CustomSerializer}) 指定自定义序列化器:\n` +
200
- ` @Serializable({with: DateSerializer.INSTANCE})\n` +
201
- ` ${propertyAnalysis.name}: ${propertyAnalysis.type.sourceText};`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
202
- }
203
- else {
204
- throw new CustomError_1.CustomError(`不支持的类型 '${propertyAnalysis.type.sourceText}' 用于属性 '${propertyAnalysis.name}' (接口: ${cls.getName()})`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
205
- }
206
- }
207
- }
207
+ this.checkUnknownType(cls, prop, propertyAnalysis);
208
208
  ownProperties.push(propertyAnalysis);
209
209
  }
210
210
  return ownProperties;
211
211
  }
212
+ static checkUnknownType(cls, prop, propertyAnalysis) {
213
+ if (propertyAnalysis.type.kind !== Types_1.PropertyKind.UNKNOWN) {
214
+ return;
215
+ }
216
+ const hasTransient = propertyAnalysis.decorators?.isTransient;
217
+ const hasCustomSerializer = !!propertyAnalysis.decorators?.with;
218
+ if (hasTransient || hasCustomSerializer) {
219
+ return;
220
+ }
221
+ if (prop instanceof ts_morph_1.PropertyDeclaration) {
222
+ throw new CustomError_1.CustomError(`不支持的类型 '${propertyAnalysis.type.sourceText}' 用于属性 '${propertyAnalysis.name}' (类: ${cls.getName()})。\n` +
223
+ `请选择以下任一解决方案:\n` +
224
+ ` 1. 添加 @Transient() 跳过序列化(属性仍会参与 Sendable 转换和对象拷贝):\n` +
225
+ ` @Transient()\n` +
226
+ ` ${propertyAnalysis.name}: ${propertyAnalysis.type.sourceText};\n\n` +
227
+ ` 2. 添加 @Serializable({with: CustomSerializer}) 指定自定义序列化器:\n` +
228
+ ` @Serializable({with: DateSerializer.INSTANCE})\n` +
229
+ ` ${propertyAnalysis.name}: ${propertyAnalysis.type.sourceText};`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
230
+ }
231
+ else {
232
+ throw new CustomError_1.CustomError(`不支持的类型 '${propertyAnalysis.type.sourceText}' 用于属性 '${propertyAnalysis.name}' (接口: ${cls.getName()})`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
233
+ }
234
+ }
212
235
  static classifyProperties(ownProperties, inheritance, currentClassGenericParams = []) {
213
236
  if (!inheritance.isInherited || !inheritance.baseClassAnalysis) {
214
237
  return {
@@ -218,20 +241,14 @@ class ClassAnalyzer {
218
241
  };
219
242
  }
220
243
  const allAncestorProperties = this.collectAllAncestorProperties(inheritance.baseClassAnalysis, inheritance.genericTypeArguments || [], currentClassGenericParams);
244
+ return this.buildPropertyClassification(ownProperties, allAncestorProperties);
245
+ }
246
+ static buildPropertyClassification(ownProperties, allAncestorProperties) {
221
247
  const ownPropertyNames = new Set(ownProperties.map((prop) => prop.name));
222
- const inheritedProperties = [];
223
- for (const ancestorProp of allAncestorProperties) {
224
- if (!ownPropertyNames.has(ancestorProp.name)) {
225
- inheritedProperties.push(ancestorProp);
226
- }
227
- }
248
+ const inheritedProperties = allAncestorProperties.filter((ancestorProp) => !ownPropertyNames.has(ancestorProp.name));
228
249
  const overriddenProperties = ownProperties.filter((prop) => allAncestorProperties.some((ancestorProp) => ancestorProp.name === prop.name));
229
250
  const properties = [...inheritedProperties, ...ownProperties];
230
- return {
231
- inheritedProperties,
232
- overriddenProperties,
233
- properties
234
- };
251
+ return { inheritedProperties, overriddenProperties, properties };
235
252
  }
236
253
  static collectAllAncestorProperties(classAnalysis, childGenericArguments = [], currentClassGenericParams = []) {
237
254
  const allProperties = [];
@@ -239,12 +256,31 @@ class ClassAnalyzer {
239
256
  const genericMapping = GenericTypeSubstitutionUtil_1.GenericTypeSubstitutionUtil.buildGenericMapping(parentGenericParams, childGenericArguments);
240
257
  const substitutedProperties = classAnalysis.ownProperties.map((property) => GenericTypeSubstitutionUtil_1.GenericTypeSubstitutionUtil.substitutePropertyType(property, genericMapping, currentClassGenericParams));
241
258
  allProperties.push(...substitutedProperties);
242
- if (classAnalysis.inheritance.isInherited && classAnalysis.inheritance.baseClassAnalysis) {
243
- const ancestorProperties = this.collectAllAncestorProperties(classAnalysis.inheritance.baseClassAnalysis, classAnalysis.inheritance.genericTypeArguments || [], currentClassGenericParams);
244
- allProperties.push(...ancestorProperties);
245
- }
259
+ this.collectAncestorPropertiesRecursively(classAnalysis, parentGenericParams, genericMapping, currentClassGenericParams, allProperties);
246
260
  return allProperties;
247
261
  }
262
+ static collectAncestorPropertiesRecursively(classAnalysis, parentGenericParams, genericMapping, currentClassGenericParams, allProperties) {
263
+ if (!classAnalysis.inheritance.isInherited || !classAnalysis.inheritance.baseClassAnalysis) {
264
+ return;
265
+ }
266
+ const parentGenericTypeArgs = classAnalysis.inheritance.genericTypeArguments || [];
267
+ const resolvedParentGenericArgs = this.resolveGenericTypeArgs(parentGenericTypeArgs, parentGenericParams, genericMapping);
268
+ Logger_1.Logger.debug(`[CollectAncestors] Resolved parent generic args: ${resolvedParentGenericArgs.map(a => a.getText()).join(', ')}`);
269
+ const ancestorProperties = this.collectAllAncestorProperties(classAnalysis.inheritance.baseClassAnalysis, resolvedParentGenericArgs, currentClassGenericParams);
270
+ allProperties.push(...ancestorProperties);
271
+ }
272
+ static resolveGenericTypeArgs(typeArgs, parentGenericParams, genericMapping) {
273
+ return typeArgs.map(typeArg => {
274
+ const typeStructure = handlers_1.TypeHandlerRegistry.getInstance().parseType(typeArg, {
275
+ depth: 0,
276
+ genericParams: parentGenericParams
277
+ });
278
+ if (typeStructure.kind === Types_1.PropertyKind.GENERIC && genericMapping.has(typeStructure.sourceText)) {
279
+ return genericMapping.get(typeStructure.sourceText);
280
+ }
281
+ return typeArg;
282
+ });
283
+ }
248
284
  static extractConstructorParams(constructor) {
249
285
  const parameters = [];
250
286
  for (const param of constructor.getParameters()) {
@@ -259,44 +295,66 @@ class ClassAnalyzer {
259
295
  }
260
296
  static createPropertyAnalysis(prop, constructorParams, genericParameters) {
261
297
  const name = prop.getName();
298
+ const typeNode = this.getTypeNode(prop);
299
+ const type = handlers_1.TypeHandlerRegistry.getInstance().parseType(typeNode, { genericParams: genericParameters, depth: 0 });
300
+ type.isOptional = prop.hasQuestionToken();
301
+ const defaultValue = prop instanceof ts_morph_1.PropertyDeclaration ?
302
+ this.analyzeDefaultValue(prop, constructorParams) : undefined;
303
+ const decorators = prop instanceof ts_morph_1.PropertyDeclaration ? this.analyzePropertyDecorators(prop) : undefined;
304
+ const visibility = this.getPropertyVisibility(prop);
305
+ const constructorParam = constructorParams.find((param) => param.name === name);
306
+ const isMust = this.calculateIsMust(prop, type, constructorParam, decorators, defaultValue);
307
+ if (decorators?.isTransient && constructorParam) {
308
+ this.validateTransientConstructorParam(name, constructorParam);
309
+ }
310
+ return {
311
+ name,
312
+ defaultValue,
313
+ decorators,
314
+ type,
315
+ isMust,
316
+ visibility
317
+ };
318
+ }
319
+ static getTypeNode(prop) {
262
320
  let typeNode = prop.getTypeNode();
263
321
  if (!typeNode) {
264
322
  typeNode = this.analyzePropertyType(prop);
265
323
  }
266
324
  if (!typeNode) {
267
- throw new CustomError_1.CustomError(`无法分析属性 '${name}' 的类型。请检查属性声明。`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
325
+ throw new CustomError_1.CustomError(`无法分析属性 '${prop.getName()}' 的类型。请检查属性声明。`, CustomError_1.ErrorCodes.TYPE_NOT_SUPPORT);
268
326
  }
269
- const defaultValue = prop instanceof ts_morph_1.PropertyDeclaration ? this.analyzeDefaultValue(prop, constructorParams) : undefined;
270
- const decorators = prop instanceof ts_morph_1.PropertyDeclaration ? this.analyzePropertyDecorators(prop) : undefined;
271
- const type = handlers_1.TypeHandlerRegistry.getInstance().parseType(typeNode, { genericParams: genericParameters, depth: 0 });
272
- type.isOptional = prop.hasQuestionToken();
273
- const constructorParam = constructorParams.find((param) => param.name === name);
274
- const isParamOptional = constructorParam
275
- ? constructorParam.isOptional ||
276
- constructorParam.defaultValue !== undefined ||
277
- this.hasUndefinedInUnion(constructorParam.type)
278
- : true;
279
- let isMust;
280
- if (constructorParam) {
281
- isMust = !isParamOptional;
327
+ return typeNode;
328
+ }
329
+ static getPropertyVisibility(prop) {
330
+ if (prop.hasModifier(ts_morph_1.SyntaxKind.PrivateKeyword)) {
331
+ return Types_1.PropertyVisibility.PRIVATE;
282
332
  }
283
- else {
284
- isMust = decorators?.isRequired || !this.isOptional(prop, defaultValue, type);
333
+ if (prop.hasModifier(ts_morph_1.SyntaxKind.ProtectedKeyword)) {
334
+ return Types_1.PropertyVisibility.PROTECTED;
285
335
  }
286
- if (decorators?.isTransient && constructorParam && !isParamOptional) {
336
+ return Types_1.PropertyVisibility.PUBLIC;
337
+ }
338
+ static calculateIsMust(prop, type, constructorParam, decorators, defaultValue) {
339
+ if (constructorParam) {
340
+ const isParamOptional = constructorParam.isOptional ||
341
+ constructorParam.defaultValue !== undefined ||
342
+ this.hasUndefinedInUnion(constructorParam.type);
343
+ return !isParamOptional;
344
+ }
345
+ return decorators?.isRequired || !this.isOptional(prop, defaultValue, type);
346
+ }
347
+ static validateTransientConstructorParam(name, constructorParam) {
348
+ const isParamOptional = constructorParam.isOptional ||
349
+ constructorParam.defaultValue !== undefined ||
350
+ this.hasUndefinedInUnion(constructorParam.type);
351
+ if (!isParamOptional) {
287
352
  throw new CustomError_1.CustomError(`@Transient 属性 '${name}' 的构造函数参数必须是可选的或有默认值。\n` +
288
353
  `因为 @Transient 属性不参与序列化,反序列化时无法从外部数据获取值。\n` +
289
354
  `请修改构造函数参数为以下任一形式:\n` +
290
355
  ` 1. 可选参数: constructor(..., ${name}?: ${constructorParam.type})\n` +
291
356
  ` 2. 带默认值: constructor(..., ${name}: ${constructorParam.type} = defaultValue)`, CustomError_1.ErrorCodes.TRANSIENT_ATTR_OPTIONAL);
292
357
  }
293
- return {
294
- name,
295
- defaultValue,
296
- decorators,
297
- type,
298
- isMust
299
- };
300
358
  }
301
359
  static analyzePropertyType(prop) {
302
360
  const name = prop.getName();
@@ -352,7 +410,8 @@ class ClassAnalyzer {
352
410
  return undefined;
353
411
  }
354
412
  const exprText = expression.getText();
355
- const supportedTypes = ['Map', 'Set', 'WeakMap', 'WeakSet', 'Array', 'Object', 'ArrayList', 'HashMap', 'HashSet', 'LinkedList', 'Decimal', 'List'];
413
+ const supportedTypes = ['Map', 'Set', 'WeakMap', 'WeakSet', 'Array', 'Object', 'ArrayList', 'HashMap', 'HashSet',
414
+ 'LinkedList', 'Decimal', 'List'];
356
415
  if (!supportedTypes.includes(exprText)) {
357
416
  return undefined;
358
417
  }
@@ -434,6 +493,7 @@ class ClassAnalyzer {
434
493
  const decorators = prop.getDecorators();
435
494
  let isRequired = false;
436
495
  let isTransient = false;
496
+ let isPlainValue = false;
437
497
  let serialName;
438
498
  let _with;
439
499
  decorators.forEach((decorator) => {
@@ -448,33 +508,53 @@ class ClassAnalyzer {
448
508
  case constants_1.DecoratorConstants.TRANSIENT:
449
509
  isTransient = true;
450
510
  break;
511
+ case constants_1.DecoratorConstants.PLAIN_VALUE:
512
+ isPlainValue = true;
513
+ break;
451
514
  case constants_1.DecoratorConstants.SERIALIZABLE:
452
515
  _with = this.parseSerializableOptions(decorator).with;
516
+ break;
453
517
  }
454
518
  });
455
- if (isTransient) {
456
- const conflictingDecorators = [];
457
- if (isRequired) {
458
- conflictingDecorators.push('@Required');
459
- }
460
- if (serialName) {
461
- conflictingDecorators.push('@SerialName');
462
- }
463
- if (_with) {
464
- conflictingDecorators.push('@Serializable');
465
- }
466
- if (conflictingDecorators.length > 0) {
467
- throw new CustomError_1.CustomError(`属性 '${prop.getName()}' 的注解冲突:@Transient 与 ${conflictingDecorators.join(', ')} 不能同时使用。\n` +
468
- `@Transient 表示跳过序列化,与其他序列化配置注解互斥。\n` +
469
- `请移除 @Transient 或移除其他序列化注解。`, CustomError_1.ErrorCodes.ANNOTATION_CONFLICT);
470
- }
471
- }
519
+ this.checkTransientConflicts(prop.getName(), isTransient, isRequired, !!serialName, !!_with, isPlainValue);
520
+ this.checkPlainValueConflicts(prop.getName(), isPlainValue, !!_with);
472
521
  return {
473
522
  isRequired,
474
523
  isTransient,
524
+ isPlainValue,
475
525
  serialName,
476
526
  with: _with
477
527
  };
478
528
  }
529
+ static checkTransientConflicts(propName, isTransient, isRequired, hasSerialName, hasWith, isPlainValue) {
530
+ if (!isTransient) {
531
+ return;
532
+ }
533
+ const conflictingDecorators = [];
534
+ if (isRequired) {
535
+ conflictingDecorators.push('@Required');
536
+ }
537
+ if (hasSerialName) {
538
+ conflictingDecorators.push('@SerialName');
539
+ }
540
+ if (hasWith) {
541
+ conflictingDecorators.push('@Serializable');
542
+ }
543
+ if (isPlainValue) {
544
+ conflictingDecorators.push('@PlainValue');
545
+ }
546
+ if (conflictingDecorators.length > 0) {
547
+ throw new CustomError_1.CustomError(`属性 '${propName}' 的注解冲突:@Transient 与 ${conflictingDecorators.join(', ')} 不能同时使用。\n` +
548
+ `@Transient 表示跳过序列化,与其他序列化配置注解互斥。\n` +
549
+ `请移除 @Transient 或移除其他序列化注解。`, CustomError_1.ErrorCodes.ANNOTATION_CONFLICT);
550
+ }
551
+ }
552
+ static checkPlainValueConflicts(propName, isPlainValue, hasWith) {
553
+ if (isPlainValue && hasWith) {
554
+ throw new CustomError_1.CustomError(`属性 '${propName}' 的注解冲突:@PlainValue 与 @Serializable(with:) 不能同时使用。\n` +
555
+ `@PlainValue 跳过类型转换直接使用原始值,与自定义序列化器冲突。\n` +
556
+ `请移除 @PlainValue 或移除自定义序列化器。`, CustomError_1.ErrorCodes.ANNOTATION_CONFLICT);
557
+ }
558
+ }
479
559
  }
480
560
  exports.ClassAnalyzer = ClassAnalyzer;
@@ -10,9 +10,12 @@ export declare class CustomTypeAnalyzer {
10
10
  clearCache(): void;
11
11
  private findInCurrentFile;
12
12
  private findInImports;
13
+ private processImportMatch;
13
14
  private findInCrossModule;
14
15
  private searchInSourceFile;
15
16
  private parseEnumDetails;
17
+ private parseEnumMember;
18
+ private createStringEnumResult;
16
19
  private parseClassDetails;
17
20
  private parseInterfaceDetails;
18
21
  private parseTypeAliasDetails;