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 type { SourceFile } from 'typescript'; 17import { SyntaxKind } from 'typescript'; 18import type { FunctionEntity } from '../declaration-node/functionDeclaration'; 19import { 20 getCallbackStatement, 21 getReturnStatement, 22 getWarnConsole, 23 getReturnData, 24 getOverloadedFunctionCallbackStatement, 25 overloadedFunctionArr 26} from './generateCommonUtil'; 27import { methodArrayItemForEach } from './generateCommonMethod'; 28 29interface AssemblyFunctionProps { 30 functionArray: Array<FunctionEntity>; 31 functionEntity: FunctionEntity; 32 functionBody: string; 33 sourceFile: SourceFile; 34 mockApi: string; 35} 36 37interface AssemblyFunctionBack { 38 isReturnPromise: boolean; 39 promiseReturnValue: string; 40 functionOtherReturnValue: string; 41 isCallBack: boolean; 42 functionBody: string; 43} 44 45/** 46 * generate function 47 * @param rootName 48 * @param functionArray 49 * @param sourceFile 50 * @param mockApi 51 * @param isRoot 52 * @returns 53 */ 54export function generateCommonFunction( 55 rootName: string, 56 functionArray: Array<FunctionEntity>, 57 sourceFile: SourceFile, 58 mockApi: string, 59 isRoot: boolean 60): string { 61 let functionBody = ''; 62 const functionEntity = functionArray[0]; 63 if (isRoot) { 64 functionBody = `${functionEntity.isExport ? 'export ' : ''}const ${ 65 functionEntity.functionName 66 } = function(...args) {`; 67 } else { 68 functionBody = `${functionEntity.functionName}: function(...args) {`; 69 } 70 functionBody += getWarnConsole(rootName, functionEntity.functionName); 71 72 if (functionArray.length === 1) { 73 const args = functionEntity.args; 74 const len = args.length; 75 if (len && args[len - 1].paramName.toLowerCase().includes('callback')) { 76 functionBody += getCallbackStatement(mockApi, args[len - 1]?.paramTypeString); 77 } 78 if (functionEntity.returnType.returnKind !== SyntaxKind.VoidKeyword) { 79 if (rootName === 'featureAbility' && functionEntity.returnType.returnKindName === 'Context') { 80 functionBody += 'return _Context;'; 81 } else if (rootName === 'inputMethod' && functionEntity.returnType.returnKindName === 'InputMethodSubtype') { 82 functionBody += 'return mockInputMethodSubtype().InputMethodSubtype;'; 83 } else { 84 functionBody += getReturnStatement(functionEntity.returnType, sourceFile); 85 } 86 } 87 } else { 88 const assemblyBack = assemblyFunctionBody({ functionArray, functionEntity, functionBody, mockApi, sourceFile }); 89 functionBody = assemblyFuntion(assemblyBack, functionArray, sourceFile, mockApi); 90 functionBody = assemblyBack.functionBody; 91 } 92 functionBody += isRoot ? '};' : '},'; 93 if (isRoot) { 94 functionBody += ` 95 if (!global.${functionEntity.functionName}) { 96 global.${functionEntity.functionName} = ${functionEntity.functionName}; 97 } 98 `; 99 } 100 return functionBody; 101} 102 103/** 104 * generate assembly function 105 * @param props 106 * @returns 107 */ 108function assemblyFunctionBody(props: AssemblyFunctionProps): AssemblyFunctionBack { 109 let argSet: Set<string> = new Set<string>(); 110 let argParamsSet: string = ''; 111 let returnSet: Set<string> = new Set<string>(); 112 let isCallBack = false; 113 let needOverloaded = false; 114 props.functionArray.forEach(value => { 115 ({ returnSet, argSet, isCallBack, argParamsSet, needOverloaded} = 116 methodArrayItemForEach({returnSet, value, argSet, isCallBack, argParamsSet, needOverloaded})); 117 }); 118 props.functionBody = forEachFuntionArray(isCallBack, props, needOverloaded, argParamsSet); 119 let isReturnPromise = false; 120 let promiseReturnValue = ''; 121 let functionOtherReturnValue = ''; 122 returnSet.forEach(value => { 123 if (value.includes('Promise<')) { 124 isReturnPromise = true; 125 promiseReturnValue = value; 126 } else { 127 if (!functionOtherReturnValue) { 128 functionOtherReturnValue = value; 129 } 130 } 131 }); 132 return { 133 isReturnPromise, 134 promiseReturnValue, 135 functionOtherReturnValue, 136 isCallBack, 137 functionBody: props.functionBody 138 }; 139} 140 141/** 142 * forEach functionArray 143 * @param isCallBack 144 * @param props 145 * @param needOverloaded 146 * @param argParamsSet 147 * @returns 148 */ 149function forEachFuntionArray( 150 isCallBack: boolean, 151 props: AssemblyFunctionProps, 152 needOverloaded: boolean, 153 argParamsSet: string 154): string { 155 if (isCallBack) { 156 if (overloadedFunctionArr.includes(props.functionEntity.functionName) && needOverloaded) { 157 const stateEment = getOverloadedFunctionCallbackStatement(props.functionArray, props.sourceFile, props.mockApi); 158 props.functionBody += stateEment; 159 } else { 160 props.functionBody += getCallbackStatement(props.mockApi, argParamsSet); 161 } 162 } 163 return props.functionBody; 164} 165 166/** 167 * assembly Function 168 * @param porps 169 * @param functionArray 170 * @param sourceFile 171 * @param mockApi 172 * @returns 173 */ 174function assemblyFuntion( 175 porps: AssemblyFunctionBack, 176 functionArray: Array<FunctionEntity>, 177 sourceFile: SourceFile, 178 mockApi: string 179): string { 180 if (porps.isReturnPromise) { 181 if (porps.promiseReturnValue) { 182 let returnType = null; 183 functionArray.forEach(value => { 184 if (value.returnType.returnKindName === porps.promiseReturnValue) { 185 returnType = value.returnType; 186 } 187 }); 188 porps.functionBody += getReturnData(porps.isCallBack, porps.isReturnPromise, returnType, sourceFile, mockApi); 189 } else { 190 porps.functionBody += ` 191 return new Promise((resolve, reject) => { 192 resolve('[PC Preview] unknow boolean'); 193 }) 194 `; 195 } 196 } else if (porps.functionOtherReturnValue) { 197 let returnType = null; 198 functionArray.forEach(value => { 199 if (value.returnType.returnKindName === porps.functionOtherReturnValue) { 200 returnType = value.returnType; 201 } 202 }); 203 porps.functionBody += getReturnData(porps.isCallBack, porps.isReturnPromise, returnType, sourceFile, mockApi); 204 } 205 return porps.functionBody; 206} 207