mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-09 19:16:02 +00:00
GMLCompiler: Use synthetic widget definition when original is missing
This makes it possible to use externally defined toplevel widgets that have no C++ header defining them. Note that this only allows widget-native properties on the object, as the actual original definition is not available.
This commit is contained in:
parent
4b51a36044
commit
5c17b61378
Notes:
sideshowbarker
2024-07-16 23:17:55 +09:00
Author: https://github.com/alimpfard
Commit: 5c17b61378
Pull-request: https://github.com/SerenityOS/serenity/pull/24098
Reviewed-by: https://github.com/ADKaster ✅
1 changed files with 36 additions and 3 deletions
|
@ -102,10 +102,11 @@ static ErrorOr<String> include_path_for(StringView class_name, LexicalPath const
|
|||
}
|
||||
|
||||
// Each entry is an include path, without the "#include" itself.
|
||||
static ErrorOr<HashTable<String>> extract_necessary_includes(GUI::GML::Object const& gml_hierarchy, LexicalPath const& gml_file_name)
|
||||
static ErrorOr<HashTable<String>> extract_necessary_includes(GUI::GML::Object const& gml_hierarchy, LexicalPath const& gml_file_name, bool is_root = false)
|
||||
{
|
||||
HashTable<String> necessary_includes;
|
||||
TRY(necessary_includes.try_set(TRY(include_path_for(gml_hierarchy.name(), gml_file_name))));
|
||||
if (!is_root)
|
||||
TRY(necessary_includes.try_set(TRY(include_path_for(gml_hierarchy.name(), gml_file_name))));
|
||||
if (gml_hierarchy.layout_object() != nullptr)
|
||||
TRY(necessary_includes.try_set(TRY(include_path_for(gml_hierarchy.layout_object()->name(), gml_file_name))));
|
||||
|
||||
|
@ -126,6 +127,22 @@ static char const header[] = R"~~~(
|
|||
|
||||
)~~~";
|
||||
|
||||
static char const class_declaration[] = R"~~~(
|
||||
// A barebones definition of @main_class_name@ used to emit the symbol try_create.
|
||||
// Requirements:
|
||||
// - Inherits from GUI::Widget (indirectly, is declared as 'class')
|
||||
// - Has a default ctor
|
||||
// - Has declared a compatible static ErrorOr<NonnullRefPtr<@pure_class_name@>> try_create().
|
||||
namespace @class_namespace@ {
|
||||
class @pure_class_name@ : public GUI::Widget {
|
||||
public:
|
||||
@pure_class_name@();
|
||||
static ErrorOr<NonnullRefPtr<@pure_class_name@>> try_create();
|
||||
};
|
||||
}
|
||||
|
||||
)~~~";
|
||||
|
||||
static char const function_start[] = R"~~~(
|
||||
// Creates a @main_class_name@ and initializes it.
|
||||
// This function was auto-generated by the GML compiler.
|
||||
|
@ -350,7 +367,7 @@ static ErrorOr<String> generate_cpp(NonnullRefPtr<GUI::GML::GMLFile> gml, Lexica
|
|||
generator.append(header);
|
||||
|
||||
auto& main_class = gml->main_class();
|
||||
auto necessary_includes = TRY(extract_necessary_includes(main_class, gml_file_name));
|
||||
auto necessary_includes = TRY(extract_necessary_includes(main_class, gml_file_name, true));
|
||||
static String const always_necessary_includes[] = {
|
||||
"<AK/Error.h>"_string,
|
||||
"<AK/JsonValue.h>"_string,
|
||||
|
@ -367,8 +384,24 @@ static ErrorOr<String> generate_cpp(NonnullRefPtr<GUI::GML::GMLFile> gml, Lexica
|
|||
for (auto const& include : necessary_includes)
|
||||
generator.appendln(TRY(String::formatted("#include {}", include)));
|
||||
|
||||
auto main_file_header = TRY(include_path_for(main_class.name(), gml_file_name));
|
||||
generator.appendln(TRY(String::formatted("#if __has_include({})", main_file_header)));
|
||||
generator.appendln(TRY(String::formatted("#include {}", main_file_header)));
|
||||
generator.appendln("#else");
|
||||
|
||||
// FIXME: Use a UTF-8 aware function once possible.
|
||||
auto ns_position = main_class.name().find_last("::"sv);
|
||||
auto ns = main_class.name().substring_view(0, ns_position.value_or(0));
|
||||
auto pure_class_name = main_class.name().substring_view(ns_position.map([](auto x) { return x + 2; }).value_or(0));
|
||||
|
||||
generator.set("class_namespace", ns);
|
||||
generator.set("pure_class_name", pure_class_name);
|
||||
generator.set("main_class_name", main_class.name());
|
||||
|
||||
generator.append(class_declaration);
|
||||
|
||||
generator.appendln("#endif // __has_include(...)");
|
||||
|
||||
generator.append(function_start);
|
||||
TRY(generate_loader_for_object(main_class, generator.fork(), "main_object"_string, 2, UseObjectConstructor::No));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue