• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "sa_cpp_code_emitter.h"
17 
18 #include <regex>
19 #include <unordered_set>
20 
21 #include "util/options.h"
22 #include "util/logger.h"
23 
24 namespace OHOS {
25 namespace Idl {
GetImportInclusions(HeaderFile::HeaderFileSet & headerFiles)26 void SACppCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
27 {
28     for (const auto &importName : ast_->GetImportNames()) {
29         size_t index = importName.rfind(SEPARATOR);
30         if (index == std::string::npos) {
31             index = -1;
32         }
33         std::string fileName = importName.substr(index + 1);
34         std::string relativePath = importName.substr(0, index + 1) + FileName(fileName).c_str();
35         std::replace(relativePath.begin(), relativePath.end(), '\\', '/');
36         headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, relativePath);
37     }
38 }
39 
EmitImportUsingNamespace(StringBuilder & sb) const40 void SACppCodeEmitter::EmitImportUsingNamespace(StringBuilder &sb) const
41 {
42     std::unordered_map<std::string, int> usedNamespace;
43     for (const auto &importPair : ast_->GetImports()) {
44         AutoPtr<AST> importAst = importPair.second;
45         if (importAst->GetASTFileType() == ASTFileType::AST_SEQUENCEABLE ||
46             importAst->GetASTFileType() == ASTFileType::AST_RAWDATA) {
47             continue;
48         }
49         size_t index = importPair.first.rfind(".");
50         std::string usingName = importPair.first.substr(0, index);
51         if (usingName.empty()) {
52             continue;
53         }
54         std::regex dotToColons("\\.");
55         usingName = std::regex_replace(usingName, dotToColons, "::");
56         if (usedNamespace[usingName] == 0) {
57             usedNamespace[usingName] = 1;
58             sb.Append("using namespace ").AppendFormat("%s;\n", usingName.c_str());
59         }
60     }
61     sb.Append("\n");
62 }
63 
GetStdlibInclusions(HeaderFile::HeaderFileSet & headerFiles)64 void SACppCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
65 {
66     const AST::TypeStringMap &types = ast_->GetTypes();
67 
68     // Add header files dependency by default to avoid compatibility problems
69     headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
70     headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
71     for (const auto &pair : types) {
72         AutoPtr<ASTType> type = pair.second;
73         switch (type->GetTypeKind()) {
74             case TypeKind::TYPE_ARRAY:
75             case TypeKind::TYPE_LIST: {
76                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "vector");
77                 break;
78             }
79             case TypeKind::TYPE_SET: {
80                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "set");
81                 break;
82             }
83             case TypeKind::TYPE_MAP: {
84                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "unordered_map");
85                 break;
86             }
87             case TypeKind::TYPE_ORDEREDMAP: {
88                 headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "map");
89                 break;
90             }
91             default:
92                 break;
93         }
94     }
95 }
96 
EmitBeginNamespace(StringBuilder & sb) const97 void SACppCodeEmitter::EmitBeginNamespace(StringBuilder &sb) const
98 {
99     std::string fullnamespace = GetNamespace(interface_->GetNamespace()->ToString());
100     std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
101 
102     for (const auto &nspace : namespaceVec) {
103         sb.AppendFormat("namespace %s {\n", nspace.c_str());
104     }
105 }
106 
EmitEndNamespace(StringBuilder & sb) const107 void SACppCodeEmitter::EmitEndNamespace(StringBuilder &sb) const
108 {
109     std::string fullnamespace = GetNamespace(interface_->GetNamespace()->ToString());
110     std::vector<std::string> namespaceVec = StringHelper::Split(fullnamespace, ".");
111 
112     for (std::vector<std::string>::const_reverse_iterator nspaceIter = namespaceVec.rbegin();
113         nspaceIter != namespaceVec.rend(); ++nspaceIter) {
114         sb.AppendFormat("} // namespace %s\n", nspaceIter->c_str());
115     }
116 }
117 
EmitWriteMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,StringBuilder & sb,const std::string & prefix) const118 void SACppCodeEmitter::EmitWriteMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &parcelName,
119     StringBuilder &sb, const std::string &prefix) const
120 {
121     AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
122     if (typeEmitter != nullptr) {
123         typeEmitter->isParamInout = param->GetAttribute() == ASTParamAttr::PARAM_INOUT;
124         typeEmitter->isProxy = isProxy;
125         typeEmitter->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix);
126     }
127 }
128 
EmitReadMethodParameter(const AutoPtr<ASTParameter> & param,const std::string & parcelName,bool emitType,StringBuilder & sb,const std::string & prefix) const129 void SACppCodeEmitter::EmitReadMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &parcelName,
130     bool emitType, StringBuilder &sb, const std::string &prefix) const
131 {
132     AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
133     if (typeEmitter != nullptr) {
134         typeEmitter->EmitCppReadVar(parcelName, param->GetName(), sb, prefix, emitType);
135     }
136 }
137 
EmitInterfaceMethodParams(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const138 void SACppCodeEmitter::EmitInterfaceMethodParams(AutoPtr<ASTMethod> &method, StringBuilder &sb,
139     const std::string &prefix) const
140 {
141     EmitParamsWithReturnType(method, sb, prefix, true);
142 }
143 
EmitInterfaceClientMethodParams(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool includeValue) const144 void SACppCodeEmitter::EmitInterfaceClientMethodParams(AutoPtr<ASTMethod> &method, StringBuilder &sb,
145     const std::string &prefix, bool includeValue) const
146 {
147     EmitParamsWithReturnType(method, sb, prefix, true);
148     if (!method->IsOneWay()) {
149         int paramNumber = static_cast<int>(method->GetParameterNumber());
150         if (paramNumber == 0) {
151             sb.Append("int32_t timeout");
152         } else {
153             sb.Append(",\n").Append(prefix).Append("int32_t timeout");
154         }
155         if (includeValue) {
156             sb.Append(" = LOAD_SA_TIMEOUT");
157         }
158     }
159 }
160 
EmitInterfaceClientMethodParamsWithoutType(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const161 void SACppCodeEmitter::EmitInterfaceClientMethodParamsWithoutType(AutoPtr<ASTMethod> &method, StringBuilder &sb,
162     const std::string &prefix) const
163 {
164     EmitParamsWithReturnType(method, sb, prefix, false);
165 }
166 
EmitParamsWithReturnType(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix,bool includeType) const167 void SACppCodeEmitter::EmitParamsWithReturnType(AutoPtr<ASTMethod> &method, StringBuilder &sb,
168     const std::string &prefix, bool includeType) const
169 {
170     AutoPtr<ASTType> returnType = method->GetReturnType();
171     TypeKind retTypeKind = returnType->GetTypeKind();
172     int paramNumber = static_cast<int>(method->GetParameterNumber());
173 
174     for (int i = 0; i < paramNumber; i++) {
175         AutoPtr<ASTParameter> param = method->GetParameter(i);
176         if (param == nullptr) {
177             return;
178         }
179         sb.Append("\n").Append(prefix);
180         if (includeType) {
181             sb.AppendFormat(EmitCppParameter(param).c_str());
182         } else {
183             sb.AppendFormat(param->GetName().c_str());
184         }
185         if ((i != paramNumber - 1) || (retTypeKind != TypeKind::TYPE_VOID)) {
186             sb.Append(",");
187         }
188     }
189     if (retTypeKind != TypeKind::TYPE_VOID) {
190         AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(returnType);
191         if (typeEmitter != nullptr) {
192             sb.Append("\n").Append(prefix).AppendFormat(includeType ? "%s funcResult" : "funcResult",
193                 typeEmitter->EmitCppType(TypeMode::PARAM_OUT).c_str());
194         }
195     }
196 }
197 
EmitCppParameter(AutoPtr<ASTParameter> & param) const198 std::string SACppCodeEmitter::EmitCppParameter(AutoPtr<ASTParameter> &param) const
199 {
200     std::string name = param->GetName();
201     AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
202     if (typeEmitter == nullptr) {
203         return StringHelper::Format("unknow param attr %s", name.c_str());
204     }
205     ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
206     if (attrAttr == ASTParamAttr::PARAM_INOUT) {
207         return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_INOUT).c_str(), name.c_str());
208     } else if (attrAttr == ASTParamAttr::PARAM_IN) {
209         return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_IN).c_str(), name.c_str());
210     } else if (attrAttr == ASTParamAttr::PARAM_OUT) {
211         return StringHelper::Format("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_OUT).c_str(), name.c_str());
212     }
213     return StringHelper::Format("unknow param attr %s", name.c_str());
214 }
215 
EmitSecurecInclusion(StringBuilder & sb) const216 void SACppCodeEmitter::EmitSecurecInclusion(StringBuilder &sb) const
217 {
218     size_t methodNumber = interface_->GetMethodNumber();
219     for (size_t i = 0; i < methodNumber; i++) {
220         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
221         size_t paramNumber = method->GetParameterNumber();
222         for (size_t j = 0; j < paramNumber; j++) {
223             AutoPtr<ASTParameter> param = method->GetParameter(j);
224             TypeKind paramTypeKind = param->GetType()->GetTypeKind();
225             if (paramTypeKind == TypeKind::TYPE_UNION || paramTypeKind == TypeKind::TYPE_STRUCT) {
226                 sb.Append("#include <securec.h>\n");
227                 return;
228             }
229         }
230 
231         AutoPtr<ASTType> returnType = method->GetReturnType();
232         TypeKind retTypeKind = returnType->GetTypeKind();
233         if (retTypeKind == TypeKind::TYPE_UNION || retTypeKind == TypeKind::TYPE_STRUCT) {
234             sb.Append("#include <securec.h>\n");
235             return;
236         }
237     }
238 }
239 
GetOverloadName(AutoPtr<ASTMethod> & method,std::string & overloadname) const240 void SACppCodeEmitter::GetOverloadName(AutoPtr<ASTMethod> &method, std::string &overloadname) const
241 {
242     size_t paramNumber = method->GetParameterNumber();
243 
244     for (size_t i = 0; i < paramNumber; i++) {
245         AutoPtr<ASTParameter> param = method->GetParameter(i);
246         ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
247         if (attrAttr == ASTParamAttr::PARAM_INOUT) {
248             overloadname += "_inout_";
249         } else if (attrAttr == ASTParamAttr::PARAM_IN) {
250             overloadname += "_in_";
251         } else if (attrAttr == ASTParamAttr::PARAM_OUT) {
252             overloadname += "_out_";
253         }
254         AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
255         if (typeEmitter == nullptr) {
256             return;
257         }
258         overloadname += typeEmitter->GetTypeName();
259     }
260 
261     AutoPtr<ASTType> returnType = method->GetReturnType();
262     TypeKind retTypeKind = returnType->GetTypeKind();
263     if (retTypeKind != TypeKind::TYPE_VOID) {
264         AutoPtr<SaTypeEmitter> typeEmitter = GetTypeEmitter(returnType);
265         if (typeEmitter == nullptr) {
266             return;
267         }
268         overloadname += "_out_" + typeEmitter->GetTypeName();
269     }
270 
271     // Convert all characters in 'overloadname' to lowercase
272     std::transform(overloadname.begin(), overloadname.end(), overloadname.begin(), ::tolower);
273     // Remove any alphabetical characters followed by a dot (e.g., "std::" -> "")
274     overloadname = std::regex_replace(overloadname, std::regex("[a-zA-Z]+::"), "");
275     // Remove any alphabetical characters followed by a dot (e.g., "OHOS." -> "")
276     overloadname = std::regex_replace(overloadname, std::regex("[a-zA-Z]+\\.+"), "");
277     // Replace "[]" (array notation) with "_vector" (e.g., "int[]" -> "int_vector")
278     overloadname = std::regex_replace(overloadname, std::regex("\\[]"), "_vector");
279     // Replace spaces and '<' characters with underscores (e.g., "func <int>" -> "func_int")
280     overloadname = std::regex_replace(overloadname, std::regex("[ <]"), "_");
281     // Remove commas and '>' characters (e.g., "int, float>" -> "int_float")
282     overloadname = std::regex_replace(overloadname, std::regex("[,>]"), "");
283 }
284 
CheckMethodOverload(AutoPtr<ASTMethod> & method,size_t & index,std::string & overloadname) const285 void SACppCodeEmitter::CheckMethodOverload(AutoPtr<ASTMethod> &method, size_t &index, std::string &overloadname) const
286 {
287     for (size_t i = 0; i < index; i++) {
288         if (interface_->GetMethod(i)->GetName() == method->GetName()) {
289             GetOverloadName(method, overloadname);
290             break;
291         }
292     }
293 }
294 
EmitInterfaceMethodCommands(StringBuilder & sb,const std::string & prefix)295 void SACppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix)
296 {
297     size_t methodNumber = interface_->GetMethodNumber();
298     sb.AppendFormat("enum class %sIpcCode {\n", interface_->GetName().c_str());
299     for (size_t i = 0; i < methodNumber; i++) {
300         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
301         std::string overloadname = "";
302         CheckMethodOverload(method, i, overloadname);
303         std::string commandCode = "COMMAND_" + ConstantName(method->GetName() + overloadname);
304         bool hasIpcCode = method->HasIpcCode();
305         if (i == 0 && !hasIpcCode) {
306             commandCode += " = MIN_TRANSACTION_ID";
307         } else if (hasIpcCode) {
308             commandCode += " = " + method->GetIpcCodeStr();
309         }
310         commandCode += ",\n";
311         sb.Append(prefix).AppendFormat(commandCode.c_str());
312     }
313     sb.Append("};\n\n");
314 }
315 
316 } // namespace Idl
317 } // namespace OHOS