@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
|
@@ -47,7 +47,7 @@ export class ImportManager {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
registerArkTSImports(names: string[]) {
|
|
50
|
+
registerArkTSImports(names: string[]): void {
|
|
51
51
|
const arkTSModule = '@kit.ArkTS';
|
|
52
52
|
|
|
53
53
|
for (const name of names) {
|
|
@@ -59,7 +59,7 @@ export class ImportManager {
|
|
|
59
59
|
// 智能去重:检查是否已有同名类型的更好路径
|
|
60
60
|
if (this.typeToModulePath.has(importedName)) {
|
|
61
61
|
const existingModulePath = this.typeToModulePath.get(importedName)!;
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
// 如果当前路径是模块化路径,而已存在的是相对路径,则替换
|
|
64
64
|
if (this.isModularPath(modulePath) && this.isRelativePath(existingModulePath)) {
|
|
65
65
|
// 移除旧的相对路径导入
|
|
@@ -106,10 +106,10 @@ export class ImportManager {
|
|
|
106
106
|
* 判断是否为模块化路径(不以 . 或 / 开头,不是 @开头的包名)
|
|
107
107
|
*/
|
|
108
108
|
private isModularPath(modulePath: string): boolean {
|
|
109
|
-
return !modulePath.startsWith('.') &&
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
return !modulePath.startsWith('.') &&
|
|
110
|
+
!modulePath.startsWith('/') &&
|
|
111
|
+
!modulePath.startsWith('@') &&
|
|
112
|
+
modulePath.includes('/');
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
private isRelativePath(modulePath: string): boolean {
|
|
@@ -120,7 +120,7 @@ export class ImportManager {
|
|
|
120
120
|
if (this.imports.has(modulePath)) {
|
|
121
121
|
const existingInfo = this.imports.get(modulePath)!;
|
|
122
122
|
const filteredNames = existingInfo.importedNames.filter(name => name !== importedName);
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
if (filteredNames.length === 0) {
|
|
125
125
|
// 如果该模块没有其他导入,则删除整个模块
|
|
126
126
|
this.imports.delete(modulePath);
|
|
@@ -134,7 +134,7 @@ export class ImportManager {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
getImportDeclarations() {
|
|
137
|
+
getImportDeclarations(): Array<{ specifier: string, names: string[] }> {
|
|
138
138
|
const imports: Array<{ specifier: string, names: string[] }> = [];
|
|
139
139
|
for (const [specifier, infos] of this.imports) {
|
|
140
140
|
imports.push({ specifier: specifier, names: infos.importedNames });
|
|
@@ -15,8 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
import * as Handlebars from 'handlebars';
|
|
17
17
|
import {
|
|
18
|
-
ClassAnalysis,
|
|
19
|
-
|
|
18
|
+
ClassAnalysis,
|
|
19
|
+
ConstructorParam,
|
|
20
|
+
DecoratorConstants,
|
|
21
|
+
DeserializationMode,
|
|
22
|
+
GenerationContext,
|
|
23
|
+
InterfaceAnalysis,
|
|
24
|
+
PropertyAnalysis,
|
|
25
|
+
PropertyDecorators,
|
|
26
|
+
PropertyGenerationInfo,
|
|
27
|
+
PropertyKind
|
|
20
28
|
} from '..';
|
|
21
29
|
import SerializationPathUtil from '../utils/SerializationPathUtil';
|
|
22
30
|
import { CustomError, ErrorCodes } from '../utils/CustomError';
|
|
@@ -97,14 +105,24 @@ export class HandlebarsTemplateEngine {
|
|
|
97
105
|
this.registerLogicHelpers();
|
|
98
106
|
}
|
|
99
107
|
|
|
108
|
+
private isPrimitiveType(kind: string): boolean {
|
|
109
|
+
return ['string', 'number', 'boolean', 'bigint', 'undefined', 'null'].includes(kind);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private toUpperCase(name: string): string {
|
|
113
|
+
if (!name) {
|
|
114
|
+
return '';
|
|
115
|
+
}
|
|
116
|
+
return name.charAt(0).toUpperCase() + name.substring(1);
|
|
117
|
+
}
|
|
118
|
+
|
|
100
119
|
private registerComparisonHelpers(): void {
|
|
101
120
|
this.registerHelper('eq', (arg1: unknown, arg2: unknown) => {
|
|
102
121
|
return (arg1 === arg2);
|
|
103
122
|
});
|
|
104
123
|
|
|
105
124
|
this.registerHelper('eqPrimitiveType', (kind: string) => {
|
|
106
|
-
|
|
107
|
-
return primitives.includes(kind);
|
|
125
|
+
return this.isPrimitiveType(kind);
|
|
108
126
|
});
|
|
109
127
|
|
|
110
128
|
this.registerHelper('eqEmptyType', (kind: string) => {
|
|
@@ -149,9 +167,7 @@ export class HandlebarsTemplateEngine {
|
|
|
149
167
|
|
|
150
168
|
private hasNonSerializableClassDecorator(classAnalysis: ClassAnalysis): boolean {
|
|
151
169
|
const classDecorators = classAnalysis.originalClass?.getDecorators() || [];
|
|
152
|
-
return classDecorators.some(decorator =>
|
|
153
|
-
decorator.getName() !== 'Serializable'
|
|
154
|
-
);
|
|
170
|
+
return classDecorators.some(decorator => decorator.getName() !== 'Serializable');
|
|
155
171
|
}
|
|
156
172
|
|
|
157
173
|
private hasNonSerializablePropertyDecorators(classAnalysis: ClassAnalysis): boolean {
|
|
@@ -163,9 +179,8 @@ export class HandlebarsTemplateEngine {
|
|
|
163
179
|
for (const prop of props) {
|
|
164
180
|
const decorators = prop.getDecorators();
|
|
165
181
|
if (decorators && Array.isArray(decorators)) {
|
|
166
|
-
const hasNonSerializableDecorator =
|
|
167
|
-
!DecoratorConstants.SERIAL_DECORATORS.includes(decorator.getName())
|
|
168
|
-
);
|
|
182
|
+
const hasNonSerializableDecorator =
|
|
183
|
+
decorators.some(decorator => !DecoratorConstants.SERIAL_DECORATORS.includes(decorator.getName()));
|
|
169
184
|
if (hasNonSerializableDecorator) {
|
|
170
185
|
return true;
|
|
171
186
|
}
|
|
@@ -223,6 +238,18 @@ export class HandlebarsTemplateEngine {
|
|
|
223
238
|
return str.toLowerCase();
|
|
224
239
|
});
|
|
225
240
|
|
|
241
|
+
this.registerHelper('toUpperCase', (str: string) => {
|
|
242
|
+
return this.toUpperCase(str);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
this.registerHelper('getSerializer', (analysis: PropertyAnalysis) => {
|
|
246
|
+
if (this.isPrimitiveType(analysis.type.kind)) {
|
|
247
|
+
return `${analysis.name}Serializer`;
|
|
248
|
+
} else {
|
|
249
|
+
return `get${this.toUpperCase(analysis.name)}Serializer()`;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
226
253
|
this.registerHelper('genericParametersString', (parameters: string[]) => {
|
|
227
254
|
return parameters.join(', ');
|
|
228
255
|
});
|
|
@@ -230,6 +257,12 @@ export class HandlebarsTemplateEngine {
|
|
|
230
257
|
this.registerHelper('genericParametersESObjString', (parameters: string[]) => {
|
|
231
258
|
return parameters.map(() => 'ESObject').join(', ');
|
|
232
259
|
});
|
|
260
|
+
|
|
261
|
+
// 过滤出泛型类型的属性(用于生成静态方法的泛型序列化器参数)
|
|
262
|
+
this.registerHelper('filterGenericProperties', (properties: PropertyGenerationInfo[]) => {
|
|
263
|
+
return properties.filter(
|
|
264
|
+
p => p.analysis.type.kind === PropertyKind.GENERIC && !p.analysis.decorators?.isTransient);
|
|
265
|
+
});
|
|
233
266
|
}
|
|
234
267
|
|
|
235
268
|
private registerPropertyAnalysisHelpers(): void {
|
|
@@ -19,7 +19,8 @@ export class ConfigManager {
|
|
|
19
19
|
private static instance: ConfigManager;
|
|
20
20
|
private config: TurboTransJsonPluginOptions | null = null;
|
|
21
21
|
|
|
22
|
-
private constructor() {
|
|
22
|
+
private constructor() {
|
|
23
|
+
}
|
|
23
24
|
|
|
24
25
|
public static getInstance(): ConfigManager {
|
|
25
26
|
if (!ConfigManager.instance) {
|
|
@@ -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
|
}
|
|
@@ -173,7 +175,7 @@ export class DeepCopyUtil {
|
|
|
173
175
|
if (typeof obj === 'object') {
|
|
174
176
|
const copy: any = {};
|
|
175
177
|
for (const key in obj) {
|
|
176
|
-
if (
|
|
178
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
177
179
|
copy[key] = this.deepCopy((obj as any)[key]);
|
|
178
180
|
}
|
|
179
181
|
}
|
|
@@ -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
|
-
|
|
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,11 @@ 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
|
+
|
|
100
114
|
// 重新计算依赖信息
|
|
101
115
|
newStructure.dependencies = this.collectDependenciesFromChildren(newStructure);
|
|
102
116
|
|
|
@@ -110,7 +124,36 @@ export class GenericTypeSubstitutionUtil {
|
|
|
110
124
|
return TypeHandlerRegistry.getInstance().parseType(typeNode, {
|
|
111
125
|
depth: 0,
|
|
112
126
|
genericParams: currentClassGenericParams // ✅ 传递当前类的泛型参数上下文
|
|
113
|
-
})
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 根据替换后的 args 重新生成 sourceText
|
|
132
|
+
* 保持原始格式(数组字面量 T[] 或泛型形式 Container<T>)
|
|
133
|
+
* @param structure 类型结构
|
|
134
|
+
* @returns 重新生成的 sourceText
|
|
135
|
+
*/
|
|
136
|
+
private static regenerateSourceText(structure: TypeStructure): string {
|
|
137
|
+
if (!structure.args || structure.args.length === 0) {
|
|
138
|
+
return structure.sourceText;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 处理数组字面量形式: T[] -> NewT[]
|
|
142
|
+
if (structure.sourceText.endsWith('[]')) {
|
|
143
|
+
return `${structure.args[0].sourceText}[]`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 处理泛型形式: Container<T> 或 Container<K, V>
|
|
147
|
+
// 提取容器名称(在 < 之前的部分)
|
|
148
|
+
const genericStart = structure.sourceText.indexOf('<');
|
|
149
|
+
if (genericStart > 0) {
|
|
150
|
+
const containerName = structure.sourceText.substring(0, genericStart);
|
|
151
|
+
const argsText = structure.args.map(arg => arg.sourceText).join(', ');
|
|
152
|
+
return `${containerName}<${argsText}>`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 其他情况保持原样
|
|
156
|
+
return structure.sourceText;
|
|
114
157
|
}
|
|
115
158
|
|
|
116
159
|
private static collectDependenciesFromChildren(children: TypeStructure): TypeDependency[] {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { FileUtil } from '@ohos/hvigor';
|
|
17
|
-
import * as path from
|
|
18
|
-
import * as fs from
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
import * as fs from 'fs';
|
|
19
19
|
import { ITaskContext, PathConstants } from '..';
|
|
20
20
|
|
|
21
21
|
export default class SerializationPathUtil extends FileUtil {
|
|
@@ -34,11 +34,11 @@ export default class SerializationPathUtil extends FileUtil {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
static isAbsolute(p: string): boolean {
|
|
37
|
-
return path.isAbsolute(p)
|
|
37
|
+
return path.isAbsolute(p);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
static normalize(p: string): string {
|
|
41
|
-
return path.normalize(p)
|
|
41
|
+
return path.normalize(p);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
static relative(from: string, to: string): string {
|
|
@@ -101,7 +101,8 @@ export default class SerializationPathUtil extends FileUtil {
|
|
|
101
101
|
static scanEtsFiles(directory: string): string[] {
|
|
102
102
|
const etsFiles: string[] = [];
|
|
103
103
|
|
|
104
|
-
const deepScanEtsFiles
|
|
104
|
+
const deepScanEtsFiles: (scanPath: string, relativePath: string) => void = (scanPath: string,
|
|
105
|
+
relativePath: string) => {
|
|
105
106
|
let resolvePath = this.pathResolve(scanPath, relativePath);
|
|
106
107
|
|
|
107
108
|
if (!this.exist(resolvePath)) {
|
|
@@ -119,7 +120,7 @@ export default class SerializationPathUtil extends FileUtil {
|
|
|
119
120
|
etsFiles.push(resolvePath);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
|
-
}
|
|
123
|
+
};
|
|
123
124
|
|
|
124
125
|
deepScanEtsFiles(directory, '');
|
|
125
126
|
|
|
@@ -13,17 +13,24 @@
|
|
|
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 {
|
|
20
20
|
public static project: Project | null = null;
|
|
21
|
-
|
|
21
|
+
|
|
22
|
+
private constructor() {
|
|
23
|
+
}
|
|
24
|
+
|
|
22
25
|
public static getProject(options?: ProjectOptions): Project {
|
|
23
26
|
if (!this.project) {
|
|
24
27
|
Logger.info('创建ts-morph项目');
|
|
25
28
|
this.project = new Project(
|
|
26
29
|
options || {
|
|
30
|
+
manipulationSettings: {
|
|
31
|
+
indentationText: IndentationText.TwoSpaces,
|
|
32
|
+
quoteKind: QuoteKind.Single
|
|
33
|
+
},
|
|
27
34
|
compilerOptions: {
|
|
28
35
|
allowNonTsExtensions: true
|
|
29
36
|
}
|
package/src/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ class TurboTransJSONPluginManager {
|
|
|
51
51
|
return TurboTransJSONPluginManager.instance;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
initialization(node: HvigorNode, options: TurboTransJsonPluginOptions) {
|
|
54
|
+
initialization(node: HvigorNode, options: TurboTransJsonPluginOptions): void {
|
|
55
55
|
initializeTypeHandlers();
|
|
56
56
|
node.subNodes(subNode => {
|
|
57
57
|
const subNodeName = subNode.getNodeName();
|
|
@@ -63,7 +63,7 @@ class TurboTransJSONPluginManager {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
private setupHvigorHooks(hvigor: Hvigor) {
|
|
66
|
+
private setupHvigorHooks(hvigor: Hvigor): void {
|
|
67
67
|
hvigor.nodesEvaluated(() => {
|
|
68
68
|
this.moduleExecuteControllers.forEach(controller => {
|
|
69
69
|
controller.execute();
|
|
@@ -65,7 +65,7 @@ export class JSONExecuteController {
|
|
|
65
65
|
// 编译结束后的清理逻辑由clean任务处理
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
private initTasks() {
|
|
68
|
+
private initTasks(): void {
|
|
69
69
|
this.tasks.add(new CodeProcessingTask());
|
|
70
70
|
this.tasks.add(new CleanTask());
|
|
71
71
|
this.tasks.add(new SyncTask());
|
|
@@ -82,53 +82,66 @@ export class JSONExecuteController {
|
|
|
82
82
|
SendableMergeabilityRegistry.clear();
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
private registerHvigorTasks(target: Target, context: IModuleContext) {
|
|
85
|
+
private registerHvigorTasks(target: Target, context: IModuleContext): void {
|
|
86
86
|
const targetContext = new TargetContextImpl(target, context);
|
|
87
87
|
this.tasks.forEach((task) => {
|
|
88
88
|
this.node.registerTask({
|
|
89
89
|
name: task.taskName,
|
|
90
|
-
run: async () =>
|
|
91
|
-
try {
|
|
92
|
-
Logger.info(`${task.taskName} run`);
|
|
93
|
-
TempSerializerGenerator.getInstance().init(targetContext);
|
|
94
|
-
const result = task.run(targetContext);
|
|
95
|
-
// clean任务不需要生成序列化器
|
|
96
|
-
if (task.taskName !== TaskConstants.CLEAN_TASK) {
|
|
97
|
-
TempSerializerGenerator.getInstance().saveFile();
|
|
98
|
-
}
|
|
99
|
-
if (result instanceof Promise) {
|
|
100
|
-
await result;
|
|
101
|
-
}
|
|
102
|
-
if (task.taskName === TaskConstants.SYNC_TASK || task.taskName === TaskConstants.CODE_PROCESSING_TASK) {
|
|
103
|
-
this.taskCleanUp();
|
|
104
|
-
}
|
|
105
|
-
Logger.info(`${task.taskName} end`);
|
|
106
|
-
} catch (error) {
|
|
107
|
-
if (error instanceof CustomError) {
|
|
108
|
-
Logger.error(`Error: ${error.constructor.name}: ${error.code} ${error.message}\n${error.stack}`);
|
|
109
|
-
} else {
|
|
110
|
-
const err = error as Error;
|
|
111
|
-
Logger.error(`Error: ${err.constructor.name}: ${ErrorCodes.INTERNAL_ERROR} ${err.message}\n${err.stack}`);
|
|
112
|
-
}
|
|
113
|
-
this.taskCleanUp();
|
|
114
|
-
throw new Error('serialization execute failed');
|
|
115
|
-
}
|
|
116
|
-
},
|
|
90
|
+
run: async () => this.runTask(task, targetContext),
|
|
117
91
|
dependencies: task.dependencies.map((dep) => `${target.getTargetName()}@${dep}`),
|
|
118
92
|
postDependencies: task.postDependencies.map((dep) => `${target.getTargetName()}@${dep}`)
|
|
119
93
|
});
|
|
120
94
|
});
|
|
121
95
|
|
|
96
|
+
this.registerCleanTaskHook(targetContext);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private async runTask(task: ITask, targetContext: TargetContextImpl): Promise<void> {
|
|
100
|
+
try {
|
|
101
|
+
Logger.info(`${task.taskName} run`);
|
|
102
|
+
TempSerializerGenerator.getInstance().init(targetContext);
|
|
103
|
+
const result = task.run(targetContext);
|
|
104
|
+
// clean任务不需要生成序列化器
|
|
105
|
+
if (task.taskName !== TaskConstants.CLEAN_TASK) {
|
|
106
|
+
TempSerializerGenerator.getInstance().saveFile();
|
|
107
|
+
}
|
|
108
|
+
if (result instanceof Promise) {
|
|
109
|
+
await result;
|
|
110
|
+
}
|
|
111
|
+
if (task.taskName === TaskConstants.SYNC_TASK || task.taskName === TaskConstants.CODE_PROCESSING_TASK) {
|
|
112
|
+
this.taskCleanUp();
|
|
113
|
+
}
|
|
114
|
+
Logger.info(`${task.taskName} end`);
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.handleTaskError(error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private handleTaskError(error: unknown): void {
|
|
121
|
+
if (error instanceof CustomError) {
|
|
122
|
+
Logger.error(`Error: ${error.constructor.name}: ${error.code} ${error.message}\n${error.stack}`);
|
|
123
|
+
} else {
|
|
124
|
+
const err = error as Error;
|
|
125
|
+
Logger.error(`Error: ${err.constructor.name}: ${ErrorCodes.INTERNAL_ERROR} ${err.message}\n${err.stack}`);
|
|
126
|
+
}
|
|
127
|
+
this.taskCleanUp();
|
|
128
|
+
throw new Error('serialization execute failed');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private registerCleanTaskHook(targetContext: TargetContextImpl): void {
|
|
122
132
|
const cleanTask = this.node.getTaskByName('clean');
|
|
123
|
-
if (cleanTask) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
if (!cleanTask) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
cleanTask.beforeRun(() => this.cleanGeneratedDirectory(targetContext));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private cleanGeneratedDirectory(targetContext: TargetContextImpl): void {
|
|
140
|
+
const generatedRootDir = targetContext.getOutputRoot();
|
|
141
|
+
if (!SerializationPathUtil.exist(generatedRootDir)) {
|
|
142
|
+
return;
|
|
132
143
|
}
|
|
144
|
+
Logger.info(`Clean up the generated directory: ${generatedRootDir}`);
|
|
145
|
+
SerializationPathUtil.rmSync(generatedRootDir, { recursive: true, force: true });
|
|
133
146
|
}
|
|
134
147
|
}
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { HvigorNode } from '@ohos/hvigor'
|
|
17
|
-
import { ModuleBuildProfile } from '@ohos/hvigor-ohos-plugin/src/options/build/module-build-profile'
|
|
18
|
-
import { OhosModuleContext } from '@ohos/hvigor-ohos-plugin/src/plugin/context/plugin-context'
|
|
16
|
+
import { HvigorNode } from '@ohos/hvigor';
|
|
17
|
+
import { ModuleBuildProfile } from '@ohos/hvigor-ohos-plugin/src/options/build/module-build-profile';
|
|
18
|
+
import { OhosModuleContext } from '@ohos/hvigor-ohos-plugin/src/plugin/context/plugin-context';
|
|
19
19
|
|
|
20
20
|
export interface IModuleContext {
|
|
21
|
-
readonly node: HvigorNode
|
|
22
|
-
readonly moduleContext: OhosModuleContext
|
|
23
|
-
readonly buildProfileOpt: ModuleBuildProfile.ModuleBuildOpt
|
|
24
|
-
readonly scanFiles: string[]
|
|
21
|
+
readonly node: HvigorNode;
|
|
22
|
+
readonly moduleContext: OhosModuleContext;
|
|
23
|
+
readonly buildProfileOpt: ModuleBuildProfile.ModuleBuildOpt;
|
|
24
|
+
readonly scanFiles: string[];
|
|
25
25
|
|
|
26
|
-
initScanFiles(scanDir: string[]): void
|
|
26
|
+
initScanFiles(scanDir: string[]): void;
|
|
27
27
|
}
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { Target } from '@ohos/hvigor-ohos-plugin'
|
|
17
|
-
import { IModuleContext } from './IModuleContext'
|
|
18
|
-
import { ITaskContext } from '../../core'
|
|
16
|
+
import { Target } from '@ohos/hvigor-ohos-plugin';
|
|
17
|
+
import { IModuleContext } from './IModuleContext';
|
|
18
|
+
import { ITaskContext } from '../../core';
|
|
19
19
|
|
|
20
20
|
export interface ITargetContext extends ITaskContext {
|
|
21
|
-
readonly target: Target
|
|
22
|
-
readonly context: IModuleContext
|
|
21
|
+
readonly target: Target;
|
|
22
|
+
readonly context: IModuleContext;
|
|
23
23
|
|
|
24
|
-
getCurrentTargetScanFiles(): string[]
|
|
24
|
+
getCurrentTargetScanFiles(): string[];
|
|
25
25
|
}
|
|
@@ -13,20 +13,20 @@
|
|
|
13
13
|
* limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { HvigorNode } from '@ohos/hvigor'
|
|
17
|
-
import { IModuleContext } from '../IModuleContext'
|
|
16
|
+
import { HvigorNode } from '@ohos/hvigor';
|
|
17
|
+
import { IModuleContext } from '../IModuleContext';
|
|
18
18
|
import SerializationPathUtil from '../../../core/utils/SerializationPathUtil';
|
|
19
19
|
import { OhosHapContext } from '@ohos/hvigor-ohos-plugin';
|
|
20
20
|
import { ModuleBuildProfile } from '@ohos/hvigor-ohos-plugin/src/options/build/module-build-profile';
|
|
21
21
|
|
|
22
22
|
export class ModuleContextImpl implements IModuleContext {
|
|
23
|
-
readonly node: HvigorNode
|
|
24
|
-
readonly moduleContext: OhosHapContext
|
|
25
|
-
readonly scanFiles: string[] = []
|
|
23
|
+
readonly node: HvigorNode;
|
|
24
|
+
readonly moduleContext: OhosHapContext;
|
|
25
|
+
readonly scanFiles: string[] = [];
|
|
26
26
|
|
|
27
27
|
constructor(node: HvigorNode, moduleContext: OhosHapContext) {
|
|
28
|
-
this.node = node
|
|
29
|
-
this.moduleContext = moduleContext
|
|
28
|
+
this.node = node;
|
|
29
|
+
this.moduleContext = moduleContext;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -38,8 +38,8 @@ export class ModuleContextImpl implements IModuleContext {
|
|
|
38
38
|
|
|
39
39
|
initScanFiles(scanDir: string[]): void {
|
|
40
40
|
scanDir.forEach(dir => {
|
|
41
|
-
const scanPath = SerializationPathUtil.pathResolve(this.moduleContext.getModulePath(), dir)
|
|
42
|
-
this.scanFiles.push(...SerializationPathUtil.scanEtsFiles(scanPath))
|
|
43
|
-
})
|
|
41
|
+
const scanPath = SerializationPathUtil.pathResolve(this.moduleContext.getModulePath(), dir);
|
|
42
|
+
this.scanFiles.push(...SerializationPathUtil.scanEtsFiles(scanPath));
|
|
43
|
+
});
|
|
44
44
|
}
|
|
45
45
|
}
|