1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import type {Node, TransformerFactory} from 'typescript'; 17import {lstatSync, readdirSync} from 'fs'; 18import {join, resolve} from 'path'; 19 20import type {IOptions} from '../configs/IOptions'; 21import type {TransformPlugin} from './TransformPlugin'; 22import { Extension } from '../common/type'; 23 24export class TransformerManager { 25 private static sInstance: TransformerManager | null = null; 26 27 private static readonly sLoadPath: string = join(__dirname, '../', 'transformers'); 28 29 private readonly mTransformers: TransformerFactory<Node>[]; 30 31 public static getInstance(options: IOptions): TransformerManager { 32 if (!this.sInstance) { 33 this.sInstance = new TransformerManager(); 34 this.sInstance.loadTransformers(options); 35 } 36 37 return this.sInstance as TransformerManager; 38 } 39 40 private constructor() { 41 this.mTransformers = []; 42 } 43 44 public getTransformers(): TransformerFactory<Node>[] { 45 return this.mTransformers; 46 } 47 48 private loadTransformers(options: IOptions): TransformerFactory<Node>[] { 49 let subFiles: string[] = readdirSync(TransformerManager.sLoadPath); 50 let plugins: TransformPlugin[] = []; 51 for (const subFile of subFiles) { 52 let subPath: string = resolve(TransformerManager.sLoadPath + '/' + subFile); 53 let isDir: boolean = lstatSync(subPath)?.isDirectory(); 54 if (!isDir) { 55 continue; 56 } 57 58 let subDir: string[] = readdirSync(subPath); 59 for (const file of subDir) { 60 if (!file.endsWith(Extension.TS)) { 61 continue; 62 } 63 const fileNameNoSuffix = file.lastIndexOf(Extension.DTS) > -1 ? file.slice(0, file.lastIndexOf(Extension.DTS)) : 64 file.slice(0, file.lastIndexOf(Extension.TS)); 65 let path: string = join(subPath, fileNameNoSuffix); 66 let module = require(path); 67 let plugin: TransformPlugin = module?.transformerPlugin; 68 if (plugin) { 69 plugins.push(plugin as TransformPlugin); 70 } 71 } 72 } 73 74 plugins.sort((plugin1: TransformPlugin, plugin2: TransformPlugin) => { 75 return plugin1.order - plugin2.order; 76 }); 77 78 plugins.forEach((plugin: TransformPlugin) => { 79 let transformerFactory: TransformerFactory<Node> = plugin?.createTransformerFactory(options); 80 let name: string = plugin?.name; 81 if (transformerFactory && name) { 82 this.mTransformers.push(transformerFactory); 83 } 84 }); 85 86 return this.mTransformers; 87 } 88} 89