• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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