main.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021-2022, 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 "Namespaces.h"
  10. #include <AK/Debug.h>
  11. #include <AK/LexicalPath.h>
  12. #include <LibCore/ArgsParser.h>
  13. #include <LibCore/File.h>
  14. #include <LibCore/Stream.h>
  15. #include <LibIDL/IDLParser.h>
  16. #include <LibIDL/Types.h>
  17. extern Vector<StringView> s_header_search_paths;
  18. namespace IDL {
  19. void generate_constructor_header(IDL::Interface const&, StringBuilder&);
  20. void generate_constructor_implementation(IDL::Interface const&, StringBuilder&);
  21. void generate_prototype_header(IDL::Interface const&, StringBuilder&);
  22. void generate_prototype_implementation(IDL::Interface const&, StringBuilder&);
  23. void generate_iterator_prototype_header(IDL::Interface const&, StringBuilder&);
  24. void generate_iterator_prototype_implementation(IDL::Interface const&, StringBuilder&);
  25. }
  26. ErrorOr<int> serenity_main(Main::Arguments arguments)
  27. {
  28. Core::ArgsParser args_parser;
  29. StringView path;
  30. StringView import_base_path;
  31. StringView output_path = "-"sv;
  32. bool constructor_header_mode = false;
  33. bool constructor_implementation_mode = false;
  34. bool prototype_header_mode = false;
  35. bool prototype_implementation_mode = false;
  36. bool iterator_prototype_header_mode = false;
  37. bool iterator_prototype_implementation_mode = false;
  38. args_parser.add_option(constructor_header_mode, "Generate the constructor .h file", "constructor-header", 'C');
  39. args_parser.add_option(constructor_implementation_mode, "Generate the constructor .cpp file", "constructor-implementation", 'O');
  40. args_parser.add_option(prototype_header_mode, "Generate the prototype .h file", "prototype-header", 'P');
  41. args_parser.add_option(prototype_implementation_mode, "Generate the prototype .cpp file", "prototype-implementation", 'R');
  42. args_parser.add_option(iterator_prototype_header_mode, "Generate the iterator prototype .h file", "iterator-prototype-header", 0);
  43. args_parser.add_option(iterator_prototype_implementation_mode, "Generate the iterator prototype .cpp file", "iterator-prototype-implementation", 0);
  44. args_parser.add_option(Core::ArgsParser::Option {
  45. .argument_mode = Core::ArgsParser::OptionArgumentMode::Required,
  46. .help_string = "Add a header search path passed to the compiler",
  47. .long_name = "header-include-path",
  48. .short_name = 'i',
  49. .value_name = "path",
  50. .accept_value = [&](char const* s) {
  51. s_header_search_paths.append({ s, strlen(s) });
  52. return true;
  53. },
  54. });
  55. args_parser.add_option(output_path, "Path to output generated file into", "output-path", 'o', "output-path");
  56. args_parser.add_positional_argument(path, "IDL file", "idl-file");
  57. args_parser.add_positional_argument(import_base_path, "Import base path", "import-base-path", Core::ArgsParser::Required::No);
  58. args_parser.parse(arguments);
  59. auto file = TRY(Core::Stream::File::open(path, Core::Stream::OpenMode::Read));
  60. LexicalPath lexical_path(path);
  61. auto& namespace_ = lexical_path.parts_view().at(lexical_path.parts_view().size() - 2);
  62. auto data = TRY(file->read_all());
  63. if (import_base_path.is_null())
  64. import_base_path = lexical_path.dirname();
  65. auto output_file = TRY(Core::Stream::File::open_file_or_standard_stream(output_path, Core::Stream::OpenMode::Write));
  66. IDL::Parser parser(path, data, import_base_path);
  67. auto& interface = parser.parse();
  68. if (IDL::libweb_interface_namespaces.span().contains_slow(namespace_)) {
  69. StringBuilder builder;
  70. builder.append(namespace_);
  71. builder.append("::"sv);
  72. builder.append(interface.name);
  73. interface.fully_qualified_name = builder.to_deprecated_string();
  74. } else {
  75. interface.fully_qualified_name = interface.name;
  76. }
  77. if constexpr (BINDINGS_GENERATOR_DEBUG) {
  78. dbgln("Attributes:");
  79. for (auto& attribute : interface.attributes) {
  80. dbgln(" {}{}{}{} {}",
  81. attribute.inherit ? "inherit " : "",
  82. attribute.readonly ? "readonly " : "",
  83. attribute.type->name(),
  84. attribute.type->is_nullable() ? "?" : "",
  85. attribute.name);
  86. }
  87. dbgln("Functions:");
  88. for (auto& function : interface.functions) {
  89. dbgln(" {}{} {}",
  90. function.return_type->name(),
  91. function.return_type->is_nullable() ? "?" : "",
  92. function.name);
  93. for (auto& parameter : function.parameters) {
  94. dbgln(" {}{} {}",
  95. parameter.type->name(),
  96. parameter.type->is_nullable() ? "?" : "",
  97. parameter.name);
  98. }
  99. }
  100. dbgln("Static Functions:");
  101. for (auto& function : interface.static_functions) {
  102. dbgln(" static {}{} {}",
  103. function.return_type->name(),
  104. function.return_type->is_nullable() ? "?" : "",
  105. function.name);
  106. for (auto& parameter : function.parameters) {
  107. dbgln(" {}{} {}",
  108. parameter.type->name(),
  109. parameter.type->is_nullable() ? "?" : "",
  110. parameter.name);
  111. }
  112. }
  113. }
  114. StringBuilder output_builder;
  115. if (constructor_header_mode)
  116. IDL::generate_constructor_header(interface, output_builder);
  117. if (constructor_implementation_mode)
  118. IDL::generate_constructor_implementation(interface, output_builder);
  119. if (prototype_header_mode)
  120. IDL::generate_prototype_header(interface, output_builder);
  121. if (prototype_implementation_mode)
  122. IDL::generate_prototype_implementation(interface, output_builder);
  123. if (iterator_prototype_header_mode)
  124. IDL::generate_iterator_prototype_header(interface, output_builder);
  125. if (iterator_prototype_implementation_mode)
  126. IDL::generate_iterator_prototype_implementation(interface, output_builder);
  127. TRY(output_file->write(output_builder.string_view().bytes()));
  128. return 0;
  129. }