17c804472Sopenharmony_ci/*
27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47c804472Sopenharmony_ci * you may not use this file except in compliance with the License.
57c804472Sopenharmony_ci * You may obtain a copy of the License at
67c804472Sopenharmony_ci *
77c804472Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87c804472Sopenharmony_ci *
97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c804472Sopenharmony_ci * See the License for the specific language governing permissions and
137c804472Sopenharmony_ci * limitations under the License.
147c804472Sopenharmony_ci */
157c804472Sopenharmony_ci
167c804472Sopenharmony_ciimport fs from 'fs';
177c804472Sopenharmony_ciimport path from 'path';
187c804472Sopenharmony_ciimport ts from 'typescript';
197c804472Sopenharmony_ciimport { ImportElementEntity } from '../declaration-node/importAndExportDeclaration';
207c804472Sopenharmony_ci
217c804472Sopenharmony_ciexport interface KitImportInfo {
227c804472Sopenharmony_ci  fromPath: string;
237c804472Sopenharmony_ci  isExport: string[];
247c804472Sopenharmony_ci  isDefaultExport: string;
257c804472Sopenharmony_ci}
267c804472Sopenharmony_ci
277c804472Sopenharmony_ci// kit file map
287c804472Sopenharmony_ciexport const KIT_MAP = new Map<string, KitImportInfo[]>();
297c804472Sopenharmony_ci
307c804472Sopenharmony_ci/**
317c804472Sopenharmony_ci * get all kit files
327c804472Sopenharmony_ci * @param kitDir root path
337c804472Sopenharmony_ci */
347c804472Sopenharmony_ciexport function collectAllKitFiles(kitDir: string): void {
357c804472Sopenharmony_ci  const arr = fs.readdirSync(kitDir);
367c804472Sopenharmony_ci  arr.forEach(value => {
377c804472Sopenharmony_ci    const fullPath = path.join(kitDir, value);
387c804472Sopenharmony_ci    const stats = fs.statSync(fullPath);
397c804472Sopenharmony_ci    if (stats.isDirectory()) {
407c804472Sopenharmony_ci      collectAllKitFiles(fullPath);
417c804472Sopenharmony_ci    } else {
427c804472Sopenharmony_ci      let fileBaseName: string;
437c804472Sopenharmony_ci      if (value.endsWith('.d.ts')) {
447c804472Sopenharmony_ci        fileBaseName = path.basename(value, '.d.ts');
457c804472Sopenharmony_ci      }
467c804472Sopenharmony_ci      if (fileBaseName) {
477c804472Sopenharmony_ci        handleKitFile(fullPath, fileBaseName);
487c804472Sopenharmony_ci      }
497c804472Sopenharmony_ci    }
507c804472Sopenharmony_ci  });
517c804472Sopenharmony_ci}
527c804472Sopenharmony_ci
537c804472Sopenharmony_ci/**
547c804472Sopenharmony_ci * kit file convert to ast
557c804472Sopenharmony_ci * @param kitPath kit file path
567c804472Sopenharmony_ci * @param fileName kit file name
577c804472Sopenharmony_ci */
587c804472Sopenharmony_cifunction handleKitFile(kitPath: string, fileName: string): void {
597c804472Sopenharmony_ci  KIT_MAP.set(fileName, []);
607c804472Sopenharmony_ci
617c804472Sopenharmony_ci  const code = fs.readFileSync(kitPath);
627c804472Sopenharmony_ci  const sourceFile = ts.createSourceFile(kitPath, code.toString(), ts.ScriptTarget.Latest);
637c804472Sopenharmony_ci  sourceFile.forEachChild(node => {
647c804472Sopenharmony_ci    if (ts.isImportDeclaration(node)) {
657c804472Sopenharmony_ci      KIT_MAP.get(fileName).push(getKitImportDeclaration(node));
667c804472Sopenharmony_ci    }
677c804472Sopenharmony_ci  });
687c804472Sopenharmony_ci}
697c804472Sopenharmony_ci
707c804472Sopenharmony_ci/**
717c804472Sopenharmony_ci * get kit file import declaration
727c804472Sopenharmony_ci * @param importNode kit file import node
737c804472Sopenharmony_ci * @returns KitImportInfo
747c804472Sopenharmony_ci */
757c804472Sopenharmony_ciexport function getKitImportDeclaration(importNode: ts.ImportDeclaration): KitImportInfo {
767c804472Sopenharmony_ci  let isDefaultExport = '';
777c804472Sopenharmony_ci  const isExport = [];
787c804472Sopenharmony_ci  const moduleSpecifier = importNode.moduleSpecifier as ts.StringLiteral;
797c804472Sopenharmony_ci  const fromPath = moduleSpecifier.text.trim();
807c804472Sopenharmony_ci  const importClause = importNode.importClause;
817c804472Sopenharmony_ci  if (importClause !== undefined) {
827c804472Sopenharmony_ci    if (importClause.name) {
837c804472Sopenharmony_ci      isDefaultExport = importClause.name.text.trim();
847c804472Sopenharmony_ci    }
857c804472Sopenharmony_ci    importClause.namedBindings?.forEachChild((node: ts.ImportSpecifier) => {
867c804472Sopenharmony_ci      if (node.name) {
877c804472Sopenharmony_ci        isExport.push(node.name.text.trim());
887c804472Sopenharmony_ci      }
897c804472Sopenharmony_ci    });
907c804472Sopenharmony_ci  }
917c804472Sopenharmony_ci
927c804472Sopenharmony_ci  return {
937c804472Sopenharmony_ci    fromPath,
947c804472Sopenharmony_ci    isDefaultExport,
957c804472Sopenharmony_ci    isExport
967c804472Sopenharmony_ci  };
977c804472Sopenharmony_ci}
987c804472Sopenharmony_ci
997c804472Sopenharmony_ci/**
1007c804472Sopenharmony_ci * handle kit file import map info
1017c804472Sopenharmony_ci * @param importEntity import entity data
1027c804472Sopenharmony_ci * @returns ImportElementEntity[]
1037c804472Sopenharmony_ci */
1047c804472Sopenharmony_ciexport function handleImportKit(importEntity: ImportElementEntity): ImportElementEntity[] {
1057c804472Sopenharmony_ci  const importPath = importEntity.importPath.replace(/(\'|\")/g, '');
1067c804472Sopenharmony_ci  if (!importPath.startsWith('@kit.')) {
1077c804472Sopenharmony_ci    return [];
1087c804472Sopenharmony_ci  }
1097c804472Sopenharmony_ci  const importEntities: ImportElementEntity[] = [];
1107c804472Sopenharmony_ci  let importElements: string[];
1117c804472Sopenharmony_ci  if (importEntity.importElements.startsWith('{') && importEntity.importElements.endsWith('}')) {
1127c804472Sopenharmony_ci    importElements = importEntity.importElements
1137c804472Sopenharmony_ci      .substring(1, importEntity.importElements.length - 1)
1147c804472Sopenharmony_ci      .split(',')
1157c804472Sopenharmony_ci      .map(element => element.trim());
1167c804472Sopenharmony_ci  }
1177c804472Sopenharmony_ci
1187c804472Sopenharmony_ci  const kitImportInfos: KitImportInfo[] = KIT_MAP.get(importPath);
1197c804472Sopenharmony_ci  if (!kitImportInfos) {
1207c804472Sopenharmony_ci    throw new Error(`Can't find kitFileInfos from ${importPath}`);
1217c804472Sopenharmony_ci  }
1227c804472Sopenharmony_ci
1237c804472Sopenharmony_ci  importElements.forEach(element => {
1247c804472Sopenharmony_ci    importEntities.push(getKitImportInfo(kitImportInfos, element, importPath));
1257c804472Sopenharmony_ci  });
1267c804472Sopenharmony_ci  return importEntities;
1277c804472Sopenharmony_ci}
1287c804472Sopenharmony_ci
1297c804472Sopenharmony_ci/**
1307c804472Sopenharmony_ci * get Kit file import map info
1317c804472Sopenharmony_ci * @param kitImportInfos map infos
1327c804472Sopenharmony_ci * @param element import entity info
1337c804472Sopenharmony_ci * @param importPath import file path
1347c804472Sopenharmony_ci * @returns ImportElementEntity
1357c804472Sopenharmony_ci */
1367c804472Sopenharmony_cifunction getKitImportInfo(kitImportInfos: KitImportInfo[], element: string, importPath: string): ImportElementEntity {
1377c804472Sopenharmony_ci  let defaultImport: string;
1387c804472Sopenharmony_ci  let commonImport: string;
1397c804472Sopenharmony_ci  const kitImportInfo = kitImportInfos.find(kitInfo => {
1407c804472Sopenharmony_ci    if (element === kitInfo.isDefaultExport) {
1417c804472Sopenharmony_ci      defaultImport = kitInfo.isDefaultExport;
1427c804472Sopenharmony_ci      return true;
1437c804472Sopenharmony_ci    } else if (kitInfo.isExport.includes(element)) {
1447c804472Sopenharmony_ci      commonImport = element;
1457c804472Sopenharmony_ci      return true;
1467c804472Sopenharmony_ci    } else {
1477c804472Sopenharmony_ci      return false;
1487c804472Sopenharmony_ci    }
1497c804472Sopenharmony_ci  });
1507c804472Sopenharmony_ci
1517c804472Sopenharmony_ci  if (!kitImportInfo) {
1527c804472Sopenharmony_ci    throw new Error(`Can't find ${element} from ${importPath}`);
1537c804472Sopenharmony_ci  }
1547c804472Sopenharmony_ci
1557c804472Sopenharmony_ci  const defaultImportStr = defaultImport ? `${defaultImport}${commonImport ? ',' : ''}` : '';
1567c804472Sopenharmony_ci  const commonImportsStr = commonImport ? `{ ${commonImport} }` : '';
1577c804472Sopenharmony_ci  return {
1587c804472Sopenharmony_ci    importElements: `${defaultImportStr} ${commonImportsStr}`,
1597c804472Sopenharmony_ci    importPath: kitImportInfo.fromPath
1607c804472Sopenharmony_ci  };
1617c804472Sopenharmony_ci}
162