• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 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 fs from 'fs';
17import path from 'path';
18import {
19  DECLARES,
20  IGNORE_REFERENCES,
21  importDeclarationFiles,
22  KeyValueTypes,
23  mockBufferMap,
24  MockedFileMap,
25  TSTypes,
26  specialOverloadedFunctionArr,
27  callbackError, ClassNotInEts
28} from '../common/constants';
29import {
30  Declare,
31  KeyValue,
32  ReferenceFindResult,
33  Members,
34  MockBuffer,
35  OverloadedFunctionType,
36  CallbackParamMockData
37} from '../types';
38import { generateKeyValue } from '../common/commonUtils';
39
40/**
41 * 生成文件内容
42 * @param mockBuffer mock信息
43 * @param members 文件根节点的成员
44 * @returns
45 */
46export function generateContent(mockBuffer: MockBuffer, members: Members): string {
47  const membersContent: string[] = [];
48  Object.keys(members).forEach(memberKey => {
49    if (memberKey === 'default') {
50      return;
51    }
52    const keyValue = members[memberKey];
53    if (!keyValue.isNeedMock) {
54      return;
55    }
56    if (keyValue.type === KeyValueTypes.IMPORT) {
57      return;
58    }
59    if (keyValue.isGlobalDeclare) {
60      membersContent.push(`export const ${memberKey}=global.${memberKey};`);
61    } else {
62      const memberBody = handleKeyValue(memberKey, keyValue, mockBuffer, [], keyValue, keyValue.property);
63      membersContent.push(`export const ${memberKey} = ${memberBody};`);
64    }
65    if (keyValue.isDefault) {
66      const exportDefaultStr = `export default ${keyValue.key}`;
67      membersContent.push(exportDefaultStr);
68    }
69  });
70  return membersContent.join('\n');
71}
72
73/**
74 * 处理KV节点
75 * @param key KV节点key值
76 * @param keyValue KV节点
77 * @param mockBuffer KV节点所在文件的mock信息
78 * @param kvPath KV节点路径
79 * @param rootKeyValue 仅次于FILE节点的根节点
80 * @param property KV节点的调用属性节点,如A.b, b节点为property
81 * @returns
82 */
83function handleKeyValue(
84  key: string,
85  keyValue: KeyValue,
86  mockBuffer: MockBuffer,
87  kvPath: KeyValue[],
88  rootKeyValue: KeyValue,
89  property: KeyValue
90): string {
91  if (keyValue.value !== undefined) {
92    return keyValue.value;
93  }
94  if (new Set<KeyValueTypes>([
95    KeyValueTypes.CLASS,
96    KeyValueTypes.MODULE,
97    KeyValueTypes.INTERFACE
98  ]).has(keyValue.type) && kvPath.includes(keyValue)) {
99    if (keyValue.isGlobalDeclare) {
100      return `global.${keyValue.key}`;
101    }
102    if (keyValue.parent.isGlobalDeclare) {
103      return `global.${keyValue.parent.key}_temp.${keyValue.key}`;
104    }
105    return 'this';
106  } else {
107    kvPath = kvPath.concat([keyValue]);
108  }
109
110  return mockKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue, property);
111}
112
113/**
114 * 根据KV节点生成文件内容
115 * @param key KV节点key值
116 * @param keyValue KV节点
117 * @param mockBuffer KV节点所在文件的mock信息
118 * @param kvPath KV节点路径
119 * @param rootKeyValue 仅次于FILE节点的根节点
120 * @param property KV节点的调用属性节点,如A.b, b节点为property
121 * @returns
122 */
123function mockKeyValue(
124  key: string,
125  keyValue: KeyValue,
126  mockBuffer: MockBuffer,
127  kvPath: KeyValue[],
128  rootKeyValue: KeyValue,
129  property: KeyValue
130): string {
131  let value: string;
132  switch (keyValue.type) {
133    case KeyValueTypes.CLASS: {
134      value = handleClassKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
135      break;
136    }
137    case KeyValueTypes.EXPORT: {
138      value = handleExportKeyValue(keyValue, mockBuffer);
139      break;
140    }
141    case KeyValueTypes.FILE: {
142      value = handleFileKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue, property);
143      break;
144    }
145    case KeyValueTypes.FUNCTION: {
146      value = handleFunctionKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue);
147      break;
148    }
149    case KeyValueTypes.IMPORT: {
150      value = handleImportKeyValue(keyValue, kvPath, rootKeyValue, property);
151      break;
152    }
153    case KeyValueTypes.INTERSECTION: {
154      value = handleIntersectionKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue);
155      break;
156    }
157    case KeyValueTypes.MODULE: {
158      value = handleModuleKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue, property);
159      break;
160    }
161    case KeyValueTypes.INTERFACE: {
162      value = handleInterfaceKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
163      break;
164    }
165    case KeyValueTypes.VALUE: {
166      value = handleValueKeyValue(keyValue);
167      break;
168    }
169    case KeyValueTypes.VARIABLE: {
170      value = handleVariableKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
171      break;
172    }
173    case KeyValueTypes.PROPERTY: {
174      value = handlePropertyKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
175      break;
176    }
177    case KeyValueTypes.REFERENCE: {
178      value = handleReferenceKeyValue(key, keyValue, mockBuffer, kvPath, rootKeyValue, property);
179      break;
180    }
181    case KeyValueTypes.ENUM: {
182      value = handleEnumKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
183      break;
184    }
185    case KeyValueTypes.EXPRESSION: {
186      value = handleExpressionKeyValue(keyValue, mockBuffer, kvPath, rootKeyValue);
187      break;
188    }
189  }
190  keyValue.value = value;
191  return value;
192}
193
194/**
195 * 处理class KV节点
196 * @param keyValue KV节点
197 * @param mockBuffer KV节点所在文件的mock信息
198 * @param kvPath KV节点路径
199 * @param rootKeyValue 仅次于FILE节点的根节点
200 * @returns
201 */
202function handleClassKeyValue(
203  keyValue: KeyValue,
204  mockBuffer: MockBuffer,
205  kvPath: KeyValue[],
206  rootKeyValue: KeyValue
207): string {
208  const memberLines: string[] = [];
209  const dynamicProperties: string[] = ['this.isAutoMock=true'];
210
211  if (keyValue.heritage) {
212    handleHeritage(keyValue, mockBuffer, kvPath.concat([keyValue.heritage]), rootKeyValue);
213  }
214
215  Object.keys(keyValue.members).forEach(memberKey => {
216    const memberKeyValue = keyValue.members[memberKey];
217    let elementName = memberKey;
218
219    if (memberKeyValue.type === KeyValueTypes.EXPRESSION) {
220      memberKeyValue.key = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
221      memberKeyValue.type = KeyValueTypes.FUNCTION;
222      memberKeyValue.value = undefined;
223      elementName = memberKeyValue.key;
224    }
225    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property)
226      .replace(/^function\*?/, '');
227
228    if (memberKeyValue.type === KeyValueTypes.FUNCTION) {
229      if (memberKeyValue.members.IterableIterator) {
230        memberLines.push(`*${elementName}${value}`);
231      } else {
232        memberLines.push(`${memberKeyValue.isStatic ? 'static ' : ''}${elementName}${value}`);
233      }
234    } else {
235      if (memberKeyValue.isStatic) {
236        memberLines.push(`static get ${elementName}(){return ${value}}`);
237      } else {
238        dynamicProperties.push(`this.${elementName} = ${value}`);
239      }
240    }
241  });
242
243  return `class {constructor() {\n${dynamicProperties.join(';\n')}\n}\n${memberLines.join(';\n')}\n}`;
244}
245
246/**
247 * 处理继承
248 * @param keyValue KV节点
249 * @param mockBuffer KV节点所在文件的mock信息
250 * @param kvPath KV节点路径
251 * @param rootKeyValue 仅次于FILE节点的根节点
252 * @returns
253 */
254function handleHeritage(
255  keyValue: KeyValue,
256  mockBuffer: MockBuffer,
257  kvPath: KeyValue[],
258  rootKeyValue: KeyValue
259): void {
260  const keyValueInfo = findKeyValueDefined(keyValue.heritage.key, keyValue.heritage, mockBuffer, kvPath, rootKeyValue, keyValue.heritage.property);
261  const defKeyValue = keyValueInfo.keyValue;
262  const defMockBuffer = keyValueInfo.mockBuffer;
263  handleKeyValue(defKeyValue.key, defKeyValue, defMockBuffer, kvPath, rootKeyValue, defKeyValue.property);
264
265  Object.keys(defKeyValue.members).forEach(memberKey => {
266    const memberKeyValue = Object.assign({}, defKeyValue.members[memberKey]);
267    memberKeyValue.isMocked = false;
268    if (memberKeyValue.type === KeyValueTypes.EXPRESSION) {
269      memberKeyValue.key = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
270      memberKeyValue.type = KeyValueTypes.PROPERTY;
271    }
272    if (keyValue.members[memberKeyValue.key]) {
273      return;
274    }
275    keyValue.members[memberKeyValue.key] = memberKeyValue;
276  });
277}
278
279/**
280 * 处理export KV节点
281 * @param keyValue KV节点
282 * @param mockBuffer KV节点所在文件的mock信息
283 * @returns
284 */
285function handleExportKeyValue(
286  keyValue: KeyValue,
287  mockBuffer: MockBuffer
288): string {
289  return `export * from './${path.relative(path.dirname(mockBuffer.mockedFilePath), keyValue.key)}';`;
290}
291
292/**
293 * 处理file KV节点
294 * @param key KV节点key值
295 * @param keyValue KV节点
296 * @param mockBuffer KV节点所在文件的mock信息
297 * @param kvPath KV节点路径
298 * @param rootKeyValue 仅次于FILE节点的根节点
299 * @param property KV节点的调用属性节点,如A.b, b节点为property
300 * @returns
301 */
302function handleFileKeyValue(
303  key: string,
304  keyValue: KeyValue,
305  mockBuffer: MockBuffer,
306  kvPath: KeyValue[],
307  rootKeyValue: KeyValue,
308  property: KeyValue
309): string {
310  if (property) {
311    const propertyKeyValue = keyValue.members[property.key];
312    if (propertyKeyValue) {
313      return handleKeyValue(property.key, propertyKeyValue, mockBuffer, kvPath, rootKeyValue, property);
314    } else {
315      console.warn(`Not found ${property.key} from ${key} in file ${mockBuffer.rawFilePath}`);
316    }
317  }
318  return '\'\'';
319}
320
321/**
322 * 处理function KV节点
323 * @param key
324 * @param keyValue KV节点
325 * @param mockBuffer KV节点所在文件的mock信息
326 * @param kvPath KV节点路径
327 * @param rootKeyValue 仅次于FILE节点的根节点
328 * @returns
329 */
330function handleFunctionKeyValue(
331  key: string,
332  keyValue: KeyValue,
333  mockBuffer: MockBuffer,
334  kvPath: KeyValue[],
335  rootKeyValue: KeyValue
336): string {
337  const memberKey = 'IterableIterator';
338  const memberKeyValue = keyValue.members[memberKey];
339  if (memberKeyValue) {
340    return handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
341  }
342
343  const sameFuncList: KeyValue[] = [];
344  sameFuncList.push(keyValue);
345
346  keyValue.sameName.forEach(sameFunction => {
347    sameFuncList.push(sameFunction);
348  });
349  return handleSameFunctions(key, sameFuncList, mockBuffer, kvPath, rootKeyValue);
350}
351
352/**
353 * 处理import KV节点
354 * @param keyValue KV节点
355 * @param kvPath KV节点路径
356 * @param rootKeyValue 仅次于FILE节点的根节点
357 * @param property KV节点的调用属性节点,如A.b, b节点为property
358 * @returns
359 */
360function handleImportKeyValue(
361  keyValue: KeyValue,
362  kvPath: KeyValue[],
363  rootKeyValue: KeyValue,
364  property: KeyValue
365): string {
366  const importedMockBuffer = mockBufferMap.get(MockedFileMap.get(keyValue.importedModulePath));
367  const importedRootKeyValue = importedMockBuffer.contents;
368  if (keyValue.isImportDefault) {
369    const defaultKeyValue = importedRootKeyValue.members.default;
370    if (!defaultKeyValue) {
371      console.warn(`The file: ${importedMockBuffer.rawFilePath} does not contain the default export.`);
372      return `'The file: ${importedMockBuffer.rawFilePath} does not contain the default export.'`;
373    }
374    return handleKeyValue(defaultKeyValue.key, defaultKeyValue, importedMockBuffer, kvPath, rootKeyValue, property);
375  }
376
377  const targetKeyValue = importedRootKeyValue.members[keyValue.rawName ?? keyValue.key];
378  if (!targetKeyValue) {
379    console.warn(`The ${keyValue.rawName ?? keyValue.key} does not export from ${MockedFileMap.get(keyValue.importedModulePath)}.`);
380    return '"Unknown type"';
381  }
382  return handleKeyValue(targetKeyValue.key, targetKeyValue, importedMockBuffer, kvPath, rootKeyValue, property);
383}
384
385/**
386 * 处理intersection KV节点
387 * @param key KV节点key值
388 * @param keyValue KV节点
389 * @param mockBuffer KV节点所在文件的mock信息
390 * @param kvPath KV节点路径
391 * @param rootKeyValue 仅次于FILE节点的根节点
392 * @returns
393 */
394function handleIntersectionKeyValue(
395  key: string,
396  keyValue: KeyValue,
397  mockBuffer: MockBuffer,
398  kvPath: KeyValue[],
399  rootKeyValue: KeyValue
400): string {
401  const params: string[] = [];
402  Object.keys(keyValue.methodParams).forEach(param => {
403    const paramKeyValue = keyValue.methodParams[param];
404    const value = handleKeyValue(param, paramKeyValue, mockBuffer, kvPath, rootKeyValue, paramKeyValue.property);
405    // 因为rollup在编译时,会将this编译成undefined,导致有运行时报错,因此需要打个补丁
406    params.push(`(${value}) || {}`);
407  });
408  return `${key}(${params.join(', ')})`;
409}
410
411/**
412 * 处理module KV节点
413 * @param key KV节点key值
414 * @param keyValue KV节点
415 * @param mockBuffer KV节点所在文件的mock信息
416 * @param kvPath KV节点路径
417 * @param rootKeyValue 仅次于FILE节点的根节点
418 * @param property KV节点的调用属性节点,如A.b, b节点为property
419 * @returns
420 */
421function handleModuleKeyValue(
422  key: string,
423  keyValue: KeyValue,
424  mockBuffer: MockBuffer,
425  kvPath: KeyValue[],
426  rootKeyValue: KeyValue,
427  property?: KeyValue
428): string {
429  const memberLines: string[] = [];
430  if (property) {
431    const propertyKeyValue = keyValue.members[property.key];
432    if (propertyKeyValue) {
433      return handleKeyValue(property.key, propertyKeyValue, mockBuffer, kvPath, rootKeyValue, propertyKeyValue.property);
434    } else {
435      console.warn(`Not found ${property.key} from ${key} in file ${mockBuffer.rawFilePath}`);
436    }
437  }
438  Object.keys(keyValue.members).forEach(memberKey => {
439    const memberKeyValue = keyValue.members[memberKey];
440    if (!keyValue.isGlobalDeclare && !memberKeyValue.isNeedMock) {
441      return;
442    }
443    const value = `${memberKeyValue.key}: ${handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property)}`;
444    memberLines.push(value);
445  });
446  return `{\n${memberLines.join(',\n')}\n}`;
447}
448
449/**
450 * 处理interface KV节点
451 * @param keyValue KV节点
452 * @param mockBuffer KV节点所在文件的mock信息
453 * @param kvPath KV节点路径
454 * @param rootKeyValue 仅次于FILE节点的根节点
455 * @returns
456 */
457function handleInterfaceKeyValue(
458  keyValue: KeyValue,
459  mockBuffer: MockBuffer,
460  kvPath: KeyValue[],
461  rootKeyValue: KeyValue
462): string {
463  const memberLines: string[] = ['isAutoMock: true'];
464
465  if (keyValue.heritage) {
466    handleHeritage(keyValue, mockBuffer, kvPath.concat([keyValue.heritage]), rootKeyValue);
467  }
468  Object.keys(keyValue.members).forEach(memberKey => {
469    const memberKeyValue = keyValue.members[memberKey];
470    const value = `${memberKeyValue.key}: ${handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property)}`;
471    memberLines.push(value);
472  });
473  return `{\n${memberLines.join(',\n')}\n}`;
474}
475
476/**
477 * 处理value KV节点
478 * @param keyValue KV节点
479 * @returns
480 */
481function handleValueKeyValue(
482  keyValue: KeyValue
483): string {
484  return keyValue.key;
485}
486
487/**
488 * 处理variable KV节点
489 * @param keyValue KV节点
490 * @param mockBuffer KV节点所在文件的mock信息
491 * @param kvPath KV节点路径
492 * @param rootKeyValue 仅次于FILE节点的根节点
493 * @returns
494 */
495function handleVariableKeyValue(
496  keyValue: KeyValue,
497  mockBuffer: MockBuffer,
498  kvPath: KeyValue[],
499  rootKeyValue: KeyValue
500): string {
501  const memberLines: string[] = [];
502  Object.keys(keyValue.members).forEach(memberKey => {
503    const memberKeyValue = keyValue.members[memberKey];
504    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
505    memberLines.push(value);
506  });
507  return memberLines.join(',\n');
508}
509
510/**
511 * 查找reference KV节点定义位置
512 * @param key KV节点key值
513 * @param targetKeyValue 需要查找的reference KV节点
514 * @param mockBuffer KV节点所在文件的mock信息
515 * @param kvPath KV节点路径
516 * @param rootKeyValue 仅次于FILE节点的根节点
517 * @param property KV节点的调用属性节点,如A.b, b节点为property
518 * @returns
519 */
520function findKeyValueDefined(
521  key: string,
522  targetKeyValue: KeyValue,
523  mockBuffer: MockBuffer,
524  kvPath: KeyValue[],
525  rootKeyValue: KeyValue,
526  property: KeyValue
527): ReferenceFindResult {
528  let keyValueInfo: ReferenceFindResult;
529
530  // 在js库中找
531  keyValueInfo = findInLibs(key, targetKeyValue, mockBuffer, kvPath, rootKeyValue);
532  if (keyValueInfo) {
533    return keyValueInfo;
534  }
535
536  // 在当前文件中找
537  keyValueInfo = findInCurrentFile(key, targetKeyValue, targetKeyValue.parent, mockBuffer, kvPath, rootKeyValue, property);
538  if (keyValueInfo) {
539    return keyValueInfo;
540  }
541
542  // 在全局定义中找
543  keyValueInfo = findInDeclares(key);
544  if (keyValueInfo) {
545    return keyValueInfo;
546  }
547
548  // 在TS内置类型中找
549  keyValueInfo = findTSTypes(key, targetKeyValue, mockBuffer, kvPath, rootKeyValue);
550  if (keyValueInfo) {
551    return keyValueInfo;
552  }
553
554  // 在所有文件中找
555  keyValueInfo = findInAllFiles(key, property);
556  if (keyValueInfo) {
557    return keyValueInfo;
558  }
559
560  const keyValuePath: string[] = getKeyValuePath(targetKeyValue);
561  const fromFilePath = MockedFileMap.get(keyValuePath[0]).replace(/\\/, '/');
562  const value: string = `'Cannot find type definition for ${keyValuePath.slice(1).join('->')} from file ${fromFilePath}'`;
563  console.warn(value);
564  const keyValue: KeyValue = generateKeyValue(key, KeyValueTypes.VALUE);
565  keyValue.value = value;
566  return { keyValue, mockBuffer };
567}
568
569/**
570 * 在 typescript 内置类型库中查找类型定义
571 * @param key KV节点key值
572 * @param targetKeyValue 需要查找的reference KV节点
573 * @param mockBuffer KV节点所在文件的mock信息
574 * @param kvPath KV节点路径
575 * @param rootKeyValue 仅次于FILE节点的根节点
576 * @returns
577 */
578function findTSTypes(
579  key: string,
580  targetKeyValue: KeyValue,
581  mockBuffer: MockBuffer,
582  kvPath: KeyValue[],
583  rootKeyValue: KeyValue
584): ReferenceFindResult {
585  const paramsContent: string[] = [];
586  Object.keys(targetKeyValue.typeParameters).forEach(typeParameter => {
587    const typeParameterKeyValue: KeyValue = targetKeyValue.typeParameters[typeParameter];
588    const paramContent: string = handleKeyValue(typeParameter, typeParameterKeyValue, mockBuffer, kvPath, rootKeyValue, typeParameterKeyValue.property);
589    paramsContent.push(paramContent);
590  });
591  if (!TSTypes[key]) {
592    return undefined;
593  }
594  const keyValue: KeyValue = generateKeyValue(key, KeyValueTypes.VALUE);
595  keyValue.value = TSTypes[key](paramsContent.join(', '));
596  return { keyValue, mockBuffer };
597}
598
599/**
600 * 处理函数参数
601 * @param params 参数成员
602 * @param mockBuffer 当前文件mock信息
603 * @param kvPath KV节点路径
604 * @param rootKeyValue 仅次于FILE节点的根节点
605 * @returns
606 */
607function handleParams(
608  params: Members,
609  mockBuffer: MockBuffer,
610  kvPath: KeyValue[],
611  rootKeyValue: KeyValue
612): string {
613  const contents: string[] = [];
614  Object.keys(params).forEach(key => {
615    const paramKeyValue = params[key];
616    contents.push(handleKeyValue(paramKeyValue.key, paramKeyValue, mockBuffer, kvPath, rootKeyValue, paramKeyValue.property));
617  });
618  return contents.join(', ');
619}
620
621/**
622 * 在 typescript 内置类型库中查找类型定义
623 * @param key KV节点key值
624 * @param targetKeyValue 需要查找的reference KV节点
625 * @param mockBuffer KV节点所在文件的mock信息
626 * @param kvPath KV节点路径
627 * @param rootKeyValue 仅次于FILE节点的根节点
628 * @returns
629 */
630function findInLibs(
631  key: string,
632  targetKeyValue: KeyValue,
633  mockBuffer: MockBuffer,
634  kvPath: KeyValue[],
635  rootKeyValue: KeyValue
636): ReferenceFindResult {
637  if (key === 'globalThis') {
638    const globalThisKeyValue = generateKeyValue(key, KeyValueTypes.VALUE);
639    return { keyValue: globalThisKeyValue, mockBuffer };
640  }
641  if (ClassNotInEts.has(key) || !global[key]) {
642    return undefined;
643  }
644  if (key === 'Symbol') {
645    return {
646      keyValue: generateKeyValue('[Symbol.iterator]', KeyValueTypes.VALUE),
647      mockBuffer
648    };
649  }
650  switch (typeof global[key]) {
651    case 'bigint': {
652      break;
653    }
654    case 'boolean': {
655      break;
656    }
657    case 'function': {
658      return findInLibFunction(key, targetKeyValue, mockBuffer, kvPath, rootKeyValue);
659    }
660    case 'number': {
661      break;
662    }
663    case 'object': {
664      break;
665    }
666    case 'string': {
667      break;
668    }
669    case 'symbol': {
670      break;
671    }
672    case 'undefined': {
673      break;
674    }
675  }
676  return undefined;
677}
678
679/**
680 * 在库函数中查找类型定义
681 * @param key KV节点key值
682 * @param targetKeyValue 需要查找的reference KV节点
683 * @param mockBuffer KV节点所在文件的mock信息
684 * @param kvPath KV节点路径
685 * @param rootKeyValue 仅次于FILE节点的根节点
686 * @returns
687 */
688function findInLibFunction(
689  key: string,
690  targetKeyValue: KeyValue,
691  mockBuffer: MockBuffer,
692  kvPath: KeyValue[],
693  rootKeyValue: KeyValue
694): ReferenceFindResult {
695  const params = handleParams(targetKeyValue.methodParams, mockBuffer, kvPath, rootKeyValue);
696  let value: string;
697  // 判断是否是函数
698  if (typeof global[key].constructor === 'function') {
699    value = `new ${key}(${params})`;
700  } else {
701    value = `${key}(${params})`;
702  }
703  return {
704    keyValue: generateKeyValue(value, KeyValueTypes.VALUE),
705    mockBuffer
706  };
707}
708
709/**
710 * 在当前文件中查找类型定义
711 * @param key KV节点key值
712 * @param targetKeyValue 需要查找的reference KV节点
713 * @param parent 父节点
714 * @param mockBuffer KV节点所在文件的mock信息
715 * @param kvPath KV节点路径
716 * @param rootKeyValue 仅次于FILE节点的根节点
717 * @param property KV节点的调用属性节点,如A.b, b节点为property
718 * @returns
719 */
720function findInCurrentFile(
721  key: string,
722  targetKeyValue: KeyValue,
723  parent: KeyValue,
724  mockBuffer: MockBuffer,
725  kvPath: KeyValue[],
726  rootKeyValue: KeyValue,
727  property: KeyValue
728): ReferenceFindResult {
729  if (!parent) {
730    return undefined as ReferenceFindResult;
731  }
732  if (parent.typeParameters[key] && parent.typeParameters[key] !== targetKeyValue) {
733    return { keyValue: parent.typeParameters[key], mockBuffer } as ReferenceFindResult;
734  }
735  const foundKeyValue = parent.members[key];
736  if (foundKeyValue && foundKeyValue !== targetKeyValue) {
737    if (foundKeyValue.type === KeyValueTypes.IMPORT) {
738      return findDefFromImport(foundKeyValue, mockBuffer, rootKeyValue, property) as ReferenceFindResult;
739    }
740    const defKeyValue = findProperty(foundKeyValue, property);
741    if (defKeyValue) {
742      return {keyValue: defKeyValue, mockBuffer} as ReferenceFindResult;
743    }
744  }
745  return findInCurrentFile(key, targetKeyValue, parent.parent, mockBuffer, kvPath, rootKeyValue, property) as ReferenceFindResult;
746}
747
748/**
749 * 在全局声明中查找类型定义
750 * @param key KV节点key值
751 * @returns
752 */
753function findInDeclares(
754  key: string
755): ReferenceFindResult {
756  if (DECLARES[key]) {
757    const mockBuffer = mockBufferMap.get(MockedFileMap.get(DECLARES[key].from));
758    return {
759      keyValue: DECLARES[key].keyValue,
760      mockBuffer,
761      isGlobalDeclaration: path.basename(mockBuffer.rawFilePath).startsWith('@')
762    } as ReferenceFindResult;
763  } else {
764    return undefined as ReferenceFindResult;
765  }
766}
767
768/**
769 * 在所有文件中查找类型定义
770 * @param key KV节点key值
771 * @param property KV节点的调用属性节点,如A.b, b节点为property
772 * @returns
773 */
774function findInAllFiles(
775  key: string,
776  property?: KeyValue
777): ReferenceFindResult {
778  for (const definedMockBuffer of mockBufferMap.values()) {
779    const members = definedMockBuffer.contents.members;
780    if (members[key]) {
781      const defKeyValue = findProperty(members[key], property);
782      return { keyValue: defKeyValue, mockBuffer: definedMockBuffer } as ReferenceFindResult;
783    }
784  }
785  return undefined as ReferenceFindResult;
786}
787
788/**
789 * 获取节点在当前文件的路径
790 * 以递归的方式逐级向上获取所有祖先节点的key
791 * @param keyValue KV节点
792 * @param paths 节点路径
793 * @returns
794 */
795function getKeyValuePath(keyValue: KeyValue, paths = []): string[] {
796  if (!keyValue) {
797    return paths;
798  }
799  paths.unshift(keyValue.key);
800  return getKeyValuePath(keyValue.parent, paths);
801}
802
803/**
804 * 处理同名函数
805 * @param key
806 * @param sameFuncList 同名函数列表
807 * @param mockBuffer 当前文件的mock信息
808 * @param kvPath KV节点路径
809 * @param rootKeyValue 仅次于FILE节点的根节点
810 * @returns
811 */
812function handleSameFunctions(
813  key: string,
814  sameFuncList: KeyValue[],
815  mockBuffer: MockBuffer,
816  kvPath: KeyValue[],
817  rootKeyValue: KeyValue
818): string {
819  const functionName = sameFuncList[0].key;
820  if (sameFuncList.length >= 2) {
821    return handleOverloadedFunction(key, sameFuncList, mockBuffer, kvPath, rootKeyValue, functionName);
822  } else {
823    return handleSingleFunction(key, sameFuncList, mockBuffer, kvPath, rootKeyValue, functionName);
824  }
825}
826
827/**
828 * 处理重载函数
829 * @param key
830 * @param sameFuncList 同名函数列表
831 * @param mockBuffer 当前文件的mock信息
832 * @param kvPath KV节点路径
833 * @param rootKeyValue 仅次于FILE节点的根节点
834 * @param functionName
835 * @returns
836 */
837function handleOverloadedFunction(
838  key: string,
839  sameFuncList: KeyValue[],
840  mockBuffer: MockBuffer,
841  kvPath: KeyValue[],
842  rootKeyValue: KeyValue,
843  functionName: string
844): string {
845  const func = sameFuncList.find(func => func.members.Promise);
846  if (!func) {
847    return handleSingleFunction(key, sameFuncList, mockBuffer, kvPath, rootKeyValue, functionName);
848  }
849  const promiseTypes = func.members.Promise;
850  const memberLines: string[] = [];
851  const returnData: string[] = [];
852  const paramIndex: number = 1;
853  Object.keys(promiseTypes.typeParameters).forEach(memberKey => {
854    const memberKeyValue = promiseTypes.typeParameters[memberKey];
855    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
856    memberLines.push(`const p${paramIndex} = ${value}`);
857    returnData.push(`p${paramIndex}`);
858  });
859  const isSpecial = specialOverloadedFunctionArr.includes(functionName);
860  const paramMockData = handleFunParamMockData(sameFuncList, mockBuffer, kvPath, rootKeyValue, isSpecial, 'multiple', returnData);
861  return `function (${key.startsWith('get ' + functionName) ? '' : '...args'}) {
862    console.warn(ts.replace('{{}}', '${func.key}'));
863    ${memberLines.join(';\n')}${paramMockData ? '\n' + paramMockData : ''}
864    return new Promise(function (resolve, reject) {
865      resolve(${returnData.join(', ')});
866    });
867  }`;
868}
869
870function handleFunParamMockData(
871  funcList: KeyValue[],
872  mockBuffer: MockBuffer,
873  kvPath: KeyValue[],
874  rootKeyValue: KeyValue,
875  isSpecial: boolean,
876  funType: OverloadedFunctionType,
877  returnData?: string[]
878): string {
879  let paramMockData = '';
880  for (let i = 0; i < funcList.length; i++) {
881    const funInfo = funcList[i];
882    const { paramName, callBackParams, isAsyncCallback } = getCallbackMockData(funInfo, mockBuffer, kvPath, rootKeyValue, isSpecial);
883    if (!callBackParams.length) {
884      continue;
885    }
886    const returnInfo = isSpecial
887      ? callBackParams.join(', ')
888      : funType === 'single'
889        ? callBackParams.join(', ')
890        : returnData?.join(', ');
891    const data = `if (args && typeof args[args.length - 1] === 'function') {
892      args[args.length - 1].call(this, ${isAsyncCallback ? callbackError : ''}${returnInfo});
893    }`;
894    const info = (paramName ? `if(args && ['${paramName}'].includes(args[0])){\n` : '') + data + (paramName ? '}\n' : '');
895    if (funType === 'single' || isSpecial || !isSpecial && !paramMockData) {
896      paramMockData += info;
897    }
898  }
899  return paramMockData;
900}
901
902function getCallbackMockData(
903  funInfo: KeyValue,
904  mockBuffer: MockBuffer,
905  kvPath: KeyValue[],
906  rootKeyValue: KeyValue,
907  isSpecial: boolean
908): CallbackParamMockData {
909  let paramName = '';
910  let isAsyncCallback = true;
911  let callBackParams: string[] = [];
912  Object.keys(funInfo.methodParams).forEach(key => {
913    const paramInfo = funInfo.methodParams[key];
914    const callbackData = handleCallbackParamMockData(key, paramInfo, callBackParams, paramName, isAsyncCallback, mockBuffer, kvPath, rootKeyValue, isSpecial);
915    paramName = callbackData.paramName;
916    isAsyncCallback = callbackData.isAsyncCallback;
917    callBackParams = callbackData.callBackParams;
918  });
919  return {
920    paramName,
921    isAsyncCallback,
922    callBackParams
923  };
924}
925
926function handleCallbackParamMockData(
927  key: string,
928  paramInfo: KeyValue,
929  callBackParams: string[],
930  paramName: string,
931  isAsyncCallback: boolean,
932  mockBuffer: MockBuffer,
933  kvPath: KeyValue[],
934  rootKeyValue: KeyValue,
935  isSpecial: boolean
936): CallbackParamMockData {
937  if (key === 'callback') {
938    let callbackInfo: KeyValue;
939    if (paramInfo.members.Callback) {
940      isAsyncCallback = false;
941      callbackInfo = paramInfo.members.Callback;
942    }
943    if (paramInfo.members.AsyncCallback) {
944      isAsyncCallback = true;
945      callbackInfo = paramInfo.members.AsyncCallback;
946    }
947    callbackInfo && Object.keys(callbackInfo.typeParameters).forEach(memberKey => {
948      const memberKeyValue = callbackInfo.typeParameters[memberKey];
949      const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
950      callBackParams.push(value);
951    });
952  }
953  if (key === 'type' && isSpecial) {
954    Object.keys(paramInfo.members).forEach(memberKey => {
955      if (!paramName) {
956        paramName = memberKey;
957      }
958    });
959  }
960
961  return {
962    isAsyncCallback,
963    callBackParams,
964    paramName
965  };
966}
967
968/**
969 * 拼接property
970 * 通过递归方式,逐层将调用的属性拼接起来
971 * 如:将{A:{key:A, property: {key:b, property: {key: c}}}}
972 * 拼接成:A.b.c
973 * @param property 调用的属性
974 * @returns
975 */
976function concatProperty(property?: KeyValue): string {
977  if (!property) {
978    return '';
979  }
980  return `.${property.key}${concatProperty(property.property)}`;
981}
982
983/**
984 * 获取获取定义KV节点的最后一个property
985 *
986 * @param keyValue 定义的KV节点
987 * @param property 调用KV节点的属性
988 * @returns
989 */
990function findProperty(keyValue: KeyValue, property?: KeyValue): KeyValue {
991  const keyValueKey = keyValue.key;
992  while (property && keyValue) {
993    keyValue = keyValue.members[property.key];
994    property = property.property;
995  }
996  if (!keyValue && property) {
997    throw new Error(`未能在${keyValueKey}下找到${property.key}子孙属性`);
998  }
999  return keyValue;
1000}
1001
1002/**
1003 * 处理property KV节点
1004 * @param keyValue KV节点
1005 * @param mockBuffer KV节点所在文件的mock信息
1006 * @param kvPath KV节点路径
1007 * @param rootKeyValue 仅次于FILE节点的根节点
1008 * @returns
1009 */
1010function handlePropertyKeyValue(
1011  keyValue: KeyValue,
1012  mockBuffer: MockBuffer,
1013  kvPath: KeyValue[],
1014  rootKeyValue: KeyValue
1015): string {
1016  const memberLines: string[] = [];
1017  Object.keys(keyValue.members).forEach(memberKey => {
1018    const memberKeyValue = keyValue.members[memberKey];
1019    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1020    memberLines.push(value);
1021  });
1022  return memberLines.join(',');
1023}
1024
1025/**
1026 * 处理reference KV节点
1027 * @param key KV节点key值
1028 * @param keyValue KV节点
1029 * @param mockBuffer KV节点所在文件的mock信息
1030 * @param kvPath KV节点路径
1031 * @param rootKeyValue 仅次于FILE节点的根节点
1032 * @param property KV节点的调用属性节点,如A.b, b节点为property
1033 * @returns
1034 */
1035function handleReferenceKeyValue(
1036  key: string,
1037  keyValue: KeyValue,
1038  mockBuffer: MockBuffer,
1039  kvPath: KeyValue[],
1040  rootKeyValue: KeyValue,
1041  property: KeyValue
1042): string {
1043  if (IGNORE_REFERENCES.has(key)) {
1044    const memberLines: string[] = [];
1045    Object.keys(keyValue.typeParameters).forEach(memberKey => {
1046      const memberKeyValue = keyValue.typeParameters[memberKey];
1047      const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1048      memberLines.push(value);
1049    });
1050    return memberLines.join(',\n');
1051  }
1052  const keyValueInfo = findKeyValueDefined(key, keyValue, mockBuffer, kvPath, rootKeyValue, keyValue.property);
1053  let value: string;
1054
1055  if (keyValueInfo.isGlobalDeclaration) {
1056    const properties = concatProperty(keyValue.property);
1057    value = `global.${keyValueInfo.keyValue.key}${properties}`;
1058    const dependKeyValue = property ? keyValueInfo.keyValue.members[property.key] : keyValueInfo.keyValue;
1059    !dependKeyValue.isMocked && rootKeyValue.dependOnGlobals.add(dependKeyValue);
1060  } else {
1061    value = handleKeyValue(keyValueInfo.keyValue.key, keyValueInfo.keyValue, keyValueInfo.mockBuffer, kvPath, rootKeyValue, property);
1062  }
1063
1064  if (value !== 'this') {
1065    switch (keyValueInfo.keyValue.type) {
1066      case KeyValueTypes.CLASS: {
1067        value = `new (${value})()`;
1068        break;
1069      }
1070      case KeyValueTypes.ENUM: {
1071        if (keyValue.parent.type !== KeyValueTypes.VARIABLE) {
1072          const firstMemberKey = Object.keys(keyValueInfo.keyValue.members)[0];
1073          const firstMemberKeyValue = keyValueInfo.keyValue.members[firstMemberKey];
1074          value = handleKeyValue(firstMemberKey, firstMemberKeyValue, keyValueInfo.mockBuffer, kvPath, rootKeyValue, firstMemberKeyValue.property);
1075        }
1076        break;
1077      }
1078    }
1079  }
1080
1081  return value;
1082}
1083
1084/**
1085 * 处理enum KV节点
1086 * @param keyValue KV节点
1087 * @param mockBuffer KV节点所在文件的mock信息
1088 * @param kvPath KV节点路径
1089 * @param rootKeyValue 仅次于FILE节点的根节点
1090 * @returns
1091 */
1092function handleEnumKeyValue(
1093  keyValue: KeyValue,
1094  mockBuffer: MockBuffer,
1095  kvPath: KeyValue[],
1096  rootKeyValue: KeyValue
1097): string {
1098  const memberLines: string[] = ['isAutoMock: 0'];
1099  Object.keys(keyValue.members).forEach(memberKey => {
1100    const memberKeyValue = keyValue.members[memberKey];
1101    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1102    memberLines.push(`${memberKey}: ${value}`);
1103  });
1104  return `{${memberLines.join(',\n')}}`;
1105}
1106
1107/**
1108 * 处理expression KV节点
1109 * @param keyValue KV节点
1110 * @param mockBuffer KV节点所在文件的mock信息
1111 * @param kvPath KV节点路径
1112 * @param rootKeyValue 仅次于FILE节点的根节点
1113 * @returns
1114 */
1115function handleExpressionKeyValue(
1116  keyValue: KeyValue,
1117  mockBuffer: MockBuffer,
1118  kvPath: KeyValue[],
1119  rootKeyValue: KeyValue
1120): string {
1121  const elements = keyValue.operateElements;
1122  return elements.map(element => {
1123    return handleKeyValue(element.key, element, mockBuffer, kvPath, rootKeyValue, element.property);
1124  }).join(' ');
1125}
1126
1127/**
1128 * 处理非重载函数
1129 * @param key
1130 * @param sameFuncList
1131 * @param mockBuffer KV节点所在文件的mock信息
1132 * @param kvPath KV节点路径
1133 * @param rootKeyValue 仅次于FILE节点的根节点
1134 * @param functionName
1135 * @returns
1136 */
1137function handleSingleFunction(
1138  key: string,
1139  sameFuncList: KeyValue[],
1140  mockBuffer: MockBuffer,
1141  kvPath: KeyValue[],
1142  rootKeyValue: KeyValue,
1143  functionName: string
1144): string {
1145  const funcKeyValue = sameFuncList[0];
1146  const memberLines: string[] = [];
1147  Object.keys(funcKeyValue.members).forEach(memberKey => {
1148    const memberKeyValue = funcKeyValue.members[memberKey];
1149    const value = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1150    memberLines.push(value);
1151  });
1152  const isSpecial = specialOverloadedFunctionArr.includes(functionName);
1153  const funcList = isSpecial ? sameFuncList : [sameFuncList[0]];
1154  const paramMockData = handleFunParamMockData(funcList, mockBuffer, kvPath, rootKeyValue, isSpecial, 'single');
1155
1156  const returnStr = funcKeyValue.members.Promise && funcKeyValue.members.Promise.type === KeyValueTypes.REFERENCE ?
1157    `return new Promise(function (resolve, reject) {
1158          resolve(${memberLines.join(',')});
1159        })` :
1160    `return ${memberLines.join(',')}`;
1161  return `function (${key.startsWith('get ' + functionName) ? '' : '...args'}) {
1162  console.warn(ts.replace('{{}}', '${funcKeyValue.key}'));
1163  ${paramMockData ?? ''}${returnStr}
1164  }`;
1165}
1166
1167/**
1168 * 获取KV节点的最后一个property的类型
1169 * @param keyValue KV节点
1170 * @param property 调用的属性
1171 * @returns
1172 */
1173function getKeyValueType(keyValue: KeyValue, property?: KeyValue): KeyValueTypes {
1174  while (property) {
1175    keyValue = keyValue.members[property.key];
1176    property = property.property;
1177  }
1178  return keyValue.type;
1179}
1180
1181/**
1182 * 处理所有全局声明的KV节点
1183 * @param outMockJsFileDir mock文件输出路径
1184 */
1185export function handleDeclares(outMockJsFileDir: string): void {
1186  const declarations: string[] = [];
1187  const mockedDeclarations: Set<string> = new Set();
1188  Object.keys(DECLARES).forEach(key => {
1189    const keyValue = DECLARES[key].keyValue;
1190    switch (keyValue.type) {
1191      case KeyValueTypes.CLASS: {
1192        declarations.push(`global.${key}_temp = class {constructor(){this.isAutoMock=true}};\nglobal.${key} = global.${key} || global.${key}_temp;`);
1193        break;
1194      }
1195      case KeyValueTypes.INTERFACE:
1196      case KeyValueTypes.MODULE: {
1197        declarations.push(`global.${key}_temp = {isAutoMock: true};\nglobal.${key} = global.${key} || global.${key}_temp;`);
1198      }
1199    }
1200  });
1201
1202  Object.keys(DECLARES).forEach(key => {
1203    handleDeclare(DECLARES[key], declarations, mockedDeclarations);
1204  });
1205
1206  const INTERVAL = 100;
1207  for (let counter = 0; counter < declarations.length; counter += INTERVAL) {
1208    const index = Math.floor(counter / INTERVAL) + 1;
1209    const filePath = path.join(outMockJsFileDir, `globalDeclarations${index}.js`);
1210    importDeclarationFiles.push(`import * as globalDeclarations${index} from './globalDeclarations${index}';`);
1211    const content = declarations.slice(counter, counter + INTERVAL).join('\n');
1212    fs.writeFileSync(filePath, content);
1213  }
1214}
1215
1216/**
1217 * 处理全局声明的KV节点
1218 * @param declaration 全局声明的KV节点
1219 * @param declarations 所有全局声明的KV节点
1220 * @param mockedDeclarations 已mock的全局声明的KV节点的集合,避免重复mock
1221 * @param member 不为undefined时,只mock这个member节点
1222 * @returns
1223 */
1224function handleDeclare(
1225  declaration: Declare,
1226  declarations: string[],
1227  mockedDeclarations: Set<string>,
1228  member?: KeyValue
1229): void {
1230  if (member?.isMocked) {
1231    return;
1232  }
1233  const keyValue = declaration.keyValue;
1234  const key = keyValue.key;
1235  const mockBuffer = mockBufferMap.get(MockedFileMap.get(declaration.from));
1236
1237  const values: string[] = [];
1238  switch (keyValue.type) {
1239    case KeyValueTypes.FUNCTION: {
1240      if (!mockedDeclarations.has(key)) {
1241        const functionBody = handleKeyValue(key, keyValue, mockBuffer, [], keyValue, keyValue.property);
1242        const value = `global.${key} = global.${key} || (${functionBody});`;
1243        values.push(value);
1244        mockedDeclarations.add(key);
1245      }
1246      break;
1247    }
1248    case KeyValueTypes.CLASS: {
1249      handleGlobalClass(keyValue, mockBuffer, values, [keyValue], member);
1250      break;
1251    }
1252    case KeyValueTypes.MODULE: {
1253      handleGlobalModule(keyValue, mockBuffer, values, [keyValue], member);
1254      break;
1255    }
1256    case KeyValueTypes.INTERFACE: {
1257      handleGlobalInterface(keyValue, mockBuffer, values, [keyValue], member);
1258      break;
1259    }
1260    default: {
1261      if (!mockedDeclarations.has(key)) {
1262        const value = `global.${key} = global.${key} || (${handleKeyValue(key, keyValue, mockBuffer, [], keyValue, keyValue.property)});`;
1263        values.push(value);
1264        mockedDeclarations.add(key);
1265      }
1266      break;
1267    }
1268  }
1269  handleDependOnGlobals(keyValue, declarations, mockedDeclarations);
1270  Array.prototype.push.apply(declarations, values);
1271}
1272
1273/**
1274 * 处理KV节点用到的全局节点
1275 * @param keyValue KV节点
1276 * @param declarations 已mock的文本内容
1277 * @param mockedDeclarations 已mock的全局节点的集合
1278 * @returns
1279 */
1280function handleDependOnGlobals(
1281  keyValue: KeyValue,
1282  declarations: string[],
1283  mockedDeclarations: Set<string>
1284): void {
1285  if (keyValue.type === KeyValueTypes.FUNCTION) {
1286    return;
1287  }
1288  keyValue.dependOnGlobals.forEach(dependKeyValue => {
1289    if (dependKeyValue.isGlobalDeclare) {
1290      handleDeclare(DECLARES[dependKeyValue.key], declarations, mockedDeclarations);
1291    } else if (dependKeyValue.parent.isGlobalDeclare) {
1292      handleDeclare(DECLARES[dependKeyValue.parent.key], declarations, mockedDeclarations, dependKeyValue);
1293    } else {
1294      throw new Error(`${keyValue.key}非全局节点。`);
1295    }
1296  });
1297}
1298
1299/**
1300 * 处理全局class KV节点
1301 * @param keyValue class类型的KV节点
1302 * @param mockBuffer mock信息
1303 * @param declarations 已mock的文本内容
1304 * @param kvPath KV节点路径
1305 * @param member 不为undefined时,只mock这个member节点
1306 * @returns
1307 */
1308function handleGlobalClass(
1309  keyValue: KeyValue,
1310  mockBuffer: MockBuffer,
1311  declarations: string[],
1312  kvPath: KeyValue[],
1313  member?: KeyValue
1314): void {
1315  if (member) {
1316    if (!member.isMocked) {
1317      const memberValue = handleKeyValue(member.key, member, mockBuffer, kvPath, keyValue, member.property);
1318      const functionKeyword = member.type === KeyValueTypes.FUNCTION ? 'function' : '';
1319      const prototypeStr = member.isStatic ? '' : '.prototype';
1320      const value = `global.${keyValue.key}_temp${prototypeStr}.${member.key} = ${functionKeyword}${memberValue};`;
1321      member.isMocked = true;
1322      declarations.push(value);
1323    }
1324    return;
1325  }
1326  if (keyValue.heritage) {
1327    handleHeritage(keyValue, mockBuffer, kvPath.concat(keyValue), keyValue);
1328  }
1329
1330  Object.keys(keyValue.members).forEach(
1331    memberKey => handleClassMembers(memberKey, keyValue, mockBuffer, kvPath, declarations)
1332  );
1333  // 处理同名declare
1334  keyValue.sameDeclares.forEach(sameDeclare => {
1335    const sameKeyValue = sameDeclare.keyValue;
1336    const sameMockBuffer = mockBufferMap.get(MockedFileMap.get(sameDeclare.from));
1337    Object.keys(sameKeyValue.members).forEach(
1338      memberKey => handleClassMembers(memberKey, sameKeyValue, sameMockBuffer, kvPath, declarations)
1339    );
1340  });
1341}
1342
1343/**
1344 * 处理class KV节点的属性和方法
1345 * @param memberKey 属性或方法的名称
1346 * @param parent 父级class KV节点
1347 * @param mockBuffer 所属文件的mock信息
1348 * @param kvPath KV节点路径
1349 * @param declarations 已mock的文本内容
1350 * @returns
1351 */
1352function handleClassMembers(
1353  memberKey: string,
1354  parent: KeyValue,
1355  mockBuffer: MockBuffer,
1356  kvPath: KeyValue[],
1357  declarations: string[]
1358): void {
1359  const memberKeyValue = parent.members[memberKey];
1360  if (memberKeyValue.isMocked) {
1361    return;
1362  }
1363  let elementName = `.${memberKey}`;
1364  if (memberKeyValue.type === KeyValueTypes.EXPRESSION) {
1365    memberKeyValue.key = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, parent, memberKeyValue.property);
1366    memberKeyValue.type = KeyValueTypes.FUNCTION;
1367    memberKeyValue.value = undefined;
1368    elementName = memberKeyValue.key;
1369  }
1370
1371  const memberValue = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, parent, memberKeyValue.property);
1372  let value: string;
1373  if (memberKeyValue.type === KeyValueTypes.FUNCTION) {
1374    value = handleClassMethod(memberKey, memberKeyValue, parent, mockBuffer, kvPath, elementName, memberValue);
1375  } else {
1376    value = `global.${parent.key}_temp${memberKeyValue.isStatic ? '' : '.prototype'}${elementName} = ${memberValue};`;
1377  }
1378  if (!memberKeyValue.isStatic && memberKeyValue.sameName.some(sameKeyValue => sameKeyValue.isStatic)) {
1379    value += `\nglobal.${parent.key}_temp${elementName} = global.${parent.key}_temp.prototype${elementName}`;
1380  }
1381  memberKeyValue.isMocked = true;
1382  declarations.push(value);
1383}
1384
1385/**
1386 * 处理全局module KV节点
1387 * @param keyValue KV节点
1388 * @param mockBuffer 所属文件的mock信息
1389 * @param declarations 已mock的文本内容
1390 * @param kvPath KV节点路径
1391 * @param member 不为undefined时,只mock这个member节点
1392 * @returns
1393 */
1394function handleGlobalModule(
1395  keyValue: KeyValue,
1396  mockBuffer: MockBuffer,
1397  declarations: string[],
1398  kvPath: KeyValue[],
1399  member?: KeyValue
1400): void {
1401  return handleGlobalModuleOrInterface(keyValue, mockBuffer, declarations, kvPath, member);
1402}
1403
1404/**
1405 * 处理全局module或interface KV节点
1406 * @param keyValue KV节点
1407 * @param mockBuffer 所属文件的mock信息
1408 * @param declarations 已mock的文本内容
1409 * @param kvPath KV节点路径
1410 * @param member 不为undefined时,只mock这个member节点
1411 * @returns
1412 */
1413function handleGlobalModuleOrInterface(
1414  keyValue: KeyValue,
1415  mockBuffer: MockBuffer,
1416  declarations: string[],
1417  kvPath: KeyValue[],
1418  member?: KeyValue
1419): void {
1420  if (member) {
1421    if (!member.isMocked) {
1422      const memberKey = member.key;
1423      const memberValue = handleKeyValue(memberKey, member, mockBuffer, kvPath, keyValue, member.property);
1424      const value = `global.${keyValue.key}_temp.${memberKey} = ${memberValue};`;
1425      member.isMocked = true;
1426      declarations.push(value);
1427    }
1428    return;
1429  }
1430  Object.keys(keyValue.members).forEach(memberKey => handleModuleOrInterfaceMember(memberKey, keyValue, mockBuffer, kvPath, declarations, keyValue));
1431  // 处理同名declare
1432  keyValue.sameDeclares.forEach(sameDeclare => {
1433    const sameKeyValue = sameDeclare.keyValue;
1434    const sameMockBuffer = mockBufferMap.get(MockedFileMap.get(sameDeclare.from));
1435    const needHandleTypes = new Set([KeyValueTypes.CLASS, KeyValueTypes.INTERFACE, KeyValueTypes.MODULE]);
1436    if (!needHandleTypes.has(sameKeyValue.type) && path.basename(sameMockBuffer.rawFilePath).startsWith('@')) {
1437      return;
1438    }
1439    Object.keys(sameKeyValue.members).forEach(
1440      memberKey => handleModuleOrInterfaceMember(memberKey, sameKeyValue, sameMockBuffer, kvPath, declarations, keyValue)
1441    );
1442  });
1443}
1444
1445/**
1446 * 处理module和interface的成员
1447 * @param memberKey 成员名称
1448 * @param parent 成员父节点
1449 * @param mockBuffer 当前文件mock信息
1450 * @param kvPath KV节点路径
1451 * @param declarations 已mock的全局接口
1452 * @param rootKeyValue
1453 */
1454function handleModuleOrInterfaceMember(
1455  memberKey: string,
1456  parent: KeyValue,
1457  mockBuffer: MockBuffer,
1458  kvPath: KeyValue[],
1459  declarations: string[],
1460  rootKeyValue: KeyValue
1461): void {
1462  const memberKeyValue = parent.members[memberKey];
1463  if (memberKeyValue.isMocked) {
1464    return;
1465  }
1466  let elementName = `.${memberKey}`;
1467  if (memberKeyValue.type === KeyValueTypes.EXPRESSION) {
1468    memberKeyValue.key = handleKeyValue(memberKey, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1469    memberKeyValue.type = KeyValueTypes.PROPERTY;
1470    memberKeyValue.value = undefined;
1471    elementName = memberKeyValue.key;
1472  }
1473  const memberValue = handleKeyValue(elementName, memberKeyValue, mockBuffer, kvPath, rootKeyValue, memberKeyValue.property);
1474  const value = `global.${parent.key}_temp${elementName} = ${memberValue};`;
1475  memberKeyValue.isMocked = true;
1476  declarations.push(value);
1477}
1478
1479/**
1480 * 处理全局interface KV节点
1481 * @param keyValue KV节点
1482 * @param mockBuffer 所属文件的mock信息
1483 * @param declarations 已mock的文本内容
1484 * @param kvPath KV节点路径
1485 * @param member 不为undefined时,只mock这个member节点
1486 * @returns
1487 */
1488function handleGlobalInterface(
1489  keyValue: KeyValue,
1490  mockBuffer: MockBuffer,
1491  declarations: string[],
1492  kvPath: KeyValue[],
1493  member?: KeyValue
1494): void {
1495  if (keyValue.heritage) {
1496    handleHeritage(keyValue, mockBuffer, kvPath.concat(keyValue), keyValue);
1497  }
1498  return handleGlobalModuleOrInterface(keyValue, mockBuffer, declarations, kvPath, member);
1499}
1500
1501/**
1502 * 从导入节点向上查找类型定义
1503 * @param importKeyValue 导入的KV节点
1504 * @param mockBuffer 当前文件的mock信息
1505 * @param rootKeyValue 仅次于FILE节点的根节点
1506 * @param property KV节点的调用属性节点,如A.b, b节点为property
1507 * @returns
1508 */
1509function findDefFromImport(
1510  importKeyValue: KeyValue,
1511  mockBuffer: MockBuffer,
1512  rootKeyValue: KeyValue,
1513  property?: KeyValue
1514): ReferenceFindResult {
1515  const importedMockBuffer = mockBufferMap.get(MockedFileMap.get(importKeyValue.importedModulePath));
1516  if (!importedMockBuffer) {
1517    throw new Error('未找到foundKeyValue.importedModulePath对应的mockBuffer');
1518  }
1519  let defKeyValue: KeyValue;
1520  if (importKeyValue.isImportDefault) {
1521    defKeyValue = importedMockBuffer.contents.members.default;
1522  } else if (importKeyValue.isNamespaceImport) {
1523    defKeyValue = importedMockBuffer.contents;
1524  } else {
1525    defKeyValue = importedMockBuffer.contents.members[importKeyValue.rawName ?? importKeyValue.key];
1526  }
1527  if (defKeyValue.isGlobalDeclare) {
1528    const dependKeyValue = property ? defKeyValue.members[property.key] : defKeyValue;
1529    if (dependKeyValue.type === KeyValueTypes.ENUM) {
1530      defKeyValue = dependKeyValue;
1531    } else {
1532      !dependKeyValue.isMocked && rootKeyValue.dependOnGlobals.add(dependKeyValue);
1533      const keyValueType = getKeyValueType(defKeyValue, property);
1534      const newKey = `global.${defKeyValue.key}${concatProperty(property)}`;
1535      defKeyValue = generateKeyValue(newKey, keyValueType);
1536      defKeyValue.value = newKey;
1537      !dependKeyValue.isMocked && defKeyValue.dependOnGlobals.add(dependKeyValue);
1538    }
1539  } else {
1540    defKeyValue = findProperty(defKeyValue, property);
1541  }
1542
1543  if (!defKeyValue) {
1544    const value = `Not exported ${importKeyValue.rawName ?? importKeyValue.key} from ${importedMockBuffer.rawFilePath} in ${mockBuffer.rawFilePath}`.replace(/\\/g, '/');
1545    console.error(value);
1546    defKeyValue = generateKeyValue(value, KeyValueTypes.VALUE, importedMockBuffer.contents);
1547    defKeyValue.value = `'${value}'`;
1548  }
1549  return { keyValue: defKeyValue, mockBuffer: importedMockBuffer };
1550}
1551
1552/**
1553 * mock类方法
1554 * @param memberKey 方法原名
1555 * @param memberKeyValue 方法KV节点
1556 * @param parent  负极节点
1557 * @param mockBuffer 当前文件的mock信息
1558 * @param kvPath KV检点路径
1559 * @param elementName 方法名转换后方法名
1560 * @param memberValue 类方法的mock内容
1561 */
1562function handleClassMethod(
1563  memberKey: string,
1564  memberKeyValue: KeyValue,
1565  parent: KeyValue,
1566  mockBuffer: MockBuffer,
1567  kvPath: KeyValue[],
1568  elementName: string,
1569  memberValue: string
1570): string {
1571  let value:string;
1572  if (memberKey.startsWith('get ') || memberKey.startsWith('set ')) {
1573    value = handleClassGetterOrSetterMethod(memberKeyValue, parent, mockBuffer, kvPath);
1574  } else {
1575    value = `global.${parent.key}_temp${memberKeyValue.isStatic ? '' : '.prototype'}${elementName} = ${memberValue};`;
1576  }
1577  return value;
1578}
1579
1580/**
1581 * mock 类中带get和set关键字的方法
1582 * @param memberKeyValue 类方法KV节点
1583 * @param parent 父级KV节点
1584 * @param mockBuffer 当前文件的mock信息
1585 * @param kvPath KV节点路径
1586 */
1587function handleClassGetterOrSetterMethod(
1588  memberKeyValue: KeyValue,
1589  parent: KeyValue,
1590  mockBuffer: MockBuffer,
1591  kvPath: KeyValue[]
1592): string {
1593  const getKey = `get ${memberKeyValue.key}`;
1594  let getMethodValue: string = '';
1595  if (parent.members[getKey]) {
1596    const getFunctionBody = handleKeyValue(getKey, parent.members[getKey], mockBuffer, kvPath, parent, memberKeyValue.property);
1597    getMethodValue = `get: ${getFunctionBody},`;
1598  }
1599
1600  let setMethodValue: string = '';
1601  const setKey = `set ${memberKeyValue.key}`;
1602  if (parent.members[setKey]) {
1603    const setFunctionBody = handleKeyValue(setKey, parent.members[setKey], mockBuffer, kvPath, parent, memberKeyValue.property);
1604    setMethodValue = `set: ${setFunctionBody},`;
1605  }
1606
1607  if (parent.members[getKey]) {
1608    parent.members[getKey].isMocked = true;
1609  }
1610  if (parent.members[setKey]) {
1611    parent.members[setKey].isMocked = true;
1612  }
1613
1614  return `Object.defineProperty(global.${parent.key}_temp, '${memberKeyValue.key}', {
1615  ${getMethodValue}
1616  ${setMethodValue}
1617});`;
1618}
1619