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
26namespace OHOS {
27namespace Idl {
28namespace {
29const std::string PROXY = "proxy";
30const std::string THIS_PROXY = "this.proxy";
31static const char* TAG = "TsCodeEmitter";
32const std::string UNKNOWN_TYPE = "unknown type";
33const String NEWLINE = "\n";
34const String RETURN_VALUE = "returnValue";
35const std::string ERR_CODE_TYPE = "errCode: number";
36const String ERR_CODE = "errCode";
37}
38
39void 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
62void 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
86void 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
101void 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
114void 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
122void 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
160void 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
206void 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
212void 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
218void 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
230void 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
253void 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
267void 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
274void 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
285void 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
312void 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
349void 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
404void 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
448void 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
456void 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
464void 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
486void 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
496void 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
503void 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
555void 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
598void 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
647void 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
656void TsCodeEmitter::EmitLicense(StringBuilder& stringBuilder)
657{
658    stringBuilder.Append(metaInterface_->license_).Append(NEWLINE);
659}
660
661void 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
689void 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
738void 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
791void 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
822void 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
872void 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
911void 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
951void 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
984void 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
1036String 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
1085String 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
1106String 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
1114String 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
1137String TsCodeEmitter::StubName(const String& name)
1138{
1139    return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub");
1140}
1141
1142const std::string TsCodeEmitter::UnderlineAdded(const String& originName)
1143{
1144    std::string underline("_");
1145    return underline + std::string(originName.string());
1146}
1147
1148const std::string TsCodeEmitter::SuffixAdded(const String& originName)
1149{
1150    std::string varSuffix("Var");
1151    return  std::string(originName.string()) + varSuffix;
1152}
1153
1154bool 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