main.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
  5. * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include "IDLParser.h"
  10. #include "IDLTypes.h"
  11. #include <AK/Debug.h>
  12. #include <AK/LexicalPath.h>
  13. #include <LibCore/ArgsParser.h>
  14. #include <LibCore/File.h>
  15. extern Vector<StringView> s_header_search_paths;
  16. namespace IDL {
  17. void generate_constructor_header(IDL::Interface const&);
  18. void generate_constructor_implementation(IDL::Interface const&);
  19. void generate_prototype_header(IDL::Interface const&);
  20. void generate_prototype_implementation(IDL::Interface const&);
  21. void generate_header(IDL::Interface const&);
  22. void generate_implementation(IDL::Interface const&);
  23. void generate_iterator_prototype_header(IDL::Interface const&);
  24. void generate_iterator_prototype_implementation(IDL::Interface const&);
  25. void generate_iterator_header(IDL::Interface const&);
  26. void generate_iterator_implementation(IDL::Interface const&);
  27. }
  28. int main(int argc, char** argv)
  29. {
  30. Core::ArgsParser args_parser;
  31. StringView path = nullptr;
  32. StringView import_base_path = nullptr;
  33. bool header_mode = false;
  34. bool implementation_mode = false;
  35. bool constructor_header_mode = false;
  36. bool constructor_implementation_mode = false;
  37. bool prototype_header_mode = false;
  38. bool prototype_implementation_mode = false;
  39. bool iterator_header_mode = false;
  40. bool iterator_implementation_mode = false;
  41. bool iterator_prototype_header_mode = false;
  42. bool iterator_prototype_implementation_mode = false;
  43. args_parser.add_option(header_mode, "Generate the wrapper .h file", "header", 'H');
  44. args_parser.add_option(implementation_mode, "Generate the wrapper .cpp file", "implementation", 'I');
  45. args_parser.add_option(constructor_header_mode, "Generate the constructor .h file", "constructor-header", 'C');
  46. args_parser.add_option(constructor_implementation_mode, "Generate the constructor .cpp file", "constructor-implementation", 'O');
  47. args_parser.add_option(prototype_header_mode, "Generate the prototype .h file", "prototype-header", 'P');
  48. args_parser.add_option(prototype_implementation_mode, "Generate the prototype .cpp file", "prototype-implementation", 'R');
  49. args_parser.add_option(iterator_header_mode, "Generate the iterator wrapper .h file", "iterator-header", 0);
  50. args_parser.add_option(iterator_implementation_mode, "Generate the iterator wrapper .cpp file", "iterator-implementation", 0);
  51. args_parser.add_option(iterator_prototype_header_mode, "Generate the iterator prototype .h file", "iterator-prototype-header", 0);
  52. args_parser.add_option(iterator_prototype_implementation_mode, "Generate the iterator prototype .cpp file", "iterator-prototype-implementation", 0);
  53. args_parser.add_option(Core::ArgsParser::Option {
  54. .requires_argument = true,
  55. .help_string = "Add a header search path passed to the compiler",
  56. .long_name = "header-include-path",
  57. .short_name = 'i',
  58. .value_name = "path",
  59. .accept_value = [&](char const* s) {
  60. s_header_search_paths.append({ s, strlen(s) });
  61. return true;
  62. },
  63. });
  64. args_parser.add_positional_argument(path, "IDL file", "idl-file");
  65. args_parser.add_positional_argument(import_base_path, "Import base path", "import-base-path", Core::ArgsParser::Required::No);
  66. args_parser.parse(argc, argv);
  67. auto file_or_error = Core::File::open(path, Core::OpenMode::ReadOnly);
  68. if (file_or_error.is_error()) {
  69. warnln("Failed to open {}: {}", path, file_or_error.error());
  70. return 1;
  71. }
  72. LexicalPath lexical_path(path);
  73. auto& namespace_ = lexical_path.parts_view().at(lexical_path.parts_view().size() - 2);
  74. auto data = file_or_error.value()->read_all();
  75. if (import_base_path.is_null())
  76. import_base_path = lexical_path.dirname();
  77. auto& interface = IDL::Parser(path, data, import_base_path).parse();
  78. if (namespace_.is_one_of("Crypto", "CSS", "DOM", "DOMParsing", "Encoding", "HTML", "UIEvents", "Geometry", "HighResolutionTime", "IntersectionObserver", "NavigationTiming", "RequestIdleCallback", "ResizeObserver", "SVG", "Selection", "URL", "WebGL", "WebSockets", "XHR")) {
  79. StringBuilder builder;
  80. builder.append(namespace_);
  81. builder.append("::");
  82. builder.append(interface.name);
  83. interface.fully_qualified_name = builder.to_string();
  84. } else {
  85. interface.fully_qualified_name = interface.name;
  86. }
  87. if constexpr (WRAPPER_GENERATOR_DEBUG) {
  88. dbgln("Attributes:");
  89. for (auto& attribute : interface.attributes) {
  90. dbgln(" {}{}{} {}",
  91. attribute.readonly ? "readonly " : "",
  92. attribute.type->name,
  93. attribute.type->nullable ? "?" : "",
  94. attribute.name);
  95. }
  96. dbgln("Functions:");
  97. for (auto& function : interface.functions) {
  98. dbgln(" {}{} {}",
  99. function.return_type->name,
  100. function.return_type->nullable ? "?" : "",
  101. function.name);
  102. for (auto& parameter : function.parameters) {
  103. dbgln(" {}{} {}",
  104. parameter.type->name,
  105. parameter.type->nullable ? "?" : "",
  106. parameter.name);
  107. }
  108. }
  109. dbgln("Static Functions:");
  110. for (auto& function : interface.static_functions) {
  111. dbgln(" static {}{} {}",
  112. function.return_type->name,
  113. function.return_type->nullable ? "?" : "",
  114. function.name);
  115. for (auto& parameter : function.parameters) {
  116. dbgln(" {}{} {}",
  117. parameter.type->name,
  118. parameter.type->nullable ? "?" : "",
  119. parameter.name);
  120. }
  121. }
  122. }
  123. if (header_mode)
  124. IDL::generate_header(interface);
  125. if (implementation_mode)
  126. IDL::generate_implementation(interface);
  127. if (constructor_header_mode)
  128. IDL::generate_constructor_header(interface);
  129. if (constructor_implementation_mode)
  130. IDL::generate_constructor_implementation(interface);
  131. if (prototype_header_mode)
  132. IDL::generate_prototype_header(interface);
  133. if (prototype_implementation_mode)
  134. IDL::generate_prototype_implementation(interface);
  135. if (iterator_header_mode)
  136. IDL::generate_iterator_header(interface);
  137. if (iterator_implementation_mode)
  138. IDL::generate_iterator_implementation(interface);
  139. if (iterator_prototype_header_mode)
  140. IDL::generate_iterator_prototype_header(interface);
  141. if (iterator_prototype_implementation_mode)
  142. IDL::generate_iterator_prototype_implementation(interface);
  143. return 0;
  144. }