@hadss/turbo-trans-json-plugin 1.0.0-rc.0 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/core/Types.d.ts +7 -0
- package/dist/core/Types.js +7 -1
- package/dist/core/analyzers/ClassAnalyzer.d.ts +15 -0
- package/dist/core/analyzers/ClassAnalyzer.js +200 -120
- package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +3 -0
- package/dist/core/analyzers/CustomTypeAnalyzer.js +65 -60
- package/dist/core/constants/DecoratorConstants.d.ts +1 -0
- package/dist/core/constants/DecoratorConstants.js +3 -1
- package/dist/core/handlers/CustomClassHandler.js +0 -1
- package/dist/core/import-rewrite/services/BuildProfileUpdater.js +1 -1
- package/dist/core/import-rewrite/services/ImportRewriteService.js +1 -1
- package/dist/core/interfaces/index.d.ts +2 -2
- package/dist/core/services/CodeAnalysisService.js +2 -1
- package/dist/core/services/CodeGenerationService/CodeGenerationService.js +1 -1
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.d.ts +0 -1
- package/dist/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.js +0 -20
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +4 -4
- package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +26 -45
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +22 -0
- package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +194 -129
- package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +20 -15
- package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +2 -1
- package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +2 -2
- package/dist/core/template/HandlebarsTemplateEngine.d.ts +2 -0
- package/dist/core/template/HandlebarsTemplateEngine.js +24 -2
- package/dist/core/utils/DeepCopyUtil.js +4 -2
- package/dist/core/utils/GenericTypeSubstitutionUtil.d.ts +1 -0
- package/dist/core/utils/GenericTypeSubstitutionUtil.js +27 -1
- package/dist/core/utils/SerializationPathUtil.d.ts +1 -1
- package/dist/core/utils/TsMorphUtil.js +6 -1
- package/dist/json-plugin/JSONExecuteController.d.ts +4 -0
- package/dist/json-plugin/JSONExecuteController.js +46 -36
- package/dist/json-plugin/interfaces/impl/TargetContext.js +4 -2
- package/dist/json-plugin/tasks/BaseTask.d.ts +2 -2
- package/dist/json-plugin/tasks/WatchTask.js +2 -1
- package/package.json +1 -1
- package/src/core/Types.ts +97 -89
- package/src/core/analyzers/ClassAnalyzer.ts +358 -197
- package/src/core/analyzers/CustomTypeAnalyzer.ts +145 -74
- package/src/core/constants/DecoratorConstants.ts +7 -5
- package/src/core/constants/PathConstants.ts +7 -7
- package/src/core/constants/StringConstants.ts +95 -97
- package/src/core/handlers/BaseTypeHandler.ts +11 -2
- package/src/core/handlers/CustomClassHandler.ts +4 -7
- package/src/core/handlers/DateHandler.ts +54 -46
- package/src/core/handlers/DecimalHandler.ts +53 -45
- package/src/core/handlers/EnumHandler.ts +2 -1
- package/src/core/handlers/GenericContainerHandler.ts +3 -1
- package/src/core/handlers/TupleHandler.ts +2 -1
- package/src/core/handlers/TypeHandlerRegistry.ts +3 -2
- package/src/core/handlers/UnionTypeHandler.ts +8 -7
- package/src/core/import-rewrite/services/BuildProfileUpdater.ts +7 -5
- package/src/core/import-rewrite/services/ImportRewriteService.ts +1 -3
- package/src/core/import-rewrite/services/ImportTransformService.ts +2 -2
- package/src/core/import-rewrite/types/ImportRewriteTypes.ts +3 -3
- package/src/core/index.ts +4 -4
- package/src/core/interfaces/ITask.ts +6 -5
- package/src/core/interfaces/ITaskContext.ts +9 -9
- package/src/core/interfaces/index.ts +2 -2
- package/src/core/logger/Logger.ts +28 -28
- package/src/core/services/CodeAnalysisService.ts +3 -2
- package/src/core/services/CodeGenerationEngine.ts +42 -42
- package/src/core/services/CodeGenerationService/CodeGenerationService.ts +1 -2
- package/src/core/services/CodeGenerationService/generators/MergedSendableClassGenerator.ts +0 -29
- package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +31 -64
- package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +261 -170
- package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +26 -19
- package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +5 -3
- package/src/core/services/CodeGenerationService/shared/ImportManager.ts +8 -8
- package/src/core/template/HandlebarsTemplateEngine.ts +43 -10
- package/src/core/utils/ConfigManager.ts +2 -1
- package/src/core/utils/DeepCopyUtil.ts +4 -2
- package/src/core/utils/GenericTypeSubstitutionUtil.ts +45 -2
- package/src/core/utils/SerializationPathUtil.ts +7 -6
- package/src/core/utils/TsMorphUtil.ts +9 -2
- package/src/index.ts +2 -2
- package/src/json-plugin/JSONExecuteController.ts +51 -38
- package/src/json-plugin/interfaces/IModuleContext.ts +8 -8
- package/src/json-plugin/interfaces/ITargetContext.ts +6 -6
- package/src/json-plugin/interfaces/impl/ModuleContext.ts +10 -10
- package/src/json-plugin/interfaces/impl/TargetContext.ts +63 -58
- package/src/json-plugin/tasks/BaseTask.ts +5 -4
- package/src/json-plugin/tasks/CleanTask.ts +7 -7
- package/src/json-plugin/tasks/WatchTask.ts +20 -18
- package/template/SerializerPerformanceTemplate.hbs +14 -4
- package/template/SerializerStrictTemplate.hbs +9 -1
- package/template/SerializerTemplate.hbs +71 -46
|
@@ -4,11 +4,14 @@ exports.GenericTypeSubstitutionUtil = void 0;
|
|
|
4
4
|
const __1 = require("..");
|
|
5
5
|
const handlers_1 = require("../handlers");
|
|
6
6
|
const DeepCopyUtil_1 = require("./DeepCopyUtil");
|
|
7
|
+
const Logger_1 = require("../logger/Logger");
|
|
7
8
|
class GenericTypeSubstitutionUtil {
|
|
8
9
|
static buildGenericMapping(parentGenericParams, childTypeArguments) {
|
|
9
10
|
const mapping = new Map();
|
|
10
11
|
const length = Math.min(parentGenericParams.length, childTypeArguments.length);
|
|
12
|
+
Logger_1.Logger.debug(`[GenericMapping] Building mapping with ${length} parameters`);
|
|
11
13
|
for (let i = 0; i < length; i++) {
|
|
14
|
+
Logger_1.Logger.debug(`[GenericMapping] ${parentGenericParams[i]} -> ${childTypeArguments[i].getText()}`);
|
|
12
15
|
mapping.set(parentGenericParams[i], childTypeArguments[i]);
|
|
13
16
|
}
|
|
14
17
|
return mapping;
|
|
@@ -24,10 +27,17 @@ class GenericTypeSubstitutionUtil {
|
|
|
24
27
|
static substituteTypeStructure(typeStructure, mapping, currentClassGenericParams = []) {
|
|
25
28
|
if (typeStructure.kind === __1.PropertyKind.GENERIC) {
|
|
26
29
|
const genericTypeName = typeStructure.sourceText;
|
|
30
|
+
Logger_1.Logger.debug(`[GenericSubstitution] Processing generic type: ${genericTypeName}`);
|
|
31
|
+
Logger_1.Logger.debug(`[GenericSubstitution] Available mappings: ${Array.from(mapping.keys()).join(', ')}`);
|
|
32
|
+
Logger_1.Logger.debug(`[GenericSubstitution] Current class generic params: ${currentClassGenericParams.join(', ')}`);
|
|
27
33
|
if (mapping.has(genericTypeName)) {
|
|
28
34
|
const substitutedTypeNode = mapping.get(genericTypeName);
|
|
29
|
-
|
|
35
|
+
Logger_1.Logger.debug(`[GenericSubstitution] Found mapping for ${genericTypeName} -> ${substitutedTypeNode.getText()}`);
|
|
36
|
+
const result = this.constructTypeStructureFromTypeName(substitutedTypeNode, currentClassGenericParams);
|
|
37
|
+
Logger_1.Logger.debug(`[GenericSubstitution] Result kind: ${result.kind}, sourceText: ${result.sourceText}`);
|
|
38
|
+
return result;
|
|
30
39
|
}
|
|
40
|
+
Logger_1.Logger.warn(`[GenericSubstitution] No mapping found for generic type: ${genericTypeName}, keeping as-is`);
|
|
31
41
|
return typeStructure;
|
|
32
42
|
}
|
|
33
43
|
const newStructure = DeepCopyUtil_1.DeepCopyUtil.copyTypeStructure(typeStructure);
|
|
@@ -36,6 +46,7 @@ class GenericTypeSubstitutionUtil {
|
|
|
36
46
|
}
|
|
37
47
|
if (newStructure.args) {
|
|
38
48
|
newStructure.args = newStructure.args.map(arg => this.substituteTypeStructure(arg, mapping, currentClassGenericParams));
|
|
49
|
+
newStructure.sourceText = this.regenerateSourceText(newStructure);
|
|
39
50
|
}
|
|
40
51
|
newStructure.dependencies = this.collectDependenciesFromChildren(newStructure);
|
|
41
52
|
return newStructure;
|
|
@@ -46,6 +57,21 @@ class GenericTypeSubstitutionUtil {
|
|
|
46
57
|
genericParams: currentClassGenericParams
|
|
47
58
|
});
|
|
48
59
|
}
|
|
60
|
+
static regenerateSourceText(structure) {
|
|
61
|
+
if (!structure.args || structure.args.length === 0) {
|
|
62
|
+
return structure.sourceText;
|
|
63
|
+
}
|
|
64
|
+
if (structure.sourceText.endsWith('[]')) {
|
|
65
|
+
return `${structure.args[0].sourceText}[]`;
|
|
66
|
+
}
|
|
67
|
+
const genericStart = structure.sourceText.indexOf('<');
|
|
68
|
+
if (genericStart > 0) {
|
|
69
|
+
const containerName = structure.sourceText.substring(0, genericStart);
|
|
70
|
+
const argsText = structure.args.map(arg => arg.sourceText).join(', ');
|
|
71
|
+
return `${containerName}<${argsText}>`;
|
|
72
|
+
}
|
|
73
|
+
return structure.sourceText;
|
|
74
|
+
}
|
|
49
75
|
static collectDependenciesFromChildren(children) {
|
|
50
76
|
const allDependencies = [];
|
|
51
77
|
if (children.unionDetails) {
|
|
@@ -4,11 +4,16 @@ exports.TsMorphUtil = void 0;
|
|
|
4
4
|
const ts_morph_1 = require("ts-morph");
|
|
5
5
|
const Logger_1 = require("../logger/Logger");
|
|
6
6
|
class TsMorphUtil {
|
|
7
|
-
constructor() {
|
|
7
|
+
constructor() {
|
|
8
|
+
}
|
|
8
9
|
static getProject(options) {
|
|
9
10
|
if (!this.project) {
|
|
10
11
|
Logger_1.Logger.info('创建ts-morph项目');
|
|
11
12
|
this.project = new ts_morph_1.Project(options || {
|
|
13
|
+
manipulationSettings: {
|
|
14
|
+
indentationText: ts_morph_1.IndentationText.TwoSpaces,
|
|
15
|
+
quoteKind: ts_morph_1.QuoteKind.Single
|
|
16
|
+
},
|
|
12
17
|
compilerOptions: {
|
|
13
18
|
allowNonTsExtensions: true
|
|
14
19
|
}
|
|
@@ -56,48 +56,58 @@ class JSONExecuteController {
|
|
|
56
56
|
this.tasks.forEach((task) => {
|
|
57
57
|
this.node.registerTask({
|
|
58
58
|
name: task.taskName,
|
|
59
|
-
run: async () =>
|
|
60
|
-
try {
|
|
61
|
-
core_1.Logger.info(`${task.taskName} run`);
|
|
62
|
-
core_1.TempSerializerGenerator.getInstance().init(targetContext);
|
|
63
|
-
const result = task.run(targetContext);
|
|
64
|
-
if (task.taskName !== TaskConstants_1.TaskConstants.CLEAN_TASK) {
|
|
65
|
-
core_1.TempSerializerGenerator.getInstance().saveFile();
|
|
66
|
-
}
|
|
67
|
-
if (result instanceof Promise) {
|
|
68
|
-
await result;
|
|
69
|
-
}
|
|
70
|
-
if (task.taskName === TaskConstants_1.TaskConstants.SYNC_TASK || task.taskName === TaskConstants_1.TaskConstants.CODE_PROCESSING_TASK) {
|
|
71
|
-
this.taskCleanUp();
|
|
72
|
-
}
|
|
73
|
-
core_1.Logger.info(`${task.taskName} end`);
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (error instanceof CustomError_1.CustomError) {
|
|
77
|
-
core_1.Logger.error(`Error: ${error.constructor.name}: ${error.code} ${error.message}\n${error.stack}`);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
const err = error;
|
|
81
|
-
core_1.Logger.error(`Error: ${err.constructor.name}: ${CustomError_1.ErrorCodes.INTERNAL_ERROR} ${err.message}\n${err.stack}`);
|
|
82
|
-
}
|
|
83
|
-
this.taskCleanUp();
|
|
84
|
-
throw new Error('serialization execute failed');
|
|
85
|
-
}
|
|
86
|
-
},
|
|
59
|
+
run: async () => this.runTask(task, targetContext),
|
|
87
60
|
dependencies: task.dependencies.map((dep) => `${target.getTargetName()}@${dep}`),
|
|
88
61
|
postDependencies: task.postDependencies.map((dep) => `${target.getTargetName()}@${dep}`)
|
|
89
62
|
});
|
|
90
63
|
});
|
|
64
|
+
this.registerCleanTaskHook(targetContext);
|
|
65
|
+
}
|
|
66
|
+
async runTask(task, targetContext) {
|
|
67
|
+
try {
|
|
68
|
+
core_1.Logger.info(`${task.taskName} run`);
|
|
69
|
+
core_1.TempSerializerGenerator.getInstance().init(targetContext);
|
|
70
|
+
const result = task.run(targetContext);
|
|
71
|
+
if (task.taskName !== TaskConstants_1.TaskConstants.CLEAN_TASK) {
|
|
72
|
+
core_1.TempSerializerGenerator.getInstance().saveFile();
|
|
73
|
+
}
|
|
74
|
+
if (result instanceof Promise) {
|
|
75
|
+
await result;
|
|
76
|
+
}
|
|
77
|
+
if (task.taskName === TaskConstants_1.TaskConstants.SYNC_TASK || task.taskName === TaskConstants_1.TaskConstants.CODE_PROCESSING_TASK) {
|
|
78
|
+
this.taskCleanUp();
|
|
79
|
+
}
|
|
80
|
+
core_1.Logger.info(`${task.taskName} end`);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
this.handleTaskError(error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
handleTaskError(error) {
|
|
87
|
+
if (error instanceof CustomError_1.CustomError) {
|
|
88
|
+
core_1.Logger.error(`Error: ${error.constructor.name}: ${error.code} ${error.message}\n${error.stack}`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const err = error;
|
|
92
|
+
core_1.Logger.error(`Error: ${err.constructor.name}: ${CustomError_1.ErrorCodes.INTERNAL_ERROR} ${err.message}\n${err.stack}`);
|
|
93
|
+
}
|
|
94
|
+
this.taskCleanUp();
|
|
95
|
+
throw new Error('serialization execute failed');
|
|
96
|
+
}
|
|
97
|
+
registerCleanTaskHook(targetContext) {
|
|
91
98
|
const cleanTask = this.node.getTaskByName('clean');
|
|
92
|
-
if (cleanTask) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
if (!cleanTask) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
cleanTask.beforeRun(() => this.cleanGeneratedDirectory(targetContext));
|
|
103
|
+
}
|
|
104
|
+
cleanGeneratedDirectory(targetContext) {
|
|
105
|
+
const generatedRootDir = targetContext.getOutputRoot();
|
|
106
|
+
if (!SerializationPathUtil_1.default.exist(generatedRootDir)) {
|
|
107
|
+
return;
|
|
100
108
|
}
|
|
109
|
+
core_1.Logger.info(`Clean up the generated directory: ${generatedRootDir}`);
|
|
110
|
+
SerializationPathUtil_1.default.rmSync(generatedRootDir, { recursive: true, force: true });
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
exports.JSONExecuteController = JSONExecuteController;
|
|
@@ -90,7 +90,8 @@ class TargetContextImpl {
|
|
|
90
90
|
}
|
|
91
91
|
const sourceRootForRelative = sourceRoot.replace(/\/$/, '');
|
|
92
92
|
const absolutePathForRelative = normalizedAbsolutePath.replace(/\/$/, '');
|
|
93
|
-
return SerializationPathUtil_1.default.relative(sourceRootForRelative, absolutePathForRelative)
|
|
93
|
+
return SerializationPathUtil_1.default.relative(sourceRootForRelative, absolutePathForRelative)
|
|
94
|
+
.replaceAll(SerializationPathUtil_1.default.sep, '/');
|
|
94
95
|
}
|
|
95
96
|
get targetSourceRoots() {
|
|
96
97
|
if (!this.targetOpt.source?.sourceRoots) {
|
|
@@ -106,7 +107,8 @@ class TargetContextImpl {
|
|
|
106
107
|
return this.targetSourceRoots.map((sourceRoot) => {
|
|
107
108
|
const absolutePath = SerializationPathUtil_1.default.pathResolve(moduleRoot, sourceRoot);
|
|
108
109
|
const normalizedPath = SerializationPathUtil_1.default.normalize(absolutePath);
|
|
109
|
-
return normalizedPath.endsWith(SerializationPathUtil_1.default.sep) ? normalizedPath :
|
|
110
|
+
return normalizedPath.endsWith(SerializationPathUtil_1.default.sep) ? normalizedPath :
|
|
111
|
+
normalizedPath + SerializationPathUtil_1.default.sep;
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ITask, CodeGenerationEngine } from '../../core';
|
|
1
|
+
import { ITask, CodeGenerationEngine, IGenerationResult } from '../../core';
|
|
2
2
|
import { BuildProfileUpdaterImpl } from '../../core/import-rewrite/services/BuildProfileUpdater';
|
|
3
3
|
import { ITargetContext } from '../interfaces/ITargetContext';
|
|
4
4
|
export declare abstract class BaseTask implements ITask {
|
|
@@ -8,7 +8,7 @@ export declare abstract class BaseTask implements ITask {
|
|
|
8
8
|
protected readonly engine: CodeGenerationEngine;
|
|
9
9
|
protected readonly buildProfileUpdater: BuildProfileUpdaterImpl;
|
|
10
10
|
protected getScanFiles(context: ITargetContext): string[];
|
|
11
|
-
protected processWithLogging(scanFiles: string[], context: ITargetContext, taskName: string):
|
|
11
|
+
protected processWithLogging(scanFiles: string[], context: ITargetContext, taskName: string): IGenerationResult;
|
|
12
12
|
protected executeImportRewrite(context: ITargetContext, taskName: string): void;
|
|
13
13
|
abstract run(context: ITargetContext): void | Promise<void>;
|
|
14
14
|
}
|
package/package.json
CHANGED
package/src/core/Types.ts
CHANGED
|
@@ -19,40 +19,40 @@ import { ClassDeclaration, InterfaceDeclaration, TypeNode } from 'ts-morph';
|
|
|
19
19
|
|
|
20
20
|
export enum PropertyKind {
|
|
21
21
|
// ===== 基础类型(对应PrimitiveKind) =====
|
|
22
|
-
STRING = 'string',
|
|
23
|
-
NUMBER = 'number',
|
|
24
|
-
BOOLEAN = 'boolean',
|
|
25
|
-
BIGINT = 'bigint',
|
|
22
|
+
STRING = 'string', // StringSerializer.INSTANCE
|
|
23
|
+
NUMBER = 'number', // NumberSerializer.INSTANCE
|
|
24
|
+
BOOLEAN = 'boolean', // BooleanSerializer.INSTANCE
|
|
25
|
+
BIGINT = 'bigint', // BigintSerializer.INSTANCE
|
|
26
26
|
|
|
27
27
|
// ===== 特殊原始类型 =====
|
|
28
|
-
NULL = 'null',
|
|
29
|
-
UNDEFINED = 'undefined',
|
|
28
|
+
NULL = 'null', // NullSerializer.INSTANCE
|
|
29
|
+
UNDEFINED = 'undefined', // UndefinedSerializer.INSTANCE
|
|
30
30
|
|
|
31
31
|
// ===== 集合类型(泛型构造器) =====
|
|
32
|
-
ARRAY = 'array',
|
|
33
|
-
MAP = 'map',
|
|
34
|
-
SET = 'set',
|
|
35
|
-
RECORD = 'record',
|
|
36
|
-
COLLECTIONS_ARRAY = 'collections.Array',
|
|
37
|
-
COLLECTIONS_SET = 'collections.Set',
|
|
38
|
-
COLLECTIONS_MAP = 'collections.Map',
|
|
32
|
+
ARRAY = 'array', // new ArraySerializer<T>(elementSerializer)
|
|
33
|
+
MAP = 'map', // new MapSerializer<K,V>(keySerializer, valueSerializer)
|
|
34
|
+
SET = 'set', // new SetSerializer<T>(elementSerializer)
|
|
35
|
+
RECORD = 'record', // new RecordSerializer<K,V>(keySerializer, valueSerializer)
|
|
36
|
+
COLLECTIONS_ARRAY = 'collections.Array', // new CollectionsArraySerializer<T>(elementSerializer)
|
|
37
|
+
COLLECTIONS_SET = 'collections.Set', // new CollectionsSetSerializer<T>(elementSerializer)
|
|
38
|
+
COLLECTIONS_MAP = 'collections.Map', // new CollectionsMapSerializer<K,V>(keySerializer, valueSerializer)
|
|
39
39
|
|
|
40
40
|
// ===== 复杂对象类型 =====
|
|
41
|
-
OBJECT = 'object',
|
|
42
|
-
GENERIC = 'generic',
|
|
41
|
+
OBJECT = 'object', // ObjectSerializer.INSTANCE
|
|
42
|
+
GENERIC = 'generic', // Serializer<T>
|
|
43
43
|
|
|
44
44
|
// ===== 高级类型 =====
|
|
45
|
-
UNION = 'union',
|
|
46
|
-
OPTIONAL = 'optional',
|
|
47
|
-
NULLABLE = 'nullable',
|
|
45
|
+
UNION = 'union', // new UnionTypeSerializer<string | number>([string, number])
|
|
46
|
+
OPTIONAL = 'optional', // new OptionalSerializer<T>(serializer) - for T | undefined
|
|
47
|
+
NULLABLE = 'nullable', // new NullableSerializer<T>(serializer) - for T | null
|
|
48
48
|
OPTIONAL_NULLABLE = 'optionalNullable', // new OptionalNullableSerializer<T>(serializer) - for T | null | undefined
|
|
49
|
-
ENUM = 'enum',
|
|
50
|
-
TUPLE = 'tuple',
|
|
51
|
-
ARRAY_LIST = 'arrayList',
|
|
52
|
-
HASH_MAP = 'hashMap',
|
|
53
|
-
HASH_SET = 'hashSet',
|
|
54
|
-
LIST = 'list',
|
|
55
|
-
Date = 'date',
|
|
49
|
+
ENUM = 'enum', // new EnumSerializer<number>('Habit', [['HAVE_FUN', 0], ['READING', 1], ['SPORT', 2]])
|
|
50
|
+
TUPLE = 'tuple', // new TupleSerializer<[string, number]>([string, number])
|
|
51
|
+
ARRAY_LIST = 'arrayList', // new ArrayListSerializer<T>(elementSerializer)
|
|
52
|
+
HASH_MAP = 'hashMap', // new HashMapSerializer<K,V>(keySerializer, valueSerializer)
|
|
53
|
+
HASH_SET = 'hashSet', // new HashSetSerializer<T>(elementSerializer)
|
|
54
|
+
LIST = 'list', // new ListSerializer<T>(elementSerializer)
|
|
55
|
+
Date = 'date', // new DateSerializer()
|
|
56
56
|
Decimal = 'decimal', // new DecimalSerializer()
|
|
57
57
|
INTERFACE = 'interface', // new AnySerializer<T>(interfaceDeclaration)
|
|
58
58
|
|
|
@@ -73,23 +73,23 @@ export enum DeserializationMode {
|
|
|
73
73
|
*/
|
|
74
74
|
export interface ClassAnalysis {
|
|
75
75
|
// 基础信息
|
|
76
|
-
className: string;
|
|
77
|
-
sourceFilePath: string;
|
|
76
|
+
className: string; // 类名
|
|
77
|
+
sourceFilePath: string; // 类在源码中的绝对路径
|
|
78
78
|
originalClass?: ClassDeclaration; // 原始AST引用(可选,用于高级处理和回溯)
|
|
79
79
|
|
|
80
80
|
// 核心特性
|
|
81
|
-
generics: GenericInfo;
|
|
82
|
-
inheritance: InheritanceInfo;
|
|
83
|
-
decorators: ClassDecorators;
|
|
81
|
+
generics: GenericInfo; // 泛型信息
|
|
82
|
+
inheritance: InheritanceInfo; // 继承信息
|
|
83
|
+
decorators: ClassDecorators; // 类装饰器
|
|
84
84
|
|
|
85
85
|
// 属性分组(基于继承信息的智能分组)
|
|
86
|
-
ownProperties: PropertyAnalysis[];
|
|
87
|
-
inheritedProperties: PropertyAnalysis[];
|
|
86
|
+
ownProperties: PropertyAnalysis[]; // 当前类自己定义的属性
|
|
87
|
+
inheritedProperties: PropertyAnalysis[]; // 从父类继承且未重写的属性
|
|
88
88
|
overriddenProperties: PropertyAnalysis[]; // 重写了父类的属性
|
|
89
|
-
properties: PropertyAnalysis[];
|
|
89
|
+
properties: PropertyAnalysis[]; // 所有属性的合并视图(重写后的属性会覆盖父类属性,只保留一个)
|
|
90
90
|
|
|
91
91
|
// 构造函数信息
|
|
92
|
-
constructorParams: ConstructorParam[];
|
|
92
|
+
constructorParams: ConstructorParam[]; // 构造函数参数
|
|
93
93
|
|
|
94
94
|
// Sendable合并性
|
|
95
95
|
canMerge?: boolean;
|
|
@@ -103,10 +103,10 @@ export interface InterfaceAnalysis {
|
|
|
103
103
|
inheritance: InheritanceInfo;
|
|
104
104
|
decorators?: ClassDecorators;
|
|
105
105
|
|
|
106
|
-
ownProperties: PropertyAnalysis[];
|
|
107
|
-
inheritedProperties: PropertyAnalysis[];
|
|
106
|
+
ownProperties: PropertyAnalysis[]; // 当前接口自己定义的属性
|
|
107
|
+
inheritedProperties: PropertyAnalysis[]; // 从父类继承且未重写的属性
|
|
108
108
|
overriddenProperties: PropertyAnalysis[]; // 重写了父类的属性
|
|
109
|
-
properties: PropertyAnalysis[];
|
|
109
|
+
properties: PropertyAnalysis[]; // 所有属性的合并视图(重写后的属性会覆盖父类属性,只保留一个)
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
// ============= 第二层:类的核心特性 =============
|
|
@@ -116,8 +116,8 @@ export interface InterfaceAnalysis {
|
|
|
116
116
|
* 专门处理类和方法的泛型参数、约束、变型信息
|
|
117
117
|
*/
|
|
118
118
|
export interface GenericInfo {
|
|
119
|
-
isGeneric: boolean;
|
|
120
|
-
parameters: string[];
|
|
119
|
+
isGeneric: boolean; // 是否为泛型类/方法
|
|
120
|
+
parameters: string[]; // 泛型参数名列表 ['T', 'U']
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
|
@@ -125,9 +125,9 @@ export interface GenericInfo {
|
|
|
125
125
|
* 描述类的继承关系
|
|
126
126
|
*/
|
|
127
127
|
export interface InheritanceInfo {
|
|
128
|
-
isInherited: boolean;
|
|
129
|
-
baseClassAnalysis?: ClassAnalysis | InterfaceAnalysis;
|
|
130
|
-
genericTypeArguments?: TypeNode[];
|
|
128
|
+
isInherited: boolean; // 是否继承其他类
|
|
129
|
+
baseClassAnalysis?: ClassAnalysis | InterfaceAnalysis; // 直接父类的详细信息
|
|
130
|
+
genericTypeArguments?: TypeNode[]; // 继承时传入的泛型参数
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
@@ -144,8 +144,8 @@ export interface ClassDecorators {
|
|
|
144
144
|
* 配置序列化行为的选项
|
|
145
145
|
*/
|
|
146
146
|
export interface SerializableOptions {
|
|
147
|
-
generateSendable?: boolean;
|
|
148
|
-
with?: string;
|
|
147
|
+
generateSendable?: boolean; // 是否生成Sendable变体类
|
|
148
|
+
with?: string; // 自定义序列化器工厂(完整表达式内容)
|
|
149
149
|
deserializationMode?: DeserializationMode; // 反序列化模式(粗糙/精确)
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -154,10 +154,10 @@ export interface SerializableOptions {
|
|
|
154
154
|
* 描述类构造函数的参数结构
|
|
155
155
|
*/
|
|
156
156
|
export interface ConstructorParam {
|
|
157
|
-
name: string;
|
|
158
|
-
type: string;
|
|
159
|
-
isOptional: boolean;
|
|
160
|
-
defaultValue?: string;
|
|
157
|
+
name: string; // 参数名称
|
|
158
|
+
type: string; // 参数类型字符串
|
|
159
|
+
isOptional: boolean; // 是否可选
|
|
160
|
+
defaultValue?: string; // 默认值(可选)
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
// ============= 第三层:属性分析结果 =============
|
|
@@ -167,11 +167,18 @@ export interface ConstructorParam {
|
|
|
167
167
|
* 阅读路径:PropertyAnalysis → 基础信息 → 类型分析 → 装饰器
|
|
168
168
|
*/
|
|
169
169
|
export interface PropertyAnalysis {
|
|
170
|
-
name: string;
|
|
171
|
-
defaultValue?: string;
|
|
170
|
+
name: string; // 属性名称
|
|
171
|
+
defaultValue?: string; // 默认值表达式字符串
|
|
172
172
|
decorators?: PropertyDecorators; // 装饰器信息
|
|
173
|
-
isMust: boolean;
|
|
174
|
-
type: TypeStructure;
|
|
173
|
+
isMust: boolean; // 精确模式下反序列化时的必要性
|
|
174
|
+
type: TypeStructure; // 完整的类型分析结果(详细类型信息)
|
|
175
|
+
visibility: PropertyVisibility; // 属性可见性修饰符
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export enum PropertyVisibility {
|
|
179
|
+
PUBLIC = 'public',
|
|
180
|
+
PRIVATE = 'private',
|
|
181
|
+
PROTECTED = 'protected',
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
/**
|
|
@@ -179,10 +186,11 @@ export interface PropertyAnalysis {
|
|
|
179
186
|
* 分离装饰器解析结果,避免与分析结果混合
|
|
180
187
|
*/
|
|
181
188
|
export interface PropertyDecorators {
|
|
182
|
-
serialName?: string;
|
|
183
|
-
isRequired: boolean;
|
|
184
|
-
isTransient: boolean;
|
|
185
|
-
|
|
189
|
+
serialName?: string; // @SerialName 自定义序列化名称
|
|
190
|
+
isRequired: boolean; // @Required 是否必需字段
|
|
191
|
+
isTransient: boolean; // @Transient 是否跳过序列化
|
|
192
|
+
isPlainValue: boolean; // @PlainValue 是否使用原始值(跳过类型转换)
|
|
193
|
+
with?: string; // @Serializable 自定义序列化器
|
|
186
194
|
}
|
|
187
195
|
|
|
188
196
|
// ============= 第五层:类型结构详情 =============
|
|
@@ -192,17 +200,17 @@ export interface PropertyDecorators {
|
|
|
192
200
|
* 阅读路径:TypeStructure → 基础信息 → 子结构 → 特殊类型信息
|
|
193
201
|
*/
|
|
194
202
|
export interface TypeStructure {
|
|
195
|
-
kind: PropertyKind;
|
|
196
|
-
depth: number;
|
|
197
|
-
sourceText: string;
|
|
198
|
-
args: TypeStructure[]
|
|
203
|
+
kind: PropertyKind; // 类型种类(STRING, ARRAY, MAP等)
|
|
204
|
+
depth: number; // 嵌套深度(用于复杂度控制)
|
|
205
|
+
sourceText: string; // 原始类型文本(如 "Array<Map<string, User>>")
|
|
206
|
+
args: TypeStructure[]; // 泛型参数的类型
|
|
199
207
|
// 类型依赖和特殊信息
|
|
200
208
|
dependencies: TypeDependency[]; // 依赖信息列表(包含完整导入信息)
|
|
201
|
-
enumDetails?: EnumDetails;
|
|
202
|
-
classDetails?: ClassDetails;
|
|
203
|
-
interfaceDetails?: InterfaceDetails;
|
|
209
|
+
enumDetails?: EnumDetails; // 枚举类型详细信息(仅当kind=ENUM时)
|
|
210
|
+
classDetails?: ClassDetails; // 枚举类型详细信息(仅当kind=OBJECT时)
|
|
211
|
+
interfaceDetails?: InterfaceDetails; // (仅当kind=INTERFACE时)
|
|
204
212
|
unionDetails?: TypeStructure[]; // Union types 的成员类型
|
|
205
|
-
isOptional?: boolean;
|
|
213
|
+
isOptional?: boolean; // 是否可选
|
|
206
214
|
}
|
|
207
215
|
|
|
208
216
|
// ============= 第六层:类型依赖信息 =============
|
|
@@ -219,12 +227,12 @@ export enum TypeKind {
|
|
|
219
227
|
* 阅读路径:TypeDependency → 基础信息 → 来源信息 → 详细信息
|
|
220
228
|
*/
|
|
221
229
|
export interface TypeDependency {
|
|
222
|
-
typeName: string;
|
|
223
|
-
typeKind: TypeKind;
|
|
224
|
-
importPath: string;
|
|
230
|
+
typeName: string; // 类型名称(如 "User")
|
|
231
|
+
typeKind: TypeKind; // 类型种类
|
|
232
|
+
importPath: string; // 导入路径(如 "sampleentry/ets/model/User")
|
|
225
233
|
|
|
226
|
-
source: DependencySource;
|
|
227
|
-
details?: TypeDetails;
|
|
234
|
+
source: DependencySource; // 统一的来源信息
|
|
235
|
+
details?: TypeDetails; // 扩展的类型详细信息(按需包含)
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
/**
|
|
@@ -232,9 +240,9 @@ export interface TypeDependency {
|
|
|
232
240
|
*/
|
|
233
241
|
export interface DependencySource {
|
|
234
242
|
type: 'local' | 'imported' | 'builtin'; // 本地定义/外部导入/内置类型
|
|
235
|
-
sourceFilePath?: string;
|
|
236
|
-
originalImport?: string;
|
|
237
|
-
packageName?: string;
|
|
243
|
+
sourceFilePath?: string; // 源文件绝对路径(仅当 type='local'|'imported' 时)
|
|
244
|
+
originalImport?: string; // 原始导入语句(仅当 type='imported' 时)
|
|
245
|
+
packageName?: string; // 包名(如果是包导入)
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
// ============= 第七层:类型详细信息 =============
|
|
@@ -254,7 +262,7 @@ export type TypeDetails =
|
|
|
254
262
|
*/
|
|
255
263
|
export interface EnumDetails {
|
|
256
264
|
kind: TypeKind.ENUM;
|
|
257
|
-
members: EnumMemberInfo[];
|
|
265
|
+
members: EnumMemberInfo[]; // 枚举成员列表
|
|
258
266
|
valueType: 'string' | 'number'; // 枚举值类型
|
|
259
267
|
}
|
|
260
268
|
|
|
@@ -262,9 +270,9 @@ export interface EnumDetails {
|
|
|
262
270
|
* 枚举成员信息(从EnumDetails.members跳转到这里)
|
|
263
271
|
*/
|
|
264
272
|
export interface EnumMemberInfo {
|
|
265
|
-
name: string;
|
|
266
|
-
value: string | number;
|
|
267
|
-
literalValue: string;
|
|
273
|
+
name: string; // 枚举成员名称(如 'HAVE_FUN')
|
|
274
|
+
value: string | number; // 枚举成员值(如 0 或 'football')
|
|
275
|
+
literalValue: string; // 字面量形式(用于代码生成,如 '0' 或 "'football'")
|
|
268
276
|
}
|
|
269
277
|
|
|
270
278
|
/**
|
|
@@ -273,7 +281,7 @@ export interface EnumMemberInfo {
|
|
|
273
281
|
export interface ClassDetails {
|
|
274
282
|
kind: TypeKind.CLASS;
|
|
275
283
|
classDecl: ClassDeclaration;
|
|
276
|
-
isGeneric: boolean;
|
|
284
|
+
isGeneric: boolean; // 是否为泛型类
|
|
277
285
|
}
|
|
278
286
|
|
|
279
287
|
/**
|
|
@@ -282,7 +290,7 @@ export interface ClassDetails {
|
|
|
282
290
|
export interface InterfaceDetails {
|
|
283
291
|
kind: TypeKind.INTERFACE;
|
|
284
292
|
interfaceDecl: InterfaceDeclaration;
|
|
285
|
-
isGeneric: boolean;
|
|
293
|
+
isGeneric: boolean; // 是否为泛型接口
|
|
286
294
|
}
|
|
287
295
|
|
|
288
296
|
/**
|
|
@@ -290,8 +298,8 @@ export interface InterfaceDetails {
|
|
|
290
298
|
*/
|
|
291
299
|
export interface TypeAliasDetails {
|
|
292
300
|
kind: TypeKind.TYPE;
|
|
293
|
-
aliasedType: string;
|
|
294
|
-
resolvedType: TypeStructure;
|
|
301
|
+
aliasedType: string; // 别名指向的类型字符串(如 "User | Admin")
|
|
302
|
+
resolvedType: TypeStructure; // 解析后的实际类型(递归分析结果)
|
|
295
303
|
}
|
|
296
304
|
|
|
297
305
|
// ============= 代码生成阶段 =============
|
|
@@ -301,7 +309,7 @@ export interface TypeAliasDetails {
|
|
|
301
309
|
* 阅读路径:GenerationContext → 类分析 → 属性生成信息 → 模板和配置
|
|
302
310
|
*/
|
|
303
311
|
export interface GenerationContext {
|
|
304
|
-
class: ClassAnalysis | InterfaceAnalysis;
|
|
312
|
+
class: ClassAnalysis | InterfaceAnalysis; // 类分析结果
|
|
305
313
|
properties: PropertyGenerationInfo[]; // 属性生成信息列表
|
|
306
314
|
serialNameConstant: string;
|
|
307
315
|
}
|
|
@@ -311,7 +319,7 @@ export interface GenerationContext {
|
|
|
311
319
|
* 阅读路径:PropertyGenerationInfo → 分析结果 → 序列化器元数据 → 模板数据
|
|
312
320
|
*/
|
|
313
321
|
export interface PropertyGenerationInfo {
|
|
314
|
-
analysis: PropertyAnalysis;
|
|
322
|
+
analysis: PropertyAnalysis; // 引用分析结果(不重复存储)
|
|
315
323
|
serializer: SerializerMetadata; // 序列化器生成元数据
|
|
316
324
|
}
|
|
317
325
|
|
|
@@ -319,13 +327,13 @@ export interface PropertyGenerationInfo {
|
|
|
319
327
|
* 序列化器元数据(从PropertyGenerationInfo.serializer跳转到这里)
|
|
320
328
|
*/
|
|
321
329
|
export interface SerializerMetadata {
|
|
322
|
-
name: string;
|
|
323
|
-
typeDeclaration: string;
|
|
324
|
-
instantiationTemplate: string;
|
|
325
|
-
encodeMethod: string;
|
|
326
|
-
decodeMethod: string;
|
|
327
|
-
decoderType: string;
|
|
328
|
-
needsTypeAssertion?: boolean;
|
|
330
|
+
name: string; // 序列化器名称(如 "ArraySerializer")
|
|
331
|
+
typeDeclaration: string; // 类型声明(如 "ArraySerializer<User>")
|
|
332
|
+
instantiationTemplate: string; // 实例化模板(如 "new ArraySerializer<User>(UserSerializer.INSTANCE)")
|
|
333
|
+
encodeMethod: string; // 编码方法名(如 "encodeSerializableElement")
|
|
334
|
+
decodeMethod: string; // 解码方法名(如 "decodeSerializableElement")
|
|
335
|
+
decoderType: string; // 解码器类型(如 "string | undefined")
|
|
336
|
+
needsTypeAssertion?: boolean; // 是否需要类型断言(字符串枚举等情况)
|
|
329
337
|
}
|
|
330
338
|
|
|
331
339
|
// ============= 配置和选项 =============
|