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 type { SourceFile } from 'typescript';
177c804472Sopenharmony_ciimport { SyntaxKind } from 'typescript';
187c804472Sopenharmony_ciimport type { MethodEntity } from '../declaration-node/methodDeclaration';
197c804472Sopenharmony_ciimport type { FunctionEntity } from '../declaration-node/functionDeclaration';
207c804472Sopenharmony_ciimport type { MethodSignatureEntity } from '../declaration-node/methodSignatureDeclaration';
217c804472Sopenharmony_ciimport {
227c804472Sopenharmony_ci  generateSymbolIterator,
237c804472Sopenharmony_ci  getCallbackStatement,
247c804472Sopenharmony_ci  getReturnStatement,
257c804472Sopenharmony_ci  getWarnConsole,
267c804472Sopenharmony_ci  getReturnData,
277c804472Sopenharmony_ci  getOverloadedFunctionCallbackStatement,
287c804472Sopenharmony_ci  overloadedFunctionArr
297c804472Sopenharmony_ci} from './generateCommonUtil';
307c804472Sopenharmony_ci
317c804472Sopenharmony_ciinterface MethodArrayProps {
327c804472Sopenharmony_ci  methodArray: Array<MethodEntity>;
337c804472Sopenharmony_ci  methodEntity: MethodEntity;
347c804472Sopenharmony_ci  sourceFile: SourceFile;
357c804472Sopenharmony_ci  mockApi: string;
367c804472Sopenharmony_ci  methodBody: string;
377c804472Sopenharmony_ci}
387c804472Sopenharmony_ci
397c804472Sopenharmony_ciinterface MethodArrayItemForEachProps {
407c804472Sopenharmony_ci  returnSet: Set<string>;
417c804472Sopenharmony_ci  value: MethodEntity | FunctionEntity | MethodSignatureEntity;
427c804472Sopenharmony_ci  argSet: Set<string>;
437c804472Sopenharmony_ci  isCallBack: boolean;
447c804472Sopenharmony_ci  argParamsSet: string;
457c804472Sopenharmony_ci  needOverloaded: boolean;
467c804472Sopenharmony_ci}
477c804472Sopenharmony_ci
487c804472Sopenharmony_ciinterface MethodArrayBack {
497c804472Sopenharmony_ci  returnSet: Set<string>;
507c804472Sopenharmony_ci  methodBody: string;
517c804472Sopenharmony_ci  isCallBack: boolean;
527c804472Sopenharmony_ci}
537c804472Sopenharmony_ci
547c804472Sopenharmony_ci/**
557c804472Sopenharmony_ci * generate class method
567c804472Sopenharmony_ci * @param rootName
577c804472Sopenharmony_ci * @param methodArray
587c804472Sopenharmony_ci * @param sourceFile
597c804472Sopenharmony_ci * @returns
607c804472Sopenharmony_ci */
617c804472Sopenharmony_ciexport function generateCommonMethod(
627c804472Sopenharmony_ci  rootName: string,
637c804472Sopenharmony_ci  methodArray: Array<MethodEntity>,
647c804472Sopenharmony_ci  sourceFile: SourceFile,
657c804472Sopenharmony_ci  mockApi: string
667c804472Sopenharmony_ci): string {
677c804472Sopenharmony_ci  let methodBody = '';
687c804472Sopenharmony_ci  const methodEntity = methodArray[0];
697c804472Sopenharmony_ci  if (methodEntity.functionName.name === 'Symbol.iterator') {
707c804472Sopenharmony_ci    methodBody += `this[${methodEntity.functionName.name}] = function(...args) {`;
717c804472Sopenharmony_ci    methodBody += getWarnConsole(rootName, methodEntity.functionName.name);
727c804472Sopenharmony_ci    methodBody += generateSymbolIterator(methodEntity);
737c804472Sopenharmony_ci    methodBody += '};\n';
747c804472Sopenharmony_ci    return methodBody;
757c804472Sopenharmony_ci  } else {
767c804472Sopenharmony_ci    methodBody += `this.${methodEntity.functionName.name} = function(...args) {`;
777c804472Sopenharmony_ci    methodBody += getWarnConsole(rootName, methodEntity.functionName.name);
787c804472Sopenharmony_ci  }
797c804472Sopenharmony_ci
807c804472Sopenharmony_ci  if (methodArray.length === 1) {
817c804472Sopenharmony_ci    const args = methodEntity.args;
827c804472Sopenharmony_ci    const len = args.length;
837c804472Sopenharmony_ci    if (len && args[len - 1].paramName.toLowerCase().includes('callback')) {
847c804472Sopenharmony_ci      methodBody += getCallbackStatement(mockApi, args[len - 1]?.paramTypeString);
857c804472Sopenharmony_ci    }
867c804472Sopenharmony_ci    if (methodEntity.returnType.returnKind !== SyntaxKind.VoidKeyword) {
877c804472Sopenharmony_ci      if (methodEntity.functionName.name === 'getApplicationContext') {
887c804472Sopenharmony_ci        methodBody += getApplicationContextValue(methodEntity.functionName.name);
897c804472Sopenharmony_ci      } else {
907c804472Sopenharmony_ci        methodBody += getReturnStatement(methodEntity.returnType, sourceFile);
917c804472Sopenharmony_ci      }
927c804472Sopenharmony_ci    }
937c804472Sopenharmony_ci  } else {
947c804472Sopenharmony_ci    const methodArrayBack = methodArrayForEach({ methodArray, methodEntity, sourceFile, mockApi, methodBody });
957c804472Sopenharmony_ci    methodBody = returnSetForEach(methodArrayBack, methodArray, sourceFile, mockApi);
967c804472Sopenharmony_ci  }
977c804472Sopenharmony_ci  methodBody += '};\n';
987c804472Sopenharmony_ci  return methodBody;
997c804472Sopenharmony_ci}
1007c804472Sopenharmony_ci
1017c804472Sopenharmony_cifunction getApplicationContextValue(name: string): string {
1027c804472Sopenharmony_ci  return `
1037c804472Sopenharmony_ciconst mockData = {
1047c804472Sopenharmony_ci  on: function (...args) {
1057c804472Sopenharmony_ci    console.warn(
1067c804472Sopenharmony_ci      'The ${name}.on interface in the Previewer is a mocked implementation and may behave differently than on a real device.'
1077c804472Sopenharmony_ci    );
1087c804472Sopenharmony_ci    if (args && ['environment'].includes(args[0])) {
1097c804472Sopenharmony_ci      if (args && typeof args[args.length - 1] === 'function') {
1107c804472Sopenharmony_ci        const EnvironmentCallback = mockEnvironmentCallback();
1117c804472Sopenharmony_ci        args[args.length - 1].call(this, new EnvironmentCallback());
1127c804472Sopenharmony_ci      }
1137c804472Sopenharmony_ci    }
1147c804472Sopenharmony_ci    return 0;
1157c804472Sopenharmony_ci  },
1167c804472Sopenharmony_ci  off: function (...args) {
1177c804472Sopenharmony_ci    console.warn(
1187c804472Sopenharmony_ci      'The ${name}.off interface in the Previewer is a mocked implementation and may behave differently than on a real device.'
1197c804472Sopenharmony_ci    );
1207c804472Sopenharmony_ci    if (args && ['environment'].includes(args[0])) {
1217c804472Sopenharmony_ci      if (args && typeof args[args.length - 1] === 'function') {
1227c804472Sopenharmony_ci        args[args.length - 1].call(
1237c804472Sopenharmony_ci          this,
1247c804472Sopenharmony_ci          { 'code': '', 'data': '', 'name': '', 'message': '', 'stack': '' },
1257c804472Sopenharmony_ci          '[PC Preview] unknown type'
1267c804472Sopenharmony_ci        );
1277c804472Sopenharmony_ci      }
1287c804472Sopenharmony_ci    } 
1297c804472Sopenharmony_ci    return new Promise((resolve, reject) => {
1307c804472Sopenharmony_ci        resolve('[PC Preview] unknown type');
1317c804472Sopenharmony_ci    });
1327c804472Sopenharmony_ci  }
1337c804472Sopenharmony_ci};
1347c804472Sopenharmony_cireturn mockData;
1357c804472Sopenharmony_ci  `;
1367c804472Sopenharmony_ci}
1377c804472Sopenharmony_ci
1387c804472Sopenharmony_ci/**
1397c804472Sopenharmony_ci * method Array ForEach
1407c804472Sopenharmony_ci * @param props
1417c804472Sopenharmony_ci * @returns
1427c804472Sopenharmony_ci */
1437c804472Sopenharmony_cifunction methodArrayForEach(props: MethodArrayProps): MethodArrayBack {
1447c804472Sopenharmony_ci  let argSet: Set<string> = new Set<string>();
1457c804472Sopenharmony_ci  let argParamsSet: string = '';
1467c804472Sopenharmony_ci  let returnSet: Set<string> = new Set<string>();
1477c804472Sopenharmony_ci  let isCallBack = false;
1487c804472Sopenharmony_ci  let needOverloaded = false;
1497c804472Sopenharmony_ci  props.methodArray.forEach(value => {
1507c804472Sopenharmony_ci    ({ returnSet, argSet, isCallBack, argParamsSet, needOverloaded} =
1517c804472Sopenharmony_ci      methodArrayItemForEach({returnSet, value, argSet, isCallBack, argParamsSet, needOverloaded}));
1527c804472Sopenharmony_ci  });
1537c804472Sopenharmony_ci  if (isCallBack) {
1547c804472Sopenharmony_ci    if (overloadedFunctionArr.includes(props.methodEntity.functionName.name) && needOverloaded) {
1557c804472Sopenharmony_ci      props.methodBody += getOverloadedFunctionCallbackStatement(props.methodArray, props.sourceFile, props.mockApi);
1567c804472Sopenharmony_ci    } else {
1577c804472Sopenharmony_ci      props.methodBody += getCallbackStatement(props.mockApi, argParamsSet);
1587c804472Sopenharmony_ci    }
1597c804472Sopenharmony_ci  }
1607c804472Sopenharmony_ci  return {
1617c804472Sopenharmony_ci    returnSet,
1627c804472Sopenharmony_ci    methodBody: props.methodBody,
1637c804472Sopenharmony_ci    isCallBack
1647c804472Sopenharmony_ci  };
1657c804472Sopenharmony_ci}
1667c804472Sopenharmony_ci
1677c804472Sopenharmony_ci/**
1687c804472Sopenharmony_ci * method ArrayItem ForEach
1697c804472Sopenharmony_ci * @param props
1707c804472Sopenharmony_ci * @returns
1717c804472Sopenharmony_ci */
1727c804472Sopenharmony_ciexport function methodArrayItemForEach(props: MethodArrayItemForEachProps): MethodArrayItemForEachProps {
1737c804472Sopenharmony_ci  props.returnSet.add(props.value.returnType.returnKindName);
1747c804472Sopenharmony_ci  props.value.args.forEach(arg => {
1757c804472Sopenharmony_ci    props.argSet.add(arg.paramName);
1767c804472Sopenharmony_ci    if (arg.paramName.toLowerCase().includes('callback')) {
1777c804472Sopenharmony_ci      props.isCallBack = true;
1787c804472Sopenharmony_ci      if (arg.paramTypeString) {
1797c804472Sopenharmony_ci        props.argParamsSet = arg.paramTypeString;
1807c804472Sopenharmony_ci      }
1817c804472Sopenharmony_ci    }
1827c804472Sopenharmony_ci    if (
1837c804472Sopenharmony_ci      arg.paramTypeString.startsWith("'") && arg.paramTypeString.endsWith("'") ||
1847c804472Sopenharmony_ci      arg.paramTypeString.startsWith('"') && arg.paramTypeString.endsWith('"')
1857c804472Sopenharmony_ci    ) {
1867c804472Sopenharmony_ci      props.needOverloaded = true;
1877c804472Sopenharmony_ci    }
1887c804472Sopenharmony_ci  });
1897c804472Sopenharmony_ci  return props;
1907c804472Sopenharmony_ci}
1917c804472Sopenharmony_ci
1927c804472Sopenharmony_ci/**
1937c804472Sopenharmony_ci * returnSet ForEach
1947c804472Sopenharmony_ci * @param props
1957c804472Sopenharmony_ci * @param methodArray
1967c804472Sopenharmony_ci * @param sourceFile
1977c804472Sopenharmony_ci * @param mockApi
1987c804472Sopenharmony_ci * @returns
1997c804472Sopenharmony_ci */
2007c804472Sopenharmony_cifunction returnSetForEach(
2017c804472Sopenharmony_ci  props: MethodArrayBack,
2027c804472Sopenharmony_ci  methodArray: Array<MethodEntity>,
2037c804472Sopenharmony_ci  sourceFile: SourceFile,
2047c804472Sopenharmony_ci  mockApi: string
2057c804472Sopenharmony_ci): string {
2067c804472Sopenharmony_ci  let isReturnPromise = false;
2077c804472Sopenharmony_ci  let promiseReturnValue = '';
2087c804472Sopenharmony_ci  let methodOtherReturnValue = '';
2097c804472Sopenharmony_ci  props.returnSet.forEach(value => {
2107c804472Sopenharmony_ci    if (value.includes('Promise<')) {
2117c804472Sopenharmony_ci      isReturnPromise = true;
2127c804472Sopenharmony_ci      promiseReturnValue = value;
2137c804472Sopenharmony_ci    } else {
2147c804472Sopenharmony_ci      if (!methodOtherReturnValue) {
2157c804472Sopenharmony_ci        methodOtherReturnValue = value;
2167c804472Sopenharmony_ci      }
2177c804472Sopenharmony_ci    }
2187c804472Sopenharmony_ci  });
2197c804472Sopenharmony_ci  if (isReturnPromise) {
2207c804472Sopenharmony_ci    if (promiseReturnValue) {
2217c804472Sopenharmony_ci      let returnType = null;
2227c804472Sopenharmony_ci      methodArray.forEach(value => {
2237c804472Sopenharmony_ci        if (value.returnType.returnKindName === promiseReturnValue) {
2247c804472Sopenharmony_ci          returnType = value.returnType;
2257c804472Sopenharmony_ci        }
2267c804472Sopenharmony_ci      });
2277c804472Sopenharmony_ci      props.methodBody += getReturnData(props.isCallBack, isReturnPromise, returnType, sourceFile, mockApi);
2287c804472Sopenharmony_ci    } else {
2297c804472Sopenharmony_ci      props.methodBody += `
2307c804472Sopenharmony_ci            return new Promise((resolve, reject) => {
2317c804472Sopenharmony_ci              resolve('[PC Preview] unknow boolean');
2327c804472Sopenharmony_ci            })
2337c804472Sopenharmony_ci          `;
2347c804472Sopenharmony_ci    }
2357c804472Sopenharmony_ci  } else if (methodOtherReturnValue) {
2367c804472Sopenharmony_ci    let returnType = null;
2377c804472Sopenharmony_ci    methodArray.forEach(value => {
2387c804472Sopenharmony_ci      if (value.returnType.returnKindName === methodOtherReturnValue) {
2397c804472Sopenharmony_ci        returnType = value.returnType;
2407c804472Sopenharmony_ci      }
2417c804472Sopenharmony_ci    });
2427c804472Sopenharmony_ci    props.methodBody += getReturnData(props.isCallBack, isReturnPromise, returnType, sourceFile, mockApi);
2437c804472Sopenharmony_ci  }
2447c804472Sopenharmony_ci  return props.methodBody;
2457c804472Sopenharmony_ci}
246