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