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 { 17 ScriptTarget, 18 createCompilerHost, 19 createProgram, 20 createSourceFile, 21} from 'typescript'; 22 23import type { 24 CompilerHost, 25 CompilerOptions, 26 Program, 27 SourceFile, 28 TypeChecker, 29} from 'typescript'; 30import { Extension, PathAndExtension } from '../common/type'; 31import { FileUtils } from './FileUtils'; 32 33export class TypeUtils { 34 /** 35 * Create .d.ets, .d.ts, .ts ast from .d.ets, .d.ts, .ts content. 36 * Create .ts ast from .ets, .js content 37 * @param {string} sourceFilePath 38 * @param {string} content - The content in sourceFilePath 39 */ 40 public static createObfSourceFile(sourceFilePath: string, content: string): SourceFile { 41 const pathOrExtension: PathAndExtension = FileUtils.getFileSuffix(sourceFilePath); 42 const fileSuffix = pathOrExtension.ext; 43 44 if (fileSuffix === Extension.JS) { 45 sourceFilePath = pathOrExtension.path + Extension.TS; 46 } 47 48 return createSourceFile(sourceFilePath, content, ScriptTarget.ES2015, true); 49 } 50 51 public static tsToJs(ast: SourceFile): void { 52 const pathOrExtension: PathAndExtension = FileUtils.getFileSuffix(ast.fileName); 53 const fileSuffix = Extension.JS; 54 const targetName: string = pathOrExtension.path + fileSuffix; 55 ast.fileName = targetName; 56 } 57 58 public static createChecker(ast: SourceFile): TypeChecker { 59 const host: CompilerHost = createCompilerHost({}); 60 61 const customHost: CompilerHost = { 62 getSourceFile(name, languageVersion): SourceFile | undefined { 63 if (name === ast.fileName) { 64 return ast; 65 } else { 66 return host.getSourceFile(name, languageVersion); 67 } 68 }, 69 // optional 70 getDefaultLibLocation: () => '', 71 getDefaultLibFileName: () => '', 72 writeFile: (filename, data) => { 73 }, 74 getCurrentDirectory: () => '', 75 useCaseSensitiveFileNames: host.useCaseSensitiveFileNames, 76 getCanonicalFileName: host.getCanonicalFileName, 77 getNewLine: host.getNewLine, 78 fileExists: () => true, 79 readFile: (name): string => { 80 return name === ast.fileName ? ast.text : host.readFile(name); 81 }, 82 // must, read program.ts => createCompilerHost 83 directoryExists: undefined, 84 getEnvironmentVariable: undefined, 85 getDirectories: undefined, 86 }; 87 88 let option: CompilerOptions = {}; 89 if (ast.fileName.endsWith('.js')) { 90 option.allowJs = true; 91 } 92 93 let program: Program = createProgram([ast.fileName], option, customHost); 94 return program.getTypeChecker(); 95 } 96} 97