chore: mini refactorings and dead code removal (#5512)

This commit is contained in:
nerix 2024-07-20 11:35:59 +02:00 committed by GitHub
parent deb4401036
commit b3c09b65d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 65 additions and 506 deletions

View file

@ -42,7 +42,6 @@
#include "providers/twitch/PubSubActions.hpp"
#include "providers/twitch/PubSubManager.hpp"
#include "providers/twitch/PubSubMessages.hpp"
#include "providers/twitch/pubsubmessages/LowTrustUsers.hpp"
#include "providers/twitch/TwitchChannel.hpp"
#include "providers/twitch/TwitchIrcServer.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp"

View file

@ -487,7 +487,6 @@ set(SOURCE_FILES
util/ChannelHelpers.hpp
util/Clipboard.cpp
util/Clipboard.hpp
util/ConcurrentMap.hpp
util/DebugCount.cpp
util/DebugCount.hpp
util/DisplayBadge.cpp
@ -517,8 +516,6 @@ set(SOURCE_FILES
util/SampleData.cpp
util/SampleData.hpp
util/SharedPtrElementLess.hpp
util/SplitCommand.cpp
util/SplitCommand.hpp
util/StreamLink.cpp
util/StreamLink.hpp
util/ThreadGuard.hpp

View file

@ -1,102 +0,0 @@
#pragma once
#include <QMap>
#include <QMutex>
#include <QMutexLocker>
#include <functional>
#include <map>
#include <memory>
namespace chatterino {
template <typename TKey, typename TValue>
class ConcurrentMap
{
public:
ConcurrentMap() = default;
bool tryGet(const TKey &name, TValue &value) const
{
QMutexLocker lock(&this->mutex);
auto a = this->data.find(name);
if (a == this->data.end())
{
return false;
}
value = a.value();
return true;
}
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
{
QMutexLocker lock(&this->mutex);
auto a = this->data.find(name);
if (a == this->data.end())
{
TValue value = addLambda();
this->data.insert(name, value);
return value;
}
return a.value();
}
TValue &operator[](const TKey &name)
{
QMutexLocker lock(&this->mutex);
return this->data[name];
}
void clear()
{
QMutexLocker lock(&this->mutex);
this->data.clear();
}
void insert(const TKey &name, const TValue &value)
{
QMutexLocker lock(&this->mutex);
this->data.insert(name, value);
}
void each(
std::function<void(const TKey &name, const TValue &value)> func) const
{
QMutexLocker lock(&this->mutex);
QMapIterator<TKey, TValue> it(this->data);
while (it.hasNext())
{
it.next();
func(it.key(), it.value());
}
}
void each(std::function<void(const TKey &name, TValue &value)> func)
{
QMutexLocker lock(&this->mutex);
QMutableMapIterator<TKey, TValue> it(this->data);
while (it.hasNext())
{
it.next();
func(it.key(), it.value());
}
}
private:
mutable QMutex mutex;
QMap<TKey, TValue> data;
};
} // namespace chatterino

View file

@ -6,7 +6,6 @@
#include "singletons/Paths.hpp"
#include "singletons/Settings.hpp"
#include "util/CombinePath.hpp"
#include "util/Overloaded.hpp"
#include "util/Variant.hpp"
#include <QJsonDocument>

View file

@ -3,7 +3,6 @@
#include "messages/MessageBuilder.hpp"
#include "providers/irc/IrcChannel2.hpp"
#include "providers/irc/IrcServer.hpp"
#include "util/Overloaded.hpp"
#include "util/QStringHash.hpp"
namespace chatterino {

View file

@ -4,7 +4,6 @@
#include "providers/twitch/PubSubActions.hpp"
#include "providers/twitch/PubSubHelpers.hpp"
#include "providers/twitch/PubSubMessages.hpp"
#include "providers/twitch/pubsubmessages/Unlisten.hpp"
#include "singletons/Settings.hpp"
#include "util/DebugCount.hpp"
#include "util/Helpers.hpp"

View file

@ -7,7 +7,6 @@
#include "providers/twitch/PubSubHelpers.hpp"
#include "providers/twitch/PubSubMessages.hpp"
#include "providers/twitch/TwitchAccount.hpp"
#include "pubsubmessages/LowTrustUsers.hpp"
#include "util/DebugCount.hpp"
#include "util/Helpers.hpp"
#include "util/RapidjsonHelpers.hpp"

View file

@ -1,10 +1,11 @@
#pragma once
#include "providers/twitch/pubsubmessages/AutoMod.hpp"
#include "providers/twitch/pubsubmessages/Base.hpp"
#include "providers/twitch/pubsubmessages/ChannelPoints.hpp"
#include "providers/twitch/pubsubmessages/ChatModeratorAction.hpp"
#include "providers/twitch/pubsubmessages/Listen.hpp"
#include "providers/twitch/pubsubmessages/Message.hpp"
#include "providers/twitch/pubsubmessages/Unlisten.hpp"
#include "providers/twitch/pubsubmessages/Whisper.hpp"
#include "providers/twitch/pubsubmessages/AutoMod.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/Base.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/ChannelPoints.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/ChatModeratorAction.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/Listen.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/LowTrustUsers.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/Message.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/Unlisten.hpp" // IWYU pragma: export
#include "providers/twitch/pubsubmessages/Whisper.hpp" // IWYU pragma: export

View file

@ -10,8 +10,6 @@
#include "controllers/nicknames/Nickname.hpp"
#include "debug/Benchmark.hpp"
#include "pajlada/settings/signalargs.hpp"
#include "util/Clamp.hpp"
#include "util/PersistSignalVector.hpp"
#include "util/WindowsHelper.hpp"
#include <pajlada/signals/scoped-connection.hpp>
@ -267,12 +265,12 @@ void Settings::restoreSnapshot()
float Settings::getClampedUiScale() const
{
return clamp<float>(this->uiScale.getValue(), 0.2f, 10);
return std::clamp(this->uiScale.getValue(), 0.2F, 10.F);
}
void Settings::setClampedUiScale(float value)
{
this->uiScale.setValue(clamp<float>(value, 0.2f, 10));
this->uiScale.setValue(std::clamp(value, 0.2F, 10.F));
}
Settings &Settings::instance()

View file

@ -12,7 +12,6 @@
#include "singletons/Paths.hpp"
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
#include "util/Clamp.hpp"
#include "util/CombinePath.hpp"
#include "widgets/AccountSwitchPopup.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"

View file

@ -1,13 +0,0 @@
#pragma once
namespace chatterino {
// http://en.cppreference.com/w/cpp/algorithm/clamp
template <class T>
constexpr const T &clamp(const T &v, const T &lo, const T &hi)
{
return assert(!(hi < lo)), (v < lo) ? lo : (hi < v) ? hi : v;
}
} // namespace chatterino

View file

@ -1,102 +0,0 @@
#pragma once
#include <QMap>
#include <QMutex>
#include <QMutexLocker>
#include <functional>
#include <map>
#include <memory>
namespace chatterino {
template <typename TKey, typename TValue>
class ConcurrentMap
{
public:
ConcurrentMap() = default;
bool tryGet(const TKey &name, TValue &value) const
{
QMutexLocker lock(&this->mutex_);
auto a = this->data_.find(name);
if (a == this->data_.end())
{
return false;
}
value = a.value();
return true;
}
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
{
QMutexLocker lock(&this->mutex_);
auto a = this->data_.find(name);
if (a == this->data_.end())
{
TValue value = addLambda();
this->data_.insert(name, value);
return value;
}
return a.value();
}
TValue &operator[](const TKey &name)
{
QMutexLocker lock(&this->mutex_);
return this->data_[name];
}
void clear()
{
QMutexLocker lock(&this->mutex_);
this->data_.clear();
}
void insert(const TKey &name, const TValue &value)
{
QMutexLocker lock(&this->mutex_);
this->data_.insert(name, value);
}
void each(
std::function<void(const TKey &name, const TValue &value)> func) const
{
QMutexLocker lock(&this->mutex_);
QMapIterator<TKey, TValue> it(this->data_);
while (it.hasNext())
{
it.next();
func(it.key(), it.value());
}
}
void each(std::function<void(const TKey &name, TValue &value)> func)
{
QMutexLocker lock(&this->mutex_);
QMutableMapIterator<TKey, TValue> it(this->data_);
while (it.hasNext())
{
it.next();
func(it.key(), it.value());
}
}
private:
mutable QMutex mutex_;
QMap<TKey, TValue> data_;
};
} // namespace chatterino

View file

@ -3,6 +3,7 @@
#include <QString>
namespace chatterino {
class DisplayBadge
{
public:

View file

@ -6,15 +6,13 @@
namespace chatterino {
inline float distanceBetweenPoints(const QPointF &p1, const QPointF &p2)
inline qreal distanceBetweenPoints(const QPointF &p1, const QPointF &p2)
{
QPointF tmp = p1 - p2;
float distance = 0.f;
distance += tmp.x() * tmp.x();
distance += tmp.y() * tmp.y();
qreal distance = tmp.x() * tmp.x() + tmp.y() * tmp.y();
return sqrt(distance);
return std::sqrt(distance);
}
} // namespace chatterino

View file

@ -1,6 +1,5 @@
#pragma once
#include <algorithm>
#include <chrono>
namespace chatterino {
@ -20,7 +19,6 @@ public:
**/
ExponentialBackoff(const std::chrono::milliseconds &start)
: start_(start)
, step_{1}
{
static_assert(maxSteps > 1, "maxSteps must be higher than 1");
}
@ -54,7 +52,7 @@ public:
private:
const std::chrono::milliseconds start_;
unsigned step_;
unsigned step_ = 1;
};
} // namespace chatterino

View file

@ -9,7 +9,7 @@
namespace chatterino {
namespace _helpers_internal {
namespace helpers::detail {
SizeType skipSpace(QStringView view, SizeType startPos)
{
@ -110,8 +110,8 @@ namespace _helpers_internal {
return std::make_pair(0, false);
}
} // namespace _helpers_internal
using namespace _helpers_internal;
} // namespace helpers::detail
using namespace helpers::detail;
bool startsWithOrContains(const QString &str1, const QString &str2,
Qt::CaseSensitivity caseSensitivity, bool startsWith)

View file

@ -11,7 +11,7 @@
namespace chatterino {
// only qualified for tests
namespace _helpers_internal {
namespace helpers::detail {
using SizeType = QStringView::size_type;
@ -52,7 +52,7 @@ namespace _helpers_internal {
std::pair<uint64_t, bool> findUnitMultiplierToSec(QStringView view,
SizeType &pos);
} // namespace _helpers_internal
} // namespace helpers::detail
/**
* @brief startsWithOrContains is a wrapper for checking

View file

@ -6,11 +6,12 @@
#include <QWidget>
#include <cassert>
#include <type_traits>
#include <concepts>
namespace chatterino {
template <class T>
requires std::derived_from<T, QWidget> || std::derived_from<T, QLayout>
class LayoutCreator
{
public:
@ -34,49 +35,41 @@ public:
return this->item_;
}
template <typename T2>
LayoutCreator<T2> append(T2 *_item)
template <typename U>
LayoutCreator<U> append(U *item)
{
this->addItem(this->getOrCreateLayout(), _item);
addItem(this->getOrCreateLayout(), item);
return LayoutCreator<T2>(_item);
return LayoutCreator<U>(item);
}
template <typename T2, typename... Args>
// clang-format off
// clang-format can be enabled once clang-format v11+ has been installed in CI
LayoutCreator<T2> emplace(Args &&...args)
// clang-format on
template <typename U>
LayoutCreator<U> emplace(auto &&...args)
{
T2 *t = new T2(std::forward<Args>(args)...);
auto *t = new U(std::forward<decltype(args)>(args)...);
this->addItem(this->getOrCreateLayout(), t);
addItem(this->getOrCreateLayout(), t);
return LayoutCreator<T2>(t);
return LayoutCreator<U>(t);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QScrollArea, Q>::value,
int>::type = 0>
LayoutCreator<QWidget> emplaceScrollAreaWidget()
requires std::derived_from<T, QScrollArea>
{
QWidget *widget = new QWidget;
auto *widget = new QWidget;
this->item_->setWidget(widget);
return LayoutCreator<QWidget>(widget);
return {widget};
}
template <typename T2, typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
LayoutCreator<T2> setLayoutType()
template <std::derived_from<QLayout> U>
LayoutCreator<U> setLayoutType()
requires std::derived_from<T, QWidget>
{
T2 *layout = new T2;
U *layout = new U;
this->item_->setLayout(layout);
return LayoutCreator<T2>(layout);
return LayoutCreator<U>(layout);
}
LayoutCreator<T> assign(T **ptr)
@ -86,9 +79,6 @@ public:
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
LayoutCreator<T> withoutMargin()
{
this->item_->setContentsMargins(0, 0, 0, 0);
@ -97,36 +87,31 @@ public:
}
LayoutCreator<T> withoutSpacing()
requires std::derived_from<T, QLayout>
{
this->item_->setSpacing(0);
return *this;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
LayoutCreator<T> hidden()
requires std::derived_from<T, QWidget>
{
this->item_->setVisible(false);
return *this;
}
template <typename Q = T, typename T2,
typename std::enable_if<std::is_same<QTabWidget, Q>::value,
int>::type = 0>
LayoutCreator<T2> appendTab(T2 *item, const QString &title)
template <std::derived_from<QLayout> U>
LayoutCreator<U> appendTab(U *item, const QString &title)
requires std::derived_from<T, QWidget>
{
static_assert(std::is_base_of<QLayout, T2>::value,
"needs to be QLayout");
QWidget *widget = new QWidget;
auto *widget = new QWidget;
widget->setLayout(item);
this->item_->addTab(widget, title);
return LayoutCreator<T2>(item);
return LayoutCreator<U>(item);
}
template <typename Slot, typename Func>
@ -146,36 +131,26 @@ public:
private:
T *item_;
template <typename T2,
typename std::enable_if<std::is_base_of<QWidget, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
static void addItem(QLayout *layout, QWidget *item)
{
layout->addWidget(item);
}
template <typename T2,
typename std::enable_if<std::is_base_of<QLayout, T2>::value,
int>::type = 0>
void addItem(QLayout *layout, T2 *item)
static void addItem(QLayout *layout, QLayout *item)
{
QWidget *widget = new QWidget();
auto *widget = new QWidget();
widget->setLayout(item);
layout->addWidget(widget);
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QLayout, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
requires std::derived_from<T, QLayout>
{
return this->item_;
}
template <typename Q = T,
typename std::enable_if<std::is_base_of<QWidget, Q>::value,
int>::type = 0>
QLayout *getOrCreateLayout()
requires std::derived_from<T, QWidget>
{
if (!this->item_->layout())
{
@ -186,13 +161,10 @@ private:
}
};
template <typename T, typename... Args>
// clang-format off
// clang-format can be enabled once clang-format v11+ has been installed in CI
LayoutCreator<T> makeDialog(Args &&...args)
// clang-format on
template <typename T>
LayoutCreator<T> makeDialog(auto &&...args)
{
T *t = new T(std::forward<Args>(args)...);
T *t = new T(std::forward<decltype(args)>(args)...);
t->setAttribute(Qt::WA_DeleteOnClose);
return LayoutCreator<T>(t);
}

View file

@ -1,13 +0,0 @@
#pragma once
namespace chatterino {
template <class... Ts>
struct Overloaded : Ts... {
using Ts::operator()...;
};
template <class... Ts>
Overloaded(Ts...) -> Overloaded<Ts...>;
} // namespace chatterino

View file

@ -1,28 +0,0 @@
#pragma once
#include "common/ChatterinoSetting.hpp"
#include "common/SignalVector.hpp"
#include <memory>
namespace chatterino {
template <typename T>
inline void persist(SignalVector<T> &vec, const std::string &name)
{
auto setting = std::make_unique<ChatterinoSetting<std::vector<T>>>(name);
for (auto &&item : setting->getValue())
{
vec.append(item);
}
vec.delayedItemsChanged.connect([setting = setting.get(), vec = &vec] {
setting->setValue(vec->raw());
});
// TODO: Delete when appropriate.
setting.release();
}
} // namespace chatterino

View file

@ -3,33 +3,9 @@
#include "debug/AssertInGuiThread.hpp"
#include <QCoreApplication>
#include <QRunnable>
#include <QThreadPool>
#include <functional>
#define async_exec(a) \
QThreadPool::globalInstance()->start(new LambdaRunnable(a));
namespace chatterino {
class LambdaRunnable : public QRunnable
{
public:
LambdaRunnable(std::function<void()> action)
: action_(std::move(action))
{
}
void run() override
{
this->action_();
}
private:
std::function<void()> action_;
};
// Taken from
// https://stackoverflow.com/questions/21646467/how-to-execute-a-functor-or-a-lambda-in-a-given-thread-in-qt-gcd-style
// Qt 5/4 - preferred, has least allocations

View file

@ -1,97 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "SplitCommand.hpp"
#include <QString>
#include <QStringList>
#include <QStringView>
QStringList chatterino::splitCommand(QStringView command)
{
QStringList args;
QString tmp;
int quoteCount = 0;
bool inQuote = false;
// handle quoting. tokens can be surrounded by double quotes
// "hello world". three consecutive double quotes represent
// the quote character itself.
for (int i = 0; i < command.size(); ++i)
{
if (command.at(i) == QLatin1Char('"'))
{
++quoteCount;
if (quoteCount == 3)
{
// third consecutive quote
quoteCount = 0;
tmp += command.at(i);
}
continue;
}
if (quoteCount)
{
if (quoteCount == 1)
{
inQuote = !inQuote;
}
quoteCount = 0;
}
if (!inQuote && command.at(i).isSpace())
{
if (!tmp.isEmpty())
{
args += tmp;
tmp.clear();
}
}
else
{
tmp += command.at(i);
}
}
if (!tmp.isEmpty())
{
args += tmp;
}
return args;
}

View file

@ -1,15 +0,0 @@
#pragma once
#include <QStringList>
#include <QStringView>
namespace chatterino {
// Splits the string command into a list of tokens, and returns the list.
// Tokens with spaces can be surrounded by double quotes;
// three consecutive double quotes represent the quote character itself.
//
// Backported from QProcess 5.15
QStringList splitCommand(QStringView command);
} // namespace chatterino

View file

@ -7,7 +7,6 @@
#include "singletons/Settings.hpp"
#include "singletons/WindowManager.hpp"
#include "util/Helpers.hpp"
#include "util/SplitCommand.hpp"
#include "widgets/dialogs/QualityPopup.hpp"
#include "widgets/splits/Split.hpp"
#include "widgets/Window.hpp"
@ -162,16 +161,16 @@ void openStreamlink(const QString &channelURL, const QString &quality,
{
auto *proc = createStreamlinkProcess();
auto arguments = proc->arguments()
<< extraArguments << channelURL << quality;
<< std::move(extraArguments) << channelURL << quality;
// Remove empty arguments before appending additional streamlink options
// as the options might purposely contain empty arguments
arguments.removeAll(QString());
QString additionalOptions = getSettings()->streamlinkOpts.getValue();
arguments << splitCommand(additionalOptions);
arguments << QProcess::splitCommand(additionalOptions);
proc->setArguments(std::move(arguments));
proc->setArguments(arguments);
bool res = proc->startDetached();
if (!res)

View file

@ -274,17 +274,16 @@ ModerationPage::ModerationPage()
});
}
this->addModerationButtonSettings(tabs);
this->addModerationButtonSettings(tabs.getElement());
// ---- misc
this->itemsChangedTimer_.setSingleShot(true);
}
void ModerationPage::addModerationButtonSettings(
LayoutCreator<QTabWidget> &tabs)
void ModerationPage::addModerationButtonSettings(QTabWidget *tabs)
{
auto timeoutLayout =
tabs.appendTab(new QVBoxLayout, "User Timeout Buttons");
LayoutCreator{tabs}.appendTab(new QVBoxLayout, "User Timeout Buttons");
auto texts = timeoutLayout.emplace<QVBoxLayout>().withoutMargin();
{
auto infoLabel = texts.emplace<QLabel>();

View file

@ -9,9 +9,6 @@ class QPushButton;
namespace chatterino {
template <typename X>
class LayoutCreator;
class ModerationPage : public SettingsPage
{
public:
@ -20,7 +17,7 @@ public:
void selectModerationActions();
private:
void addModerationButtonSettings(LayoutCreator<QTabWidget> &);
void addModerationButtonSettings(QTabWidget *);
QTimer itemsChangedTimer_;
QTabWidget *tabWidget_{};

View file

@ -12,7 +12,6 @@
#include "providers/twitch/TwitchIrcServer.hpp"
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
#include "util/Clamp.hpp"
#include "util/Helpers.hpp"
#include "util/LayoutCreator.hpp"
#include "widgets/dialogs/EmotePopup.hpp"
@ -811,7 +810,7 @@ void SplitInput::updateCompletionPopup()
return;
}
for (int i = clamp(position, 0, (int)text.length() - 1); i >= 0; i--)
for (int i = std::clamp(position, 0, (int)text.length() - 1); i >= 0; i--)
{
if (text[i] == ' ')
{
@ -894,7 +893,7 @@ void SplitInput::insertCompletionText(const QString &input_) const
auto text = edit.toPlainText();
auto position = edit.textCursor().position() - 1;
for (int i = clamp(position, 0, (int)text.length() - 1); i >= 0; i--)
for (int i = std::clamp(position, 0, (int)text.length() - 1); i >= 0; i--)
{
bool done = false;
if (text[i] == ':')

View file

@ -3,7 +3,7 @@
#include "Test.hpp"
using namespace chatterino;
using namespace _helpers_internal;
using namespace helpers::detail;
TEST(Helpers, formatUserMention)
{