Serenity Operating System
at master 139 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include "GeneratorUtil.h" 9#include <AK/SourceGenerator.h> 10#include <AK/StringBuilder.h> 11#include <LibCore/ArgsParser.h> 12#include <LibMain/Main.h> 13 14ErrorOr<void> generate_header_file(JsonArray& identifier_data, Core::File& file); 15ErrorOr<void> generate_implementation_file(JsonArray& identifier_data, Core::File& file); 16 17ErrorOr<int> serenity_main(Main::Arguments arguments) 18{ 19 StringView generated_header_path; 20 StringView generated_implementation_path; 21 StringView identifiers_json_path; 22 23 Core::ArgsParser args_parser; 24 args_parser.add_option(generated_header_path, "Path to the ValueID header file to generate", "generated-header-path", 'h', "generated-header-path"); 25 args_parser.add_option(generated_implementation_path, "Path to the ValueID implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path"); 26 args_parser.add_option(identifiers_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path"); 27 args_parser.parse(arguments); 28 29 auto json = TRY(read_entire_file_as_json(identifiers_json_path)); 30 VERIFY(json.is_array()); 31 auto identifier_data = json.as_array(); 32 33 auto generated_header_file = TRY(Core::File::open(generated_header_path, Core::File::OpenMode::Write)); 34 auto generated_implementation_file = TRY(Core::File::open(generated_implementation_path, Core::File::OpenMode::Write)); 35 36 TRY(generate_header_file(identifier_data, *generated_header_file)); 37 TRY(generate_implementation_file(identifier_data, *generated_implementation_file)); 38 39 return 0; 40} 41 42ErrorOr<void> generate_header_file(JsonArray& identifier_data, Core::File& file) 43{ 44 StringBuilder builder; 45 SourceGenerator generator { builder }; 46 generator.append(R"~~~( 47#pragma once 48 49#include <AK/StringView.h> 50#include <AK/Traits.h> 51 52namespace Web::CSS { 53 54enum class ValueID { 55 Invalid, 56)~~~"); 57 58 identifier_data.for_each([&](auto& name) { 59 auto member_generator = generator.fork(); 60 member_generator.set("name:titlecase", title_casify(name.to_deprecated_string())); 61 62 member_generator.append(R"~~~( 63 @name:titlecase@, 64)~~~"); 65 }); 66 67 generator.append(R"~~~( 68}; 69 70ValueID value_id_from_string(StringView); 71StringView string_from_value_id(ValueID); 72 73} 74 75)~~~"); 76 77 TRY(file.write_until_depleted(generator.as_string_view().bytes())); 78 return {}; 79} 80 81ErrorOr<void> generate_implementation_file(JsonArray& identifier_data, Core::File& file) 82{ 83 StringBuilder builder; 84 SourceGenerator generator { builder }; 85 86 generator.append(R"~~~( 87#include <AK/Assertions.h> 88#include <AK/HashMap.h> 89#include <LibWeb/CSS/ValueID.h> 90 91namespace Web::CSS { 92 93HashMap<StringView, ValueID, AK::CaseInsensitiveStringViewTraits> g_stringview_to_value_id_map { 94)~~~"); 95 96 identifier_data.for_each([&](auto& name) { 97 auto member_generator = generator.fork(); 98 member_generator.set("name", name.to_deprecated_string()); 99 member_generator.set("name:titlecase", title_casify(name.to_deprecated_string())); 100 member_generator.append(R"~~~( 101 {"@name@"sv, ValueID::@name:titlecase@}, 102)~~~"); 103 }); 104 105 generator.append(R"~~~( 106}; 107 108ValueID value_id_from_string(StringView string) 109{ 110 auto maybe_value_id = g_stringview_to_value_id_map.get(string); 111 return maybe_value_id.value_or(ValueID::Invalid); 112} 113 114StringView string_from_value_id(ValueID value_id) { 115 switch (value_id) { 116)~~~"); 117 118 identifier_data.for_each([&](auto& name) { 119 auto member_generator = generator.fork(); 120 member_generator.set("name", name.to_deprecated_string()); 121 member_generator.set("name:titlecase", title_casify(name.to_deprecated_string())); 122 member_generator.append(R"~~~( 123 case ValueID::@name:titlecase@: 124 return "@name@"sv; 125 )~~~"); 126 }); 127 128 generator.append(R"~~~( 129 default: 130 return "(invalid CSS::ValueID)"sv; 131 } 132} 133 134} // namespace Web::CSS 135)~~~"); 136 137 TRY(file.write_until_depleted(generator.as_string_view().bytes())); 138 return {}; 139}