瀏覽代碼

AK: Add support for "debug only" formatters

These are formatters that can only be used with debug print
functions, such as dbgln(). Currently this is limited to
Formatter<ErrorOr<T>>. With this you can still debug log ErrorOr
values (good for debugging), but trying to use them in any
String::formatted() call will fail (which prevents .to_string()
errors with the new failable strings being ignored).

You make a formatter debug only by adding a constexpr method like:
static constexpr bool is_debug_only() { return true; }
MacDue 2 年之前
父節點
當前提交
9a120d7243

+ 1 - 1
AK/DeprecatedString.h

@@ -284,7 +284,7 @@ public:
     template<typename... Parameters>
     [[nodiscard]] static DeprecatedString formatted(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
     {
-        VariadicFormatParams variadic_format_parameters { parameters... };
+        VariadicFormatParams<AllowDebugOnlyFormatters::No, Parameters...> variadic_format_parameters { parameters... };
         return vformatted(fmtstr.view(), variadic_format_parameters);
     }
 

+ 26 - 7
AK/Format.h

@@ -33,12 +33,26 @@ struct Formatter {
     using __no_formatter_defined = void;
 };
 
+enum AllowDebugOnlyFormatters {
+    No,
+    Yes
+};
+
 template<typename T, typename = void>
 inline constexpr bool HasFormatter = true;
 
 template<typename T>
 inline constexpr bool HasFormatter<T, typename Formatter<T>::__no_formatter_defined> = false;
 
+template<typename Formatter>
+inline constexpr bool is_debug_only_formatter()
+{
+    constexpr bool has_is_debug_only = requires(Formatter const& formatter) { formatter.is_debug_only(); };
+    if constexpr (has_is_debug_only)
+        return Formatter::is_debug_only();
+    return false;
+}
+
 template<typename T>
 concept Formattable = HasFormatter<T>;
 
@@ -270,7 +284,7 @@ ErrorOr<void> __format_value(TypeErasedFormatParams& params, FormatBuilder& buil
     return formatter.format(builder, *static_cast<T const*>(value));
 }
 
-template<typename... Parameters>
+template<AllowDebugOnlyFormatters allow_debug_formatters, typename... Parameters>
 class VariadicFormatParams : public TypeErasedFormatParams {
 public:
     static_assert(sizeof...(Parameters) <= max_format_arguments);
@@ -278,6 +292,9 @@ public:
     explicit VariadicFormatParams(Parameters const&... parameters)
         : m_data({ TypeErasedParameter { &parameters, TypeErasedParameter::get_type<Parameters>(), __format_value<Parameters> }... })
     {
+        constexpr bool any_debug_formatters = (is_debug_only_formatter<Formatter<Parameters>>() || ...);
+        static_assert(!any_debug_formatters || allow_debug_formatters == AllowDebugOnlyFormatters::Yes,
+            "You are attempting to use a debug-only formatter outside of a debug log! Maybe one of your format values is an ErrorOr<T>?");
         this->set_parameters(m_data);
     }
 
@@ -574,14 +591,14 @@ void vout(FILE*, StringView fmtstr, TypeErasedFormatParams&, bool newline = fals
 template<typename... Parameters>
 void out(FILE* file, CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
 {
-    VariadicFormatParams variadic_format_params { parameters... };
+    VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
     vout(file, fmtstr.view(), variadic_format_params);
 }
 
 template<typename... Parameters>
 void outln(FILE* file, CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
 {
-    VariadicFormatParams variadic_format_params { parameters... };
+    VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
     vout(file, fmtstr.view(), variadic_format_params, true);
 }
 
@@ -625,7 +642,7 @@ void vdbgln(StringView fmtstr, TypeErasedFormatParams&);
 template<typename... Parameters>
 void dbgln(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
 {
-    VariadicFormatParams variadic_format_params { parameters... };
+    VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
     vdbgln(fmtstr.view(), variadic_format_params);
 }
 
@@ -639,7 +656,7 @@ void vdmesgln(StringView fmtstr, TypeErasedFormatParams&);
 template<typename... Parameters>
 void dmesgln(CheckedFormatString<Parameters...>&& fmt, Parameters const&... parameters)
 {
-    VariadicFormatParams variadic_format_params { parameters... };
+    VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
     vdmesgln(fmt.view(), variadic_format_params);
 }
 
@@ -650,7 +667,7 @@ void v_critical_dmesgln(StringView fmtstr, TypeErasedFormatParams&);
 template<typename... Parameters>
 void critical_dmesgln(CheckedFormatString<Parameters...>&& fmt, Parameters const&... parameters)
 {
-    VariadicFormatParams variadic_format_params { parameters... };
+    VariadicFormatParams<AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
     v_critical_dmesgln(fmt.view(), variadic_format_params);
 }
 #endif
@@ -695,7 +712,7 @@ struct Formatter<FormatString> : Formatter<StringView> {
     template<typename... Parameters>
     ErrorOr<void> format(FormatBuilder& builder, StringView fmtstr, Parameters const&... parameters)
     {
-        VariadicFormatParams variadic_format_params { parameters... };
+        VariadicFormatParams<AllowDebugOnlyFormatters::No, Parameters...> variadic_format_params { parameters... };
         return vformat(builder, fmtstr, variadic_format_params);
     }
     ErrorOr<void> vformat(FormatBuilder& builder, StringView fmtstr, TypeErasedFormatParams& params);
@@ -722,6 +739,8 @@ struct Formatter<Error> : Formatter<FormatString> {
 
 template<typename T, typename ErrorType>
 struct Formatter<ErrorOr<T, ErrorType>> : Formatter<FormatString> {
+    static constexpr bool is_debug_only() { return true; }
+
     ErrorOr<void> format(FormatBuilder& builder, ErrorOr<T, ErrorType> const& error_or)
     {
         if (error_or.is_error())

+ 1 - 1
AK/String.h

@@ -98,7 +98,7 @@ public:
     template<typename... Parameters>
     static ErrorOr<String> formatted(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
     {
-        VariadicFormatParams variadic_format_parameters { parameters... };
+        VariadicFormatParams<AllowDebugOnlyFormatters::No, Parameters...> variadic_format_parameters { parameters... };
         return vformatted(fmtstr.view(), variadic_format_parameters);
     }
 

+ 2 - 2
AK/StringBuilder.h

@@ -33,7 +33,7 @@ public:
     template<typename... Parameters>
     ErrorOr<void> try_appendff(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
     {
-        VariadicFormatParams variadic_format_params { parameters... };
+        VariadicFormatParams<AllowDebugOnlyFormatters::No, Parameters...> variadic_format_params { parameters... };
         return vformat(*this, fmtstr.view(), variadic_format_params);
     }
     ErrorOr<void> try_append(char const*, size_t);
@@ -57,7 +57,7 @@ public:
     template<typename... Parameters>
     void appendff(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
     {
-        VariadicFormatParams variadic_format_params { parameters... };
+        VariadicFormatParams<AllowDebugOnlyFormatters::No, Parameters...> variadic_format_params { parameters... };
         MUST(vformat(*this, fmtstr.view(), variadic_format_params));
     }
 

+ 1 - 1
Kernel/Bus/PCI/Device.h

@@ -48,7 +48,7 @@ void dmesgln_pci(Device const& device, AK::CheckedFormatString<Parameters...>&&
         return;
     if (builder.try_append(fmt.view()).is_error())
         return;
-    AK::VariadicFormatParams variadic_format_params { device.device_name(), device.pci_address(), parameters... };
+    AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::Yes, StringView, Address, Parameters...> variadic_format_params { device.device_name(), device.pci_address(), parameters... };
     vdmesgln(builder.string_view(), variadic_format_params);
 }
 

+ 1 - 1
Kernel/KBufferBuilder.h

@@ -37,7 +37,7 @@ public:
     {
         // FIXME: This really not ideal, but vformat expects StringBuilder.
         StringBuilder builder;
-        AK::VariadicFormatParams variadic_format_params { parameters... };
+        AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Parameters...> variadic_format_params { parameters... };
         TRY(vformat(builder, fmtstr.view(), variadic_format_params));
         return append_bytes(builder.string_view().bytes());
     }

+ 1 - 1
Kernel/KString.h

@@ -26,7 +26,7 @@ public:
     template<typename... Parameters>
     [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> formatted(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
     {
-        AK::VariadicFormatParams variadic_format_parameters { parameters... };
+        AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Parameters...> variadic_format_parameters { parameters... };
         return vformatted(fmtstr.view(), variadic_format_parameters);
     }
 

+ 1 - 1
Userland/DevTools/UserspaceEmulator/Report.h

@@ -14,7 +14,7 @@ template<typename... Ts>
 void reportln(StringView format, Ts... args)
 {
     if (g_report_to_debug) {
-        AK::VariadicFormatParams variadic_format_params { args... };
+        AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::Yes, Ts...> variadic_format_params { args... };
         AK::vdbgln(format, variadic_format_params);
     } else {
         warnln(format, args...);

+ 1 - 1
Userland/Libraries/LibJS/Runtime/ThrowableFormat.h

@@ -19,7 +19,7 @@ template<typename... Args>
 ThrowCompletionOr<DeprecatedString> deprecated_format(VM& vm, CheckedFormatString<Args...>&& fmtstr, Args const&... args)
 {
     StringBuilder builder;
-    AK::VariadicFormatParams parameters { args... };
+    AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Args...> parameters { args... };
 
     TRY_OR_THROW_OOM(vm, vformat(builder, fmtstr.view(), parameters));
     return builder.to_deprecated_string();

+ 1 - 1
Userland/Libraries/LibVideo/DecoderError.h

@@ -43,7 +43,7 @@ public:
     template<typename... Parameters>
     static DecoderError format(DecoderErrorCategory category, CheckedFormatString<Parameters...>&& format_string, Parameters const&... parameters)
     {
-        AK::VariadicFormatParams variadic_format_params { parameters... };
+        AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Parameters...> variadic_format_params { parameters... };
         return DecoderError::with_description(category, DeprecatedString::vformatted(format_string.view(), variadic_format_params));
     }