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