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
16 #include "sa_ts_client_proxy_code_emitter.h"
17 #include "util/file.h"
18 #include "util/logger.h"
19 #include "util/string_helper.h"
20
21 namespace OHOS {
22 namespace Idl {
ResolveDirectory(const std::string & targetDirectory)23 bool SaTsClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
24 {
25 directory_ = GetFileParentPath(targetDirectory);
26 if (!File::CreateParentDir(directory_)) {
27 Logger::E("SaTsClientProxyCodeEmitter", "Create '%s' failed!", directory_.c_str());
28 return false;
29 }
30
31 return true;
32 }
33
EmitCode()34 void SaTsClientProxyCodeEmitter::EmitCode()
35 {
36 if (!CheckInterfaceType()) {
37 return;
38 }
39 EmitInterfaceProxyFile();
40 }
41
EmitInterfaceProxyFile()42 void SaTsClientProxyCodeEmitter::EmitInterfaceProxyFile()
43 {
44 std::string filePath =
45 File::AdapterPath(StringHelper::Format("%s/%s.ts", directory_.c_str(), FileName(baseName_ + "Proxy").c_str()));
46 File file(filePath, File::WRITE);
47 StringBuilder sb;
48
49 EmitLicense(sb);
50 EmitInterfaceImports(sb);
51 sb.Append("\n");
52 EmitInterfaceProxyImpl(sb);
53 sb.Append("\n");
54
55 std::string data = sb.ToString();
56 file.WriteData(data.c_str(), data.size());
57 file.Flush();
58 file.Close();
59 }
60
EmitInterfaceProxyImpl(StringBuilder & sb)61 void SaTsClientProxyCodeEmitter::EmitInterfaceProxyImpl(StringBuilder &sb)
62 {
63 sb.AppendFormat("export default class %s implements %s {\n", proxyName_.c_str(), interfaceName_.c_str());
64 EmitInterfaceProxyConstructor(sb, TAB);
65 EmitInterfaceProxyMethodImpls(sb, TAB);
66 sb.Append("\n");
67 EmitInterfaceMethodCommands(sb, TAB);
68 sb.Append(TAB).Append("private proxy");
69 sb.Append("\n");
70 sb.Append("}\n");
71 }
72
EmitInterfaceProxyConstructor(StringBuilder & sb,const std::string & prefix) const73 void SaTsClientProxyCodeEmitter::EmitInterfaceProxyConstructor(StringBuilder &sb, const std::string &prefix) const
74 {
75 sb.Append(prefix).Append("constructor(proxy) {\n");
76 sb.Append(prefix).Append(TAB).Append("this.proxy = proxy;\n");
77 sb.Append(prefix).Append("}\n\n");
78 }
79
EmitInterfaceProxyMethodImpls(StringBuilder & sb,const std::string & prefix) const80 void SaTsClientProxyCodeEmitter::EmitInterfaceProxyMethodImpls(StringBuilder &sb, const std::string &prefix) const
81 {
82 int methodNumber = static_cast<int>(interface_->GetMethodNumber());
83 for (int i = 0; i < methodNumber; i++) {
84 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
85 EmitInterfaceMethodHead(method, sb, prefix);
86 sb.Append("): void\n");
87 EmitInterfaceProxyMethodBody(method, sb, prefix);
88 if (i != methodNumber - 1) {
89 sb.Append("\n");
90 }
91 }
92 }
93
EmitInterfaceProxyMethodBody(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const94 void SaTsClientProxyCodeEmitter::EmitInterfaceProxyMethodBody(AutoPtr<ASTMethod> &method, StringBuilder &sb,
95 const std::string &prefix) const
96 {
97 bool haveOutPara = false;
98 sb.Append(prefix).Append("{\n");
99 sb.Append(prefix).Append(TAB).Append("let option = new rpc.MessageOption();\n");
100 if (method->IsOneWay() || interface_->IsOneWay()) {
101 sb.Append(prefix).Append(TAB).Append("option.setFlags(_option.TF_ASYNC);\n");
102 }
103 sb.Append(prefix).Append(TAB).Append("let dataSequence = rpc.MessageSequence.create();\n");
104 sb.Append(prefix).Append(TAB).Append("let replySequence = rpc.MessageSequence.create();\n");
105 sb.Append(prefix).Append(TAB).Append("dataSequence.writeInterfaceToken(this.proxy.getDescriptor());\n");
106
107 int paramNumber = static_cast<int>(method->GetParameterNumber());
108 for (int i = 0; i < paramNumber; i++) {
109 AutoPtr<ASTParameter> param = method->GetParameter(i);
110 if (param->GetAttribute() & ASTParamAttr::PARAM_IN) {
111 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
112 typeEmitter->EmitTsWriteVar("dataSequence", param->GetName(), sb, prefix + TAB);
113 }
114 if (param->GetAttribute() & ASTParamAttr::PARAM_OUT) {
115 haveOutPara = true;
116 }
117 }
118 sb.Append(prefix).Append(TAB).AppendFormat(
119 "this.proxy.sendMessageRequest(%s.COMMAND_%s, dataSequence, replySequence, option).", proxyName_.c_str(),
120 ConstantName(method->GetName()).c_str());
121 sb.Append("then((result: rpc.RequestResult) => {\n");
122 EmitInterfaceMethodCallback(method, sb, prefix + TAB + TAB, haveOutPara);
123 sb.Append(prefix).Append(TAB).Append("}).catch((e: Error) => ").Append("{\n");
124 sb.Append(prefix).Append(TAB).Append(TAB).Append(
125 "console.log(\'sendMessageRequest failed, message: \' + e.message);\n");
126 sb.Append(prefix).Append(TAB).Append("}).finally(() => ").Append("{\n");
127 sb.Append(prefix).Append(TAB).Append(TAB).Append("dataSequence.reclaim();").Append("\n");
128 sb.Append(prefix).Append(TAB).Append(TAB).Append("replySequence.reclaim();").Append("\n");
129 sb.Append(prefix).Append(TAB).Append("});").Append("\n");
130 sb.Append(prefix).Append("}\n");
131 }
132
EmitInterfaceMethodCallback(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool haveOutPara) const133 void SaTsClientProxyCodeEmitter::EmitInterfaceMethodCallback(AutoPtr<ASTMethod> &method, StringBuilder &sb,
134 const std::string &prefix, bool haveOutPara) const
135 {
136 sb.Append(prefix).Append("if (result.errCode === 0) {\n");
137 // emit errCode
138 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(new ASTIntegerType());
139 if (typeEmitter == nullptr) {
140 return;
141 }
142 typeEmitter->EmitTsReadVar("result.reply", SuffixAdded(ERR_CODE).c_str(), sb, prefix + TAB);
143 EmitInterfaceMethodErrorCallback(method, sb, prefix + TAB, haveOutPara);
144 EmitInterfaceMethodCallbackInner(method, sb, prefix);
145 }
146
EmitInterfaceMethodErrorCallback(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool haveOutPara) const147 void SaTsClientProxyCodeEmitter::EmitInterfaceMethodErrorCallback(AutoPtr<ASTMethod> &method, StringBuilder &sb,
148 const std::string &prefix, bool haveOutPara) const
149 {
150 TypeKind retKind = method->GetReturnType()->GetTypeKind();
151 if ((retKind != TypeKind::TYPE_VOID) || haveOutPara) {
152 sb.Append(prefix).AppendFormat("if (%s != 0) {\n", SuffixAdded(ERR_CODE).c_str());
153 int paramNumber = static_cast<int>(method->GetParameterNumber());
154 for (int i = 0; i < paramNumber; i++) {
155 AutoPtr<ASTParameter> param = method->GetParameter(i);
156 if (param->GetAttribute() & ASTParamAttr::PARAM_OUT) {
157 sb.Append(prefix).Append(TAB).AppendFormat("let %s = undefined;\n",
158 SuffixAdded(param->GetName()).c_str());
159 }
160 }
161 if (retKind != TypeKind::TYPE_VOID) {
162 sb.Append(prefix).Append(TAB).AppendFormat(
163 "let %s = undefined;\n", SuffixAdded(RETURN_VALUE).c_str());
164 }
165 sb.Append(prefix).Append(TAB).AppendFormat("callback(%s", SuffixAdded(ERR_CODE).c_str());
166 if (retKind != TypeKind::TYPE_VOID) {
167 sb.AppendFormat(", %s", SuffixAdded(RETURN_VALUE).c_str());
168 }
169 for (int i = 0; i < paramNumber; i++) {
170 AutoPtr<ASTParameter> param = method->GetParameter(i);
171 if (param->GetAttribute() & ASTParamAttr::PARAM_OUT) {
172 sb.AppendFormat(", %s", SuffixAdded(param->GetName()).c_str());
173 }
174 }
175 sb.Append(");\n");
176 sb.Append(prefix).Append(TAB).Append("return;\n");
177 sb.Append(prefix).Append("}\n");
178 }
179 }
180
EmitInterfaceMethodCallbackInner(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const181 void SaTsClientProxyCodeEmitter::EmitInterfaceMethodCallbackInner(AutoPtr<ASTMethod> &method, StringBuilder &sb,
182 const std::string &prefix) const
183 {
184 // emit return
185 int paramNumber = static_cast<int>(method->GetParameterNumber());
186 for (int i = 0; i < paramNumber; i++) {
187 AutoPtr<ASTParameter> param = method->GetParameter(i);
188 if (param->GetAttribute() & ASTParamAttr::PARAM_OUT) {
189 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
190 if (typeEmitter == nullptr) {
191 return;
192 }
193 typeEmitter->EmitTsReadVar("result.reply", SuffixAdded(param->GetName()), sb, prefix + TAB,
194 TypeMode::PARAM_OUT);
195 }
196 }
197 AutoPtr<ASTType> returnType = method->GetReturnType();
198 if (returnType->GetTypeKind() != TypeKind::TYPE_VOID) {
199 AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(returnType);
200 if (typeEmitter != nullptr) {
201 typeEmitter->EmitTsReadVar("result.reply",
202 SuffixAdded(RETURN_VALUE), sb, prefix + TAB, TypeMode::PARAM_OUT);
203 }
204 }
205 sb.Append(prefix + TAB).AppendFormat("callback(%s", SuffixAdded(ERR_CODE).c_str());
206 if (returnType->GetTypeKind() != TypeKind::TYPE_VOID) {
207 sb.AppendFormat(", %s", SuffixAdded(RETURN_VALUE).c_str());
208 }
209 for (int i = 0; i < paramNumber; i++) {
210 AutoPtr<ASTParameter> param = method->GetParameter(i);
211 if (param->GetAttribute() & ASTParamAttr::PARAM_OUT) {
212 sb.AppendFormat(", %s", SuffixAdded(param->GetName()).c_str());
213 }
214 }
215 sb.Append(");\n");
216 sb.Append(prefix).Append("} else {\n");
217 sb.Append(prefix).Append(TAB).Append("console.log(\"sendMessageRequest failed, errCode: \" + result.errCode);\n");
218 sb.Append(prefix).Append("}\n");
219 }
220 } // namespace Idl
221 } // namespace OHOS