mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	Meta+LibWeb: Port PropertyID.h/cpp generators to invoke_generator()
This commit is contained in:
		
							parent
							
								
									fc81d6c9f3
								
							
						
					
					
						commit
						b07659d00c
					
				
					 4 changed files with 140 additions and 157 deletions
				
			
		|  | @ -1,8 +1,7 @@ | |||
| set(SOURCES "") # avoid pulling SOURCES from parent scope | ||||
| 
 | ||||
| lagom_tool(GenerateCSSMediaFeatureID       SOURCES GenerateCSSMediaFeatureID.cpp LIBS LagomMain) | ||||
| lagom_tool(Generate_CSS_PropertyID_h       SOURCES Generate_CSS_PropertyID_h.cpp LIBS LagomMain) | ||||
| lagom_tool(Generate_CSS_PropertyID_cpp     SOURCES Generate_CSS_PropertyID_cpp.cpp LIBS LagomMain) | ||||
| lagom_tool(GenerateCSSPropertyID           SOURCES GenerateCSSPropertyID.cpp LIBS LagomMain) | ||||
| lagom_tool(GenerateCSSValueID              SOURCES GenerateCSSValueID.cpp LIBS LagomMain) | ||||
| 
 | ||||
| add_subdirectory(WrapperGenerator) | ||||
|  |  | |||
|  | @ -6,23 +6,145 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "GeneratorUtil.h" | ||||
| #include <AK/Array.h> | ||||
| #include <AK/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibCore/ArgsParser.h> | ||||
| #include <LibMain/Main.h> | ||||
| 
 | ||||
| ErrorOr<void> generate_header_file(JsonObject& properties, Core::Stream::File& file); | ||||
| ErrorOr<void> generate_implementation_file(JsonObject& properties, Core::Stream::File& file); | ||||
| 
 | ||||
| ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||
| { | ||||
|     if (arguments.argc != 2) { | ||||
|         warnln("usage: {} <path/to/CSS/Properties.json>", arguments.strings[0]); | ||||
|         return 1; | ||||
|     StringView generated_header_path; | ||||
|     StringView generated_implementation_path; | ||||
|     StringView properties_json_path; | ||||
| 
 | ||||
|     Core::ArgsParser args_parser; | ||||
|     args_parser.add_option(generated_header_path, "Path to the PropertyID header file to generate", "generated-header-path", 'h', "generated-header-path"); | ||||
|     args_parser.add_option(generated_implementation_path, "Path to the PropertyID implementation file to generate", "generated-implementation-path", 'c', "generated-implementation-path"); | ||||
|     args_parser.add_option(properties_json_path, "Path to the JSON file to read from", "json-path", 'j', "json-path"); | ||||
|     args_parser.parse(arguments); | ||||
| 
 | ||||
|     auto json = TRY(read_entire_file_as_json(properties_json_path)); | ||||
|     VERIFY(json.is_object()); | ||||
|     auto properties = json.as_object(); | ||||
| 
 | ||||
|     auto generated_header_file = TRY(Core::Stream::File::open(generated_header_path, Core::Stream::OpenMode::Write)); | ||||
|     auto generated_implementation_file = TRY(Core::Stream::File::open(generated_implementation_path, Core::Stream::OpenMode::Write)); | ||||
| 
 | ||||
|     TRY(generate_header_file(properties, *generated_header_file)); | ||||
|     TRY(generate_implementation_file(properties, *generated_implementation_file)); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|     auto json = TRY(read_entire_file_as_json(arguments.strings[1])); | ||||
|     VERIFY(json.is_object()); | ||||
| ErrorOr<void> generate_header_file(JsonObject& properties, Core::Stream::File& file) | ||||
| { | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
|     generator.append(R"~~~( | ||||
| #pragma once | ||||
| 
 | ||||
|     auto& properties = json.as_object(); | ||||
| #include <AK/NonnullRefPtr.h> | ||||
| #include <AK/StringView.h> | ||||
| #include <AK/Traits.h> | ||||
| #include <LibWeb/Forward.h> | ||||
| 
 | ||||
| namespace Web::CSS { | ||||
| 
 | ||||
| enum class PropertyID { | ||||
|     Invalid, | ||||
|     Custom, | ||||
| )~~~"); | ||||
| 
 | ||||
|     Vector<String> shorthand_property_ids; | ||||
|     Vector<String> longhand_property_ids; | ||||
| 
 | ||||
|     properties.for_each_member([&](auto& name, auto& value) { | ||||
|         VERIFY(value.is_object()); | ||||
|         if (value.as_object().has("longhands")) | ||||
|             shorthand_property_ids.append(name); | ||||
|         else | ||||
|             longhand_property_ids.append(name); | ||||
|     }); | ||||
| 
 | ||||
|     auto first_property_id = shorthand_property_ids.first(); | ||||
|     auto last_property_id = longhand_property_ids.last(); | ||||
| 
 | ||||
|     for (auto& name : shorthand_property_ids) { | ||||
|         auto member_generator = generator.fork(); | ||||
|         member_generator.set("name:titlecase", title_casify(name)); | ||||
| 
 | ||||
|         member_generator.append(R"~~~( | ||||
|     @name:titlecase@, | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     for (auto& name : longhand_property_ids) { | ||||
|         auto member_generator = generator.fork(); | ||||
|         member_generator.set("name:titlecase", title_casify(name)); | ||||
| 
 | ||||
|         member_generator.append(R"~~~( | ||||
|     @name:titlecase@, | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     generator.set("first_property_id", title_casify(first_property_id)); | ||||
|     generator.set("last_property_id", title_casify(last_property_id)); | ||||
| 
 | ||||
|     generator.set("first_shorthand_property_id", title_casify(shorthand_property_ids.first())); | ||||
|     generator.set("last_shorthand_property_id", title_casify(shorthand_property_ids.last())); | ||||
| 
 | ||||
|     generator.set("first_longhand_property_id", title_casify(longhand_property_ids.first())); | ||||
|     generator.set("last_longhand_property_id", title_casify(longhand_property_ids.last())); | ||||
| 
 | ||||
|     generator.append(R"~~~( | ||||
| }; | ||||
| 
 | ||||
| PropertyID property_id_from_camel_case_string(StringView); | ||||
| PropertyID property_id_from_string(StringView); | ||||
| const char* string_from_property_id(PropertyID); | ||||
| bool is_inherited_property(PropertyID); | ||||
| NonnullRefPtr<StyleValue> property_initial_value(PropertyID); | ||||
| 
 | ||||
| bool property_accepts_value(PropertyID, StyleValue&); | ||||
| size_t property_maximum_value_count(PropertyID); | ||||
| 
 | ||||
| bool property_affects_layout(PropertyID); | ||||
| bool property_affects_stacking_context(PropertyID); | ||||
| 
 | ||||
| constexpr PropertyID first_property_id = PropertyID::@first_property_id@; | ||||
| constexpr PropertyID last_property_id = PropertyID::@last_property_id@; | ||||
| constexpr PropertyID first_shorthand_property_id = PropertyID::@first_shorthand_property_id@; | ||||
| constexpr PropertyID last_shorthand_property_id = PropertyID::@last_shorthand_property_id@; | ||||
| constexpr PropertyID first_longhand_property_id = PropertyID::@first_longhand_property_id@; | ||||
| constexpr PropertyID last_longhand_property_id = PropertyID::@last_longhand_property_id@; | ||||
| 
 | ||||
| enum class Quirk { | ||||
|     // https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
 | ||||
|     HashlessHexColor, | ||||
|     // https://quirks.spec.whatwg.org/#the-unitless-length-quirk
 | ||||
|     UnitlessLength, | ||||
| }; | ||||
| bool property_has_quirk(PropertyID, Quirk); | ||||
| 
 | ||||
| } // namespace Web::CSS
 | ||||
| 
 | ||||
| namespace AK { | ||||
| template<> | ||||
| struct Traits<Web::CSS::PropertyID> : public GenericTraits<Web::CSS::PropertyID> { | ||||
|     static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); } | ||||
| }; | ||||
| } // namespace AK
 | ||||
| )~~~"); | ||||
| 
 | ||||
|     TRY(file.write(generator.as_string_view().bytes())); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> generate_implementation_file(JsonObject& properties, Core::Stream::File& file) | ||||
| { | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
| 
 | ||||
|  | @ -465,6 +587,6 @@ size_t property_maximum_value_count(PropertyID property_id) | |||
| 
 | ||||
| )~~~"); | ||||
| 
 | ||||
|     outln("{}", generator.as_string_view()); | ||||
|     return 0; | ||||
|     TRY(file.write(generator.as_string_view().bytes())); | ||||
|     return {}; | ||||
| } | ||||
|  | @ -1,122 +0,0 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include "GeneratorUtil.h" | ||||
| #include <AK/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibMain/Main.h> | ||||
| 
 | ||||
| ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||
| { | ||||
|     if (arguments.argc != 2) { | ||||
|         warnln("usage: {} <path/to/CSS/Properties.json>", arguments.strings[0]); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     auto json = TRY(read_entire_file_as_json(arguments.strings[1])); | ||||
|     VERIFY(json.is_object()); | ||||
| 
 | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
|     generator.append(R"~~~( | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/NonnullRefPtr.h> | ||||
| #include <AK/StringView.h> | ||||
| #include <AK/Traits.h> | ||||
| #include <LibWeb/Forward.h> | ||||
| 
 | ||||
| namespace Web::CSS { | ||||
| 
 | ||||
| enum class PropertyID { | ||||
|     Invalid, | ||||
|     Custom, | ||||
| )~~~"); | ||||
| 
 | ||||
|     Vector<String> shorthand_property_ids; | ||||
|     Vector<String> longhand_property_ids; | ||||
| 
 | ||||
|     json.as_object().for_each_member([&](auto& name, auto& value) { | ||||
|         VERIFY(value.is_object()); | ||||
|         if (value.as_object().has("longhands")) | ||||
|             shorthand_property_ids.append(name); | ||||
|         else | ||||
|             longhand_property_ids.append(name); | ||||
|     }); | ||||
| 
 | ||||
|     auto first_property_id = shorthand_property_ids.first(); | ||||
|     auto last_property_id = longhand_property_ids.last(); | ||||
| 
 | ||||
|     for (auto& name : shorthand_property_ids) { | ||||
|         auto member_generator = generator.fork(); | ||||
|         member_generator.set("name:titlecase", title_casify(name)); | ||||
| 
 | ||||
|         member_generator.append(R"~~~( | ||||
|     @name:titlecase@, | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     for (auto& name : longhand_property_ids) { | ||||
|         auto member_generator = generator.fork(); | ||||
|         member_generator.set("name:titlecase", title_casify(name)); | ||||
| 
 | ||||
|         member_generator.append(R"~~~( | ||||
|     @name:titlecase@, | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     generator.set("first_property_id", title_casify(first_property_id)); | ||||
|     generator.set("last_property_id", title_casify(last_property_id)); | ||||
| 
 | ||||
|     generator.set("first_shorthand_property_id", title_casify(shorthand_property_ids.first())); | ||||
|     generator.set("last_shorthand_property_id", title_casify(shorthand_property_ids.last())); | ||||
| 
 | ||||
|     generator.set("first_longhand_property_id", title_casify(longhand_property_ids.first())); | ||||
|     generator.set("last_longhand_property_id", title_casify(longhand_property_ids.last())); | ||||
| 
 | ||||
|     generator.append(R"~~~( | ||||
| }; | ||||
| 
 | ||||
| PropertyID property_id_from_camel_case_string(StringView); | ||||
| PropertyID property_id_from_string(StringView); | ||||
| const char* string_from_property_id(PropertyID); | ||||
| bool is_inherited_property(PropertyID); | ||||
| NonnullRefPtr<StyleValue> property_initial_value(PropertyID); | ||||
| 
 | ||||
| bool property_accepts_value(PropertyID, StyleValue&); | ||||
| size_t property_maximum_value_count(PropertyID); | ||||
| 
 | ||||
| bool property_affects_layout(PropertyID); | ||||
| bool property_affects_stacking_context(PropertyID); | ||||
| 
 | ||||
| constexpr PropertyID first_property_id = PropertyID::@first_property_id@; | ||||
| constexpr PropertyID last_property_id = PropertyID::@last_property_id@; | ||||
| constexpr PropertyID first_shorthand_property_id = PropertyID::@first_shorthand_property_id@; | ||||
| constexpr PropertyID last_shorthand_property_id = PropertyID::@last_shorthand_property_id@; | ||||
| constexpr PropertyID first_longhand_property_id = PropertyID::@first_longhand_property_id@; | ||||
| constexpr PropertyID last_longhand_property_id = PropertyID::@last_longhand_property_id@; | ||||
| 
 | ||||
| enum class Quirk { | ||||
|     // https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
 | ||||
|     HashlessHexColor, | ||||
|     // https://quirks.spec.whatwg.org/#the-unitless-length-quirk
 | ||||
|     UnitlessLength, | ||||
| }; | ||||
| bool property_has_quirk(PropertyID, Quirk); | ||||
| 
 | ||||
| } // namespace Web::CSS
 | ||||
| 
 | ||||
| namespace AK { | ||||
| template<> | ||||
| struct Traits<Web::CSS::PropertyID> : public GenericTraits<Web::CSS::PropertyID> { | ||||
|     static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); } | ||||
| }; | ||||
| } // namespace AK
 | ||||
| )~~~"); | ||||
| 
 | ||||
|     outln("{}", generator.as_string_view()); | ||||
|     return 0; | ||||
| } | ||||
|  | @ -612,31 +612,15 @@ invoke_generator( | |||
|     arguments -j "${CMAKE_CURRENT_SOURCE_DIR}/CSS/MediaFeatures.json" | ||||
| ) | ||||
| 
 | ||||
| add_custom_command( | ||||
|     OUTPUT CSS/PropertyID.h | ||||
|     COMMAND ${CMAKE_COMMAND} -E make_directory CSS | ||||
|     COMMAND "$<TARGET_FILE:Lagom::Generate_CSS_PropertyID_h>" "${CMAKE_CURRENT_SOURCE_DIR}/CSS/Properties.json" > CSS/PropertyID.h.tmp | ||||
|     COMMAND "${CMAKE_COMMAND}" -E copy_if_different CSS/PropertyID.h.tmp CSS/PropertyID.h | ||||
|     COMMAND "${CMAKE_COMMAND}" -E remove CSS/PropertyID.h.tmp | ||||
|     VERBATIM | ||||
|     DEPENDS Lagom::Generate_CSS_PropertyID_h | ||||
|     MAIN_DEPENDENCY CSS/Properties.json | ||||
| invoke_generator( | ||||
|     "PropertyID" | ||||
|     Lagom::GenerateCSSPropertyID | ||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/CSS/Properties.json" | ||||
|     "" | ||||
|     "CSS/PropertyID.h" | ||||
|     "CSS/PropertyID.cpp" | ||||
|     arguments -j "${CMAKE_CURRENT_SOURCE_DIR}/CSS/Properties.json" | ||||
| ) | ||||
| add_custom_target(generate_PropertyID.h DEPENDS CSS/PropertyID.h) | ||||
| add_dependencies(all_generated generate_PropertyID.h) | ||||
| 
 | ||||
| add_custom_command( | ||||
|     OUTPUT CSS/PropertyID.cpp | ||||
|     COMMAND ${CMAKE_COMMAND} -E make_directory CSS | ||||
|     COMMAND "$<TARGET_FILE:Lagom::Generate_CSS_PropertyID_cpp>" "${CMAKE_CURRENT_SOURCE_DIR}/CSS/Properties.json" > CSS/PropertyID.cpp.tmp | ||||
|     COMMAND "${CMAKE_COMMAND}" -E copy_if_different CSS/PropertyID.cpp.tmp CSS/PropertyID.cpp | ||||
|     COMMAND "${CMAKE_COMMAND}" -E remove CSS/PropertyID.cpp.tmp | ||||
|     VERBATIM | ||||
|     DEPENDS Lagom::Generate_CSS_PropertyID_cpp | ||||
|     MAIN_DEPENDENCY CSS/Properties.json | ||||
| ) | ||||
| add_custom_target(generate_PropertyID.cpp DEPENDS CSS/PropertyID.cpp) | ||||
| add_dependencies(all_generated generate_PropertyID.cpp) | ||||
| 
 | ||||
| invoke_generator( | ||||
|     "ValueID" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Atkins
						Sam Atkins