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 "util/options.h" 17 18#include <cstdio> 19#include <cstring> 20#include <dirent.h> 21#include <getopt.h> 22#include <sys/stat.h> 23#include <unistd.h> 24 25#include <map> 26 27#include "util/common.h" 28#include "util/file.h" 29#include "util/logger.h" 30#include "util/string_helper.h" 31#include "util/string_builder.h" 32 33namespace OHOS { 34namespace Idl { 35const char *Options::optSupportArgs = "hvcs:m:p:d:r:o:D:t:"; 36static struct option g_longOpts[] = { 37 {"help", no_argument, nullptr, 'h'}, 38 {"version", no_argument, nullptr, 'v'}, 39 {"system", required_argument, nullptr, 'S'}, 40 {"mode", required_argument, nullptr, 'm'}, 41 {"gen-c", no_argument, nullptr, '1'}, 42 {"gen-cpp", no_argument, nullptr, '2'}, 43 {"gen-java", no_argument, nullptr, '3'}, 44 {"gen-rust", no_argument, nullptr, '4'}, 45 {"gen-ts", no_argument, nullptr, '5'}, 46 {"package", required_argument, nullptr, 'p'}, 47 {"dump-ast", no_argument, nullptr, 'a'}, 48 {"dump-metadata", no_argument, nullptr, 'e'}, 49 {"hash", no_argument, nullptr, 'H'}, 50 {"log-domainid", required_argument, nullptr, 'i'}, 51 {"log-tag", required_argument, nullptr, 'g'}, 52 {"intf-type", required_argument, nullptr, 'T'}, 53 {nullptr, 0, nullptr, 0 } 54}; 55 56Options &Options::GetInstance() 57{ 58 static Options option; 59 return option; 60} 61 62bool Options::Parse(int argc, char *argv[]) 63{ 64 int ret = true; 65 program = argv[0]; 66 opterr = 0; 67 int op = 0; 68 int optIndex = 0; 69 70 while ((op = getopt_long_only(argc, argv, optSupportArgs, g_longOpts, &optIndex)) != -1) { 71 if (optind > 0 && optind <= argc) { 72 ret = ParseSingle(op, std::string(argv[optind - 1])); 73 } 74 } 75 76 if (doCompile) { 77 int i = 0; 78 while (++i < argc) { 79 if (argv[i][0] != '-' && StringHelper::EndWith(argv[i], ".idl")) { 80 AddSources(argv[i]); 81 } 82 } 83 } 84 85 return ret ? CheckOptions() : ret; 86} 87 88bool Options::ParseSingle(int option, std::string optVal) 89{ 90 bool ret = true; 91 switch (option) { 92 case 'h': 93 doShowUsage = true; 94 break; 95 case 'v': 96 doShowVersion = true; 97 break; 98 case 'a': 99 doDumpAST = true; 100 break; 101 case 'e': 102 doDumpMetadata = true; 103 break; 104 case 'H': 105 doHashKey = true; 106 break; 107 case 'c': 108 doCompile = true; 109 break; 110 case '1': 111 SetLanguage("c"); 112 break; 113 case '2': 114 SetLanguage("cpp"); 115 break; 116 case '3': 117 SetLanguage("java"); 118 break; 119 case '4': 120 SetLanguage("rust"); 121 break; 122 case '5': 123 SetLanguage("ts"); 124 break; 125 default: 126 ret = ParseOptionWithValue(option, optVal); 127 break; 128 } 129 return ret; 130} 131 132bool Options::ParseOptionWithValue(int option, std::string optVal) 133{ 134 bool ret = true; 135 StringBuilder errors; 136 137 switch (option) { 138 case 'o': 139 outPutFile = optarg; 140 break; 141 case 'S': 142 ret = SetSystemLevel(optarg); 143 break; 144 case 'm': 145 ret = SetGenerateMode(optarg); 146 break; 147 case 's': 148 SetMetadataFile(optarg); 149 break; 150 case 'p': 151 SetPackage(optarg); 152 break; 153 case 'D': 154 AddSourcesByDir(optarg); 155 break; 156 case 'd': 157 SetOutDir(optarg); 158 break; 159 case 'r': 160 ret = AddPackagePath(optarg); 161 break; 162 case 't': 163 ret = SetHiTrace(optarg); 164 break; 165 case 'i': 166 ret = SetLogDomainId(optarg); 167 break; 168 case 'g': 169 ret = SetLogTag(optarg); 170 break; 171 case 'T': 172 ret = SetInterfaceType(optarg); 173 break; 174 default: 175 errors.Append(optVal.c_str()); 176 break; 177 } 178 illegalOptions = errors.ToString(); 179 return ret; 180} 181 182bool Options::SetSystemLevel(const std::string &system) 183{ 184 static std::map<std::string, SystemLevel> systemLevelMap = { 185 {"mini", SystemLevel::MINI}, 186 {"lite", SystemLevel::LITE}, 187 {"full", SystemLevel::FULL}, 188 }; 189 190 auto levelIter = systemLevelMap.find(system); 191 if (levelIter == systemLevelMap.end()) { 192 Logger::E(TAG, "invalid system level set: '%s', please input mini/lite/full", system.c_str()); 193 return false; 194 } 195 systemLevel = levelIter->second; 196 return true; 197} 198 199bool Options::SetGenerateMode(const std::string &mode) 200{ 201 static std::map<std::string, GenMode> codeGenMap = { 202 {"low", GenMode::LOW}, 203 {"passthrough", GenMode::PASSTHROUGH}, 204 {"ipc", GenMode::IPC}, 205 {"kernel", GenMode::KERNEL}, 206 }; 207 208 auto codeGenIter = codeGenMap.find(mode); 209 if (codeGenIter == codeGenMap.end()) { 210 Logger::E(TAG, "invalid generate mode set: '%s', please input low/passthrough/ipc/kernel/sa.", mode.c_str()); 211 return false; 212 } 213 genMode = codeGenIter->second; 214 return true; 215} 216 217bool Options::SetLanguage(const std::string &language) 218{ 219 static const std::map<std::string, Language> languageMap = { 220 {"c", Language::C}, 221 {"cpp", Language::CPP}, 222 {"java", Language::JAVA}, 223 {"rust", Language::RUST}, 224 {"ts", Language::TS}, 225 }; 226 227 const auto kindIter = languageMap.find(language); 228 if (kindIter == languageMap.end()) { 229 Logger::E(TAG, "invalid language '%s', please input c, cpp, java, rust or ts", language.c_str()); 230 return false; 231 } 232 233 doGenerateCode = true; 234 genLanguage = kindIter->second; 235 return true; 236} 237 238bool Options::SetMetadataFile(const std::string &file) 239{ 240 doSaveMetadata = true; 241 metadataFile = file; 242 return true; 243} 244 245void Options::SetPackage(const std::string &infPackage) 246{ 247 idlPackage = infPackage; 248} 249 250void Options::AddSources(const std::string &sourceFile) 251{ 252 std::string realPath = File::AdapterRealPath(sourceFile); 253 if (realPath.empty()) { 254 Logger::E(TAG, "invalid idl file path:%s", sourceFile.c_str()); 255 return; 256 } 257 258 if (sourceFiles.insert(realPath).second == false) { 259 Logger::E(TAG, "this idl file has been add:%s", sourceFile.c_str()); 260 return; 261 } 262} 263 264void Options::AddSourcesByDir(const std::string &dir) 265{ 266 sourceDir = dir; 267 std::set<std::string> files = File::FindFiles(sourceDir); 268 if (!files.empty()) { 269 doCompile = true; 270 sourceFiles.insert(files.begin(), files.end()); 271 } 272} 273 274bool Options::AddPackagePath(const std::string &packagePath) 275{ 276 size_t index = packagePath.find(":"); 277 if (index == std::string::npos || index == packagePath.size() - 1) { 278 Logger::E(TAG, "invalid option parameters '%s'.", packagePath.c_str()); 279 return false; 280 } 281 282 std::string package = packagePath.substr(0, index); 283 std::string path = File::AdapterRealPath(packagePath.substr(index + 1)); 284 if (path.empty()) { 285 Logger::E(TAG, "invalid path '%s'.", packagePath.substr(index + 1).c_str()); 286 return false; 287 } 288 289 auto it = packagePathMap.find(package); 290 if (it != packagePathMap.end()) { 291 Logger::E(TAG, "The '%s:%s' has been set.", package.c_str(), path.c_str()); 292 return false; 293 } 294 295 packagePathMap[package] = path; 296 return true; 297} 298 299void Options::SetOutDir(const std::string &dir) 300{ 301 doOutDir = true; 302 genDir = dir; 303} 304 305bool Options::CheckOptions() 306{ 307 if (doShowUsage || doShowVersion) { 308 return true; 309 } 310 if (HasErrors()) { 311 ShowErrors(); 312 return false; 313 } 314 if (interfaceType == InterfaceType::SA) { 315 return CheckSaOptions(); 316 } else if (interfaceType == InterfaceType::HDI) { 317 return CheckHdiOptions(); 318 } else if (interfaceType == InterfaceType::SM || 319 interfaceType == InterfaceType::SAM || 320 interfaceType == InterfaceType::SAM_SM || 321 interfaceType == InterfaceType::SAM_UDS || 322 interfaceType == InterfaceType::SM_UDS) { 323 return CheckSmOptions(); 324 } else { 325 Logger::E(TAG, "Interface type 'intf-type' value '%d' invalid, please input 'hdi' or 'sa'.", interfaceType); 326 return false; 327 } 328} 329 330bool Options::CheckSaOptions() 331{ 332 if (!DoSupportSaType()) { 333 return false; 334 } 335 336 if (sourceFiles.empty() && !DoSaveMetadata()) { 337 Logger::E(TAG, "Option 'intf-type sa' must set idl file."); 338 return false; 339 } 340 341 if (!DoLegalLog()) { 342 Logger::E(TAG, "Option 'log-domainid' and 'log-tag' must be used together."); 343 return false; 344 } 345 346 attribute.doHitrace = doHitrace; 347 attribute.hitraceTag = hitraceTag; 348 attribute.logTag = logTag; 349 attribute.domainId = domainId; 350 attribute.doLog = DoLogOn(); 351 352 return true; 353} 354 355bool Options::DoSupportSaType() 356{ 357 bool ret = true; 358 if (genLanguage != Language::CPP && genLanguage != Language::RUST && genLanguage != Language::TS) { 359 Logger::E(TAG, "Option 'intf-type sa' only support language option 'gen-cpp', 'gen-rust' or 'gen-ts'."); 360 ret = false; 361 } 362 363 if (systemLevel != SystemLevel::INIT) { 364 Logger::E(TAG, "Option 'intf-type sa' not support option 'system'."); 365 ret = false; 366 } 367 368 if (genMode != GenMode::INIT) { 369 Logger::E(TAG, "Option 'intf-type sa' not support option 'm' or 'mode'."); 370 ret = false; 371 } 372 373 if (!idlPackage.empty()) { 374 Logger::E(TAG, "Option 'intf-type sa' not support option 'p' or 'package'."); 375 ret = false; 376 } 377 378 if (doHashKey) { 379 Logger::E(TAG, "Option 'intf-type sa' not support option 'hash'."); 380 ret = false; 381 } 382 383 if (!packagePathMap.empty()) { 384 Logger::E(TAG, "Option 'intf-type sa' not support option 'r'."); 385 ret = false; 386 } 387 388 if (!sourceDir.empty()) { 389 Logger::E(TAG, "Option 'intf-type sa' not support option 'D'."); 390 ret = false; 391 } 392 393 if (!outPutFile.empty()) { 394 Logger::E(TAG, "Option 'intf-type sa' not support option 'o'."); 395 ret = false; 396 } 397 398 if (!ret) { 399 printf("Use \"-h, --help\" to show usage.\n"); 400 } 401 return ret; 402} 403 404bool Options::CheckHdiOptions() 405{ 406 SetHdiDefaultOption(); 407 if (!DoSupportHdiType()) { 408 return false; 409 } 410 411 if (doCompile) { 412 if (!DoGetHashKey() && !doDumpAST && !doGenerateCode && !doOutDir) { 413 Logger::E(TAG, "nothing to do."); 414 return false; 415 } 416 417 if (!doGenerateCode && doOutDir) { 418 Logger::E(TAG, "no target language."); 419 return false; 420 } 421 422 if (doGenerateCode && !doOutDir) { 423 Logger::E(TAG, "no out directory."); 424 return false; 425 } 426 } else { 427 if (DoGetHashKey() || doDumpAST || doGenerateCode || doOutDir) { 428 Logger::E(TAG, "no idl files."); 429 return false; 430 } 431 } 432 433 return true; 434} 435 436void Options::SetHdiDefaultOption() 437{ 438 if (systemLevel == SystemLevel::INIT) { 439 systemLevel = SystemLevel::FULL; 440 } 441 if (genMode == GenMode::INIT) { 442 genMode = GenMode::IPC; 443 } 444 return; 445} 446 447bool Options::DoSupportHdiType() 448{ 449 bool ret = true; 450 451 if (genLanguage != Language::C && genLanguage != Language::CPP && genLanguage != Language::JAVA) { 452 Logger::E(TAG, "Option 'intf-type hdi' only support language option 'gen-c', 'gen-cpp' or 'gen-java'."); 453 ret = false; 454 } 455 456 if (doDumpMetadata) { 457 Logger::E(TAG, "Option 'intf-type hdi' not support option 'dump-metadata'."); 458 ret = false; 459 } 460 461 if (doKeywords) { 462 Logger::E(TAG, "Option 'intf-type hdi' not support option '-t', '-log-domainid' or '-log-tag'."); 463 ret = false; 464 } 465 466 if (doSaveMetadata) { 467 Logger::E(TAG, "Option 'intf-type hdi' not support option '-s'."); 468 ret = false; 469 } 470 471 if (!ret) { 472 printf("Use \"-h, --help\" to show usage.\n"); 473 } 474 return ret; 475} 476 477bool Options::DoSupportSmType() 478{ 479 bool ret = true; 480 481 if (genLanguage != Language::CPP && genLanguage != Language::JAVA) { 482 Logger::E(TAG, "Option 'intf-type sm' only support language option 'gen-cpp' or 'gen-java'."); 483 ret = false; 484 } 485 486 if (doDumpMetadata) { 487 Logger::E(TAG, "Option 'intf-type sm' not support option 'dump-metadata'."); 488 ret = false; 489 } 490 491 if (doKeywords) { 492 Logger::E(TAG, "Option 'intf-type sm' not support option '-t', '-log-domainid' or '-log-tag'."); 493 ret = false; 494 } 495 496 if (doSaveMetadata) { 497 Logger::E(TAG, "Option 'intf-type sm' not support option '-s'."); 498 ret = false; 499 } 500 501 if (!ret) { 502 printf("Use \"-h, --help\" to show usage.\n"); 503 } 504 return ret; 505} 506 507void Options::SetSmDefaultOption() 508{ 509 systemLevel = SystemLevel::INIT; 510 genMode = GenMode::INIT; 511 return; 512} 513 514bool Options::CheckSmOptions() 515{ 516 SetSmDefaultOption(); 517 if (!DoSupportSmType()) { 518 return false; 519 } 520 521 if (doCompile) { 522 if (!DoGetHashKey() && !doDumpAST && !doGenerateCode && !doOutDir) { 523 Logger::E(TAG, "nothing to do."); 524 return false; 525 } 526 527 if (!doGenerateCode && doOutDir) { 528 Logger::E(TAG, "no target language."); 529 return false; 530 } 531 532 if (doGenerateCode && !doOutDir) { 533 Logger::E(TAG, "no out directory."); 534 return false; 535 } 536 } else { 537 if (DoGetHashKey() || doDumpAST || doGenerateCode || doOutDir) { 538 Logger::E(TAG, "no idl files."); 539 return false; 540 } 541 } 542 543 return true; 544} 545 546bool Options::SetHiTrace(const std::string &tag) 547{ 548 doKeywords = true; 549 hitraceTag = tag; 550 doHitrace = true; 551 return true; 552} 553 554bool Options::SetLogDomainId(const std::string &id) 555{ 556 doKeywords = true; 557 domainId = id; 558 return true; 559} 560 561bool Options::SetLogTag(const std::string &tag) 562{ 563 doKeywords = true; 564 logTag = tag; 565 return true; 566} 567 568bool Options::SetInterfaceType(const std::string &type) 569{ 570 static std::map<std::string, InterfaceType> Type = { 571 {"hdi", InterfaceType::HDI}, 572 {"sa", InterfaceType::SA}, 573 {"sm", InterfaceType::SM}, 574 {"sam", InterfaceType::SAM}, 575 {"sam_sm", InterfaceType::SAM_SM}, 576 {"sam_uds", InterfaceType::SAM_UDS}, 577 {"sm_uds", InterfaceType::SM_UDS}, 578 }; 579 580 auto codeGenIter = Type.find(type); 581 if (codeGenIter == Type.end()) { 582 Logger::E(TAG, "invalid interface type set: '%s', please input hdi/sa.", type.c_str()); 583 return false; 584 } 585 interfaceType = codeGenIter->second; 586 return true; 587} 588 589bool Options::DoLogOn() const 590{ 591 if (!domainId.empty() && !logTag.empty()) { 592 return true; 593 } 594 return false; 595} 596 597bool Options::DoLegalLog() const 598{ 599 if (genLanguage == Language::CPP) { 600 if (!domainId.empty() && !logTag.empty()) { 601 return true; 602 } else if (domainId.empty() && logTag.empty()) { 603 return true; 604 } else { 605 return false; 606 } 607 } 608 return true; 609} 610 611bool Options::HasErrors() const 612{ 613 return !illegalOptions.empty(); 614} 615 616void Options::ShowErrors() const 617{ 618 std::vector<std::string> illegalOptionsVec = StringHelper::Split(illegalOptions, " "); 619 for (size_t i = 0; i < illegalOptionsVec.size(); i++) { 620 Logger::E(TAG, "The Option \"%s\" is illegal.", illegalOptionsVec[i].c_str()); 621 } 622 printf("Use \"-h, --help\" to show usage.\n"); 623 return; 624} 625 626bool Options::HasWarning() const 627{ 628 if (interfaceType == InterfaceType::SA) { 629 if (genLanguage == Language::RUST || genLanguage == Language::TS) { 630 if (DoSearchKeywords()) { 631 return true; 632 } 633 } 634 } 635 return false; 636} 637 638void Options::ShowWarning() const 639{ 640 printf("Warning : Executed successfully, but contains invalid commands !\n"); 641} 642 643void Options::ShowVersion() const 644{ 645 printf("idl %d.%d\n" 646 "Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.\n\n", 647 VERSION_MAJOR, VERSION_MINOR); 648} 649 650void Options::ShowUsage() const 651{ 652 printf("Compile a .idl file and generate C/C++/Ts/Rust and Java codes.\n" 653 "Usage: idl [options] file\n" 654 "Options:\n" 655 " -h, --help Display command line options\n" 656 " -v, --version Display toolchain version information\n" 657 " --system <value> Set system level 'mini','lite' or 'full', the default value is 'full', " 658 "only support 'intf-type hdi'\n" 659 " -m, --mode <value> Set generate code mode 'low', 'passthrough', 'ipc' or 'kernel'," 660 " the default value is 'ipc', only support 'intf-type hdi'\n" 661 " -p, --package <package name> Set package of idl files, only support 'intf-type hdi'\n" 662 " --dump-ast Display the AST of the compiled file\n" 663 " --dump-metadata Display the metadata generated from the compiled file, " 664 "only support 'intf-type sa'\n" 665 " --hash Generate hash info of idl files, only support 'intf-type hdi'\n" 666 " -r <rootPackage>:<rootPath> Set root path of root package, only support 'intf-type hdi'\n" 667 " -c Compile the .idl file\n" 668 " -D <directory> Directory of the idl file, only support 'intf-type hdi'\n" 669 " -d <directory> Place generated codes into <directory>\n" 670 " -o <file> Place the output into <file>, only support 'intf-type hdi'\n" 671 " -s <file> Place the metadata into <file>, only support 'intf-type sa'\n" 672 " --gen-c Generate C codes, only support 'intf-type hdi'\n" 673 " --gen-cpp Generate C++ codes\n" 674 " --gen-java Generate Java codes, only support 'intf-type hdi'\n" 675 " --gen-rust Generate Rust codes, only support 'intf-type sa'\n" 676 " --gen-ts Generate Ts codes, only support 'intf-type sa'\n" 677 " --log-domainid <domainid> Place the service domain in <domainid>, Enable log(Pair with -log-tag), " 678 "only support 'intf-type sa'\n" 679 " --log-tag <tag> Place the subsystem name in <tag>, Enable log(Pair with -log-domainid), " 680 "only support 'intf-type sa'\n" 681 " -t <hitrace tag> Place the constant name from hitrace_meter.h file in <hitrace tag>, " 682 "only support 'intf-type sa'\n" 683 " --intf-type <tag> Set type of generated codes 'sa' or 'hdi', default type is 'sa'\n"); 684} 685 686/* 687 * -r option: -r ohos.hdi:./drivers/interface 688 * package:ohos.hdi.foo.v1_0 689 * rootPackage:ohos.hdi 690 */ 691std::string Options::GetRootPackage(const std::string &package) const 692{ 693 const auto &packagePaths = GetPackagePathMap(); 694 for (const auto &packageRoot : packagePaths) { 695 if (StringHelper::StartWith(package, packageRoot.first)) { 696 return packageRoot.first; 697 } 698 } 699 700 return ""; 701} 702 703/* 704 * -r option: -r ohos.hdi:./drivers/interface 705 * package:ohos.hdi.foo.v1_0 706 * rootPath:./drivers/interface 707 */ 708std::string Options::GetRootPath(const std::string &package) const 709{ 710 const auto &packagePaths = GetPackagePathMap(); 711 for (const auto &packageRoot : packagePaths) { 712 if (StringHelper::StartWith(package, packageRoot.first)) { 713 return packageRoot.second; 714 } 715 } 716 717 return ""; 718} 719 720/* 721 * -r option: -r ohos.hdi:./drivers/interface 722 * package:ohos.hdi.foo.v1_0 723 * subPackage:foo.v1_0 724 */ 725std::string Options::GetSubPackage(const std::string &package) const 726{ 727 if (interfaceType == InterfaceType::SM || 728 interfaceType == InterfaceType::SM_UDS) { 729 return package; 730 } 731 std::string rootPackage = GetRootPackage(package); 732 if (rootPackage.empty()) { 733 return package; 734 } 735 736 return package.substr(rootPackage.size() + 1); 737} 738 739/* 740 * -r option: -r ohos.hdi:./drivers/interface 741 * package:ohos.hdi.foo.v1_0 742 * packagePath:./drivers/interface/foo/v1_0 743 */ 744std::string Options::GetPackagePath(const std::string &package) const 745{ 746 std::string rootPackage = ""; 747 std::string rootPath = ""; 748 const auto &packagePaths = GetPackagePathMap(); 749 for (const auto &packageRoot : packagePaths) { 750 if (StringHelper::StartWith(package, packageRoot.first)) { 751 rootPackage = packageRoot.first; 752 rootPath = packageRoot.second; 753 } 754 } 755 756 if (rootPackage.empty()) { 757 // The current path is the root path 758 std::string curPath = File::AdapterPath(StringHelper::Replace(package, '.', SEPARATOR)); 759 return File::AdapterRealPath(curPath); 760 } 761 762 if (StringHelper::EndWith(rootPath, SEPARATOR)) { 763 rootPath.pop_back(); 764 } 765 766 std::string subPath = StringHelper::Replace(package.substr(rootPackage.size() + 1), '.', SEPARATOR); 767 return File::AdapterPath(rootPath + "/" + subPath); 768} 769 770/* 771 * -r option: -r ohos.hdi:./drivers/interface 772 * import: ohos.hdi.foo.v1_0.MyTypes 773 * packagePath:./drivers/interface/foo/v1_0/MyTypes.idl 774 */ 775std::string Options::GetImportFilePath(const std::string &import) const 776{ 777 size_t index = import.rfind('.'); 778 if (index == std::string::npos) { 779 return import; 780 } 781 782 std::string dir = GetPackagePath(StringHelper::SubStr(import, 0, index)); 783 std::string className = import.substr(index + 1); 784 return StringHelper::Format("%s%c%s.idl", dir.c_str(), SEPARATOR, className.c_str()); 785} 786} // namespace Idl 787} // namespace OHOS