1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:28:12 +00:00

AK: Remove fallible SourceGenerator::try_append()

And fall back to the infallible append().
This commit is contained in:
Andreas Kling 2023-08-21 16:39:43 +02:00
parent a1d694ccdc
commit 244516142a
9 changed files with 293 additions and 297 deletions

View file

@ -65,12 +65,12 @@ public:
StringView as_string_view() const { return m_builder.string_view(); } StringView as_string_view() const { return m_builder.string_view(); }
ErrorOr<void> try_append(StringView pattern) void append(StringView pattern)
{ {
GenericLexer lexer { pattern }; GenericLexer lexer { pattern };
while (!lexer.is_eof()) { while (!lexer.is_eof()) {
TRY(m_builder.try_append(lexer.consume_until(m_opening))); m_builder.append(lexer.consume_until(m_opening));
if (lexer.consume_specific(m_opening)) { if (lexer.consume_specific(m_opening)) {
auto const placeholder = lexer.consume_until(m_closing); auto const placeholder = lexer.consume_until(m_closing);
@ -78,12 +78,11 @@ public:
if (!lexer.consume_specific(m_closing)) if (!lexer.consume_specific(m_closing))
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
TRY(m_builder.try_append(get(placeholder))); m_builder.append(get(placeholder));
} else { } else {
VERIFY(lexer.is_eof()); VERIFY(lexer.is_eof());
} }
} }
return {};
} }
void appendln(StringView pattern) void appendln(StringView pattern)
@ -105,9 +104,9 @@ public:
} }
template<size_t N> template<size_t N>
ErrorOr<void> try_append(char const (&pattern)[N]) void append(char const (&pattern)[N])
{ {
return try_append(StringView { pattern, N - 1 }); append(StringView { pattern, N - 1 });
} }
template<size_t N> template<size_t N>
@ -126,9 +125,6 @@ public:
{ {
set(StringView { key, N - 1 }, value); set(StringView { key, N - 1 }, value);
} }
void append(StringView pattern) { MUST(try_append(pattern)); }
template<size_t N>
void append(char const (&pattern)[N]) { MUST(try_append(pattern)); }
private: private:
StringBuilder& m_builder; StringBuilder& m_builder;

View file

@ -44,7 +44,7 @@ ErrorOr<void> generate_header_file(JsonObject& easing_data, Core::File& file)
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/Optional.h> #include <AK/Optional.h>
@ -53,7 +53,7 @@ ErrorOr<void> generate_header_file(JsonObject& easing_data, Core::File& file)
namespace Web::CSS { namespace Web::CSS {
)~~~")); )~~~");
generator.appendln("enum class EasingFunction {"); generator.appendln("enum class EasingFunction {");
TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
@ -67,7 +67,7 @@ namespace Web::CSS {
generator.appendln("Optional<EasingFunction> easing_function_from_string(StringView);"); generator.appendln("Optional<EasingFunction> easing_function_from_string(StringView);");
generator.appendln("StringView to_string(EasingFunction);"); generator.appendln("StringView to_string(EasingFunction);");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
enum class EasingFunctionParameterType { enum class EasingFunctionParameterType {
Integer, Integer,
Number, Number,
@ -84,7 +84,7 @@ struct EasingFunctionMetadata {
Vector<EasingFunctionParameter> parameters; Vector<EasingFunctionParameter> parameters;
}; };
EasingFunctionMetadata easing_function_metadata(EasingFunction); EasingFunctionMetadata easing_function_metadata(EasingFunction);
)~~~")); )~~~");
generator.appendln("\n}"); generator.appendln("\n}");
@ -97,68 +97,68 @@ ErrorOr<void> generate_implementation_file(JsonObject& easing_data, Core::File&
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <LibWeb/CSS/EasingFunctions.h> #include <LibWeb/CSS/EasingFunctions.h>
#include <AK/Assertions.h> #include <AK/Assertions.h>
namespace Web::CSS { namespace Web::CSS {
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
Optional<EasingFunction> easing_function_from_string(StringView name) Optional<EasingFunction> easing_function_from_string(StringView name)
{ {
)~~~")); )~~~");
TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (name.equals_ignoring_ascii_case("@name@"sv)) if (name.equals_ignoring_ascii_case("@name@"sv))
return EasingFunction::@name:titlecase@; return EasingFunction::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return {}; return {};
} }
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
StringView to_string(EasingFunction easing_function) StringView to_string(EasingFunction easing_function)
{ {
switch (easing_function) { switch (easing_function) {
)~~~")); )~~~");
TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(easing_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case EasingFunction::@name:titlecase@: case EasingFunction::@name:titlecase@:
return "@name@"sv; return "@name@"sv;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
EasingFunctionMetadata easing_function_metadata(EasingFunction easing_function) EasingFunctionMetadata easing_function_metadata(EasingFunction easing_function)
{ {
switch (easing_function) { switch (easing_function) {
)~~~")); )~~~");
TRY(easing_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(easing_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case EasingFunction::@name:titlecase@: case EasingFunction::@name:titlecase@:
return EasingFunctionMetadata { return EasingFunctionMetadata {
.parameters = {)~~~")); .parameters = {)~~~");
if (auto parameters = value.as_object().get_array("parameters"sv); parameters.has_value()) { if (auto parameters = value.as_object().get_array("parameters"sv); parameters.has_value()) {
bool first = true; bool first = true;
@ -189,28 +189,28 @@ EasingFunctionMetadata easing_function_metadata(EasingFunction easing_function)
else else
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
TRY(member_generator.try_append(first ? " "sv : ", "sv)); member_generator.append(first ? " "sv : ", "sv);
first = false; first = false;
TRY(member_generator.try_append(TRY(String::formatted( member_generator.append(TRY(String::formatted(
"{{ EasingFunctionParameterType::{}, {} }}", "{{ EasingFunctionParameterType::{}, {} }}",
parameter_type, parameter_type,
is_optional ? "true"sv : "false"sv)))); is_optional ? "true"sv : "false"sv)));
return {}; return {};
})); }));
} }
TRY(member_generator.try_append(R"~~~( } member_generator.append(R"~~~( }
}; };
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
generator.appendln("\n}"); generator.appendln("\n}");

View file

@ -43,7 +43,7 @@ ErrorOr<void> generate_header_file(JsonObject& enums_data, Core::File& file)
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/Optional.h> #include <AK/Optional.h>
@ -52,7 +52,7 @@ namespace Web::CSS {
enum class ValueID; enum class ValueID;
)~~~")); )~~~");
TRY(enums_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(enums_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_array()); VERIFY(value.is_array());
@ -90,7 +90,7 @@ enum class ValueID;
enum_generator.appendln("Optional<@name:titlecase@> value_id_to_@name:snakecase@(ValueID);"); enum_generator.appendln("Optional<@name:titlecase@> value_id_to_@name:snakecase@(ValueID);");
enum_generator.appendln("ValueID to_value_id(@name:titlecase@);"); enum_generator.appendln("ValueID to_value_id(@name:titlecase@);");
enum_generator.appendln("StringView to_string(@name:titlecase@);"); enum_generator.appendln("StringView to_string(@name:titlecase@);");
TRY(enum_generator.try_append("\n")); enum_generator.append("\n");
return {}; return {};
})); }));
@ -105,12 +105,12 @@ ErrorOr<void> generate_implementation_file(JsonObject& enums_data, Core::File& f
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <LibWeb/CSS/Enums.h> #include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/ValueID.h> #include <LibWeb/CSS/ValueID.h>
namespace Web::CSS { namespace Web::CSS {
)~~~")); )~~~");
TRY(enums_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(enums_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_array()); VERIFY(value.is_array());
@ -120,10 +120,10 @@ namespace Web::CSS {
enum_generator.set("name:titlecase", TRY(title_casify(name))); enum_generator.set("name:titlecase", TRY(title_casify(name)));
enum_generator.set("name:snakecase", TRY(snake_casify(name))); enum_generator.set("name:snakecase", TRY(snake_casify(name)));
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
Optional<@name:titlecase@> value_id_to_@name:snakecase@(ValueID value_id) Optional<@name:titlecase@> value_id_to_@name:snakecase@(ValueID value_id)
{ {
switch (value_id) {)~~~")); switch (value_id) {)~~~");
for (auto& member : members.values()) { for (auto& member : members.values()) {
auto member_generator = TRY(enum_generator.fork()); auto member_generator = TRY(enum_generator.fork());
@ -136,22 +136,22 @@ Optional<@name:titlecase@> value_id_to_@name:snakecase@(ValueID value_id)
member_generator.set("valueid:titlecase", TRY(title_casify(member_name))); member_generator.set("valueid:titlecase", TRY(title_casify(member_name)));
member_generator.set("member:titlecase", TRY(title_casify(member_name))); member_generator.set("member:titlecase", TRY(title_casify(member_name)));
} }
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case ValueID::@valueid:titlecase@: case ValueID::@valueid:titlecase@:
return @name:titlecase@::@member:titlecase@;)~~~")); return @name:titlecase@::@member:titlecase@;)~~~");
} }
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
default: default:
return {}; return {};
} }
} }
)~~~")); )~~~");
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
ValueID to_value_id(@name:titlecase@ @name:snakecase@_value) ValueID to_value_id(@name:titlecase@ @name:snakecase@_value)
{ {
switch (@name:snakecase@_value) {)~~~")); switch (@name:snakecase@_value) {)~~~");
for (auto& member : members.values()) { for (auto& member : members.values()) {
auto member_generator = TRY(enum_generator.fork()); auto member_generator = TRY(enum_generator.fork());
@ -160,22 +160,22 @@ ValueID to_value_id(@name:titlecase@ @name:snakecase@_value)
continue; continue;
member_generator.set("member:titlecase", TRY(title_casify(member_name))); member_generator.set("member:titlecase", TRY(title_casify(member_name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case @name:titlecase@::@member:titlecase@: case @name:titlecase@::@member:titlecase@:
return ValueID::@member:titlecase@;)~~~")); return ValueID::@member:titlecase@;)~~~");
} }
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
StringView to_string(@name:titlecase@ value) StringView to_string(@name:titlecase@ value)
{ {
switch (value) {)~~~")); switch (value) {)~~~");
for (auto& member : members.values()) { for (auto& member : members.values()) {
auto member_generator = TRY(enum_generator.fork()); auto member_generator = TRY(enum_generator.fork());
@ -185,17 +185,17 @@ StringView to_string(@name:titlecase@ value)
member_generator.set("member:css", TRY(String::from_deprecated_string(member_name))); member_generator.set("member:css", TRY(String::from_deprecated_string(member_name)));
member_generator.set("member:titlecase", TRY(title_casify(member_name))); member_generator.set("member:titlecase", TRY(title_casify(member_name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case @name:titlecase@::@member:titlecase@: case @name:titlecase@::@member:titlecase@:
return "@member:css@"sv;)~~~")); return "@member:css@"sv;)~~~");
} }
TRY(enum_generator.try_append(R"~~~( enum_generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
return {}; return {};
})); }));

View file

@ -43,7 +43,7 @@ ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file)
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
// This file is generated by GenerateCSSMathFunctions.cpp // This file is generated by GenerateCSSMathFunctions.cpp
#pragma once #pragma once
@ -51,7 +51,7 @@ ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file)
namespace Web::CSS { namespace Web::CSS {
enum class MathFunction { enum class MathFunction {
)~~~")); )~~~");
TRY(functions_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(functions_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
@ -60,11 +60,11 @@ enum class MathFunction {
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};
@ -77,7 +77,7 @@ ErrorOr<String> generate_calculation_type_check(StringView calculation_variable_
bool first_type_check = true; bool first_type_check = true;
for (auto const& allowed_type_name : allowed_types) { for (auto const& allowed_type_name : allowed_types) {
if (!first_type_check) if (!first_type_check)
TRY(builder.try_append(" || "sv)); builder.append(" || "sv);
first_type_check = false; first_type_check = false;
if (allowed_type_name == "<angle>"sv) { if (allowed_type_name == "<angle>"sv) {
@ -111,7 +111,7 @@ ErrorOr<void> generate_implementation_file(JsonObject& functions_data, Core::Fil
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
// This file is generated by GenerateCSSMathFunctions.cpp // This file is generated by GenerateCSSMathFunctions.cpp
#include <AK/Debug.h> #include <AK/Debug.h>
@ -148,7 +148,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
{ {
TokenStream stream { function.values() }; TokenStream stream { function.values() };
auto arguments = parse_a_comma_separated_list_of_component_values(stream); auto arguments = parse_a_comma_separated_list_of_component_values(stream);
)~~~")); )~~~");
TRY(functions_data.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> { TRY(functions_data.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> {
auto& function_data = value.as_object(); auto& function_data = value.as_object();
@ -160,7 +160,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
function_generator.appendln(" if (function.name().equals_ignoring_ascii_case(\"@name:lowercase@\"sv)) {"); function_generator.appendln(" if (function.name().equals_ignoring_ascii_case(\"@name:lowercase@\"sv)) {");
if (function_data.get_bool("is-variadic"sv).value_or(false)) { if (function_data.get_bool("is-variadic"sv).value_or(false)) {
// Variadic function // Variadic function
TRY(function_generator.try_append(R"~~~( function_generator.append(R"~~~(
CSSNumericType determined_argument_type; CSSNumericType determined_argument_type;
Vector<NonnullOwnPtr<CalculationNode>> parsed_arguments; Vector<NonnullOwnPtr<CalculationNode>> parsed_arguments;
parsed_arguments.ensure_capacity(arguments.size()); parsed_arguments.ensure_capacity(arguments.size());
@ -179,13 +179,13 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
} }
auto argument_type = maybe_argument_type.release_value(); auto argument_type = maybe_argument_type.release_value();
)~~~")); )~~~");
// Generate some type checks // Generate some type checks
VERIFY(parameters.size() == 1); VERIFY(parameters.size() == 1);
auto& parameter_data = parameters[0].as_object(); auto& parameter_data = parameters[0].as_object();
auto parameter_type_string = parameter_data.get_deprecated_string("type"sv).value(); auto parameter_type_string = parameter_data.get_deprecated_string("type"sv).value();
function_generator.set("type_check", TRY(generate_calculation_type_check("argument_type"sv, parameter_type_string))); function_generator.set("type_check", TRY(generate_calculation_type_check("argument_type"sv, parameter_type_string)));
TRY(function_generator.try_append(R"~~~( function_generator.append(R"~~~(
if (!(@type_check@)) { if (!(@type_check@)) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument #{} type ({}) is not an accepted type", parsed_arguments.size(), MUST(argument_type.dump())); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument #{} type ({}) is not an accepted type", parsed_arguments.size(), MUST(argument_type.dump()));
return nullptr; return nullptr;
@ -205,7 +205,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
return @name:titlecase@CalculationNode::create(move(parsed_arguments)); return @name:titlecase@CalculationNode::create(move(parsed_arguments));
} }
)~~~")); )~~~");
} else { } else {
// Function with specified parameters. // Function with specified parameters.
@ -219,14 +219,14 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
function_generator.set("min_argument_count", TRY(String::number(min_argument_count))); function_generator.set("min_argument_count", TRY(String::number(min_argument_count)));
function_generator.set("max_argument_count", TRY(String::number(max_argument_count))); function_generator.set("max_argument_count", TRY(String::number(max_argument_count)));
TRY(function_generator.try_append(R"~~~( function_generator.append(R"~~~(
if (arguments.size() < @min_argument_count@ || arguments.size() > @max_argument_count@) { if (arguments.size() < @min_argument_count@ || arguments.size() > @max_argument_count@) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() has wrong number of arguments {}, expected between @min_argument_count@ and @max_argument_count@ inclusive", arguments.size()); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() has wrong number of arguments {}, expected between @min_argument_count@ and @max_argument_count@ inclusive", arguments.size());
return nullptr; return nullptr;
} }
size_t argument_index = 0; size_t argument_index = 0;
[[maybe_unused]] CSSNumericType previous_argument_type; [[maybe_unused]] CSSNumericType previous_argument_type;
)~~~")); )~~~");
size_t parameter_index = 0; size_t parameter_index = 0;
StringView previous_parameter_type_string; StringView previous_parameter_type_string;
@ -268,45 +268,45 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
} }
} }
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
@parameter_type@ parameter_@parameter_index@@parameter_default@; @parameter_type@ parameter_@parameter_index@@parameter_default@;
)~~~")); )~~~");
if (parameter_required) { if (parameter_required) {
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
if (argument_index >= arguments.size()) { if (argument_index >= arguments.size()) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() missing required argument '@parameter_name@'"); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() missing required argument '@parameter_name@'");
return nullptr; return nullptr;
} else { } else {
)~~~")); )~~~");
} else { } else {
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
if (argument_index < arguments.size()) { if (argument_index < arguments.size()) {
)~~~")); )~~~");
} }
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
auto maybe_parsed_argument_@parameter_index@ = @parse_function@; auto maybe_parsed_argument_@parameter_index@ = @parse_function@;
if (maybe_parsed_argument_@parameter_index@@check_function@) { if (maybe_parsed_argument_@parameter_index@@check_function@) {
parameter_@parameter_index@ = maybe_parsed_argument_@parameter_index@@release_function@; parameter_@parameter_index@ = maybe_parsed_argument_@parameter_index@@release_function@;
argument_index++; argument_index++;
)~~~")); )~~~");
if (parameter_required) { if (parameter_required) {
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
} else { } else {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() required argument '@parameter_name@' failed to parse"); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() required argument '@parameter_name@' failed to parse");
return nullptr; return nullptr;
)~~~")); )~~~");
} }
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
} }
} }
)~~~")); )~~~");
if (parameter_is_calculation) { if (parameter_is_calculation) {
auto parameter_type_variable = TRY(String::formatted("argument_type_{}", parameter_index)); auto parameter_type_variable = TRY(String::formatted("argument_type_{}", parameter_index));
parameter_generator.set("type_check", TRY(generate_calculation_type_check(parameter_type_variable, parameter_type_string))); parameter_generator.set("type_check", TRY(generate_calculation_type_check(parameter_type_variable, parameter_type_string)));
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
auto maybe_argument_type_@parameter_index@ = parameter_@parameter_index@->determine_type(property_id); auto maybe_argument_type_@parameter_index@ = parameter_@parameter_index@->determine_type(property_id);
if (!maybe_argument_type_@parameter_index@.has_value()) { if (!maybe_argument_type_@parameter_index@.has_value()) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' couldn't determine its type"); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' couldn't determine its type");
@ -318,21 +318,21 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' type ({}) is not an accepted type", MUST(argument_type_@parameter_index@.dump())); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' type ({}) is not an accepted type", MUST(argument_type_@parameter_index@.dump()));
return nullptr; return nullptr;
} }
)~~~")); )~~~");
// NOTE: In all current cases, the parameters that take the same types must resolve to the same CSSNumericType. // NOTE: In all current cases, the parameters that take the same types must resolve to the same CSSNumericType.
// This is a bit of a hack, but serves our needs for now. // This is a bit of a hack, but serves our needs for now.
if (previous_parameter_type_string == parameter_type_string) { if (previous_parameter_type_string == parameter_type_string) {
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
if (argument_type_@parameter_index@ != previous_argument_type) { if (argument_type_@parameter_index@ != previous_argument_type) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' type ({}) doesn't match type of previous arguments ({})", MUST(argument_type_@parameter_index@.dump()), MUST(previous_argument_type.dump())); dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument '@parameter_name@' type ({}) doesn't match type of previous arguments ({})", MUST(argument_type_@parameter_index@.dump()), MUST(previous_argument_type.dump()));
return nullptr; return nullptr;
} }
)~~~")); )~~~");
} }
TRY(parameter_generator.try_append(R"~~~( parameter_generator.append(R"~~~(
previous_argument_type = argument_type_@parameter_index@; previous_argument_type = argument_type_@parameter_index@;
)~~~")); )~~~");
} }
parameter_index++; parameter_index++;
@ -341,7 +341,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
})); }));
// Generate the call to the constructor // Generate the call to the constructor
TRY(function_generator.try_append(" return @name:titlecase@CalculationNode::create("sv)); function_generator.append(" return @name:titlecase@CalculationNode::create("sv);
parameter_index = 0; parameter_index = 0;
TRY(parameters.try_for_each([&](JsonValue const& parameter_value) -> ErrorOr<void> { TRY(parameters.try_for_each([&](JsonValue const& parameter_value) -> ErrorOr<void> {
auto& parameter = parameter_value.as_object(); auto& parameter = parameter_value.as_object();
@ -358,26 +358,26 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
} }
if (parameter_index == 0) { if (parameter_index == 0) {
TRY(parameter_generator.try_append("parameter_@parameter_index@@release_value@"sv)); parameter_generator.append("parameter_@parameter_index@@release_value@"sv);
} else { } else {
TRY(parameter_generator.try_append(", parameter_@parameter_index@@release_value@"sv)); parameter_generator.append(", parameter_@parameter_index@@release_value@"sv);
} }
parameter_index++; parameter_index++;
return {}; return {};
})); }));
TRY(function_generator.try_append(R"~~~(); function_generator.append(R"~~~();
} }
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return nullptr; return nullptr;
} }
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};

View file

@ -42,7 +42,7 @@ ErrorOr<void> generate_header_file(JsonObject& media_feature_data, Core::File& f
{ {
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~(#pragma once generator.append(R"~~~(#pragma once
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/Traits.h> #include <AK/Traits.h>
@ -58,17 +58,17 @@ enum class MediaFeatureValueType {
Resolution, Resolution,
}; };
enum class MediaFeatureID {)~~~")); enum class MediaFeatureID {)~~~");
TRY(media_feature_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(media_feature_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
@name:titlecase@,)~~~")); @name:titlecase@,)~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
Optional<MediaFeatureID> media_feature_id_from_string(StringView); Optional<MediaFeatureID> media_feature_id_from_string(StringView);
@ -79,7 +79,7 @@ bool media_feature_accepts_type(MediaFeatureID, MediaFeatureValueType);
bool media_feature_accepts_identifier(MediaFeatureID, ValueID); bool media_feature_accepts_identifier(MediaFeatureID, ValueID);
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};
@ -89,23 +89,23 @@ ErrorOr<void> generate_implementation_file(JsonObject& media_feature_data, Core:
{ {
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <LibWeb/CSS/MediaFeatureID.h> #include <LibWeb/CSS/MediaFeatureID.h>
#include <LibWeb/Infra/Strings.h> #include <LibWeb/Infra/Strings.h>
namespace Web::CSS { namespace Web::CSS {
Optional<MediaFeatureID> media_feature_id_from_string(StringView string) Optional<MediaFeatureID> media_feature_id_from_string(StringView string)
{)~~~")); {)~~~");
TRY(media_feature_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(media_feature_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (Infra::is_ascii_case_insensitive_match(string, "@name@"sv)) if (Infra::is_ascii_case_insensitive_match(string, "@name@"sv))
return MediaFeatureID::@name:titlecase@; return MediaFeatureID::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
@ -121,20 +121,20 @@ StringView string_from_media_feature_id(MediaFeatureID media_feature_id)
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureID::@name:titlecase@: case MediaFeatureID::@name:titlecase@:
return "@name@"sv;)~~~")); return "@name@"sv;)~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
bool media_feature_type_is_range(MediaFeatureID media_feature_id) bool media_feature_type_is_range(MediaFeatureID media_feature_id)
{ {
switch (media_feature_id) {)~~~")); switch (media_feature_id) {)~~~");
TRY(media_feature_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(media_feature_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -146,20 +146,20 @@ bool media_feature_type_is_range(MediaFeatureID media_feature_id)
auto feature_type = feature.get_deprecated_string("type"sv); auto feature_type = feature.get_deprecated_string("type"sv);
VERIFY(feature_type.has_value()); VERIFY(feature_type.has_value());
member_generator.set("is_range", feature_type.value() == "range" ? "true"_string : "false"_string); member_generator.set("is_range", feature_type.value() == "range" ? "true"_string : "false"_string);
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureID::@name:titlecase@: case MediaFeatureID::@name:titlecase@:
return @is_range@;)~~~")); return @is_range@;)~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureValueType value_type) bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureValueType value_type)
{ {
switch (media_feature_id) {)~~~")); switch (media_feature_id) {)~~~");
TRY(media_feature_data.try_for_each_member([&](auto& name, auto& member) -> ErrorOr<void> { TRY(media_feature_data.try_for_each_member([&](auto& name, auto& member) -> ErrorOr<void> {
VERIFY(member.is_object()); VERIFY(member.is_object());
@ -167,15 +167,15 @@ bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureVal
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureID::@name:titlecase@:)~~~")); case MediaFeatureID::@name:titlecase@:)~~~");
bool have_output_value_type_switch = false; bool have_output_value_type_switch = false;
if (feature.has("values"sv)) { if (feature.has("values"sv)) {
auto append_value_type_switch_if_needed = [&]() -> ErrorOr<void> { auto append_value_type_switch_if_needed = [&]() -> ErrorOr<void> {
if (!have_output_value_type_switch) { if (!have_output_value_type_switch) {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
switch (value_type) {)~~~")); switch (value_type) {)~~~");
} }
have_output_value_type_switch = true; have_output_value_type_switch = true;
return {}; return {};
@ -191,29 +191,29 @@ bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureVal
continue; continue;
if (type_name == "<mq-boolean>") { if (type_name == "<mq-boolean>") {
TRY(append_value_type_switch_if_needed()); TRY(append_value_type_switch_if_needed());
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureValueType::Boolean: case MediaFeatureValueType::Boolean:
return true;)~~~")); return true;)~~~");
} else if (type_name == "<integer>") { } else if (type_name == "<integer>") {
TRY(append_value_type_switch_if_needed()); TRY(append_value_type_switch_if_needed());
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureValueType::Integer: case MediaFeatureValueType::Integer:
return true;)~~~")); return true;)~~~");
} else if (type_name == "<length>") { } else if (type_name == "<length>") {
TRY(append_value_type_switch_if_needed()); TRY(append_value_type_switch_if_needed());
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureValueType::Length: case MediaFeatureValueType::Length:
return true;)~~~")); return true;)~~~");
} else if (type_name == "<ratio>") { } else if (type_name == "<ratio>") {
TRY(append_value_type_switch_if_needed()); TRY(append_value_type_switch_if_needed());
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureValueType::Ratio: case MediaFeatureValueType::Ratio:
return true;)~~~")); return true;)~~~");
} else if (type_name == "<resolution>") { } else if (type_name == "<resolution>") {
TRY(append_value_type_switch_if_needed()); TRY(append_value_type_switch_if_needed());
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureValueType::Resolution: case MediaFeatureValueType::Resolution:
return true;)~~~")); return true;)~~~");
} else { } else {
warnln("Unrecognized media-feature value type: `{}`", type_name); warnln("Unrecognized media-feature value type: `{}`", type_name);
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
@ -221,25 +221,25 @@ bool media_feature_accepts_type(MediaFeatureID media_feature_id, MediaFeatureVal
} }
} }
if (have_output_value_type_switch) { if (have_output_value_type_switch) {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
default: default:
return false; return false;
})~~~")); })~~~");
} else { } else {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
return false;)~~~")); return false;)~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
bool media_feature_accepts_identifier(MediaFeatureID media_feature_id, ValueID identifier) bool media_feature_accepts_identifier(MediaFeatureID media_feature_id, ValueID identifier)
{ {
switch (media_feature_id) {)~~~")); switch (media_feature_id) {)~~~");
TRY(media_feature_data.try_for_each_member([&](auto& name, auto& member) -> ErrorOr<void> { TRY(media_feature_data.try_for_each_member([&](auto& name, auto& member) -> ErrorOr<void> {
VERIFY(member.is_object()); VERIFY(member.is_object());
@ -247,15 +247,15 @@ bool media_feature_accepts_identifier(MediaFeatureID media_feature_id, ValueID i
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case MediaFeatureID::@name:titlecase@:)~~~")); case MediaFeatureID::@name:titlecase@:)~~~");
bool have_output_identifier_switch = false; bool have_output_identifier_switch = false;
if (feature.has("values"sv)) { if (feature.has("values"sv)) {
auto append_identifier_switch_if_needed = [&]() -> ErrorOr<void> { auto append_identifier_switch_if_needed = [&]() -> ErrorOr<void> {
if (!have_output_identifier_switch) { if (!have_output_identifier_switch) {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
switch (identifier) {)~~~")); switch (identifier) {)~~~");
} }
have_output_identifier_switch = true; have_output_identifier_switch = true;
return {}; return {};
@ -273,30 +273,30 @@ bool media_feature_accepts_identifier(MediaFeatureID media_feature_id, ValueID i
auto ident_generator = TRY(member_generator.fork()); auto ident_generator = TRY(member_generator.fork());
ident_generator.set("identifier:titlecase", TRY(title_casify(identifier_name))); ident_generator.set("identifier:titlecase", TRY(title_casify(identifier_name)));
TRY(ident_generator.try_append(R"~~~( ident_generator.append(R"~~~(
case ValueID::@identifier:titlecase@: case ValueID::@identifier:titlecase@:
return true;)~~~")); return true;)~~~");
} }
} }
if (have_output_identifier_switch) { if (have_output_identifier_switch) {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
default: default:
return false; return false;
})~~~")); })~~~");
} else { } else {
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
return false;)~~~")); return false;)~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};

View file

@ -91,7 +91,7 @@ ErrorOr<void> generate_header_file(JsonObject& properties, Core::File& file)
{ {
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/NonnullRefPtr.h> #include <AK/NonnullRefPtr.h>
@ -106,7 +106,7 @@ enum class PropertyID {
Invalid, Invalid,
Custom, Custom,
All, All,
)~~~")); )~~~");
Vector<DeprecatedString> shorthand_property_ids; Vector<DeprecatedString> shorthand_property_ids;
Vector<DeprecatedString> longhand_property_ids; Vector<DeprecatedString> longhand_property_ids;
@ -126,18 +126,18 @@ enum class PropertyID {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
@name:titlecase@, @name:titlecase@,
)~~~")); )~~~");
} }
for (auto& name : longhand_property_ids) { for (auto& name : longhand_property_ids) {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
@name:titlecase@, @name:titlecase@,
)~~~")); )~~~");
} }
generator.set("first_property_id", TRY(title_casify(first_property_id))); generator.set("first_property_id", TRY(title_casify(first_property_id)));
@ -149,7 +149,7 @@ enum class PropertyID {
generator.set("first_longhand_property_id", TRY(title_casify(longhand_property_ids.first()))); generator.set("first_longhand_property_id", TRY(title_casify(longhand_property_ids.first())));
generator.set("last_longhand_property_id", TRY(title_casify(longhand_property_ids.last()))); generator.set("last_longhand_property_id", TRY(title_casify(longhand_property_ids.last())));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
Optional<PropertyID> property_id_from_camel_case_string(StringView); Optional<PropertyID> property_id_from_camel_case_string(StringView);
@ -223,7 +223,7 @@ struct Traits<Web::CSS::PropertyID> : public GenericTraits<Web::CSS::PropertyID>
static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); } static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); }
}; };
} // namespace AK } // namespace AK
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};
@ -235,11 +235,11 @@ ErrorOr<void> generate_bounds_checking_function(JsonObject& properties, SourceGe
generator.set("css_type_name", TRY(String::from_utf8(css_type_name))); generator.set("css_type_name", TRY(String::from_utf8(css_type_name)));
generator.set("type_name", TRY(String::from_utf8(type_name))); generator.set("type_name", TRY(String::from_utf8(type_name)));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @type_name@ const& value) bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @type_name@ const& value)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -252,9 +252,9 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
auto property_generator = TRY(generator.fork()); auto property_generator = TRY(generator.fork());
property_generator.set("property_name:titlecase", TRY(title_casify(name))); property_generator.set("property_name:titlecase", TRY(title_casify(name)));
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@property_name:titlecase@: case PropertyID::@property_name:titlecase@:
return )~~~")); return )~~~");
if (type_and_range.size() > 1) { if (type_and_range.size() > 1) {
auto range = type_and_range[1]; auto range = type_and_range[1];
@ -279,7 +279,7 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
property_generator.set("value_number", TRY(String::from_utf8(value_string))); property_generator.set("value_number", TRY(String::from_utf8(value_string)));
property_generator.set("value_getter", TRY(String::from_utf8(value_getter.value()))); property_generator.set("value_getter", TRY(String::from_utf8(value_getter.value())));
property_generator.set("comparator", TRY(String::from_utf8(comparator))); property_generator.set("comparator", TRY(String::from_utf8(comparator)));
TRY(property_generator.try_append("@value_getter@ @comparator@ @value_number@")); property_generator.append("@value_getter@ @comparator@ @value_number@");
return {}; return {};
} }
@ -292,14 +292,14 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
property_generator.set("value_number", TRY(String::from_utf8(value_number))); property_generator.set("value_number", TRY(String::from_utf8(value_number)));
property_generator.set("value_unit", TRY(title_casify(value_unit))); property_generator.set("value_unit", TRY(title_casify(value_unit)));
property_generator.set("comparator", TRY(String::from_utf8(comparator))); property_generator.set("comparator", TRY(String::from_utf8(comparator)));
TRY(property_generator.try_append("value @comparator@ @type_name@(@value_number@, @type_name@::Type::@value_unit@)")); property_generator.append("value @comparator@ @type_name@(@value_number@, @type_name@::Type::@value_unit@)");
return {}; return {};
}; };
if (!min_value_string.is_empty()) if (!min_value_string.is_empty())
TRY(output_check(min_value_string, ">="sv)); TRY(output_check(min_value_string, ">="sv));
if (!min_value_string.is_empty() && !max_value_string.is_empty()) if (!min_value_string.is_empty() && !max_value_string.is_empty())
TRY(property_generator.try_append(" && ")); property_generator.append(" && ");
if (!max_value_string.is_empty()) if (!max_value_string.is_empty())
TRY(output_check(max_value_string, "<="sv)); TRY(output_check(max_value_string, "<="sv));
property_generator.appendln(";"); property_generator.appendln(";");
@ -312,12 +312,12 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return false; return false;
} }
} }
)~~~")); )~~~");
return {}; return {};
} }
@ -326,7 +326,7 @@ ErrorOr<void> generate_implementation_file(JsonObject& properties, Core::File& f
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <LibWeb/CSS/Enums.h> #include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/Parser/Parser.h>
@ -340,7 +340,7 @@ namespace Web::CSS {
Optional<PropertyID> property_id_from_camel_case_string(StringView string) Optional<PropertyID> property_id_from_camel_case_string(StringView string)
{ {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -349,14 +349,14 @@ Optional<PropertyID> property_id_from_camel_case_string(StringView string)
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
member_generator.set("name:camelcase", TRY(camel_casify(name))); member_generator.set("name:camelcase", TRY(camel_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (string.equals_ignoring_ascii_case("@name:camelcase@"sv)) if (string.equals_ignoring_ascii_case("@name:camelcase@"sv))
return PropertyID::@name:titlecase@; return PropertyID::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return {}; return {};
} }
@ -364,7 +364,7 @@ Optional<PropertyID> property_id_from_string(StringView string)
{ {
if (Infra::is_ascii_case_insensitive_match(string, "all"sv)) if (Infra::is_ascii_case_insensitive_match(string, "all"sv))
return PropertyID::All; return PropertyID::All;
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -372,20 +372,20 @@ Optional<PropertyID> property_id_from_string(StringView string)
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (Infra::is_ascii_case_insensitive_match(string, "@name@"sv)) if (Infra::is_ascii_case_insensitive_match(string, "@name@"sv))
return PropertyID::@name:titlecase@; return PropertyID::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return {}; return {};
} }
StringView string_from_property_id(PropertyID property_id) { StringView string_from_property_id(PropertyID property_id) {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -393,14 +393,14 @@ StringView string_from_property_id(PropertyID property_id) {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
return "@name@"sv; return "@name@"sv;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return "(invalid CSS::PropertyID)"sv; return "(invalid CSS::PropertyID)"sv;
} }
@ -409,7 +409,7 @@ StringView string_from_property_id(PropertyID property_id) {
bool is_inherited_property(PropertyID property_id) bool is_inherited_property(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -424,15 +424,15 @@ bool is_inherited_property(PropertyID property_id)
if (inherited) { if (inherited) {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
return true; return true;
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return false; return false;
} }
@ -441,7 +441,7 @@ bool is_inherited_property(PropertyID property_id)
bool property_affects_layout(PropertyID property_id) bool property_affects_layout(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -453,14 +453,14 @@ bool property_affects_layout(PropertyID property_id)
if (affects_layout) { if (affects_layout) {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return true; return true;
default: default:
return false; return false;
@ -470,7 +470,7 @@ bool property_affects_layout(PropertyID property_id)
bool property_affects_stacking_context(PropertyID property_id) bool property_affects_stacking_context(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -482,14 +482,14 @@ bool property_affects_stacking_context(PropertyID property_id)
if (affects_stacking_context) { if (affects_stacking_context) {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return true; return true;
default: default:
return false; return false;
@ -508,7 +508,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
Parser::ParsingContext parsing_context(context_realm); Parser::ParsingContext parsing_context(context_realm);
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
auto output_initial_value_code = [&](auto& name, auto& object) -> ErrorOr<void> { auto output_initial_value_code = [&](auto& name, auto& object) -> ErrorOr<void> {
if (!object.has("initial"sv)) { if (!object.has("initial"sv)) {
@ -522,7 +522,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
member_generator.set("initial_value_string", TRY(String::from_deprecated_string(initial_value_string))); member_generator.set("initial_value_string", TRY(String::from_deprecated_string(initial_value_string)));
TRY(member_generator.try_append( member_generator.append(
R"~~~( case PropertyID::@name:titlecase@: R"~~~( case PropertyID::@name:titlecase@:
{ {
auto parsed_value = parse_css_value(parsing_context, "@initial_value_string@"sv, PropertyID::@name:titlecase@); auto parsed_value = parse_css_value(parsing_context, "@initial_value_string@"sv, PropertyID::@name:titlecase@);
@ -531,7 +531,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
initial_values[to_underlying(PropertyID::@name:titlecase@)] = initial_value; initial_values[to_underlying(PropertyID::@name:titlecase@)] = initial_value;
return initial_value; return initial_value;
} }
)~~~")); )~~~");
return {}; return {};
}; };
@ -541,7 +541,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
return {}; return {};
})); }));
TRY(generator.try_append( generator.append(
R"~~~( default: VERIFY_NOT_REACHED(); R"~~~( default: VERIFY_NOT_REACHED();
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
@ -550,7 +550,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
bool property_has_quirk(PropertyID property_id, Quirk quirk) bool property_has_quirk(PropertyID property_id, Quirk quirk)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -562,31 +562,31 @@ bool property_has_quirk(PropertyID property_id, Quirk quirk)
if (!quirks.is_empty()) { if (!quirks.is_empty()) {
auto property_generator = TRY(generator.fork()); auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name))); property_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: { case PropertyID::@name:titlecase@: {
switch (quirk) { switch (quirk) {
)~~~")); )~~~");
for (auto& quirk : quirks.values()) { for (auto& quirk : quirks.values()) {
VERIFY(quirk.is_string()); VERIFY(quirk.is_string());
auto quirk_generator = TRY(property_generator.fork()); auto quirk_generator = TRY(property_generator.fork());
quirk_generator.set("quirk:titlecase", TRY(title_casify(quirk.as_string()))); quirk_generator.set("quirk:titlecase", TRY(title_casify(quirk.as_string())));
TRY(quirk_generator.try_append(R"~~~( quirk_generator.append(R"~~~(
case Quirk::@quirk:titlecase@: case Quirk::@quirk:titlecase@:
return true; return true;
)~~~")); )~~~");
} }
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
default: default:
return false; return false;
} }
} }
)~~~")); )~~~");
} }
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return false; return false;
} }
@ -595,7 +595,7 @@ bool property_has_quirk(PropertyID property_id, Quirk quirk)
bool property_accepts_type(PropertyID property_id, ValueType value_type) bool property_accepts_type(PropertyID property_id, ValueType value_type)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
auto& object = value.as_object(); auto& object = value.as_object();
@ -603,10 +603,10 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type)
auto& valid_types = maybe_valid_types.value(); auto& valid_types = maybe_valid_types.value();
auto property_generator = TRY(generator.fork()); auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name))); property_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: { case PropertyID::@name:titlecase@: {
switch (value_type) { switch (value_type) {
)~~~")); )~~~");
bool did_output_accepted_type = false; bool did_output_accepted_type = false;
for (auto& type : valid_types.values()) { for (auto& type : valid_types.values()) {
@ -658,16 +658,16 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type)
if (did_output_accepted_type) if (did_output_accepted_type)
property_generator.appendln(" return true;"); property_generator.appendln(" return true;");
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
default: default:
return false; return false;
} }
} }
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return false; return false;
} }
@ -676,7 +676,7 @@ bool property_accepts_type(PropertyID property_id, ValueType value_type)
bool property_accepts_identifier(PropertyID property_id, ValueID identifier) bool property_accepts_identifier(PropertyID property_id, ValueID identifier)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
auto& object = value.as_object(); auto& object = value.as_object();
@ -693,12 +693,12 @@ bool property_accepts_identifier(PropertyID property_id, ValueID identifier)
identifier_generator.set("identifier:titlecase", TRY(title_casify(identifier.as_string()))); identifier_generator.set("identifier:titlecase", TRY(title_casify(identifier.as_string())));
identifier_generator.appendln(" case ValueID::@identifier:titlecase@:"); identifier_generator.appendln(" case ValueID::@identifier:titlecase@:");
} }
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
return true; return true;
default: default:
break; break;
} }
)~~~")); )~~~");
} }
if (auto maybe_valid_types = object.get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) { if (auto maybe_valid_types = object.get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) {
@ -710,19 +710,19 @@ bool property_accepts_identifier(PropertyID property_id, ValueID identifier)
auto type_generator = TRY(generator.fork()); auto type_generator = TRY(generator.fork());
type_generator.set("type_name:snakecase", TRY(snake_casify(type_name))); type_generator.set("type_name:snakecase", TRY(snake_casify(type_name)));
TRY(type_generator.try_append(R"~~~( type_generator.append(R"~~~(
if (value_id_to_@type_name:snakecase@(identifier).has_value()) if (value_id_to_@type_name:snakecase@(identifier).has_value())
return true; return true;
)~~~")); )~~~");
} }
} }
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
return false; return false;
} }
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return false; return false;
} }
@ -731,7 +731,7 @@ bool property_accepts_identifier(PropertyID property_id, ValueID identifier)
Optional<ValueType> property_resolves_percentages_relative_to(PropertyID property_id) Optional<ValueType> property_resolves_percentages_relative_to(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -739,15 +739,15 @@ Optional<ValueType> property_resolves_percentages_relative_to(PropertyID propert
auto property_generator = TRY(generator.fork()); auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name))); property_generator.set("name:titlecase", TRY(title_casify(name)));
property_generator.set("resolved_type:titlecase", TRY(title_casify(resolved_type.value()))); property_generator.set("resolved_type:titlecase", TRY(title_casify(resolved_type.value())));
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
return ValueType::@resolved_type:titlecase@; return ValueType::@resolved_type:titlecase@;
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return {}; return {};
} }
@ -756,7 +756,7 @@ Optional<ValueType> property_resolves_percentages_relative_to(PropertyID propert
size_t property_maximum_value_count(PropertyID property_id) size_t property_maximum_value_count(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
@ -766,19 +766,19 @@ size_t property_maximum_value_count(PropertyID property_id)
auto property_generator = TRY(generator.fork()); auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name))); property_generator.set("name:titlecase", TRY(title_casify(name)));
property_generator.set("max_values", TRY(String::from_deprecated_string(max_values->to_deprecated_string()))); property_generator.set("max_values", TRY(String::from_deprecated_string(max_values->to_deprecated_string())));
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
return @max_values@; return @max_values@;
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return 1; return 1;
} }
})~~~")); })~~~");
TRY(generate_bounds_checking_function(properties, generator, "angle"sv, "Angle"sv, "Deg"sv)); TRY(generate_bounds_checking_function(properties, generator, "angle"sv, "Angle"sv, "Deg"sv));
TRY(generate_bounds_checking_function(properties, generator, "frequency"sv, "Frequency"sv, "Hertz"sv)); TRY(generate_bounds_checking_function(properties, generator, "frequency"sv, "Frequency"sv, "Hertz"sv));
@ -789,11 +789,11 @@ size_t property_maximum_value_count(PropertyID property_id)
TRY(generate_bounds_checking_function(properties, generator, "resolution"sv, "Resolution"sv, "Dpi"sv)); TRY(generate_bounds_checking_function(properties, generator, "resolution"sv, "Resolution"sv, "Dpi"sv));
TRY(generate_bounds_checking_function(properties, generator, "time"sv, "Time"sv, "S"sv)); TRY(generate_bounds_checking_function(properties, generator, "time"sv, "Time"sv, "S"sv));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
Vector<PropertyID> longhands_for_shorthand(PropertyID property_id) Vector<PropertyID> longhands_for_shorthand(PropertyID property_id)
{ {
switch (property_id) { switch (property_id) {
)~~~")); )~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
if (value.as_object().has("longhands"sv)) { if (value.as_object().has("longhands"sv)) {
auto longhands = value.as_object().get("longhands"sv); auto longhands = value.as_object().get("longhands"sv);
@ -807,30 +807,30 @@ Vector<PropertyID> longhands_for_shorthand(PropertyID property_id)
if (first) if (first)
first = false; first = false;
else else
TRY(builder.try_append(", "sv)); builder.append(", "sv);
TRY(builder.try_appendff("PropertyID::{}", TRY(title_casify(longhand.to_deprecated_string())))); TRY(builder.try_appendff("PropertyID::{}", TRY(title_casify(longhand.to_deprecated_string()))));
return IterationDecision::Continue; return IterationDecision::Continue;
})); }));
property_generator.set("longhands", builder.to_deprecated_string()); property_generator.set("longhands", builder.to_deprecated_string());
TRY(property_generator.try_append(R"~~~( property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: case PropertyID::@name:titlecase@:
return { @longhands@ }; return { @longhands@ };
)~~~")); )~~~");
} }
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return { }; return { };
} }
} }
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} // namespace Web::CSS } // namespace Web::CSS
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};

View file

@ -42,7 +42,7 @@ ErrorOr<void> generate_header_file(JsonObject& pseudo_classes_data, Core::File&
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/Optional.h> #include <AK/Optional.h>
@ -51,7 +51,7 @@ ErrorOr<void> generate_header_file(JsonObject& pseudo_classes_data, Core::File&
namespace Web::CSS { namespace Web::CSS {
enum class PseudoClass { enum class PseudoClass {
)~~~")); )~~~");
TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
@ -60,7 +60,7 @@ enum class PseudoClass {
member_generator.appendln(" @name:titlecase@,"); member_generator.appendln(" @name:titlecase@,");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
Optional<PseudoClass> pseudo_class_from_string(StringView); Optional<PseudoClass> pseudo_class_from_string(StringView);
@ -83,7 +83,7 @@ struct PseudoClassMetadata {
PseudoClassMetadata pseudo_class_metadata(PseudoClass); PseudoClassMetadata pseudo_class_metadata(PseudoClass);
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};
@ -94,28 +94,28 @@ ErrorOr<void> generate_implementation_file(JsonObject& pseudo_classes_data, Core
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <LibWeb/CSS/PseudoClass.h> #include <LibWeb/CSS/PseudoClass.h>
namespace Web::CSS { namespace Web::CSS {
Optional<PseudoClass> pseudo_class_from_string(StringView string) Optional<PseudoClass> pseudo_class_from_string(StringView string)
{ {
)~~~")); )~~~");
TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (string.equals_ignoring_ascii_case("@name@"sv)) if (string.equals_ignoring_ascii_case("@name@"sv))
return PseudoClass::@name:titlecase@; return PseudoClass::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return {}; return {};
} }
@ -123,21 +123,21 @@ Optional<PseudoClass> pseudo_class_from_string(StringView string)
StringView pseudo_class_name(PseudoClass pseudo_class) StringView pseudo_class_name(PseudoClass pseudo_class)
{ {
switch (pseudo_class) { switch (pseudo_class) {
)~~~")); )~~~");
TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(pseudo_classes_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name))); member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PseudoClass::@name:titlecase@: case PseudoClass::@name:titlecase@:
return "@name@"sv; return "@name@"sv;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -145,7 +145,7 @@ StringView pseudo_class_name(PseudoClass pseudo_class)
PseudoClassMetadata pseudo_class_metadata(PseudoClass pseudo_class) PseudoClassMetadata pseudo_class_metadata(PseudoClass pseudo_class)
{ {
switch (pseudo_class) { switch (pseudo_class) {
)~~~")); )~~~");
TRY(pseudo_classes_data.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> { TRY(pseudo_classes_data.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
@ -187,24 +187,24 @@ PseudoClassMetadata pseudo_class_metadata(PseudoClass pseudo_class)
member_generator.set("is_valid_as_function", is_valid_as_function ? "true"_string : "false"_string); member_generator.set("is_valid_as_function", is_valid_as_function ? "true"_string : "false"_string);
member_generator.set("is_valid_as_identifier", is_valid_as_identifier ? "true"_string : "false"_string); member_generator.set("is_valid_as_identifier", is_valid_as_identifier ? "true"_string : "false"_string);
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case PseudoClass::@name:titlecase@: case PseudoClass::@name:titlecase@:
return { return {
.parameter_type = PseudoClassMetadata::ParameterType::@parameter_type@, .parameter_type = PseudoClassMetadata::ParameterType::@parameter_type@,
.is_valid_as_function = @is_valid_as_function@, .is_valid_as_function = @is_valid_as_function@,
.is_valid_as_identifier = @is_valid_as_identifier@, .is_valid_as_identifier = @is_valid_as_identifier@,
}; };
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};

View file

@ -53,7 +53,7 @@ ErrorOr<void> generate_header_file(JsonObject& transforms_data, Core::File& file
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/Optional.h> #include <AK/Optional.h>
@ -62,7 +62,7 @@ ErrorOr<void> generate_header_file(JsonObject& transforms_data, Core::File& file
namespace Web::CSS { namespace Web::CSS {
)~~~")); )~~~");
generator.appendln("enum class TransformFunction {"); generator.appendln("enum class TransformFunction {");
TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
@ -76,7 +76,7 @@ namespace Web::CSS {
generator.appendln("Optional<TransformFunction> transform_function_from_string(StringView);"); generator.appendln("Optional<TransformFunction> transform_function_from_string(StringView);");
generator.appendln("StringView to_string(TransformFunction);"); generator.appendln("StringView to_string(TransformFunction);");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
enum class TransformFunctionParameterType { enum class TransformFunctionParameterType {
Angle, Angle,
Length, Length,
@ -93,7 +93,7 @@ struct TransformFunctionMetadata {
Vector<TransformFunctionParameter> parameters; Vector<TransformFunctionParameter> parameters;
}; };
TransformFunctionMetadata transform_function_metadata(TransformFunction); TransformFunctionMetadata transform_function_metadata(TransformFunction);
)~~~")); )~~~");
generator.appendln("\n}"); generator.appendln("\n}");
@ -106,68 +106,68 @@ ErrorOr<void> generate_implementation_file(JsonObject& transforms_data, Core::Fi
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <LibWeb/CSS/TransformFunctions.h> #include <LibWeb/CSS/TransformFunctions.h>
#include <AK/Assertions.h> #include <AK/Assertions.h>
namespace Web::CSS { namespace Web::CSS {
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
Optional<TransformFunction> transform_function_from_string(StringView name) Optional<TransformFunction> transform_function_from_string(StringView name)
{ {
)~~~")); )~~~");
TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify_transform_function(name))); member_generator.set("name:titlecase", TRY(title_casify_transform_function(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
if (name.equals_ignoring_ascii_case("@name@"sv)) if (name.equals_ignoring_ascii_case("@name@"sv))
return TransformFunction::@name:titlecase@; return TransformFunction::@name:titlecase@;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
return {}; return {};
} }
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
StringView to_string(TransformFunction transform_function) StringView to_string(TransformFunction transform_function)
{ {
switch (transform_function) { switch (transform_function) {
)~~~")); )~~~");
TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> { TRY(transforms_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name))); member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify_transform_function(name))); member_generator.set("name:titlecase", TRY(title_casify_transform_function(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case TransformFunction::@name:titlecase@: case TransformFunction::@name:titlecase@:
return "@name@"sv; return "@name@"sv;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
TransformFunctionMetadata transform_function_metadata(TransformFunction transform_function) TransformFunctionMetadata transform_function_metadata(TransformFunction transform_function)
{ {
switch (transform_function) { switch (transform_function) {
)~~~")); )~~~");
TRY(transforms_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> { TRY(transforms_data.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object()); VERIFY(value.is_object());
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify_transform_function(name))); member_generator.set("name:titlecase", TRY(title_casify_transform_function(name)));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case TransformFunction::@name:titlecase@: case TransformFunction::@name:titlecase@:
return TransformFunctionMetadata { return TransformFunctionMetadata {
.parameters = {)~~~")); .parameters = {)~~~");
JsonArray const& parameters = value.as_object().get_array("parameters"sv).value(); JsonArray const& parameters = value.as_object().get_array("parameters"sv).value();
bool first = true; bool first = true;
@ -189,24 +189,24 @@ TransformFunctionMetadata transform_function_metadata(TransformFunction transfor
else else
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
TRY(member_generator.try_append(first ? " "sv : ", "sv)); member_generator.append(first ? " "sv : ", "sv);
first = false; first = false;
TRY(member_generator.try_append(TRY(String::formatted("{{ TransformFunctionParameterType::{}, {}}}", parameter_type, value.as_object().get("required"sv)->to_deprecated_string())))); member_generator.append(TRY(String::formatted("{{ TransformFunctionParameterType::{}, {}}}", parameter_type, value.as_object().get("required"sv)->to_deprecated_string())));
return {}; return {};
})); }));
TRY(member_generator.try_append(R"~~~( } member_generator.append(R"~~~( }
}; };
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
)~~~")); )~~~");
generator.appendln("\n}"); generator.appendln("\n}");

View file

@ -43,7 +43,7 @@ ErrorOr<void> generate_header_file(JsonArray& identifier_data, Core::File& file)
{ {
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#pragma once #pragma once
#include <AK/StringView.h> #include <AK/StringView.h>
@ -53,19 +53,19 @@ namespace Web::CSS {
enum class ValueID { enum class ValueID {
Invalid, Invalid,
)~~~")); )~~~");
TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> { TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string()))); member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string())));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
@name:titlecase@, @name:titlecase@,
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
Optional<ValueID> value_id_from_string(StringView); Optional<ValueID> value_id_from_string(StringView);
@ -73,7 +73,7 @@ StringView string_from_value_id(ValueID);
} }
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};
@ -84,7 +84,7 @@ ErrorOr<void> generate_implementation_file(JsonArray& identifier_data, Core::Fil
StringBuilder builder; StringBuilder builder;
SourceGenerator generator { builder }; SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
#include <AK/Assertions.h> #include <AK/Assertions.h>
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <LibWeb/CSS/ValueID.h> #include <LibWeb/CSS/ValueID.h>
@ -92,19 +92,19 @@ ErrorOr<void> generate_implementation_file(JsonArray& identifier_data, Core::Fil
namespace Web::CSS { namespace Web::CSS {
HashMap<StringView, ValueID, AK::CaseInsensitiveASCIIStringViewTraits> g_stringview_to_value_id_map { HashMap<StringView, ValueID, AK::CaseInsensitiveASCIIStringViewTraits> g_stringview_to_value_id_map {
)~~~")); )~~~");
TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> { TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name.to_deprecated_string()))); member_generator.set("name", TRY(String::from_deprecated_string(name.to_deprecated_string())));
member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string()))); member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string())));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
{"@name@"sv, ValueID::@name:titlecase@}, {"@name@"sv, ValueID::@name:titlecase@},
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
}; };
Optional<ValueID> value_id_from_string(StringView string) Optional<ValueID> value_id_from_string(StringView string)
@ -114,27 +114,27 @@ Optional<ValueID> value_id_from_string(StringView string)
StringView string_from_value_id(ValueID value_id) { StringView string_from_value_id(ValueID value_id) {
switch (value_id) { switch (value_id) {
)~~~")); )~~~");
TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> { TRY(identifier_data.try_for_each([&](auto& name) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork()); auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name.to_deprecated_string()))); member_generator.set("name", TRY(String::from_deprecated_string(name.to_deprecated_string())));
member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string()))); member_generator.set("name:titlecase", TRY(title_casify(name.to_deprecated_string())));
TRY(member_generator.try_append(R"~~~( member_generator.append(R"~~~(
case ValueID::@name:titlecase@: case ValueID::@name:titlecase@:
return "@name@"sv; return "@name@"sv;
)~~~")); )~~~");
return {}; return {};
})); }));
TRY(generator.try_append(R"~~~( generator.append(R"~~~(
default: default:
return "(invalid CSS::ValueID)"sv; return "(invalid CSS::ValueID)"sv;
} }
} }
} // namespace Web::CSS } // namespace Web::CSS
)~~~")); )~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes())); TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {}; return {};