1 /*
2 * Copyright (c) 2022 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 "codegen/ts_code_emitter.h"
17
18 #include <cctype>
19 #include <cstdio>
20 #include <algorithm>
21
22 #include "securec.h"
23 #include "util/file.h"
24 #include "util/logger.h"
25
26 namespace OHOS {
27 namespace Idl {
28 namespace {
29 const std::string PROXY = "proxy";
30 const std::string THIS_PROXY = "this.proxy";
31 static const char* TAG = "TsCodeEmitter";
32 const std::string UNKNOWN_TYPE = "unknown type";
33 const String NEWLINE = "\n";
34 const String RETURN_VALUE = "returnValue";
35 const std::string ERR_CODE_TYPE = "errCode: number";
36 const String ERR_CODE = "errCode";
37 }
38
EmitInterface()39 void TsCodeEmitter::EmitInterface()
40 {
41 if (!CheckInterfaceType()) {
42 return;
43 }
44 String filePath = String::Format("%s/%s.ts", directory_.string(), FileName(interfaceName_).string());
45 File file(filePath, File::WRITE);
46
47 StringBuilder stringBuilder;
48
49 EmitLicense(stringBuilder);
50 stringBuilder.Append(NEWLINE);
51 EmitInterfaceSelfDefinedTypeImports(stringBuilder);
52 stringBuilder.Append(NEWLINE);
53 EmitInterfaceDefinition(stringBuilder);
54 stringBuilder.Append(NEWLINE);
55
56 String data = stringBuilder.ToString();
57 file.WriteData(data.string(), data.GetLength());
58 file.Flush();
59 file.Close();
60 }
61
EmitInterfaceImports(StringBuilder & stringBuilder)62 void TsCodeEmitter::EmitInterfaceImports(StringBuilder& stringBuilder)
63 {
64 for (const auto &item : methods_) {
65 if (item.callbackName_.size() > 0) {
66 stringBuilder.AppendFormat("import {%s} from \"./%s\";\n",
67 item.callbackName_.c_str(), FileName(interfaceName_).string());
68 }
69 }
70 stringBuilder.AppendFormat("import %s from \"./%s\";\n", metaInterface_->name_, FileName(interfaceName_).string());
71 stringBuilder.Append("import rpc from \"@ohos.rpc\";\n");
72 EmitInterfaceSelfDefinedTypeImports(stringBuilder);
73
74 for (int index = 0; index < metaComponent_->interfaceNumber_; index++) {
75 MetaInterface* mi = metaComponent_->interfaces_[index];
76 if (!interfaceName_.Equals(mi->name_)) {
77 String dependInterface = mi->name_;
78 String dependStubName = dependInterface.StartsWith("I") ?
79 dependInterface.Substring(1) + "Stub" : dependInterface + "Stub";
80 stringBuilder.AppendFormat("import %s from \"./%s\";\n", dependStubName.string(),
81 FileName(dependStubName).string());
82 }
83 }
84 }
85
EmitInterfaceSelfDefinedTypeImports(StringBuilder & stringBuilder)86 void TsCodeEmitter::EmitInterfaceSelfDefinedTypeImports(StringBuilder& stringBuilder)
87 {
88 for (int index = 0; index < metaComponent_->sequenceableNumber_; index++) {
89 MetaSequenceable* mp = metaComponent_->sequenceables_[index];
90 stringBuilder.AppendFormat("import %s from \"./%s\";\n", mp->name_, FileName(mp->name_).string());
91 }
92
93 for (int index = 0; index < metaComponent_->interfaceNumber_; index++) {
94 MetaInterface* mi = metaComponent_->interfaces_[index];
95 if (mi->external_) {
96 stringBuilder.AppendFormat("import %s from \"./%s\";\n", mi->name_, FileName(mi->name_).string());
97 }
98 }
99 }
100
EmitInterfaceDefinition(StringBuilder & stringBuilder)101 void TsCodeEmitter::EmitInterfaceDefinition(StringBuilder& stringBuilder)
102 {
103 stringBuilder.AppendFormat("export default interface %s {\n", metaInterface_->name_);
104 EmitInterfaceMethods(stringBuilder, TAB);
105 stringBuilder.Append("}\n");
106
107 for (const auto &item : methods_) {
108 if (item.callbackName_.size() > 0) {
109 stringBuilder.AppendFormat("%s\n", item.exportFunction_.c_str());
110 }
111 }
112 }
113
EmitInterfaceMethods(StringBuilder & stringBuilder,const String & prefix)114 void TsCodeEmitter::EmitInterfaceMethods(StringBuilder& stringBuilder, const String& prefix)
115 {
116 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
117 MetaMethod* metaMethod = metaInterface_->methods_[index];
118 EmitInterfaceMethod(metaMethod, stringBuilder, prefix);
119 }
120 }
121
EmitInterfaceMethod(MetaMethod * metaMethod,StringBuilder & stringBuilder,const String & prefix)122 void TsCodeEmitter::EmitInterfaceMethod(MetaMethod* metaMethod, StringBuilder& stringBuilder, const String& prefix)
123 {
124 MetaType* returnType = metaComponent_->types_[metaMethod->returnTypeIndex_];
125 Method method;
126 method.properties_ = metaMethod->properties_;
127 StringBuilder callbackName;
128 callbackName.AppendFormat("%sCallback", MethodName(metaMethod->name_).string());
129 method.callbackName_ = callbackName.ToString();
130 method.exportFunction_ = "export type " + callbackName.ToString() + " = (" + ERR_CODE_TYPE.c_str();
131
132 bool haveOutPara = false;
133 StringBuilder methodStr;
134 if (returnType->kind_ != TypeKind::Void) {
135 method.retParameter_.name_ = RETURN_VALUE.string();
136 method.retParameter_.type_ = EmitType(returnType).string();
137 }
138 methodStr.Append(prefix).AppendFormat("%s(", MethodName(metaMethod->name_).string());
139 method.name_ = MethodName(metaMethod->name_).string();
140
141 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
142 MetaParameter* mp = metaMethod->parameters_[index];
143 MetaType* paraType = metaComponent_->types_[mp->typeIndex_];
144 Parameter para;
145 para.attr_ = mp->attributes_;
146 para.name_ = mp->name_;
147 para.type_ = EmitType(paraType).string();
148 if ((mp->attributes_ & ATTR_OUT) != 0) {
149 haveOutPara = true;
150 }
151 method.parameters_.emplace_back(para);
152 }
153
154 EmitInterfaceMethodLastPara(metaMethod, prefix, method, methodStr, haveOutPara);
155 methodStr.Append("): void;\n");
156 stringBuilder.Append(methodStr.ToString());
157 methods_.emplace_back(method);
158 }
159
EmitInterfaceMethodLastPara(MetaMethod * metaMethod,const String & prefix,Method & method,StringBuilder & methodStr,bool haveOutPara)160 void TsCodeEmitter::EmitInterfaceMethodLastPara(MetaMethod* metaMethod, const String& prefix, Method& method,
161 StringBuilder& methodStr, bool haveOutPara)
162 {
163 bool isLastParaTypeIn = false;
164 for (size_t index = 0; index < method.parameters_.size(); index++) {
165 if ((method.parameters_[index].attr_ & ATTR_IN) != 0) {
166 EmitMethodInParameter(methodStr, method.parameters_[index].name_, method.parameters_[index].type_,
167 prefix + TAB);
168 if (index != method.parameters_.size() - 1) {
169 methodStr.Append(", ");
170 } else {
171 isLastParaTypeIn = true;
172 }
173 }
174 }
175 std::sort(method.parameters_.begin(), method.parameters_.end());
176 if (method.callbackName_.size() > 0) {
177 if (!isLastParaTypeIn) {
178 methodStr.AppendFormat("callback: %s", method.callbackName_.c_str());
179 } else {
180 methodStr.AppendFormat(", callback: %s", method.callbackName_.c_str());
181 }
182 if (method.retParameter_.name_.size() > 0) {
183 if (!haveOutPara) {
184 method.exportFunction_ +=
185 (", " + method.retParameter_.name_ + ": " + method.retParameter_.type_ + ") => void;");
186 } else {
187 method.exportFunction_ +=
188 (", " + method.retParameter_.name_ + ": " + method.retParameter_.type_ + ", ");
189 }
190 } else {
191 if (!haveOutPara) {
192 method.exportFunction_ += ") => void;";
193 } else {
194 method.exportFunction_ += ", ";
195 }
196 }
197 for (size_t index = 0; index < method.parameters_.size(); index++) {
198 bool isLast = (index == method.parameters_.size() - 1) ? true : false;
199 if ((method.parameters_[index].attr_ & ATTR_OUT) != 0) {
200 EmitInterfaceMethodExportCallback(method, method.parameters_[index], isLast);
201 }
202 }
203 }
204 }
205
EmitInterfaceMethodParameter(MetaParameter * mp,StringBuilder & stringBuilder,const String & prefix)206 void TsCodeEmitter::EmitInterfaceMethodParameter(MetaParameter* mp, StringBuilder& stringBuilder, const String& prefix)
207 {
208 MetaType* paraType = metaComponent_->types_[mp->typeIndex_];
209 stringBuilder.AppendFormat("%s: %s", mp->name_, EmitType(paraType).string());
210 }
211
EmitMethodInParameter(StringBuilder & stringBuilder,const std::string & name,const std::string & type,const String & prefix)212 void TsCodeEmitter::EmitMethodInParameter(StringBuilder& stringBuilder, const std::string& name,
213 const std::string& type, const String& prefix)
214 {
215 stringBuilder.AppendFormat("%s: %s", name.c_str(), type.c_str());
216 }
217
EmitInterfaceMethodExportCallback(Method & m,const Parameter & para,bool isLast)218 void TsCodeEmitter::EmitInterfaceMethodExportCallback(Method& m, const Parameter& para, bool isLast)
219 {
220 StringBuilder exportCallback;
221 exportCallback.Append(m.exportFunction_.c_str());
222 if (isLast) {
223 exportCallback.AppendFormat("%s: %s) => void;", para.name_.c_str(), para.type_.c_str());
224 } else {
225 exportCallback.AppendFormat("%s: %s, ", para.name_.c_str(), para.type_.c_str());
226 }
227 m.exportFunction_ = exportCallback.ToString();
228 }
229
EmitInterfaceProxy()230 void TsCodeEmitter::EmitInterfaceProxy()
231 {
232 if (!CheckInterfaceType()) {
233 return;
234 }
235 String filePath = String::Format("%s/%s.ts", directory_.string(), FileName(proxyName_).string());
236 File file(filePath, File::WRITE);
237
238 StringBuilder stringBuilder;
239
240 EmitLicense(stringBuilder);
241 stringBuilder.Append(NEWLINE);
242 EmitInterfaceImports(stringBuilder);
243 stringBuilder.Append(NEWLINE);
244 EmitInterfaceProxyImpl(stringBuilder);
245 stringBuilder.Append(NEWLINE);
246
247 String data = stringBuilder.ToString();
248 file.WriteData(data.string(), data.GetLength());
249 file.Flush();
250 file.Close();
251 }
252
EmitInterfaceProxyImpl(StringBuilder & stringBuilder)253 void TsCodeEmitter::EmitInterfaceProxyImpl(StringBuilder& stringBuilder)
254 {
255 stringBuilder.AppendFormat("export default class %s implements %s {\n", proxyName_.string(),
256 interfaceName_.string());
257 EmitInterfaceProxyConstructor(stringBuilder, TAB);
258 stringBuilder.Append(NEWLINE);
259 EmitInterfaceProxyMethodImpls(stringBuilder, TAB);
260 stringBuilder.Append(NEWLINE);
261 EmitInterfaceMethodCommands(stringBuilder);
262 stringBuilder.Append(TAB).AppendFormat("private %s", PROXY.c_str());
263 stringBuilder.Append(NEWLINE);
264 stringBuilder.Append("}\n");
265 }
266
EmitInterfaceProxyConstructor(StringBuilder & stringBuilder,const String & prefix)267 void TsCodeEmitter::EmitInterfaceProxyConstructor(StringBuilder& stringBuilder, const String& prefix)
268 {
269 stringBuilder.Append(prefix).AppendFormat("constructor(%s) {\n", PROXY.c_str());
270 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s = %s;\n", THIS_PROXY.c_str(), PROXY.c_str());
271 stringBuilder.Append(prefix).Append("}\n");
272 }
273
EmitInterfaceProxyMethodImpls(StringBuilder & stringBuilder,const String & prefix)274 void TsCodeEmitter::EmitInterfaceProxyMethodImpls(StringBuilder& stringBuilder, const String& prefix)
275 {
276 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
277 MetaMethod* metaMethod = metaInterface_->methods_[index];
278 EmitInterfaceProxyMethodImpl(metaMethod, index, stringBuilder, prefix);
279 if (index != metaInterface_->methodNumber_ - 1) {
280 stringBuilder.Append(NEWLINE);
281 }
282 }
283 }
284
EmitInterfaceProxyMethodImpl(MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix)285 void TsCodeEmitter::EmitInterfaceProxyMethodImpl(MetaMethod* metaMethod, int methodIndex, StringBuilder& stringBuilder,
286 const String& prefix)
287 {
288 stringBuilder.Append(prefix).AppendFormat("%s(", MethodName(metaMethod->name_).string());
289 bool isLastParaTypeIn = false;
290 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
291 MetaParameter* mp = metaMethod->parameters_[index];
292 if ((mp->attributes_ & ATTR_IN) != 0) {
293 EmitInterfaceMethodParameter(mp, stringBuilder, prefix + TAB);
294 if (index != metaMethod->parameterNumber_ - 1) {
295 stringBuilder.Append(", ");
296 } else {
297 isLastParaTypeIn = true;
298 }
299 }
300 }
301 if (methods_[methodIndex].callbackName_.size() > 0) {
302 if (!isLastParaTypeIn) {
303 stringBuilder.AppendFormat("callback: %s", methods_[methodIndex].callbackName_.c_str());
304 } else {
305 stringBuilder.AppendFormat(", callback: %s", methods_[methodIndex].callbackName_.c_str());
306 }
307 }
308 stringBuilder.Append("): void\n");
309 EmitInterfaceProxyMethodBody(metaMethod, methodIndex, stringBuilder, prefix);
310 }
311
EmitInterfaceProxyMethodBody(MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix)312 void TsCodeEmitter::EmitInterfaceProxyMethodBody(MetaMethod* metaMethod, int methodIndex, StringBuilder& stringBuilder,
313 const String& prefix)
314 {
315 bool haveOutPara = false;
316 stringBuilder.Append(prefix).Append("{\n");
317 stringBuilder.Append(prefix).Append(TAB).AppendFormat("let option = new rpc.MessageOption();\n");
318 if ((metaMethod->properties_ & METHOD_PROPERTY_ONEWAY) || (metaInterface_->properties_ & METHOD_PROPERTY_ONEWAY)) {
319 stringBuilder.Append(prefix).Append(TAB).AppendFormat("option.setFlags(_option.TF_ASYNC);\n");
320 }
321 stringBuilder.Append(prefix).Append(TAB).Append("let dataSequence = rpc.MessageSequence.create();\n");
322 stringBuilder.Append(prefix).Append(TAB).Append("let replySequence = rpc.MessageSequence.create();\n");
323 stringBuilder.Append(prefix).Append(TAB).Append("dataSequence.writeInterfaceToken(this.proxy.getDescriptor());\n");
324
325 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
326 MetaParameter* mp = metaMethod->parameters_[index];
327 if ((mp->attributes_ & ATTR_IN) != 0) {
328 EmitWriteMethodParameter(mp, "dataSequence", stringBuilder, prefix + TAB);
329 }
330 if ((mp->attributes_ & ATTR_OUT) != 0) {
331 haveOutPara = true;
332 }
333 }
334 stringBuilder.Append(prefix).Append(TAB).AppendFormat(
335 "%s.sendMessageRequest(%s.COMMAND_%s, dataSequence, replySequence, option).",
336 THIS_PROXY.c_str(), proxyName_.string(), ConstantName(metaMethod->name_).string());
337 stringBuilder.Append("then((result: rpc.RequestResult) => {\n");
338 EmitInterfaceMethodCallback(metaMethod, methodIndex, stringBuilder, prefix, haveOutPara);
339 stringBuilder.Append(prefix).Append(TAB).Append("}).catch((e: Error) => ").Append("{\n");
340 stringBuilder.Append(prefix).Append(TAB).Append(TAB)
341 .Append("console.log(\'sendMessageRequest failed, message: \' + e.message);\n");
342 stringBuilder.Append(prefix).Append(TAB).Append("}).finally(() => ").Append("{\n");
343 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("dataSequence.reclaim();").Append("\n");
344 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("replySequence.reclaim();").Append("\n");
345 stringBuilder.Append(prefix).Append(TAB).Append("});").Append("\n");
346 stringBuilder.Append(prefix).Append("}\n");
347 }
348
EmitInterfaceMethodCallback(MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix,bool haveOutPara)349 void TsCodeEmitter::EmitInterfaceMethodCallback(MetaMethod* metaMethod, int methodIndex, StringBuilder& stringBuilder,
350 const String& prefix, bool haveOutPara)
351 {
352 stringBuilder.Append(prefix).Append(TAB).Append(TAB).AppendFormat("if (result.errCode === 0) {\n");
353 MetaType* returnType = metaComponent_->types_[metaMethod->returnTypeIndex_];
354 // emit errCode
355 MetaType errCode;
356 errCode.kind_ = TypeKind::Integer;
357 EmitReadOutVariable("result.reply", SuffixAdded(ERR_CODE).c_str(), &errCode, stringBuilder,
358 prefix + TAB + TAB + TAB);
359
360 if (returnType->kind_ != TypeKind::Void || haveOutPara) {
361 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).AppendFormat(
362 "if (%s != 0) {\n", SuffixAdded(ERR_CODE).c_str());
363 for (size_t index = 0; index < methods_[methodIndex].parameters_.size(); index++) {
364 if ((methods_[methodIndex].parameters_[index].attr_ & ATTR_OUT) != 0) {
365 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(TAB).AppendFormat(
366 "let %s = undefined;\n", SuffixAdded(
367 methods_[methodIndex].parameters_[index].name_.c_str()).c_str());
368 }
369 }
370 if (returnType->kind_ != TypeKind::Void) {
371 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(TAB).AppendFormat(
372 "let %s = undefined;\n", SuffixAdded(RETURN_VALUE).c_str());
373 }
374 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(TAB).AppendFormat("callback(");
375 stringBuilder.AppendFormat("%s", SuffixAdded(ERR_CODE).c_str());
376 if (methods_[methodIndex].retParameter_.name_.size() > 0) {
377 if (haveOutPara) {
378 stringBuilder.AppendFormat(", %s, ", SuffixAdded(RETURN_VALUE).c_str());
379 } else {
380 stringBuilder.AppendFormat(", %s", SuffixAdded(RETURN_VALUE).c_str());
381 }
382 } else {
383 if (haveOutPara) {
384 stringBuilder.Append(",");
385 }
386 }
387 for (size_t index = 0; index < methods_[methodIndex].parameters_.size(); index++) {
388 if ((methods_[methodIndex].parameters_[index].attr_ & ATTR_OUT) == 0) {
389 continue;
390 }
391 stringBuilder.AppendFormat("%s",
392 SuffixAdded(methods_[methodIndex].parameters_[index].name_.c_str()).c_str());
393 if (index != methods_[methodIndex].parameters_.size() - 1) {
394 stringBuilder.Append(", ");
395 }
396 }
397 stringBuilder.Append(");\n");
398 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(TAB).Append("return;\n");
399 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append("}\n");
400 }
401 EmitInterfaceMethodCallbackInner(returnType, metaMethod, methodIndex, stringBuilder, prefix, haveOutPara);
402 }
403
EmitInterfaceMethodCallbackInner(MetaType * returnType,MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix,bool haveOutPara)404 void TsCodeEmitter::EmitInterfaceMethodCallbackInner(MetaType* returnType, MetaMethod* metaMethod,
405 int methodIndex, StringBuilder& stringBuilder, const String& prefix, bool haveOutPara)
406 {
407 // emit return
408 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
409 MetaParameter* mp = metaMethod->parameters_[index];
410 if ((mp->attributes_ & ATTR_OUT) != 0) {
411 EmitReadMethodParameter(mp, "result.reply", stringBuilder, prefix + TAB + TAB + TAB);
412 }
413 }
414 if (returnType->kind_ != TypeKind::Void) {
415 String parcelName = "result.reply";
416 EmitReadOutVariable(parcelName, SuffixAdded(RETURN_VALUE), returnType, stringBuilder,
417 prefix + TAB + TAB + TAB);
418 }
419 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).AppendFormat("callback(");
420 stringBuilder.AppendFormat("%s", SuffixAdded(ERR_CODE).c_str());
421 if (methods_[methodIndex].retParameter_.name_.size() > 0) {
422 if (haveOutPara) {
423 stringBuilder.AppendFormat(", %s, ", SuffixAdded(RETURN_VALUE).c_str());
424 } else {
425 stringBuilder.AppendFormat(", %s", SuffixAdded(RETURN_VALUE).c_str());
426 }
427 } else {
428 if (haveOutPara) {
429 stringBuilder.Append(",");
430 }
431 }
432 for (size_t index = 0; index < methods_[methodIndex].parameters_.size(); index++) {
433 if ((methods_[methodIndex].parameters_[index].attr_ & ATTR_OUT) != 0) {
434 stringBuilder.AppendFormat("%s",
435 SuffixAdded(methods_[methodIndex].parameters_[index].name_.c_str()).c_str());
436 if (index != methods_[methodIndex].parameters_.size() - 1) {
437 stringBuilder.Append(", ");
438 }
439 }
440 }
441 stringBuilder.Append(");\n");
442 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("} else {\n");
443 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(
444 "console.log(\"sendMessageRequest failed, errCode: \" + result.errCode);\n");
445 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("}\n");
446 }
447
EmitWriteMethodParameter(MetaParameter * mp,const String & parcelName,StringBuilder & stringBuilder,const String & prefix)448 void TsCodeEmitter::EmitWriteMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& stringBuilder,
449 const String& prefix)
450 {
451 MetaType* mt = metaComponent_->types_[mp->typeIndex_];
452 std::string name = mp->name_;
453 EmitWriteVariable(parcelName, name, mt, stringBuilder, prefix);
454 }
455
EmitReadMethodParameter(MetaParameter * mp,const String & parcelName,StringBuilder & stringBuilder,const String & prefix)456 void TsCodeEmitter::EmitReadMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& stringBuilder,
457 const String& prefix)
458 {
459 MetaType* mt = metaComponent_->types_[mp->typeIndex_];
460 std::string name = SuffixAdded(mp->name_);
461 EmitReadOutVariable(parcelName, name, mt, stringBuilder, prefix);
462 }
463
EmitInterfaceStub()464 void TsCodeEmitter::EmitInterfaceStub()
465 {
466 if (!CheckInterfaceType()) {
467 return;
468 }
469 String filePath = String::Format("%s/%s.ts", directory_.string(), FileName(stubName_).string());
470 File file(filePath, File::WRITE);
471
472 StringBuilder stringBuilder;
473 EmitLicense(stringBuilder);
474 stringBuilder.Append(NEWLINE);
475 EmitInterfaceImports(stringBuilder);
476 stringBuilder.Append(NEWLINE);
477 EmitInterfaceStubImpl(stringBuilder);
478 stringBuilder.Append(NEWLINE);
479
480 String data = stringBuilder.ToString();
481 file.WriteData(data.string(), data.GetLength());
482 file.Flush();
483 file.Close();
484 }
485
EmitInterfaceStubImpl(StringBuilder & stringBuilder)486 void TsCodeEmitter::EmitInterfaceStubImpl(StringBuilder& stringBuilder)
487 {
488 stringBuilder.AppendFormat("export default class %s extends rpc.RemoteObject implements %s {\n",
489 stubName_.string(), interfaceName_.string());
490 EmitInterfaceStubMethodImpls(stringBuilder, TAB);
491 stringBuilder.Append(NEWLINE);
492 EmitInterfaceMethodCommands(stringBuilder);
493 stringBuilder.Append("}\n");
494 }
495
EmitInterfaceStubConstructor(StringBuilder & stringBuilder,const String & prefix)496 void TsCodeEmitter::EmitInterfaceStubConstructor(StringBuilder& stringBuilder, const String& prefix)
497 {
498 stringBuilder.Append(prefix).Append("constructor(des: string) {\n");
499 stringBuilder.Append(prefix).Append(TAB).Append("super(des);\n");
500 stringBuilder.Append(prefix).Append("}\n");
501 }
502
EmitInterfaceStubMethodImpls(StringBuilder & stringBuilder,const String & prefix)503 void TsCodeEmitter::EmitInterfaceStubMethodImpls(StringBuilder& stringBuilder, const String& prefix)
504 {
505 EmitInterfaceStubConstructor(stringBuilder, prefix);
506 stringBuilder.Append(prefix).Append(NEWLINE);
507 stringBuilder.Append(prefix).Append("async onRemoteMessageRequest(code: number, data:rpc.MessageSequence,");
508 stringBuilder.Append(" reply:rpc.MessageSequence, option:rpc.MessageOption): Promise<boolean> {\n");
509 stringBuilder.Append(prefix).Append(TAB).Append("let localDescriptor = this.getDescriptor();\n");
510 stringBuilder.Append(prefix).Append(TAB).Append("let remoteDescriptor = data.readInterfaceToken();\n");
511 stringBuilder.Append(prefix).Append(TAB).Append("if (localDescriptor !== remoteDescriptor) {\n");
512 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("console.log(\"invalid interfaceToken\");\n");
513 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("return false;\n");
514 stringBuilder.Append(prefix).Append(TAB).Append("}\n");
515 stringBuilder.Append(prefix).Append(TAB).Append(
516 "console.log(\"onRemoteMessageRequest called, code = \" + code);\n");
517 stringBuilder.Append(prefix).Append(TAB).Append("switch(code) {\n");
518 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
519 MetaMethod* metaMethod = metaInterface_->methods_[index];
520 EmitInterfaceStubMethodImpl(metaMethod, index, stringBuilder, prefix + TAB + TAB);
521 }
522 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("default: {\n");
523 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append(
524 "console.log(\"invalid request code\" + code);\n");
525 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append("break;\n");
526 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("}\n");
527 stringBuilder.Append(prefix).Append(TAB).Append("}\n");
528 stringBuilder.Append(prefix).Append(TAB).Append("return false;\n");
529 stringBuilder.Append(prefix).Append("}\n\n");
530 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
531 bool isLastParaTypeIn = false;
532 MetaMethod* metaMethod = metaInterface_->methods_[index];
533 stringBuilder.Append(prefix).AppendFormat("%s(", MethodName(metaMethod->name_).string());
534 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
535 MetaParameter* mp = metaMethod->parameters_[index];
536 if ((mp->attributes_ & ATTR_IN) == 0) {
537 continue;
538 }
539 EmitInterfaceMethodParameter(mp, stringBuilder, prefix + TAB);
540 if (index != metaMethod->parameterNumber_ - 1) {
541 stringBuilder.Append(", ");
542 } else {
543 isLastParaTypeIn = true;
544 }
545 }
546 if (!isLastParaTypeIn) {
547 stringBuilder.AppendFormat("callback: %s", methods_[index].callbackName_.c_str());
548 } else {
549 stringBuilder.AppendFormat(", callback: %s", methods_[index].callbackName_.c_str());
550 }
551 stringBuilder.Append("): void{}\n");
552 }
553 }
554
EmitInterfaceStubMethodImpl(MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix)555 void TsCodeEmitter::EmitInterfaceStubMethodImpl(MetaMethod* metaMethod, int methodIndex, StringBuilder& stringBuilder,
556 const String& prefix)
557 {
558 bool haveOutPara = false;
559 stringBuilder.Append(prefix).AppendFormat("case %s.COMMAND_%s: {\n", stubName_.string(),
560 ConstantName(metaMethod->name_).string());
561 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
562 MetaParameter* mp = metaMethod->parameters_[index];
563 if ((mp->attributes_ & ATTR_IN) != 0) {
564 MetaType* mt = metaComponent_->types_[mp->typeIndex_];
565 EmitReadVariable("data", SuffixAdded(mp->name_), mt, ATTR_IN, stringBuilder, prefix + TAB);
566 }
567 if ((mp->attributes_ & ATTR_OUT) != 0) {
568 haveOutPara = true;
569 }
570 }
571 stringBuilder.Append(prefix).Append(TAB).Append("let promise = new Promise<void>((resolve,reject) => { \n");
572 stringBuilder.Append(prefix).Append(TAB).Append(TAB)
573 .AppendFormat("this.%s(", MethodName(metaMethod->name_).string());
574 bool isLastParaTypeIn = false;
575 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
576 MetaParameter* mp = metaMethod->parameters_[index];
577 if ((mp->attributes_ & ATTR_IN) != 0) {
578 stringBuilder.Append(SuffixAdded(mp->name_).c_str());
579 if (index != metaMethod->parameterNumber_ - 1) {
580 stringBuilder.Append(", ");
581 } else {
582 isLastParaTypeIn = true;
583 }
584 }
585 }
586 if (!isLastParaTypeIn) {
587 stringBuilder.Append("(");
588 } else {
589 stringBuilder.Append(", (");
590 }
591 EmitInterfaceStubMethodPromiseImpl(metaMethod, methodIndex, stringBuilder, prefix, haveOutPara);
592 stringBuilder.Append(prefix).Append(TAB).Append("}").Append(");\n");
593 stringBuilder.Append(prefix).Append(TAB).Append("await promise;\n");
594 stringBuilder.Append(prefix).Append(TAB).Append("return true;\n");
595 stringBuilder.Append(prefix).Append("}\n");
596 }
597
EmitInterfaceStubMethodPromiseImpl(MetaMethod * metaMethod,int methodIndex,StringBuilder & stringBuilder,const String & prefix,bool haveOutPara)598 void TsCodeEmitter::EmitInterfaceStubMethodPromiseImpl(
599 MetaMethod* metaMethod, int methodIndex, StringBuilder& stringBuilder, const String& prefix, bool haveOutPara)
600 {
601 stringBuilder.Append(ERR_CODE);
602 if (methods_[methodIndex].retParameter_.name_.size() > 0) {
603 if (!haveOutPara) {
604 stringBuilder.AppendFormat(", %s", RETURN_VALUE.string());
605 } else {
606 stringBuilder.AppendFormat(", %s", RETURN_VALUE.string()).Append(", ");
607 }
608 } else {
609 if (haveOutPara) {
610 stringBuilder.Append(", ");
611 }
612 }
613 for (size_t index = 0; index < methods_[methodIndex].parameters_.size(); index++) {
614 if ((methods_[methodIndex].parameters_[index].attr_ & ATTR_OUT) != 0) {
615 stringBuilder.Append(methods_[methodIndex].parameters_[index].name_.c_str());
616 if (index != methods_[methodIndex].parameters_.size() - 1) {
617 stringBuilder.Append(", ");
618 }
619 }
620 }
621 stringBuilder.Append(") => {\n");
622 MetaType errCode;
623 errCode.kind_ = TypeKind::Integer;
624 EmitWriteVariable("reply", ERR_CODE.string(), &errCode, stringBuilder, prefix + TAB + TAB + TAB);
625 MetaType* returnType = metaComponent_->types_[metaMethod->returnTypeIndex_];
626
627 if (returnType->kind_ != TypeKind::Void || haveOutPara) {
628 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB)
629 .AppendFormat("if (%s == 0) {\n", ERR_CODE.string());
630 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
631 MetaParameter* mp = metaMethod->parameters_[index];
632 if ((mp->attributes_ & ATTR_OUT) != 0) {
633 EmitWriteMethodParameter(mp, "reply", stringBuilder, prefix + TAB + TAB + TAB + TAB);
634 }
635 }
636 if (returnType->kind_ != TypeKind::Void) {
637 EmitWriteVariable("reply", RETURN_VALUE.string(), returnType,
638 stringBuilder, prefix + TAB + TAB + TAB + TAB);
639 }
640 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append("}\n");
641 }
642 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append(TAB).Append("resolve();\n");
643 stringBuilder.Append(prefix).Append(TAB).Append(TAB).Append("}");
644 stringBuilder.Append(");\n");
645 }
646
EmitInterfaceMethodCommands(StringBuilder & stringBuilder)647 void TsCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& stringBuilder)
648 {
649 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
650 MetaMethod* metaMethod = metaInterface_->methods_[index];
651 stringBuilder.Append(TAB).AppendFormat("static readonly COMMAND_%s = %d;\n",
652 ConstantName(metaMethod->name_).string(), index + 1);
653 }
654 }
655
EmitLicense(StringBuilder & stringBuilder)656 void TsCodeEmitter::EmitLicense(StringBuilder& stringBuilder)
657 {
658 stringBuilder.Append(metaInterface_->license_).Append(NEWLINE);
659 }
660
EmitWriteVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)661 void TsCodeEmitter::EmitWriteVariable(const String& parcelName, const std::string& name, MetaType* mt,
662 StringBuilder& stringBuilder, const String& prefix)
663 {
664 switch (mt->kind_) {
665 case TypeKind::Boolean:
666 stringBuilder.Append(prefix).AppendFormat("%s.writeInt(%s ? 1 : 0);\n", parcelName.string(), name.c_str());
667 break;
668 case TypeKind::Char:
669 case TypeKind::Byte:
670 case TypeKind::Short:
671 case TypeKind::Integer:
672 stringBuilder.Append(prefix).AppendFormat("%s.writeInt(%s);\n", parcelName.string(), name.c_str());
673 break;
674 case TypeKind::Long:
675 stringBuilder.Append(prefix).AppendFormat("%s.writeLong(%s);\n", parcelName.string(), name.c_str());
676 break;
677 case TypeKind::Float:
678 stringBuilder.Append(prefix).AppendFormat("%s.writeFloat(%s);\n", parcelName.string(), name.c_str());
679 break;
680 case TypeKind::Double:
681 stringBuilder.Append(prefix).AppendFormat("%s.writeDouble(%s);\n", parcelName.string(), name.c_str());
682 break;
683 default:
684 EmitWriteVariableObject(parcelName, name, mt, stringBuilder, prefix);
685 break;
686 }
687 }
688
EmitWriteVariableObject(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)689 void TsCodeEmitter::EmitWriteVariableObject(const String& parcelName, const std::string& name, MetaType* mt,
690 StringBuilder& stringBuilder, const String& prefix)
691 {
692 switch (mt->kind_) {
693 case TypeKind::String:
694 stringBuilder.Append(prefix).AppendFormat("%s.writeString(%s);\n", parcelName.string(), name.c_str());
695 break;
696 case TypeKind::Sequenceable:
697 if (EmitType(mt).Equals("IRemoteObject")) {
698 stringBuilder.Append(prefix).AppendFormat("%s.writeRemoteObject(%s);\n", parcelName.string(),
699 name.c_str());
700 break;
701 }
702 stringBuilder.Append(prefix).AppendFormat("%s.writeParcelable(%s);\n", parcelName.string(),
703 name.c_str());
704 break;
705 case TypeKind::Interface:
706 stringBuilder.Append(prefix).AppendFormat("%s.writeRemoteObject(%s as %s);\n", parcelName.string(),
707 name.c_str(), StubName(EmitType(mt)).string());
708 break;
709 case TypeKind::List: {
710 MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
711 stringBuilder.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.c_str());
712 stringBuilder.Append(prefix).AppendFormat("for (%s element : %s) {\n",
713 EmitType(innerType).string(), name.c_str());
714 EmitWriteVariable(parcelName, "element", innerType, stringBuilder, prefix + TAB);
715 stringBuilder.Append(prefix).Append("}\n");
716 break;
717 }
718 case TypeKind::Map: {
719 MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
720 MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
721 stringBuilder.Append(prefix).AppendFormat("%s.writeInt(%s.size);\n", parcelName.string(), name.c_str());
722 stringBuilder.Append(prefix).AppendFormat("for (let [key, value] of %s) {\n", name.c_str());
723 EmitWriteVariable(parcelName, "key", keyType, stringBuilder, prefix + TAB);
724 EmitWriteVariable(parcelName, "value", valueType, stringBuilder, prefix + TAB);
725 stringBuilder.Append(prefix).Append("}\n");
726 break;
727 }
728 case TypeKind::Array: {
729 MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
730 EmitWriteArrayVariable(parcelName, name, innerType, stringBuilder, prefix);
731 break;
732 }
733 default:
734 break;
735 }
736 }
737
EmitWriteArrayVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)738 void TsCodeEmitter::EmitWriteArrayVariable(const String& parcelName, const std::string& name, MetaType* mt,
739 StringBuilder& stringBuilder,
740 const String& prefix)
741 {
742 switch (mt->kind_) {
743 case TypeKind::Boolean:
744 stringBuilder.Append(prefix).AppendFormat("%s.writeBooleanArray(%s);\n", parcelName.string(),
745 name.c_str());
746 break;
747 case TypeKind::Char:
748 stringBuilder.Append(prefix).AppendFormat("%s.writeCharArray(%s);\n", parcelName.string(), name.c_str());
749 break;
750 case TypeKind::Byte:
751 stringBuilder.Append(prefix).AppendFormat("%s.writeByteArray(%s);\n",
752 parcelName.string(), name.c_str());
753 break;
754 case TypeKind::Short:
755 stringBuilder.Append(prefix).AppendFormat("%s.writeShortArray(%s);\n", parcelName.string(), name.c_str());
756 break;
757 case TypeKind::Integer:
758 stringBuilder.Append(prefix).AppendFormat("%s.writeIntArray(%s);\n", parcelName.string(), name.c_str());
759 break;
760 case TypeKind::Long:
761 stringBuilder.Append(prefix).AppendFormat("%s.writeLongArray(%s);\n", parcelName.string(), name.c_str());
762 break;
763 case TypeKind::Float:
764 stringBuilder.Append(prefix).AppendFormat("%s.writeFloatArray(%s);\n", parcelName.string(), name.c_str());
765 break;
766 case TypeKind::Double:
767 stringBuilder.Append(prefix).AppendFormat("%s.writeDoubleArray(%s);\n", parcelName.string(), name.c_str());
768 break;
769 case TypeKind::String:
770 stringBuilder.Append(prefix).AppendFormat("%s.writeStringArray(%s);\n", parcelName.string(), name.c_str());
771 break;
772 case TypeKind::Sequenceable: {
773 String typeName = EmitType(mt).EndsWith("]") ?
774 (EmitType(mt).Substring(0, EmitType(mt).GetLength() - 2)) : EmitType(mt);
775 stringBuilder.Append(prefix).AppendFormat("let %sArray:Array<%s> = %s;\n", name.c_str(), typeName.string(),
776 name.c_str());
777 stringBuilder.Append(prefix).AppendFormat("%s.writeInt(%sArray.length);\n", parcelName.string(),
778 name.c_str());
779 stringBuilder.Append(prefix).AppendFormat("for (let index = 0; index < %sArray.length; index++) {\n",
780 name.c_str());
781 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.writeSequenceable(%s[index]);\n",
782 parcelName.string(), name.c_str());
783 stringBuilder.Append(prefix).AppendFormat("}\n");
784 }
785 break;
786 default:
787 break;
788 }
789 }
790
EmitReadVariable(const String & parcelName,const std::string & name,MetaType * mt,unsigned int attributes,StringBuilder & stringBuilder,const String & prefix)791 void TsCodeEmitter::EmitReadVariable(const String& parcelName, const std::string& name, MetaType* mt,
792 unsigned int attributes,
793 StringBuilder& stringBuilder,
794 const String& prefix)
795 {
796 switch (mt->kind_) {
797 case TypeKind::Boolean:
798 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readInt() == 1 ? true : false;\n", name.c_str(),
799 parcelName.string());
800 break;
801 case TypeKind::Char:
802 case TypeKind::Byte:
803 case TypeKind::Short:
804 case TypeKind::Integer:
805 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readInt();\n", name.c_str(), parcelName.string());
806 break;
807 case TypeKind::Long:
808 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readLong();\n", name.c_str(), parcelName.string());
809 break;
810 case TypeKind::Float:
811 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readFloat();\n", name.c_str(), parcelName.string());
812 break;
813 case TypeKind::Double:
814 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readDouble();\n", name.c_str(), parcelName.string());
815 break;
816 default:
817 EmitReadVariableObject(parcelName, name, mt, attributes, stringBuilder, prefix);
818 break;
819 }
820 }
821
EmitReadVariableObject(const String & parcelName,const std::string & name,MetaType * mt,unsigned int attributes,StringBuilder & stringBuilder,const String & prefix)822 void TsCodeEmitter::EmitReadVariableObject(const String& parcelName, const std::string& name, MetaType* mt,
823 unsigned int attributes, StringBuilder& stringBuilder, const String& prefix)
824 {
825 switch (mt->kind_) {
826 case TypeKind::String:
827 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readString();\n", name.c_str(), parcelName.string());
828 break;
829 case TypeKind::Sequenceable:
830 if ((attributes & ATTR_OUT) == 0 && EmitType(mt).Equals("IRemoteObject")) {
831 stringBuilder.Append(prefix).AppendFormat("IRemoteObject %s = %s.readRemoteObject();\n",
832 name.c_str(), parcelName.string());
833 break;
834 }
835 if ((attributes & ATTR_OUT) == 0) {
836 stringBuilder.Append(prefix).AppendFormat("let %s = new %s();\n", name.c_str(), EmitType(mt).string());
837 }
838 stringBuilder.Append(prefix).AppendFormat("%s.readParcelable(%s);\n", parcelName.string(), name.c_str());
839
840 break;
841 case TypeKind::Interface:
842 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readRemoteObject();\n", name.c_str(),
843 parcelName.string());
844 break;
845
846 case TypeKind::Map: {
847 stringBuilder.Append(prefix).AppendFormat("let %s = new Map();\n", name.c_str());
848 stringBuilder.Append(prefix).AppendFormat("let %sSize = %s.readInt();\n", name.c_str(),
849 parcelName.string());
850 stringBuilder.Append(prefix).AppendFormat("for (let i = 0; i < %sSize; ++i) {\n", name.c_str());
851 MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
852 MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
853 EmitReadVariable(parcelName, "key", keyType, ATTR_IN, stringBuilder, prefix + TAB);
854 EmitReadVariable(parcelName, "value", valueType, ATTR_IN, stringBuilder, prefix + TAB);
855 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.set(key, value);\n", name.c_str());
856 stringBuilder.Append(prefix).Append("}\n");
857 break;
858 }
859 case TypeKind::Array: {
860 if ((attributes & ATTR_MASK) == ATTR_OUT) {
861 EmitReadOutArrayVariable(parcelName, name, mt, stringBuilder, prefix);
862 } else {
863 EmitReadArrayVariable(parcelName, name, mt, attributes, stringBuilder, prefix);
864 }
865 break;
866 }
867 default:
868 break;
869 }
870 }
871
EmitReadArrayVariable(const String & parcelName,const std::string & name,MetaType * mt,unsigned int attributes,StringBuilder & stringBuilder,const String & prefix)872 void TsCodeEmitter::EmitReadArrayVariable(const String& parcelName, const std::string& name, MetaType* mt,
873 unsigned int attributes, StringBuilder& stringBuilder, const String& prefix)
874 {
875 MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
876 switch (innerType->kind_) {
877 case TypeKind::Boolean:
878 case TypeKind::Char:
879 case TypeKind::Byte:
880 case TypeKind::Short:
881 case TypeKind::Integer:
882 case TypeKind::Long:
883 case TypeKind::Float:
884 case TypeKind::Double:
885 case TypeKind::String:
886 stringBuilder.Append(prefix).AppendFormat("let %s = %s.%s();\n", name.c_str(),
887 parcelName.string(), typekind_read_array_[innerType->kind_].c_str());
888 break;
889 case TypeKind::Sequenceable: {
890 String typeName = EmitType(mt).EndsWith("]") ?
891 (EmitType(mt).Substring(0, EmitType(mt).GetLength() - 2)) : EmitType(mt);
892 stringBuilder.Append(prefix).AppendFormat("let %sSize = %s.readInt();\n", name.c_str(),
893 parcelName.string());
894 stringBuilder.Append(prefix).AppendFormat("let %s:Array<%s> = [];\n", name.c_str(), typeName.string());
895 stringBuilder.Append(prefix).AppendFormat("for (let index = 0; index < %sSize; index++) {\n",
896 name.c_str());
897 stringBuilder.Append(prefix).Append(TAB).AppendFormat("let %sValue = new %s();\n",
898 name.c_str(), typeName.string());
899 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.readSequenceable(%sValue);\n",
900 parcelName.string(), name.c_str());
901 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.push(%sValue);\n", name.c_str(),
902 name.c_str());
903 stringBuilder.Append(prefix).AppendFormat("}\n");
904 }
905 break;
906 default:
907 break;
908 }
909 }
910
EmitReadOutArrayVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)911 void TsCodeEmitter::EmitReadOutArrayVariable(const String& parcelName, const std::string& name, MetaType* mt,
912 StringBuilder& stringBuilder,
913 const String& prefix)
914 {
915 MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
916 switch (innerType->kind_) {
917 case TypeKind::Boolean:
918 case TypeKind::Char:
919 case TypeKind::Byte:
920 case TypeKind::Short:
921 case TypeKind::Integer:
922 case TypeKind::Long:
923 case TypeKind::Float:
924 case TypeKind::Double:
925 case TypeKind::String:
926 stringBuilder.Append(prefix).AppendFormat("let %s = %s.%s();\n", name.c_str(),
927 parcelName.string(), typekind_read_array_[innerType->kind_].c_str());
928 break;
929 case TypeKind::Sequenceable: {
930 stringBuilder.Append(prefix).AppendFormat("let %sSize = %s.readInt();\n", name.c_str(),
931 parcelName.string());
932 String typeName = EmitType(mt).EndsWith("]") ?
933 (EmitType(mt).Substring(0, EmitType(mt).GetLength() - 2)) : EmitType(mt);
934 stringBuilder.Append(prefix).AppendFormat("let %s:Array<%s> = [];\n", name.c_str(), typeName.string());
935 stringBuilder.Append(prefix).AppendFormat("for (let index = 0; index < %sSize; index++) {\n",
936 name.c_str());
937 stringBuilder.Append(prefix).Append(TAB).AppendFormat("let %sValue = new %s();\n",
938 name.c_str(), typeName.string());
939 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.readSequenceable(%sValue);\n",
940 parcelName.string(), name.c_str());
941 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.push(%sValue);\n", name.c_str(),
942 name.c_str());
943 stringBuilder.Append(prefix).AppendFormat("}\n");
944 }
945 break;
946 default:
947 break;
948 }
949 }
950
EmitReadOutVariable(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)951 void TsCodeEmitter::EmitReadOutVariable(const String& parcelName, const std::string& name, MetaType* mt,
952 StringBuilder& stringBuilder,
953 const String& prefix)
954 {
955 switch (mt->kind_) {
956 case TypeKind::Boolean:
957 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readInt() == 1 ? true : false;\n",
958 name.c_str(), parcelName.string());
959 break;
960 case TypeKind::Char:
961 case TypeKind::Byte:
962 case TypeKind::Short:
963 case TypeKind::Integer:
964 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readInt();\n", name.c_str(), parcelName.string());
965 break;
966 case TypeKind::Long:
967 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readLong();\n", name.c_str(), parcelName.string());
968 break;
969 case TypeKind::Float:
970 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readFloat();\n", name.c_str(), parcelName.string());
971 break;
972 case TypeKind::Double:
973 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readDouble();\n", name.c_str(), parcelName.string());
974 break;
975 case TypeKind::String:
976 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readString();\n", name.c_str(), parcelName.string());
977 break;
978 default:
979 EmitReadOutVariableObject(parcelName, name, mt, stringBuilder, prefix);
980 break;
981 }
982 }
983
EmitReadOutVariableObject(const String & parcelName,const std::string & name,MetaType * mt,StringBuilder & stringBuilder,const String & prefix)984 void TsCodeEmitter::EmitReadOutVariableObject(const String& parcelName, const std::string& name, MetaType* mt,
985 StringBuilder& stringBuilder, const String& prefix)
986 {
987 switch (mt->kind_) {
988 case TypeKind::String:
989 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readString();\n", name.c_str(), parcelName.string());
990 break;
991 case TypeKind::Sequenceable:
992 if (EmitType(mt).Equals("IRemoteObject")) {
993 stringBuilder.Append(prefix).AppendFormat("%s = %s.readRemoteObject();\n", name.c_str(),
994 parcelName.string());
995 break;
996 }
997 stringBuilder.Append(prefix).AppendFormat("let %s = new %s();\n", name.c_str(), EmitType(mt).string());
998 stringBuilder.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str());
999 break;
1000 case TypeKind::Interface:
1001 stringBuilder.Append(prefix).AppendFormat("let %s = %s.readRemoteObject();\n", name.c_str(),
1002 parcelName.string());
1003 break;
1004 case TypeKind::List: {
1005 stringBuilder.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(),
1006 parcelName.string());
1007 stringBuilder.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str());
1008 MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1009 EmitReadVariable(parcelName, "value", innerType, ATTR_IN, stringBuilder, prefix + TAB);
1010 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.add(value);\n", name.c_str());
1011 stringBuilder.Append(prefix).Append("}\n");
1012 break;
1013 }
1014 case TypeKind::Map: {
1015 stringBuilder.Append(prefix).AppendFormat("let %s = new Map();\n", name.c_str());
1016 stringBuilder.Append(prefix).AppendFormat("let %sSize = %s.readInt();\n", name.c_str(),
1017 parcelName.string());
1018 stringBuilder.Append(prefix).AppendFormat("for (let i = 0; i < %sSize; ++i) {\n", name.c_str());
1019 MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1020 MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
1021 EmitReadVariable(parcelName, "key", keyType, ATTR_IN, stringBuilder, prefix + TAB);
1022 EmitReadVariable(parcelName, "value", valueType, ATTR_IN, stringBuilder, prefix + TAB);
1023 stringBuilder.Append(prefix).Append(TAB).AppendFormat("%s.set(key, value);\n", name.c_str());
1024 stringBuilder.Append(prefix).Append("}\n");
1025 break;
1026 }
1027 case TypeKind::Array: {
1028 EmitReadOutArrayVariable(parcelName, name, mt, stringBuilder, prefix);
1029 break;
1030 }
1031 default:
1032 break;
1033 }
1034 }
1035
EmitType(MetaType * mt)1036 String TsCodeEmitter::EmitType(MetaType* mt)
1037 {
1038 switch (mt->kind_) {
1039 case TypeKind::Boolean:
1040 return "boolean";
1041 case TypeKind::Byte:
1042 return "number";
1043 case TypeKind::Short:
1044 return "number";
1045 case TypeKind::Integer:
1046 return "number";
1047 case TypeKind::Long:
1048 return "number";
1049 case TypeKind::Float:
1050 return "number";
1051 case TypeKind::Double:
1052 return "number";
1053 case TypeKind::String:
1054 return "string";
1055 case TypeKind::Void:
1056 return "void";
1057 case TypeKind::Sequenceable: {
1058 MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
1059 return mp->name_;
1060 }
1061 case TypeKind::Interface: {
1062 MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
1063 return mi->name_;
1064 }
1065 case TypeKind::Map: {
1066 MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1067 MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
1068 if (EmitType(keyType).string() == UNKNOWN_TYPE || EmitType(valueType).string() == UNKNOWN_TYPE) {
1069 return String(UNKNOWN_TYPE.c_str());
1070 }
1071 return String::Format("Map<%s, %s>", EmitType(keyType).string(), EmitType(valueType).string());
1072 }
1073 case TypeKind::Array: {
1074 MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
1075 if (EmitType(elementType).string() == UNKNOWN_TYPE) {
1076 return String(UNKNOWN_TYPE.c_str());
1077 }
1078 return String::Format("%s[]", EmitType(elementType).string());
1079 }
1080 default:
1081 return String(UNKNOWN_TYPE.c_str());
1082 }
1083 }
1084
FileName(const String & name)1085 String TsCodeEmitter::FileName(const String& name)
1086 {
1087 if (name.IsEmpty()) {
1088 return name;
1089 }
1090
1091 StringBuilder stringBuilder;
1092 for (int index = 0; index < name.GetLength(); index++) {
1093 char c = name[index];
1094 if (isupper(c) != 0) {
1095 if (index > 0) {
1096 stringBuilder.Append('_');
1097 }
1098 stringBuilder.Append(tolower(c));
1099 } else {
1100 stringBuilder.Append(c);
1101 }
1102 }
1103 return stringBuilder.ToString().Replace('.', '/');
1104 }
1105
MethodName(const String & name)1106 String TsCodeEmitter::MethodName(const String& name)
1107 {
1108 if (name.IsEmpty() || islower(name[0])) {
1109 return name;
1110 }
1111 return String::Format("%c%s", tolower(name[0]), name.Substring(1).string());
1112 }
1113
ConstantName(const String & name)1114 String TsCodeEmitter::ConstantName(const String& name)
1115 {
1116 if (name.IsEmpty()) {
1117 return name;
1118 }
1119
1120 StringBuilder stringBuilder;
1121
1122 for (int index = 0; index < name.GetLength(); index++) {
1123 char c = name[index];
1124 if (isupper(c) != 0) {
1125 if (index > 1) {
1126 stringBuilder.Append('_');
1127 }
1128 stringBuilder.Append(c);
1129 } else {
1130 stringBuilder.Append(toupper(c));
1131 }
1132 }
1133
1134 return stringBuilder.ToString();
1135 }
1136
StubName(const String & name)1137 String TsCodeEmitter::StubName(const String& name)
1138 {
1139 return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub");
1140 }
1141
UnderlineAdded(const String & originName)1142 const std::string TsCodeEmitter::UnderlineAdded(const String& originName)
1143 {
1144 std::string underline("_");
1145 return underline + std::string(originName.string());
1146 }
1147
SuffixAdded(const String & originName)1148 const std::string TsCodeEmitter::SuffixAdded(const String& originName)
1149 {
1150 std::string varSuffix("Var");
1151 return std::string(originName.string()) + varSuffix;
1152 }
1153
CheckInterfaceType()1154 bool TsCodeEmitter::CheckInterfaceType()
1155 {
1156 for (int index = 0; index < metaInterface_->methodNumber_; index++) {
1157 MetaMethod* metaMethod = metaInterface_->methods_[index];
1158 MetaType* returnType = metaComponent_->types_[metaMethod->returnTypeIndex_];
1159 std::string returnTypeStr = EmitType(returnType).string();
1160 if (returnTypeStr == UNKNOWN_TYPE) {
1161 Logger::E(TAG, "unsupported type in .idl file");
1162 return false;
1163 }
1164 for (int index = 0; index < metaMethod->parameterNumber_; index++) {
1165 MetaParameter* mp = metaMethod->parameters_[index];
1166 MetaType* paraType = metaComponent_->types_[mp->typeIndex_];
1167 std::string paraTypeStr = EmitType(paraType).string();
1168 if (paraTypeStr == UNKNOWN_TYPE) {
1169 Logger::E(TAG, "unsupported type in .idl file");
1170 return false;
1171 }
1172 }
1173 }
1174 return true;
1175 }
1176 } // namespace Idl
1177 } // namespace OHOS
1178