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