ladybird/Libraries/LibWeb/CSS/Parser/ErrorReporter.cpp
Andreas Kling 164ed80244 Meta: Enable exit-time destructor warnings for libraries
Enable -Wexit-time-destructors for all in-tree library targets and
update process-lifetime library statics so they no longer register
exit-time destructors. Long-lived caches, lookup tables, singleton
registries, and generated constants now use NeverDestroyed or leaked
references where the data is intended to live until process exit.

Update LibWeb, LibLine, and the binding generators so regenerated
sources follow the same rule instead of reintroducing destructed
statics.
2026-06-04 19:20:49 +02:00

76 lines
3 KiB
C++

/*
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/HashTable.h>
#include <LibWeb/CSS/Parser/ErrorReporter.h>
namespace Web::CSS::Parser {
String serialize_parsing_error(ParsingError const& error)
{
return error.visit(
[](UnknownPropertyError const& error) {
return MUST(String::formatted("Unknown property '{}' in {} rule.", error.property_name, error.rule_name));
},
[](UnknownRuleError const& error) {
return MUST(String::formatted("Unknown rule '{}'.", error.rule_name));
},
[](UnknownMediaFeatureError const& error) {
return MUST(String::formatted("Unknown media feature '{}'.", error.media_feature_name));
},
[](UnknownPseudoClassOrElementError const& error) {
return MUST(String::formatted("Unknown pseudo class or element '{}' in {} selector.", error.name, error.rule_name));
},
[](InvalidPropertyError const& error) {
return MUST(String::formatted("Property '{}' in {} rule has invalid value `{}`.", error.property_name, error.rule_name, error.value_string));
},
[](InvalidValueError const& error) {
return MUST(String::formatted("Unable to parse {} from `{}`: {}", error.value_type, error.value_string, error.description));
},
[](InvalidRuleError const& error) {
return MUST(String::formatted("'{}' rule with prelude `{}` is invalid: {}", error.rule_name, error.prelude, error.description));
},
[](InvalidQueryError const& error) {
return MUST(String::formatted("'{}' query `{}` is invalid: {}", error.query_type, error.value_string, error.description));
},
[](InvalidSelectorError const& error) {
return MUST(String::formatted("{} selector `{}` is invalid: {}", error.rule_name, error.value_string, error.description));
},
[](InvalidPseudoClassOrElementError const& error) {
return MUST(String::formatted("Pseudo '{}' value `{}` is invalid: {}", error.name, error.value_string, error.description));
},
[](InvalidRuleLocationError const& error) {
return MUST(String::formatted("'{}' rule is invalid inside {}", error.inner_rule_name, error.outer_rule_name));
});
}
ErrorReporter& ErrorReporter::the()
{
static ErrorReporter& error_reporter = *new ErrorReporter;
return error_reporter;
}
void ErrorReporter::report(ParsingError&& error)
{
if (auto existing = m_errors.get(error); existing.has_value()) {
existing->occurrences++;
return;
}
dbgln_if(CSS_PARSER_DEBUG, "CSS parsing error: {}", serialize_parsing_error(error));
m_errors.set(move(error), { .occurrences = 1 });
}
void ErrorReporter::dump() const
{
// TODO: Organise this in some way?
dbgln("{} CSS errors reported:", m_errors.size());
for (auto const& [error, metadata] : m_errors) {
dbgln("- {} ({} occurrences)", serialize_parsing_error(error), metadata.occurrences);
}
}
}