diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f05a6fdb..766a70cf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Minor: Removed total views from the usercard, as Twitch no longer updates the number. (#3792) - Minor: Add Quick Switcher item to open a channel in a new popup window. (#3828) - Minor: Reduced GIF frame window from 30ms to 20ms, causing fewer frame skips in animated emotes. (#3886) +- Minor: Warn when parsing an environment variable fails. (#3904) - Bugfix: Fix crash that can occur when closing and quickly reopening a split, then running a command. (#3852) - Bugfix: Connection to Twitch PubSub now recovers more reliably. (#3643, #3716) - Bugfix: Fix crash that can occur when changing channels. (#3799) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0a4c8abf..6c8150d59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -332,6 +332,7 @@ set(SOURCE_FILES util/StreamerMode.hpp util/Twitch.cpp util/Twitch.hpp + util/TypeName.hpp util/WindowsHelper.cpp util/WindowsHelper.hpp diff --git a/src/common/Env.cpp b/src/common/Env.cpp index ec278ea0f..36757b841 100644 --- a/src/common/Env.cpp +++ b/src/common/Env.cpp @@ -1,11 +1,38 @@ #include "common/Env.hpp" +#include "common/QLogging.hpp" +#include "util/TypeName.hpp" + #include namespace chatterino { namespace { + template + void warn(const char *envName, T defaultValue) + { + auto *envString = std::getenv(envName); + if (!envString) + { + // This function is not supposed to be used for non-existant + // environment variables. + return; + } + + const auto typeName = QString::fromStdString( + std::string(type_name())); + + qCWarning(chatterinoEnv).noquote() + << QStringLiteral( + "Cannot parse value '%1' of environment variable '%2' " + "as a %3, reverting to default value '%4'") + .arg(envString) + .arg(envName) + .arg(typeName) + .arg(defaultValue); + } + QString readStringEnv(const char *envName, QString defaultValue) { auto envString = std::getenv(envName); @@ -28,6 +55,10 @@ namespace { { return val; } + else + { + warn(envName, defaultValue); + } } return defaultValue; diff --git a/src/common/QLogging.cpp b/src/common/QLogging.cpp index 302883c6e..7f99b751e 100644 --- a/src/common/QLogging.cpp +++ b/src/common/QLogging.cpp @@ -13,6 +13,7 @@ Q_LOGGING_CATEGORY(chatterinoBttv, "chatterino.bttv", logThreshold); Q_LOGGING_CATEGORY(chatterinoCache, "chatterino.cache", logThreshold); Q_LOGGING_CATEGORY(chatterinoCommon, "chatterino.common", logThreshold); Q_LOGGING_CATEGORY(chatterinoEmoji, "chatterino.emoji", logThreshold); +Q_LOGGING_CATEGORY(chatterinoEnv, "chatterino.env", logThreshold); Q_LOGGING_CATEGORY(chatterinoFfzemotes, "chatterino.ffzemotes", logThreshold); Q_LOGGING_CATEGORY(chatterinoHelper, "chatterino.helper", logThreshold); Q_LOGGING_CATEGORY(chatterinoHotkeys, "chatterino.hotkeys", logThreshold); diff --git a/src/common/QLogging.hpp b/src/common/QLogging.hpp index ba18b84d7..2c3a382de 100644 --- a/src/common/QLogging.hpp +++ b/src/common/QLogging.hpp @@ -9,6 +9,7 @@ Q_DECLARE_LOGGING_CATEGORY(chatterinoBttv); Q_DECLARE_LOGGING_CATEGORY(chatterinoCache); Q_DECLARE_LOGGING_CATEGORY(chatterinoCommon); Q_DECLARE_LOGGING_CATEGORY(chatterinoEmoji); +Q_DECLARE_LOGGING_CATEGORY(chatterinoEnv); Q_DECLARE_LOGGING_CATEGORY(chatterinoFfzemotes); Q_DECLARE_LOGGING_CATEGORY(chatterinoHelper); Q_DECLARE_LOGGING_CATEGORY(chatterinoHotkeys); diff --git a/src/util/TypeName.hpp b/src/util/TypeName.hpp new file mode 100644 index 000000000..3e5c674e8 --- /dev/null +++ b/src/util/TypeName.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace chatterino { + +// Adapted from: https://stackoverflow.com/a/56766138. +// NOTE: Relies on the "magic" prefixes and suffixes. There are implementations +// that attempt to manually detect these (linked in the SO answer above) but +// they seemed too complex for the scope we have here. +template +constexpr auto type_name() +{ + std::string_view name, prefix, suffix; +#ifdef __clang__ + name = __PRETTY_FUNCTION__; + prefix = "auto chatterino::type_name() [T = "; + suffix = "]"; +#elif defined(__GNUC__) + name = __PRETTY_FUNCTION__; + prefix = "constexpr auto chatterino::type_name() [with T = "; + suffix = "]"; +#elif defined(_MSC_VER) + name = __FUNCSIG__; + prefix = "auto __cdecl chatterino::type_name<"; + suffix = ">(void)"; +#endif + name.remove_prefix(prefix.size()); + name.remove_suffix(suffix.size()); + + return name; +} + +} // namespace chatterino