2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2015-08-31 16:28:26 +02:00
|
|
|
|
|
|
|
|
#include "clangtextmark.h"
|
|
|
|
|
|
2023-01-19 09:51:10 +01:00
|
|
|
#include "clangcodemodeltr.h"
|
2015-11-30 09:43:50 +01:00
|
|
|
#include "clangconstants.h"
|
2021-06-02 17:51:31 +02:00
|
|
|
#include "clangdclient.h"
|
2016-07-22 08:57:32 +02:00
|
|
|
#include "clangdiagnostictooltipwidget.h"
|
2019-01-28 12:40:03 +01:00
|
|
|
#include "clangeditordocumentprocessor.h"
|
2018-05-09 15:12:01 +02:00
|
|
|
#include "clangutils.h"
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2019-01-28 12:40:03 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2023-01-19 09:51:10 +01:00
|
|
|
|
2021-08-30 10:58:08 +02:00
|
|
|
#include <cppeditor/clangdiagnosticconfigsmodel.h>
|
|
|
|
|
#include <cppeditor/cppeditorconstants.h>
|
|
|
|
|
#include <cppeditor/cpptoolsreuse.h>
|
|
|
|
|
#include <cppeditor/cppcodemodelsettings.h>
|
2019-01-28 12:40:03 +01:00
|
|
|
|
2022-05-11 12:30:57 +02:00
|
|
|
#include <projectexplorer/task.h>
|
2022-04-28 12:10:53 +02:00
|
|
|
|
2019-01-28 12:40:03 +01:00
|
|
|
#include <utils/fadingindicator.h>
|
2016-11-17 15:55:06 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2022-06-20 11:32:05 +02:00
|
|
|
#include <utils/stringutils.h>
|
2016-02-02 14:54:31 +01:00
|
|
|
#include <utils/theme/theme.h>
|
2019-01-28 12:40:03 +01:00
|
|
|
#include <utils/utilsicons.h>
|
2015-08-31 16:28:26 +02:00
|
|
|
|
2019-01-28 09:32:11 +01:00
|
|
|
#include <QAction>
|
2016-10-18 18:01:57 +02:00
|
|
|
#include <QLayout>
|
2022-07-22 13:27:19 +02:00
|
|
|
#include <QMainWindow>
|
2021-12-14 13:42:28 +01:00
|
|
|
#include <QRegularExpression>
|
|
|
|
|
#include <QRegularExpressionMatch>
|
2015-08-31 16:28:26 +02:00
|
|
|
#include <QString>
|
|
|
|
|
|
2021-08-30 10:58:08 +02:00
|
|
|
using namespace CppEditor;
|
2021-06-02 17:51:31 +02:00
|
|
|
using namespace LanguageClient;
|
|
|
|
|
using namespace LanguageServerProtocol;
|
2022-04-28 12:10:53 +02:00
|
|
|
using namespace ProjectExplorer;
|
2018-05-02 15:02:00 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2015-08-31 16:28:26 +02:00
|
|
|
namespace ClangCodeModel {
|
2019-02-06 16:17:03 +01:00
|
|
|
namespace Internal {
|
2015-08-31 16:28:26 +02:00
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2022-04-28 12:10:53 +02:00
|
|
|
Project *projectForCurrentEditor()
|
2019-01-28 12:40:03 +01:00
|
|
|
{
|
2022-11-23 19:00:38 +01:00
|
|
|
const FilePath filePath = currentCppEditorDocumentFilePath();
|
2019-01-28 12:40:03 +01:00
|
|
|
if (filePath.isEmpty())
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
if (auto processor = ClangEditorDocumentProcessor::get(filePath)) {
|
2021-08-20 11:21:06 +02:00
|
|
|
if (ProjectPart::ConstPtr projectPart = processor->projectPart())
|
2021-05-07 16:10:07 +02:00
|
|
|
return projectForProjectPart(*projectPart);
|
2019-01-28 12:40:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-15 15:05:02 +01:00
|
|
|
enum class DiagnosticType { Clang, Tidy, Clazy };
|
2022-05-02 12:29:57 +02:00
|
|
|
DiagnosticType diagnosticType(const ClangDiagnostic &diagnostic)
|
2019-02-15 15:05:02 +01:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if (!diagnostic.disableOption.isEmpty())
|
|
|
|
|
return DiagnosticType::Clang;
|
|
|
|
|
|
2020-07-06 15:49:35 +02:00
|
|
|
const DiagnosticTextInfo textInfo(diagnostic.text);
|
|
|
|
|
if (DiagnosticTextInfo::isClazyOption(textInfo.option()))
|
2019-02-15 15:05:02 +01:00
|
|
|
return DiagnosticType::Clazy;
|
|
|
|
|
return DiagnosticType::Tidy;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-02 12:29:57 +02:00
|
|
|
void disableDiagnosticInConfig(ClangDiagnosticConfig &config, const ClangDiagnostic &diagnostic)
|
2019-01-28 12:40:03 +01:00
|
|
|
{
|
2019-02-15 15:05:02 +01:00
|
|
|
switch (diagnosticType(diagnostic)) {
|
|
|
|
|
case DiagnosticType::Clang:
|
|
|
|
|
config.setClangOptions(config.clangOptions() + QStringList(diagnostic.disableOption));
|
|
|
|
|
break;
|
|
|
|
|
case DiagnosticType::Tidy:
|
2023-01-10 15:34:47 +01:00
|
|
|
config.setChecks(ClangToolType::Tidy, config.checks(ClangToolType::Tidy) + QString(",-")
|
2019-02-15 15:05:02 +01:00
|
|
|
+ DiagnosticTextInfo(diagnostic.text).option());
|
|
|
|
|
break;
|
|
|
|
|
case DiagnosticType::Clazy: {
|
|
|
|
|
const DiagnosticTextInfo textInfo(diagnostic.text);
|
2019-01-28 12:40:03 +01:00
|
|
|
const QString checkName = DiagnosticTextInfo::clazyCheckName(textInfo.option());
|
2023-01-10 15:34:47 +01:00
|
|
|
QStringList newChecks = config.checks(ClangToolType::Clazy).split(',');
|
2019-01-28 12:40:03 +01:00
|
|
|
newChecks.removeOne(checkName);
|
2023-01-10 15:34:47 +01:00
|
|
|
config.setChecks(ClangToolType::Clazy, newChecks.join(','));
|
2019-02-15 15:05:02 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2019-01-28 12:40:03 +01:00
|
|
|
}
|
2019-02-15 15:05:02 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-19 14:48:09 +02:00
|
|
|
ClangDiagnosticConfig diagnosticConfig()
|
2019-02-15 15:05:02 +01:00
|
|
|
{
|
2022-04-28 12:10:53 +02:00
|
|
|
Project *project = projectForCurrentEditor();
|
2019-02-15 15:05:02 +01:00
|
|
|
QTC_ASSERT(project, return {});
|
2022-05-19 14:48:09 +02:00
|
|
|
return warningsConfigForProject(project);
|
2019-02-15 15:05:02 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-11 12:49:21 +02:00
|
|
|
static bool isDiagnosticConfigChangable(Project *project)
|
2019-02-15 15:05:02 +01:00
|
|
|
{
|
|
|
|
|
if (!project)
|
|
|
|
|
return false;
|
2023-04-11 12:49:21 +02:00
|
|
|
if (diagnosticConfig().useBuildSystemWarnings())
|
2019-02-15 15:05:02 +01:00
|
|
|
return false;
|
|
|
|
|
return true;
|
2019-01-28 12:40:03 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-02 12:29:57 +02:00
|
|
|
void disableDiagnosticInCurrentProjectConfig(const ClangDiagnostic &diagnostic)
|
2019-01-28 12:40:03 +01:00
|
|
|
{
|
2022-04-28 12:10:53 +02:00
|
|
|
Project *project = projectForCurrentEditor();
|
2019-01-28 12:40:03 +01:00
|
|
|
QTC_ASSERT(project, return );
|
|
|
|
|
|
|
|
|
|
// Get config
|
2022-05-19 14:48:09 +02:00
|
|
|
ClangDiagnosticConfig config = diagnosticConfig();
|
2021-08-30 10:58:08 +02:00
|
|
|
ClangDiagnosticConfigsModel configsModel = CppEditor::diagnosticConfigsModel();
|
2019-01-28 12:40:03 +01:00
|
|
|
|
|
|
|
|
// Create copy if needed
|
|
|
|
|
if (config.isReadOnly()) {
|
2023-02-07 22:46:35 +01:00
|
|
|
const QString name = Tr::tr("Project: %1 (based on %2)")
|
2019-01-28 12:40:03 +01:00
|
|
|
.arg(project->displayName(), config.displayName());
|
|
|
|
|
config = ClangDiagnosticConfigsModel::createCustomConfig(config, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Modify diagnostic config
|
|
|
|
|
disableDiagnosticInConfig(config, diagnostic);
|
|
|
|
|
configsModel.appendOrUpdate(config);
|
|
|
|
|
|
|
|
|
|
// Set global settings
|
2022-05-19 14:48:09 +02:00
|
|
|
ClangdSettings::setCustomDiagnosticConfigs(configsModel.customConfigs());
|
2019-01-28 12:40:03 +01:00
|
|
|
|
|
|
|
|
// Set project settings
|
2022-05-19 14:48:09 +02:00
|
|
|
ClangdProjectSettings projectSettings(project);
|
|
|
|
|
if (projectSettings.useGlobalSettings())
|
|
|
|
|
projectSettings.setUseGlobalSettings(false);
|
|
|
|
|
projectSettings.setDiagnosticConfigId(config.id());
|
2019-01-28 12:40:03 +01:00
|
|
|
|
|
|
|
|
// Notify the user about changed project specific settings
|
2023-02-07 22:46:35 +01:00
|
|
|
const QString text = Tr::tr("Changes applied in Projects Mode > Clang Code Model");
|
2020-07-06 15:49:35 +02:00
|
|
|
FadingIndicator::showText(Core::ICore::mainWindow(),
|
|
|
|
|
text,
|
|
|
|
|
FadingIndicator::SmallText);
|
2019-01-28 12:40:03 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-02 12:29:57 +02:00
|
|
|
ClangDiagnostic::Severity convertSeverity(DiagnosticSeverity src)
|
2021-06-02 17:51:31 +02:00
|
|
|
{
|
|
|
|
|
if (src == DiagnosticSeverity::Error)
|
2022-05-02 12:29:57 +02:00
|
|
|
return ClangDiagnostic::Severity::Error;
|
2021-06-02 17:51:31 +02:00
|
|
|
if (src == DiagnosticSeverity::Warning)
|
2022-05-02 12:29:57 +02:00
|
|
|
return ClangDiagnostic::Severity::Warning;
|
|
|
|
|
return ClangDiagnostic::Severity::Note;
|
2021-06-02 17:51:31 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-02 12:29:57 +02:00
|
|
|
ClangSourceRange convertRange(const FilePath &filePath, const Range &src)
|
2021-06-02 17:51:31 +02:00
|
|
|
{
|
2022-05-02 12:29:57 +02:00
|
|
|
const Utils::Link start(filePath, src.start().line() + 1, src.start().character());
|
|
|
|
|
const Utils::Link end(filePath, src.end().line() + 1, src.end().character());
|
|
|
|
|
return ClangSourceRange(start, end);
|
2021-06-02 17:51:31 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-15 07:23:55 +01:00
|
|
|
ClangDiagnostic convertDiagnostic(const ClangdDiagnostic &src,
|
|
|
|
|
const FilePath &filePath,
|
|
|
|
|
const DocumentUri::PathMapper &mapper)
|
2021-06-02 17:51:31 +02:00
|
|
|
{
|
2022-05-02 12:29:57 +02:00
|
|
|
ClangDiagnostic target;
|
|
|
|
|
target.location = convertRange(filePath, src.range()).start;
|
2021-12-14 13:42:28 +01:00
|
|
|
const QStringList messages = src.message().split("\n\n", Qt::SkipEmptyParts);
|
|
|
|
|
if (!messages.isEmpty())
|
|
|
|
|
target.text = messages.first();
|
|
|
|
|
for (int i = 1; i < messages.size(); ++i) {
|
|
|
|
|
QString auxMessage = messages.at(i);
|
|
|
|
|
auxMessage.replace('\n', ' ');
|
|
|
|
|
|
|
|
|
|
// TODO: Taken from ClangParser; consolidate
|
|
|
|
|
static const QRegularExpression msgRegex(
|
|
|
|
|
"^(<command line>|([A-Za-z]:)?[^:]+\\.[^:]+)"
|
|
|
|
|
"(:(\\d+):(\\d+)|\\((\\d+)\\) *): +(fatal +)?(error|warning|note): (.*)$");
|
|
|
|
|
|
2022-05-02 12:29:57 +02:00
|
|
|
ClangDiagnostic aux;
|
2021-12-14 13:42:28 +01:00
|
|
|
if (const QRegularExpressionMatch match = msgRegex.match(auxMessage); match.hasMatch()) {
|
|
|
|
|
bool ok = false;
|
|
|
|
|
int line = match.captured(4).toInt(&ok);
|
|
|
|
|
int column = match.captured(5).toInt();
|
|
|
|
|
if (!ok) {
|
|
|
|
|
line = match.captured(6).toInt(&ok);
|
|
|
|
|
column = 0;
|
|
|
|
|
}
|
2023-02-09 08:21:09 +01:00
|
|
|
FilePath auxFilePath = mapper(FilePath::fromUserInput(match.captured(1)));
|
2021-12-14 13:42:28 +01:00
|
|
|
if (auxFilePath.isRelativePath() && auxFilePath.fileName() == filePath.fileName())
|
|
|
|
|
auxFilePath = filePath;
|
2022-05-02 12:29:57 +02:00
|
|
|
aux.location = {auxFilePath, line, column - 1};
|
2021-12-14 13:42:28 +01:00
|
|
|
aux.text = match.captured(9);
|
|
|
|
|
const QString type = match.captured(8);
|
|
|
|
|
if (type == "fatal")
|
2022-05-02 12:29:57 +02:00
|
|
|
aux.severity = ClangDiagnostic::Severity::Fatal;
|
2021-12-14 13:42:28 +01:00
|
|
|
else if (type == "error")
|
2022-05-02 12:29:57 +02:00
|
|
|
aux.severity = ClangDiagnostic::Severity::Error;
|
2021-12-14 13:42:28 +01:00
|
|
|
else if (type == "warning")
|
2022-05-02 12:29:57 +02:00
|
|
|
aux.severity = ClangDiagnostic::Severity::Warning;
|
2021-12-14 13:42:28 +01:00
|
|
|
else if (type == "note")
|
2022-05-02 12:29:57 +02:00
|
|
|
aux.severity = ClangDiagnostic::Severity::Note;
|
2021-12-14 13:42:28 +01:00
|
|
|
} else {
|
|
|
|
|
aux.text = auxMessage;
|
|
|
|
|
}
|
|
|
|
|
target.children << aux;
|
|
|
|
|
}
|
2021-06-02 17:51:31 +02:00
|
|
|
target.category = src.category();
|
|
|
|
|
if (src.severity())
|
|
|
|
|
target.severity = convertSeverity(*src.severity());
|
|
|
|
|
const Diagnostic::Code code = src.code().value_or(Diagnostic::Code());
|
2022-08-19 14:47:59 +02:00
|
|
|
const QString * const codeString = std::get_if<QString>(&code);
|
2021-06-02 17:51:31 +02:00
|
|
|
if (codeString && codeString->startsWith("-W"))
|
|
|
|
|
target.enableOption = *codeString;
|
|
|
|
|
for (const CodeAction &codeAction : src.codeActions().value_or(QList<CodeAction>())) {
|
2022-08-26 10:30:00 +02:00
|
|
|
const std::optional<WorkspaceEdit> edit = codeAction.edit();
|
2021-06-02 17:51:31 +02:00
|
|
|
if (!edit)
|
|
|
|
|
continue;
|
2022-08-26 10:30:00 +02:00
|
|
|
const std::optional<WorkspaceEdit::Changes> changes = edit->changes();
|
2021-06-02 17:51:31 +02:00
|
|
|
if (!changes)
|
|
|
|
|
continue;
|
2022-05-11 14:35:44 +02:00
|
|
|
ClangDiagnostic fixItDiag;
|
|
|
|
|
fixItDiag.text = codeAction.title();
|
2021-06-02 17:51:31 +02:00
|
|
|
for (auto it = changes->cbegin(); it != changes->cend(); ++it) {
|
|
|
|
|
for (const TextEdit &textEdit : it.value()) {
|
2022-05-11 14:35:44 +02:00
|
|
|
fixItDiag.fixIts << ClangFixIt(textEdit.newText(),
|
2022-12-15 07:23:55 +01:00
|
|
|
convertRange(it.key().toFilePath(mapper),
|
|
|
|
|
textEdit.range()));
|
2021-06-02 17:51:31 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-05-11 14:35:44 +02:00
|
|
|
target.children << fixItDiag;
|
2021-06-02 17:51:31 +02:00
|
|
|
}
|
|
|
|
|
return target;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 12:30:57 +02:00
|
|
|
Task createTask(const ClangDiagnostic &diagnostic)
|
2022-04-28 12:10:53 +02:00
|
|
|
{
|
|
|
|
|
Task::TaskType taskType = Task::TaskType::Unknown;
|
|
|
|
|
QIcon icon;
|
|
|
|
|
|
|
|
|
|
switch (diagnostic.severity) {
|
2022-05-02 12:29:57 +02:00
|
|
|
case ClangDiagnostic::Severity::Fatal:
|
|
|
|
|
case ClangDiagnostic::Severity::Error:
|
2022-04-28 12:10:53 +02:00
|
|
|
taskType = Task::TaskType::Error;
|
|
|
|
|
icon = ::Utils::Icons::CODEMODEL_ERROR.icon();
|
|
|
|
|
break;
|
2022-05-02 12:29:57 +02:00
|
|
|
case ClangDiagnostic::Severity::Warning:
|
2022-04-28 12:10:53 +02:00
|
|
|
taskType = Task::TaskType::Warning;
|
|
|
|
|
icon = ::Utils::Icons::CODEMODEL_WARNING.icon();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 12:30:57 +02:00
|
|
|
return Task(taskType,
|
|
|
|
|
diagnosticCategoryPrefixRemoved(diagnostic.text),
|
2022-08-03 14:20:57 +02:00
|
|
|
diagnostic.location.targetFilePath,
|
2022-05-11 12:30:57 +02:00
|
|
|
diagnostic.location.targetLine,
|
|
|
|
|
Constants::TASK_CATEGORY_DIAGNOSTICS,
|
|
|
|
|
icon,
|
|
|
|
|
Task::NoOptions);
|
2022-04-28 12:10:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
2021-06-02 17:51:31 +02:00
|
|
|
ClangdTextMark::ClangdTextMark(const FilePath &filePath,
|
|
|
|
|
const Diagnostic &diagnostic,
|
2022-02-25 09:31:40 +01:00
|
|
|
bool isProjectFile,
|
2022-05-12 08:48:50 +02:00
|
|
|
ClangdClient *client)
|
2023-01-09 13:14:39 +01:00
|
|
|
: TextEditor::TextMark(filePath,
|
|
|
|
|
int(diagnostic.range().start().line() + 1),
|
|
|
|
|
{client->name(), client->id()})
|
2021-06-02 17:51:31 +02:00
|
|
|
, m_lspDiagnostic(diagnostic)
|
2023-01-09 13:14:39 +01:00
|
|
|
, m_diagnostic(
|
|
|
|
|
convertDiagnostic(ClangdDiagnostic(diagnostic), filePath, client->hostPathMapper()))
|
2021-06-02 17:51:31 +02:00
|
|
|
, m_client(client)
|
|
|
|
|
{
|
2022-08-04 14:56:41 +02:00
|
|
|
setSettingsPage(CppEditor::Constants::CPP_CLANGD_SETTINGS_ID);
|
2021-06-02 17:51:31 +02:00
|
|
|
|
|
|
|
|
const bool isError = diagnostic.severity()
|
|
|
|
|
&& *diagnostic.severity() == DiagnosticSeverity::Error;
|
2023-01-19 09:51:10 +01:00
|
|
|
setDefaultToolTip(isError ? Tr::tr("Code Model Error") : Tr::tr("Code Model Warning"));
|
2021-06-02 17:51:31 +02:00
|
|
|
setPriority(isError ? TextEditor::TextMark::HighPriority
|
|
|
|
|
: TextEditor::TextMark::NormalPriority);
|
|
|
|
|
setIcon(isError ? Icons::CODEMODEL_ERROR.icon() : Icons::CODEMODEL_WARNING.icon());
|
2022-02-25 09:31:40 +01:00
|
|
|
if (isProjectFile) {
|
2021-07-29 13:39:14 +02:00
|
|
|
setLineAnnotation(diagnostic.message());
|
|
|
|
|
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
|
|
|
|
|
: Theme::CodeModel_Warning_TextMarkColor);
|
2022-05-12 08:48:50 +02:00
|
|
|
client->addTask(createTask(m_diagnostic));
|
2021-07-29 13:39:14 +02:00
|
|
|
}
|
2021-06-02 17:51:31 +02:00
|
|
|
|
2022-08-03 15:25:17 +02:00
|
|
|
setActionsProvider([diag = m_diagnostic] {
|
|
|
|
|
// Copy to clipboard action
|
|
|
|
|
QList<QAction *> actions;
|
|
|
|
|
QAction *action = new QAction();
|
|
|
|
|
action->setIcon(QIcon::fromTheme("edit-copy", Icons::COPY.icon()));
|
2023-01-19 09:51:10 +01:00
|
|
|
action->setToolTip(Tr::tr("Copy to Clipboard", "Clang Code Model Marks"));
|
2022-08-03 15:25:17 +02:00
|
|
|
QObject::connect(action, &QAction::triggered, [diag] {
|
|
|
|
|
const QString text = ClangDiagnosticWidget::createText({diag},
|
|
|
|
|
ClangDiagnosticWidget::InfoBar);
|
|
|
|
|
setClipboardAndSelection(text);
|
2021-06-02 17:51:31 +02:00
|
|
|
});
|
|
|
|
|
actions << action;
|
|
|
|
|
|
2022-08-03 15:25:17 +02:00
|
|
|
// Remove diagnostic warning action
|
|
|
|
|
Project *project = projectForCurrentEditor();
|
2023-04-11 12:49:21 +02:00
|
|
|
if (project && isDiagnosticConfigChangable(project)) {
|
2022-08-03 15:25:17 +02:00
|
|
|
action = new QAction();
|
|
|
|
|
action->setIcon(Icons::BROKEN.icon());
|
2023-01-19 09:51:10 +01:00
|
|
|
action->setToolTip(Tr::tr("Disable Diagnostic in Current Project"));
|
2022-08-03 15:25:17 +02:00
|
|
|
QObject::connect(action, &QAction::triggered, [diag] {
|
|
|
|
|
disableDiagnosticInCurrentProjectConfig(diag);
|
|
|
|
|
});
|
|
|
|
|
actions << action;
|
|
|
|
|
}
|
|
|
|
|
return actions;
|
|
|
|
|
});
|
2021-06-02 17:51:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ClangdTextMark::addToolTipContent(QLayout *target) const
|
|
|
|
|
{
|
2023-02-07 18:14:53 +01:00
|
|
|
const auto canApplyFixIt = [c = m_client, diag = m_lspDiagnostic, fp = filePath()] {
|
2022-12-15 07:23:55 +01:00
|
|
|
return QTC_GUARD(c) && c->reachable() && c->hasDiagnostic(fp, diag);
|
2021-06-02 17:51:31 +02:00
|
|
|
};
|
2021-12-07 13:26:57 +01:00
|
|
|
const QString clientName = QTC_GUARD(m_client) ? m_client->name() : "clangd [unknown]";
|
2021-06-02 17:51:31 +02:00
|
|
|
target->addWidget(ClangDiagnosticWidget::createWidget({m_diagnostic},
|
2021-12-07 13:26:57 +01:00
|
|
|
ClangDiagnosticWidget::ToolTip,
|
|
|
|
|
canApplyFixIt,
|
|
|
|
|
clientName));
|
2021-06-02 17:51:31 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-06 16:17:03 +01:00
|
|
|
} // namespace Internal
|
2015-08-31 16:28:26 +02:00
|
|
|
} // namespace ClangCodeModel
|