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'; 22 23export class TransformerManager { 24 private static sInstance: TransformerManager | null = null; 25 26 private static readonly sLoadPath: string = join(__dirname, '../', 'transformers'); 27 28 private readonly mTransformers: TransformerFactory<Node>[]; 29 30 public static getInstance(): TransformerManager { 31 if (!this.sInstance) { 32 this.sInstance = new TransformerManager(); 33 } 34 35 return this.sInstance as TransformerManager; 36 } 37 38 private constructor() { 39 this.mTransformers = []; 40 } 41 42 public loadTransformers(options: IOptions): TransformerFactory<Node>[] { 43 let subFiles: string[] = readdirSync(TransformerManager.sLoadPath); 44 let plugins: TransformPlugin[] = []; 45 for (const subFile of subFiles) { 46 let subPath: string = resolve(TransformerManager.sLoadPath + '/' + subFile); 47 let isDir: boolean = lstatSync(subPath)?.isDirectory(); 48 if (!isDir) { 49 continue; 50 } 51 52 let subDir: string[] = readdirSync(subPath); 53 for (const file of subDir) { 54 if (!file.endsWith('.ts')) { 55 continue; 56 } 57 const fileNameNoSuffix = file.lastIndexOf('.d.ts') > -1 ? file.slice(0, file.lastIndexOf('.d.ts')) : file.slice(0, file.lastIndexOf('.ts')); 58 let path: string = join(subPath, fileNameNoSuffix); 59 let module = require(path); 60 let plugin: TransformPlugin = module?.transformerPlugin; 61 if (plugin) { 62 plugins.push(plugin as TransformPlugin); 63 } 64 } 65 } 66 67 plugins.sort((plugin1: TransformPlugin, plugin2: TransformPlugin) => { 68 return plugin1.order - plugin2.order; 69 }); 70 71 plugins.forEach((plugin: TransformPlugin) => { 72 let transformerFactory: TransformerFactory<Node> = plugin?.createTransformerFactory(options); 73 let name: string = plugin?.name; 74 if (transformerFactory && name) { 75 this.mTransformers.push(transformerFactory); 76 } 77 }); 78 79 return this.mTransformers; 80 } 81} 82