• 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 * as fs from 'fs';
17import * as path from 'path';
18import { logger } from './compile_info';
19const { projectConfig } = require('../main');
20
21const red: string = '\u001b[31m';
22const reset: string = '\u001b[39m';
23
24const REG_OHM_URL: RegExp = /^@bundle:(\S+)\/(\S+)\/(ets|js)\/(\S+)$/;
25
26export class OHMResolverPlugin {
27  private source: any;
28  private target: any;
29
30  constructor(source = 'resolve', target = 'resolve') {
31    this.source = source;
32    this.target = target;
33  }
34
35  apply(resolver) {
36    const target: any = resolver.ensureHook(this.target);
37    resolver.getHook(this.source).tapAsync('OHMResolverPlugin', (request, resolveContext, callback) => {
38      if (isOhmUrl(request.request)) {
39        const resolvedSourceFile: string = resolveSourceFile(request.request);
40        const obj = Object.assign({}, request, {
41          request: resolvedSourceFile
42        });
43        return resolver.doResolve(target, obj, null, resolveContext, callback);
44      }
45      callback();
46    });
47  }
48}
49
50export function isOhmUrl(moduleRequest: string): boolean {
51  return !!/^@(\S+):/.test(moduleRequest);
52}
53
54function addExtension(file: string, srcPath: string): string {
55  let extension: string = '.d.ts';
56  if (fs.existsSync(file + '.ets') && fs.statSync(file + '.ets').isFile()) {
57    extension = '.ets';
58  }
59  if (fs.existsSync(file + '.ts') && fs.statSync(file + '.ts').isFile()) {
60    if (extension !== '.d.ts') {
61      logger.error(red, `ArkTS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset);
62    }
63    extension = '.ts';
64  }
65  if (fs.existsSync(file + '.js') && fs.statSync(file + '.js').isFile()) {
66    if (extension !== '.d.ts') {
67      logger.error(red, `ArkTS:ERROR Failed to compile with files with same name ${srcPath} in the same directory`, reset);
68    }
69    extension = '.js';
70  }
71  return file + extension;
72}
73
74export function resolveSourceFile(ohmUrl: string): string {
75  if (!projectConfig.aceBuildJson) {
76    logger.error(red, `ArkTS:ERROR Failed to resolve OhmUrl because of aceBuildJson not existing `, reset);
77    return ohmUrl;
78  }
79
80  const result: RegExpMatchArray = ohmUrl.match(REG_OHM_URL);
81  const moduleName: string = result[2];
82  const srcKind: string = result[3];
83
84  const modulePath: string = projectConfig.modulePathMap[moduleName];
85  const srcRoot: string = projectConfig.isOhosTest ? 'src/ohosTest' : 'src/main';
86  let file: string = path.join(modulePath, srcRoot, srcKind, result[4]);
87  file = addExtension(file, result[4]);
88
89  if (!fs.existsSync(file) || !fs.statSync(file).isFile()) {
90    if (projectConfig.isOhosTest) {
91      file = path.join(modulePath, 'src/main', srcKind, result[4]);
92      file = addExtension(file, result[4]);
93
94      if (fs.existsSync(file) && fs.statSync(file).isFile()) {
95        return file;
96      }
97    }
98
99    logger.error(red, `ArkTS:ERROR Failed to resolve existed file by this ohm url ${ohmUrl} `, reset);
100  }
101
102  return file;
103}
104