• 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 path from 'path';
17import fs from 'fs';
18import { Node, SourceFile, JSDoc } from 'typescript';
19import { KeyValue, Members, MockBuffer } from '../types';
20import { D_ETS, D_TS, KeyValueTypes, NAPI_DIR_PATH, needShieldingDirOrFile } from './constants';
21import { getProjectDir } from './systemUtils';
22
23/**
24 * 递归创建文件夹
25 * @param dirname 需要创建文件夹的路径
26 * @returns 是否创建成功
27 */
28export function mkdirsSync(dirname: string): boolean {
29  if (fs.existsSync(dirname)) {
30    return true;
31  } else {
32    if (mkdirsSync(path.dirname(dirname))) {
33      fs.mkdirSync(dirname);
34      return true;
35    }
36  }
37  return false;
38}
39
40/**
41 * 生成KeyValue节点
42 * @param key 节点名称
43 * @param type 节点类型
44 * @param parent 该节点的父节点
45 * @param optionMembers 其他初始化参数
46 * @returns KeyValue节点
47 */
48export function generateKeyValue(key: string, type: KeyValueTypes, parent?: KeyValue, optionMembers?: {
49  members: Members,
50  typeParameters: Members,
51  methodParams: Members,
52  constraint: Members,
53  sameName: KeyValue[],
54  dependOnGlobals: Set<KeyValue>
55}): KeyValue {
56  const keyValue = {key, type, parent, sameDeclares: []} as KeyValue;
57  if (optionMembers) {
58    keyValue.members = optionMembers.members ?? {};
59    keyValue.typeParameters = optionMembers.typeParameters ?? {};
60    keyValue.methodParams = optionMembers.methodParams ?? {};
61    keyValue.constraint = optionMembers.constraint ?? {};
62    keyValue.sameName = optionMembers.sameName ?? [];
63    keyValue.dependOnGlobals = optionMembers.dependOnGlobals ?? new Set<KeyValue>();
64  } else {
65    keyValue.members = {};
66    keyValue.typeParameters = {};
67    keyValue.methodParams = {};
68    keyValue.constraint = {};
69    keyValue.sameName = [];
70    keyValue.dependOnGlobals = new Set<KeyValue>();
71  }
72  return keyValue as KeyValue;
73}
74
75/**
76 * 获取开源接口的api路径
77 */
78export function getOhosInterfacesDir(): string {
79  return path.join(getProjectDir(), 'interface', 'sdk-js', 'api');
80}
81
82/**
83 * 获取导入路径的绝对路径
84 * @param mockBuffer 文件mock缓存信息
85 * @param specifier 导入路径
86 * @returns 导入文件的绝对路径
87 */
88export function getAbsolutePath(mockBuffer: MockBuffer, specifier: string): string {
89  let absolutePath: string;
90  const importPath = specifier.replace(/['"]/g, '');
91  if (importPath.startsWith('./') || importPath.startsWith('../')) {
92    absolutePath = path.resolve(path.dirname(mockBuffer.mockedFilePath), importPath) + '.js';
93  } else if (importPath.startsWith('@ohos.') || importPath.startsWith('@system.')) {
94    absolutePath = path.join(NAPI_DIR_PATH, 'api', importPath) + '.js';
95  } else if (importPath.startsWith('@kit.')) {
96    absolutePath = path.join(NAPI_DIR_PATH, 'kits', importPath) + '.js';
97  } else if (importPath.startsWith('@arkts.')) {
98    absolutePath = path.join(NAPI_DIR_PATH, 'arkts', importPath) + '.js';
99  } else {
100    absolutePath = path.resolve(path.dirname(mockBuffer.mockedFilePath), importPath) + '.js';
101  }
102  return absolutePath;
103}
104
105/**
106 * 处理迭代器函数
107 * @param typeParams 迭代器返回值的类型参数
108 */
109export function handleIterableIterator(typeParams: string): string {
110  return `function* () {
111    const yieldObj = ${typeParams};
112    yield yieldObj;
113    yield yieldObj;
114    yield yieldObj;
115  }`;
116}
117
118/**
119 * 关联类型参数
120 * @param keyValue KV节点
121 * @param typeParameters
122 */
123export function associateTypeParameters(keyValue: KeyValue, typeParameters: Members): void {
124  if (!keyValue.property) {
125    keyValue.typeParameters = typeParameters;
126    return;
127  }
128  associateTypeParameters(keyValue.property, typeParameters);
129}
130
131/**
132 * 判断是否是类型申明文件
133 * @param fileName 文件名
134 */
135export function isDeclarationFile(fileName: string): boolean {
136  return fileName.endsWith(D_TS) || fileName.endsWith(D_ETS);
137}
138
139/**
140 * 判断文件是否需要被mock
141 * @param filePath 文件路径
142 */
143export function isNeedMocked(filePath: string): boolean {
144  if (path.basename(filePath).startsWith('@ohos.')) {
145    return true;
146  }
147  if (path.basename(filePath).startsWith('@arkts.')) {
148    return true;
149  }
150  return path.basename(filePath).startsWith('@kit.');
151}
152
153/**
154 * .d.ets 和 .d.ts文件同时存在时,过滤掉.d.ets文件
155 * @param value 文件名称
156 * @returns boolean
157 */
158export function identifyDuplicateFile(value: string, arr: string[]): boolean {
159  const baseName = path.basename(value);
160  if (baseName.includes('.static.d.')) {
161    return true;
162  }
163  const extName = path.extname(value);
164  if (extName === '.ets' && arr.includes(value.replace('.ets', '.ts'))) {
165    return true;
166  }
167  return false;
168}
169
170/**
171 * 过滤掉不需要mock的文件
172 * @param value 文件名称
173 * @returns boolean
174 */
175export function filterDuplicateFile(value: string): boolean {
176  for (let i = 0; i < needShieldingDirOrFile.length; i++) {
177    if (value.includes(needShieldingDirOrFile[i])) {
178      return true;
179    }
180  }
181  return false;
182}
183
184/**
185 * Determine whether the content contains arkts1.2 by parsing the comments.
186 * @param node
187 * @param sourceFile
188 * @returns boolean
189 */
190export function isArktsOne(node: Node, sourceFile: SourceFile): boolean {
191  const jsDocNode = node['jsDoc'] as JSDoc[];
192  if (!jsDocNode) {
193    return true;
194  }
195  for (let i = 0; i < jsDocNode.length; i++) {
196    const element = jsDocNode[i];
197    if (sourceFile.text.substring(element.pos, element.end).includes('@arkts 1.2')) {
198      return false;
199    }
200  }
201  return true;
202}
203