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