@hadss/turbo-trans-json-plugin 1.0.0-rc.1 → 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 (76) hide show
  1. package/dist/core/analyzers/ClassAnalyzer.d.ts +15 -0
  2. package/dist/core/analyzers/ClassAnalyzer.js +193 -144
  3. package/dist/core/analyzers/CustomTypeAnalyzer.d.ts +3 -0
  4. package/dist/core/analyzers/CustomTypeAnalyzer.js +65 -60
  5. package/dist/core/constants/DecoratorConstants.js +2 -1
  6. package/dist/core/import-rewrite/services/BuildProfileUpdater.js +1 -1
  7. package/dist/core/import-rewrite/services/ImportRewriteService.js +1 -1
  8. package/dist/core/interfaces/index.d.ts +2 -2
  9. package/dist/core/services/CodeAnalysisService.js +2 -1
  10. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.d.ts +2 -0
  11. package/dist/core/services/CodeGenerationService/generators/OriginalClassGenerator.js +22 -15
  12. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.d.ts +22 -0
  13. package/dist/core/services/CodeGenerationService/generators/SendableClassGenerator.js +194 -129
  14. package/dist/core/services/CodeGenerationService/generators/SerializerGenerator.js +1 -1
  15. package/dist/core/services/CodeGenerationService/generators/TempSerializerGenerator.js +2 -1
  16. package/dist/core/services/CodeGenerationService/shared/ImportManager.d.ts +2 -2
  17. package/dist/core/template/HandlebarsTemplateEngine.d.ts +2 -0
  18. package/dist/core/template/HandlebarsTemplateEngine.js +21 -2
  19. package/dist/core/utils/DeepCopyUtil.js +1 -1
  20. package/dist/core/utils/SerializationPathUtil.d.ts +1 -1
  21. package/dist/core/utils/TsMorphUtil.js +2 -1
  22. package/dist/json-plugin/JSONExecuteController.d.ts +4 -0
  23. package/dist/json-plugin/JSONExecuteController.js +46 -36
  24. package/dist/json-plugin/interfaces/impl/TargetContext.js +4 -2
  25. package/dist/json-plugin/tasks/BaseTask.d.ts +2 -2
  26. package/dist/json-plugin/tasks/WatchTask.js +2 -1
  27. package/package.json +1 -1
  28. package/src/core/Types.ts +90 -90
  29. package/src/core/analyzers/ClassAnalyzer.ts +335 -230
  30. package/src/core/analyzers/CustomTypeAnalyzer.ts +145 -73
  31. package/src/core/constants/DecoratorConstants.ts +7 -6
  32. package/src/core/constants/PathConstants.ts +7 -7
  33. package/src/core/constants/StringConstants.ts +95 -95
  34. package/src/core/handlers/BaseTypeHandler.ts +11 -2
  35. package/src/core/handlers/CustomClassHandler.ts +4 -4
  36. package/src/core/handlers/DateHandler.ts +54 -46
  37. package/src/core/handlers/DecimalHandler.ts +53 -45
  38. package/src/core/handlers/EnumHandler.ts +2 -1
  39. package/src/core/handlers/GenericContainerHandler.ts +3 -1
  40. package/src/core/handlers/TupleHandler.ts +2 -1
  41. package/src/core/handlers/TypeHandlerRegistry.ts +2 -1
  42. package/src/core/handlers/UnionTypeHandler.ts +8 -7
  43. package/src/core/import-rewrite/services/BuildProfileUpdater.ts +6 -4
  44. package/src/core/import-rewrite/services/ImportRewriteService.ts +1 -1
  45. package/src/core/import-rewrite/services/ImportTransformService.ts +2 -2
  46. package/src/core/import-rewrite/types/ImportRewriteTypes.ts +3 -3
  47. package/src/core/index.ts +4 -4
  48. package/src/core/interfaces/ITask.ts +6 -5
  49. package/src/core/interfaces/ITaskContext.ts +9 -9
  50. package/src/core/interfaces/index.ts +2 -2
  51. package/src/core/logger/Logger.ts +28 -28
  52. package/src/core/services/CodeAnalysisService.ts +2 -1
  53. package/src/core/services/CodeGenerationEngine.ts +42 -42
  54. package/src/core/services/CodeGenerationService/generators/OriginalClassGenerator.ts +25 -22
  55. package/src/core/services/CodeGenerationService/generators/SendableClassGenerator.ts +261 -170
  56. package/src/core/services/CodeGenerationService/generators/SerializerGenerator.ts +1 -1
  57. package/src/core/services/CodeGenerationService/generators/TempSerializerGenerator.ts +5 -3
  58. package/src/core/services/CodeGenerationService/shared/ImportManager.ts +8 -8
  59. package/src/core/template/HandlebarsTemplateEngine.ts +39 -11
  60. package/src/core/utils/ConfigManager.ts +2 -1
  61. package/src/core/utils/DeepCopyUtil.ts +1 -1
  62. package/src/core/utils/GenericTypeSubstitutionUtil.ts +1 -8
  63. package/src/core/utils/SerializationPathUtil.ts +7 -6
  64. package/src/core/utils/TsMorphUtil.ts +4 -1
  65. package/src/index.ts +2 -2
  66. package/src/json-plugin/JSONExecuteController.ts +51 -38
  67. package/src/json-plugin/interfaces/IModuleContext.ts +8 -8
  68. package/src/json-plugin/interfaces/ITargetContext.ts +6 -6
  69. package/src/json-plugin/interfaces/impl/ModuleContext.ts +10 -10
  70. package/src/json-plugin/interfaces/impl/TargetContext.ts +63 -58
  71. package/src/json-plugin/tasks/BaseTask.ts +5 -3
  72. package/src/json-plugin/tasks/CleanTask.ts +7 -7
  73. package/src/json-plugin/tasks/WatchTask.ts +20 -18
  74. package/template/SerializerPerformanceTemplate.hbs +5 -5
  75. package/template/SerializerStrictTemplate.hbs +1 -1
  76. package/template/SerializerTemplate.hbs +59 -42
@@ -15,8 +15,16 @@
15
15
 
16
16
  import * as Handlebars from 'handlebars';
17
17
  import {
18
- ClassAnalysis, ConstructorParam, DecoratorConstants, DeserializationMode, GenerationContext, InterfaceAnalysis,
19
- PropertyAnalysis, PropertyDecorators, PropertyGenerationInfo, PropertyKind
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
- const primitives = ['string', 'number', 'boolean', 'bigint', 'undefined', 'null'];
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 = decorators.some(decorator =>
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
  });
@@ -233,7 +260,8 @@ export class HandlebarsTemplateEngine {
233
260
 
234
261
  // 过滤出泛型类型的属性(用于生成静态方法的泛型序列化器参数)
235
262
  this.registerHelper('filterGenericProperties', (properties: PropertyGenerationInfo[]) => {
236
- return properties.filter(p => p.analysis.type.kind === PropertyKind.GENERIC && !p.analysis.decorators?.isTransient);
263
+ return properties.filter(
264
+ p => p.analysis.type.kind === PropertyKind.GENERIC && !p.analysis.decorators?.isTransient);
237
265
  });
238
266
  }
239
267
 
@@ -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) {
@@ -175,7 +175,7 @@ export class DeepCopyUtil {
175
175
  if (typeof obj === 'object') {
176
176
  const copy: any = {};
177
177
  for (const key in obj) {
178
- if (obj.hasOwnProperty(key)) {
178
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
179
179
  copy[key] = this.deepCopy((obj as any)[key]);
180
180
  }
181
181
  }
@@ -111,13 +111,6 @@ export class GenericTypeSubstitutionUtil {
111
111
  }
112
112
 
113
113
 
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
114
  // 重新计算依赖信息
122
115
  newStructure.dependencies = this.collectDependenciesFromChildren(newStructure);
123
116
 
@@ -131,7 +124,7 @@ export class GenericTypeSubstitutionUtil {
131
124
  return TypeHandlerRegistry.getInstance().parseType(typeNode, {
132
125
  depth: 0,
133
126
  genericParams: currentClassGenericParams // ✅ 传递当前类的泛型参数上下文
134
- })
127
+ });
135
128
  }
136
129
 
137
130
  /**
@@ -14,8 +14,8 @@
14
14
  */
15
15
 
16
16
  import { FileUtil } from '@ohos/hvigor';
17
- import * as path from "path";
18
- import * as fs from "fs";
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 = (scanPath: string, relativePath: string) => {
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
 
@@ -18,7 +18,10 @@ import { Logger } from '../logger/Logger';
18
18
 
19
19
  export class TsMorphUtil {
20
20
  public static project: Project | null = null;
21
- private constructor() { }
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项目');
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
- cleanTask.beforeRun(() => {
125
- const generatedRootDir = targetContext.getOutputRoot();
126
-
127
- if (SerializationPathUtil.exist(generatedRootDir)) {
128
- Logger.info(`Clean up the generated directory: ${generatedRootDir}`);
129
- SerializationPathUtil.rmSync(generatedRootDir, { recursive: true, force: true });
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
  }
@@ -13,24 +13,24 @@
13
13
  * limitations under the License.
14
14
  */
15
15
 
16
- import { Target } from '@ohos/hvigor-ohos-plugin'
17
- import { ModuleBuildProfile } from '@ohos/hvigor-ohos-plugin/src/options/build/module-build-profile'
18
- import { PathConstants} from '../../../core';
19
- import { IModuleContext } from '../IModuleContext'
20
- import { ITargetContext } from '../ITargetContext'
16
+ import { Target } from '@ohos/hvigor-ohos-plugin';
17
+ import { ModuleBuildProfile } from '@ohos/hvigor-ohos-plugin/src/options/build/module-build-profile';
18
+ import { PathConstants } from '../../../core';
19
+ import { IModuleContext } from '../IModuleContext';
20
+ import { ITargetContext } from '../ITargetContext';
21
21
  import SerializationPathUtil from '../../../core/utils/SerializationPathUtil';
22
22
  import { CustomError, ErrorCodes } from '../../../core/utils/CustomError';
23
23
 
24
24
  export class TargetContextImpl implements ITargetContext {
25
- readonly target: Target
26
- readonly context: IModuleContext
25
+ readonly target: Target;
26
+ readonly context: IModuleContext;
27
27
 
28
- private readonly DEFAULT_SOURCE_ROOT = PathConstants.DEFAULT_SOURCE_ROOT
29
- private readonly GENERATED_ROOT = PathConstants.GENERATED_ROOT
28
+ private readonly DEFAULT_SOURCE_ROOT = PathConstants.DEFAULT_SOURCE_ROOT;
29
+ private readonly GENERATED_ROOT = PathConstants.GENERATED_ROOT;
30
30
 
31
31
  constructor(target: Target, context: IModuleContext) {
32
- this.target = target
33
- this.context = context
32
+ this.target = target;
33
+ this.context = context;
34
34
  }
35
35
 
36
36
  private get targetOpt(): ModuleBuildProfile.ModuleTargetBuildOpt {
@@ -46,21 +46,21 @@ export class TargetContextImpl implements ITargetContext {
46
46
  */
47
47
  getCurrentTargetScanFiles(): string[] {
48
48
  // 获取当前目标的所有源代码根目录的绝对路径
49
- const absoluteSourceRoots = this.getAbsoluteSourceRoots()
49
+ const absoluteSourceRoots = this.getAbsoluteSourceRoots();
50
50
 
51
51
  // 过滤扫描文件,只保留在当前目标源代码根目录下的文件
52
52
  return this.context.scanFiles.filter(item => {
53
53
  // 标准化文件路径格式,确保路径分隔符统一
54
- const normalizedFilePath = SerializationPathUtil.normalize(item)
54
+ const normalizedFilePath = SerializationPathUtil.normalize(item);
55
55
 
56
56
  // 检查文件路径是否以任一源代码根目录开头
57
57
  // 这样可以确保只处理属于当前目标的文件
58
- return absoluteSourceRoots.some(sourceRoot => normalizedFilePath.startsWith(sourceRoot))
59
- })
58
+ return absoluteSourceRoots.some(sourceRoot => normalizedFilePath.startsWith(sourceRoot));
59
+ });
60
60
  }
61
61
 
62
62
  getModuleName(): string {
63
- return this.context.moduleContext.getModuleName()
63
+ return this.context.moduleContext.getModuleName();
64
64
  }
65
65
 
66
66
  getModulePath(): string {
@@ -69,104 +69,108 @@ export class TargetContextImpl implements ITargetContext {
69
69
 
70
70
  getPackageName(): string {
71
71
  // 这里需要获取oh-package.json5中配置的name
72
- const packagePath = SerializationPathUtil.pathResolve(this.getModulePath(), 'oh-package.json5')
73
- const ohPackageObj = SerializationPathUtil.readJson5(packagePath)
74
- return ohPackageObj.name
72
+ const packagePath = SerializationPathUtil.pathResolve(this.getModulePath(), 'oh-package.json5');
73
+ const ohPackageObj = SerializationPathUtil.readJson5(packagePath);
74
+ return ohPackageObj.name;
75
75
  }
76
76
 
77
77
  mapToOutputPath(absSourceFile: string): string {
78
- const normalizedFilePath = SerializationPathUtil.normalize(absSourceFile)
79
- const moduleRoot = this.context.moduleContext.getModulePath()
80
- const srcMainAbs = SerializationPathUtil.normalize(SerializationPathUtil.pathResolve(moduleRoot, this.DEFAULT_SOURCE_ROOT))
81
- const generatedRootAbs = this.getOutputRoot()
78
+ const normalizedFilePath = SerializationPathUtil.normalize(absSourceFile);
79
+ const moduleRoot = this.context.moduleContext.getModulePath();
80
+ const srcMainAbs = SerializationPathUtil.normalize(
81
+ SerializationPathUtil.pathResolve(moduleRoot, this.DEFAULT_SOURCE_ROOT));
82
+ const generatedRootAbs = this.getOutputRoot();
82
83
 
83
84
  // 优先基于 src/main 做路径映射
84
85
  if (normalizedFilePath.startsWith(srcMainAbs + SerializationPathUtil.sep)) {
85
- const relativeToSrcMain = SerializationPathUtil.relative(srcMainAbs, normalizedFilePath)
86
- return SerializationPathUtil.join(generatedRootAbs, relativeToSrcMain)
86
+ const relativeToSrcMain = SerializationPathUtil.relative(srcMainAbs, normalizedFilePath);
87
+ return SerializationPathUtil.join(generatedRootAbs, relativeToSrcMain);
87
88
  }
88
89
 
89
90
  // 如果文件不在 src/main 下,退化为:找到匹配的任一 sourceRoot,映射到 generated 根下
90
- const absoluteSourceRoots = this.getAbsoluteSourceRoots()
91
- const matchedRoot = absoluteSourceRoots.find(root => normalizedFilePath.startsWith(root))
91
+ const absoluteSourceRoots = this.getAbsoluteSourceRoots();
92
+ const matchedRoot = absoluteSourceRoots.find(root => normalizedFilePath.startsWith(root));
92
93
  if (matchedRoot) {
93
- const rel = SerializationPathUtil.relative(matchedRoot, normalizedFilePath)
94
- return SerializationPathUtil.join(generatedRootAbs, rel)
94
+ const rel = SerializationPathUtil.relative(matchedRoot, normalizedFilePath);
95
+ return SerializationPathUtil.join(generatedRootAbs, rel);
95
96
  }
96
97
 
97
98
  // 否则直接放在 generated 根下,保持文件名
98
- return SerializationPathUtil.join(generatedRootAbs, SerializationPathUtil.basename(normalizedFilePath))
99
+ return SerializationPathUtil.join(generatedRootAbs, SerializationPathUtil.basename(normalizedFilePath));
99
100
  }
100
101
 
101
102
  getOutputRoot(): string {
102
- const moduleRoot = this.context.moduleContext.getModulePath()
103
- const absolutePath = SerializationPathUtil.pathResolve(moduleRoot, this.GENERATED_ROOT)
104
- return SerializationPathUtil.normalize(absolutePath)
103
+ const moduleRoot = this.context.moduleContext.getModulePath();
104
+ const absolutePath = SerializationPathUtil.pathResolve(moduleRoot, this.GENERATED_ROOT);
105
+ return SerializationPathUtil.normalize(absolutePath);
105
106
  }
106
107
 
107
108
  getRelativePath(absolutePath: string): string {
108
- const outputRoot = this.getOutputRoot()
109
+ const outputRoot = this.getOutputRoot();
109
110
  // 从输出根目录推断项目根目录
110
111
  // 假设输出根目录为: <module>/src/generated
111
- const moduleRoot = SerializationPathUtil.dirname(SerializationPathUtil.dirname(outputRoot))
112
+ const moduleRoot = SerializationPathUtil.dirname(SerializationPathUtil.dirname(outputRoot));
112
113
 
113
114
  try {
114
- return SerializationPathUtil.relative(moduleRoot, absolutePath).replaceAll(SerializationPathUtil.sep, '/')
115
+ return SerializationPathUtil.relative(moduleRoot, absolutePath).replaceAll(SerializationPathUtil.sep, '/');
115
116
  } catch (error) {
116
117
  // 如果相对路径计算失败,返回原路径
117
- return absolutePath
118
+ return absolutePath;
118
119
  }
119
120
  }
120
121
 
121
122
  isValidOutputPath(outputPath: string): boolean {
122
123
  try {
123
- const outputRoot = this.getOutputRoot()
124
- const resolvedOutputPath = SerializationPathUtil.pathResolve(outputPath)
125
- const resolvedOutputRoot = SerializationPathUtil.pathResolve(outputRoot)
124
+ const outputRoot = this.getOutputRoot();
125
+ const resolvedOutputPath = SerializationPathUtil.pathResolve(outputPath);
126
+ const resolvedOutputRoot = SerializationPathUtil.pathResolve(outputRoot);
126
127
 
127
128
  // 检查输出路径是否在输出根目录下
128
- return resolvedOutputPath.startsWith(resolvedOutputRoot)
129
+ return resolvedOutputPath.startsWith(resolvedOutputRoot);
129
130
  } catch (error) {
130
- return false
131
+ return false;
131
132
  }
132
133
  }
133
134
 
134
135
  ensureOutputDirectory(outputPath: string): void {
135
- SerializationPathUtil.ensureDirSync(SerializationPathUtil.dirname(outputPath))
136
+ SerializationPathUtil.ensureDirSync(SerializationPathUtil.dirname(outputPath));
136
137
  }
137
138
 
138
139
  calculateSourceRootToModuleRoot(absolutePath: string): string {
139
140
  // 处理Windows环境路径兼容性
140
- const normalizedAbsolutePath = absolutePath.replaceAll(SerializationPathUtil.sep, '/')
141
+ const normalizedAbsolutePath = absolutePath.replaceAll(SerializationPathUtil.sep, '/');
141
142
 
142
143
  // 获取所有源根路径并标准化为统一格式(以 / 结尾)
143
144
  const sourceRoots = this.getAbsoluteSourceRoots().map(root =>
144
145
  root.replaceAll(SerializationPathUtil.sep, '/').replace(/\/$/, '') + '/'
145
- )
146
+ );
146
147
 
147
148
  // 找到匹配的源根路径
148
- const sourceRoot = sourceRoots.find(root => normalizedAbsolutePath.startsWith(root))
149
+ const sourceRoot = sourceRoots.find(root => normalizedAbsolutePath.startsWith(root));
149
150
 
150
151
  if (!sourceRoot) {
151
- throw new CustomError(`无法找到匹配的源根路径: ${normalizedAbsolutePath}。可用的源根路径: ${sourceRoots.join(', ')}`, ErrorCodes.ROOT_DIRECTROY_NOT_FOUND)
152
+ throw new CustomError(
153
+ `无法找到匹配的源根路径: ${normalizedAbsolutePath}。可用的源根路径: ${sourceRoots.join(', ')}`,
154
+ ErrorCodes.ROOT_DIRECTROY_NOT_FOUND);
152
155
  }
153
156
 
154
157
  // 计算相对路径,移除源根路径的尾部分隔符进行计算
155
- const sourceRootForRelative = sourceRoot.replace(/\/$/, '')
156
- const absolutePathForRelative = normalizedAbsolutePath.replace(/\/$/, '')
158
+ const sourceRootForRelative = sourceRoot.replace(/\/$/, '');
159
+ const absolutePathForRelative = normalizedAbsolutePath.replace(/\/$/, '');
157
160
 
158
- return SerializationPathUtil.relative(sourceRootForRelative, absolutePathForRelative).replaceAll(SerializationPathUtil.sep, '/')
161
+ return SerializationPathUtil.relative(sourceRootForRelative, absolutePathForRelative)
162
+ .replaceAll(SerializationPathUtil.sep, '/');
159
163
  }
160
164
 
161
165
  private get targetSourceRoots(): string[] {
162
166
  if (!this.targetOpt.source?.sourceRoots) {
163
- return [this.DEFAULT_SOURCE_ROOT]
167
+ return [this.DEFAULT_SOURCE_ROOT];
164
168
  }
165
169
  // 检查默认路径是否已包含在sourceRoots中
166
170
  if (!this.targetOpt.source.sourceRoots.includes(this.DEFAULT_SOURCE_ROOT)) {
167
- return [this.DEFAULT_SOURCE_ROOT, ...this.targetOpt.source.sourceRoots]
171
+ return [this.DEFAULT_SOURCE_ROOT, ...this.targetOpt.source.sourceRoots];
168
172
  }
169
- return this.targetOpt.source.sourceRoots
173
+ return this.targetOpt.source.sourceRoots;
170
174
  }
171
175
 
172
176
  /**
@@ -177,20 +181,21 @@ export class TargetContextImpl implements ITargetContext {
177
181
  */
178
182
  private getAbsoluteSourceRoots(): string[] {
179
183
  // 获取当前模块的根目录路径
180
- const moduleRoot = this.context.moduleContext.getModulePath()
184
+ const moduleRoot = this.context.moduleContext.getModulePath();
181
185
 
182
186
  // 将每个相对路径源代码根目录转换为绝对路径
183
187
  return this.targetSourceRoots.map((sourceRoot: string) => {
184
188
  // 将相对路径解析为基于模块根目录的绝对路径
185
189
  // path.resolve 会处理相对路径符号(如 ../ ./)
186
- const absolutePath = SerializationPathUtil.pathResolve(moduleRoot, sourceRoot)
190
+ const absolutePath = SerializationPathUtil.pathResolve(moduleRoot, sourceRoot);
187
191
 
188
192
  // 标准化路径格式,确保路径分隔符统一,处理多余的分隔符
189
- const normalizedPath = SerializationPathUtil.normalize(absolutePath)
193
+ const normalizedPath = SerializationPathUtil.normalize(absolutePath);
190
194
 
191
195
  // 确保路径以分隔符结尾,避免路径匹配错误
192
196
  // 例如:/project/src 不会错误匹配 /project/src2
193
- return normalizedPath.endsWith(SerializationPathUtil.sep) ? normalizedPath : normalizedPath + SerializationPathUtil.sep
194
- })
197
+ return normalizedPath.endsWith(SerializationPathUtil.sep) ? normalizedPath :
198
+ normalizedPath + SerializationPathUtil.sep;
199
+ });
195
200
  }
196
201
  }