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
Notes: sideshowbarker 2024-07-16 20:39:14 +09:00
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(); }
ErrorOr<void> try_append(StringView pattern)
void append(StringView pattern)
{
GenericLexer lexer { pattern };
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)) {
auto const placeholder = lexer.consume_until(m_closing);
@ -78,12 +78,11 @@ public:
if (!lexer.consume_specific(m_closing))
VERIFY_NOT_REACHED();
TRY(m_builder.try_append(get(placeholder)));
m_builder.append(get(placeholder));
} else {
VERIFY(lexer.is_eof());
}
}
return {};
}
void appendln(StringView pattern)
@ -105,9 +104,9 @@ public:
}
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>
@ -126,9 +125,6 @@ public:
{
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:
StringBuilder& m_builder;

View File

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

View File

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

View File

@ -43,7 +43,7 @@ ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file)
StringBuilder builder;
SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
// This file is generated by GenerateCSSMathFunctions.cpp
#pragma once
@ -51,7 +51,7 @@ ErrorOr<void> generate_header_file(JsonObject& functions_data, Core::File& file)
namespace Web::CSS {
enum class MathFunction {
)~~~"));
)~~~");
TRY(functions_data.try_for_each_member([&](auto& name, auto&) -> ErrorOr<void> {
auto member_generator = TRY(generator.fork());
@ -60,11 +60,11 @@ enum class MathFunction {
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
};
}
)~~~"));
)~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};
@ -77,7 +77,7 @@ ErrorOr<String> generate_calculation_type_check(StringView calculation_variable_
bool first_type_check = true;
for (auto const& allowed_type_name : allowed_types) {
if (!first_type_check)
TRY(builder.try_append(" || "sv));
builder.append(" || "sv);
first_type_check = false;
if (allowed_type_name == "<angle>"sv) {
@ -111,7 +111,7 @@ ErrorOr<void> generate_implementation_file(JsonObject& functions_data, Core::Fil
StringBuilder builder;
SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
// This file is generated by GenerateCSSMathFunctions.cpp
#include <AK/Debug.h>
@ -148,7 +148,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
{
TokenStream stream { function.values() };
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> {
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)) {");
if (function_data.get_bool("is-variadic"sv).value_or(false)) {
// Variadic function
TRY(function_generator.try_append(R"~~~(
function_generator.append(R"~~~(
CSSNumericType determined_argument_type;
Vector<NonnullOwnPtr<CalculationNode>> parsed_arguments;
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();
)~~~"));
)~~~");
// Generate some type checks
VERIFY(parameters.size() == 1);
auto& parameter_data = parameters[0].as_object();
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)));
TRY(function_generator.try_append(R"~~~(
function_generator.append(R"~~~(
if (!(@type_check@)) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() argument #{} type ({}) is not an accepted type", parsed_arguments.size(), MUST(argument_type.dump()));
return nullptr;
@ -205,7 +205,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
return @name:titlecase@CalculationNode::create(move(parsed_arguments));
}
)~~~"));
)~~~");
} else {
// 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("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@) {
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;
}
size_t argument_index = 0;
[[maybe_unused]] CSSNumericType previous_argument_type;
)~~~"));
)~~~");
size_t parameter_index = 0;
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@;
)~~~"));
)~~~");
if (parameter_required) {
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
if (argument_index >= arguments.size()) {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() missing required argument '@parameter_name@'");
return nullptr;
} else {
)~~~"));
)~~~");
} else {
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
if (argument_index < arguments.size()) {
)~~~"));
)~~~");
}
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
auto maybe_parsed_argument_@parameter_index@ = @parse_function@;
if (maybe_parsed_argument_@parameter_index@@check_function@) {
parameter_@parameter_index@ = maybe_parsed_argument_@parameter_index@@release_function@;
argument_index++;
)~~~"));
)~~~");
if (parameter_required) {
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
} else {
dbgln_if(CSS_PARSER_DEBUG, "@name:lowercase@() required argument '@parameter_name@' failed to parse");
return nullptr;
)~~~"));
)~~~");
}
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
}
}
)~~~"));
)~~~");
if (parameter_is_calculation) {
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)));
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
auto maybe_argument_type_@parameter_index@ = parameter_@parameter_index@->determine_type(property_id);
if (!maybe_argument_type_@parameter_index@.has_value()) {
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()));
return nullptr;
}
)~~~"));
)~~~");
// 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.
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) {
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;
}
)~~~"));
)~~~");
}
TRY(parameter_generator.try_append(R"~~~(
parameter_generator.append(R"~~~(
previous_argument_type = argument_type_@parameter_index@;
)~~~"));
)~~~");
}
parameter_index++;
@ -341,7 +341,7 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
}));
// 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;
TRY(parameters.try_for_each([&](JsonValue const& parameter_value) -> ErrorOr<void> {
auto& parameter = parameter_value.as_object();
@ -358,26 +358,26 @@ OwnPtr<CalculationNode> Parser::parse_math_function(PropertyID property_id, Func
}
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 {
TRY(parameter_generator.try_append(", parameter_@parameter_index@@release_value@"sv));
parameter_generator.append(", parameter_@parameter_index@@release_value@"sv);
}
parameter_index++;
return {};
}));
TRY(function_generator.try_append(R"~~~();
function_generator.append(R"~~~();
}
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
return nullptr;
}
}
)~~~"));
)~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};

View File

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

View File

@ -91,7 +91,7 @@ ErrorOr<void> generate_header_file(JsonObject& properties, Core::File& file)
{
StringBuilder builder;
SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
#pragma once
#include <AK/NonnullRefPtr.h>
@ -106,7 +106,7 @@ enum class PropertyID {
Invalid,
Custom,
All,
)~~~"));
)~~~");
Vector<DeprecatedString> shorthand_property_ids;
Vector<DeprecatedString> longhand_property_ids;
@ -126,18 +126,18 @@ enum class PropertyID {
auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
@name:titlecase@,
)~~~"));
)~~~");
}
for (auto& name : longhand_property_ids) {
auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
@name:titlecase@,
)~~~"));
)~~~");
}
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("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);
@ -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); }
};
} // namespace AK
)~~~"));
)~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
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("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)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, JsonValue const& value) -> ErrorOr<void> {
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());
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@:
return )~~~"));
return )~~~");
if (type_and_range.size() > 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_getter", TRY(String::from_utf8(value_getter.value())));
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 {};
}
@ -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_unit", TRY(title_casify(value_unit)));
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 {};
};
if (!min_value_string.is_empty())
TRY(output_check(min_value_string, ">="sv));
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())
TRY(output_check(max_value_string, "<="sv));
property_generator.appendln(";");
@ -312,12 +312,12 @@ bool property_accepts_@css_type_name@(PropertyID property_id, [[maybe_unused]] @
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return false;
}
}
)~~~"));
)~~~");
return {};
}
@ -326,7 +326,7 @@ ErrorOr<void> generate_implementation_file(JsonObject& properties, Core::File& f
StringBuilder builder;
SourceGenerator generator { builder };
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
#include <AK/Assertions.h>
#include <LibWeb/CSS/Enums.h>
#include <LibWeb/CSS/Parser/Parser.h>
@ -340,7 +340,7 @@ namespace Web::CSS {
Optional<PropertyID> property_id_from_camel_case_string(StringView string)
{
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
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:titlecase", TRY(title_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))
return PropertyID::@name:titlecase@;
)~~~"));
)~~~");
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
return {};
}
@ -364,7 +364,7 @@ Optional<PropertyID> property_id_from_string(StringView string)
{
if (Infra::is_ascii_case_insensitive_match(string, "all"sv))
return PropertyID::All;
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -372,20 +372,20 @@ Optional<PropertyID> property_id_from_string(StringView string)
auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(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))
return PropertyID::@name:titlecase@;
)~~~"));
)~~~");
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
return {};
}
StringView string_from_property_id(PropertyID property_id) {
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -393,14 +393,14 @@ StringView string_from_property_id(PropertyID property_id) {
auto member_generator = TRY(generator.fork());
member_generator.set("name", TRY(String::from_deprecated_string(name)));
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
return "@name@"sv;
)~~~"));
)~~~");
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return "(invalid CSS::PropertyID)"sv;
}
@ -409,7 +409,7 @@ StringView string_from_property_id(PropertyID property_id) {
bool is_inherited_property(PropertyID property_id)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -424,15 +424,15 @@ bool is_inherited_property(PropertyID property_id)
if (inherited) {
auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
return true;
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return false;
}
@ -441,7 +441,7 @@ bool is_inherited_property(PropertyID property_id)
bool property_affects_layout(PropertyID property_id)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -453,14 +453,14 @@ bool property_affects_layout(PropertyID property_id)
if (affects_layout) {
auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
return true;
default:
return false;
@ -470,7 +470,7 @@ bool property_affects_layout(PropertyID property_id)
bool property_affects_stacking_context(PropertyID property_id)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -482,14 +482,14 @@ bool property_affects_stacking_context(PropertyID property_id)
if (affects_stacking_context) {
auto member_generator = TRY(generator.fork());
member_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(member_generator.try_append(R"~~~(
member_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
return true;
default:
return false;
@ -508,7 +508,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
Parser::ParsingContext parsing_context(context_realm);
switch (property_id) {
)~~~"));
)~~~");
auto output_initial_value_code = [&](auto& name, auto& object) -> ErrorOr<void> {
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());
member_generator.set("name:titlecase", TRY(title_casify(name)));
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@:
{
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;
return initial_value;
}
)~~~"));
)~~~");
return {};
};
@ -541,7 +541,7 @@ NonnullRefPtr<StyleValue> property_initial_value(JS::Realm& context_realm, Prope
return {};
}));
TRY(generator.try_append(
generator.append(
R"~~~( default: 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)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -562,31 +562,31 @@ bool property_has_quirk(PropertyID property_id, Quirk quirk)
if (!quirks.is_empty()) {
auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: {
switch (quirk) {
)~~~"));
)~~~");
for (auto& quirk : quirks.values()) {
VERIFY(quirk.is_string());
auto quirk_generator = TRY(property_generator.fork());
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@:
return true;
)~~~"));
)~~~");
}
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
default:
return false;
}
}
)~~~"));
)~~~");
}
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
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)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_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 property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name)));
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
case PropertyID::@name:titlecase@: {
switch (value_type) {
)~~~"));
)~~~");
bool did_output_accepted_type = false;
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)
property_generator.appendln(" return true;");
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
default:
return false;
}
}
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
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)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_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.appendln(" case ValueID::@identifier:titlecase@:");
}
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
return true;
default:
break;
}
)~~~"));
)~~~");
}
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());
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())
return true;
)~~~"));
)~~~");
}
}
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
return false;
}
)~~~"));
)~~~");
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
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)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -739,15 +739,15 @@ Optional<ValueType> property_resolves_percentages_relative_to(PropertyID propert
auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name)));
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@:
return ValueType::@resolved_type:titlecase@;
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return {};
}
@ -756,7 +756,7 @@ Optional<ValueType> property_resolves_percentages_relative_to(PropertyID propert
size_t property_maximum_value_count(PropertyID property_id)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
VERIFY(value.is_object());
@ -766,19 +766,19 @@ size_t property_maximum_value_count(PropertyID property_id)
auto property_generator = TRY(generator.fork());
property_generator.set("name:titlecase", TRY(title_casify(name)));
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@:
return @max_values@;
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return 1;
}
})~~~"));
})~~~");
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));
@ -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, "time"sv, "Time"sv, "S"sv));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
Vector<PropertyID> longhands_for_shorthand(PropertyID property_id)
{
switch (property_id) {
)~~~"));
)~~~");
TRY(properties.try_for_each_member([&](auto& name, auto& value) -> ErrorOr<void> {
if (value.as_object().has("longhands"sv)) {
auto longhands = value.as_object().get("longhands"sv);
@ -807,30 +807,30 @@ Vector<PropertyID> longhands_for_shorthand(PropertyID property_id)
if (first)
first = false;
else
TRY(builder.try_append(", "sv));
builder.append(", "sv);
TRY(builder.try_appendff("PropertyID::{}", TRY(title_casify(longhand.to_deprecated_string()))));
return IterationDecision::Continue;
}));
property_generator.set("longhands", builder.to_deprecated_string());
TRY(property_generator.try_append(R"~~~(
property_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
return { @longhands@ };
)~~~"));
)~~~");
}
return {};
}));
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
default:
return { };
}
}
)~~~"));
)~~~");
TRY(generator.try_append(R"~~~(
generator.append(R"~~~(
} // namespace Web::CSS
)~~~"));
)~~~");
TRY(file.write_until_depleted(generator.as_string_view().bytes()));
return {};

View File

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

View File

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

View File

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