2016-01-29 17:17:18 +01:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** 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 General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** 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-3.0.html.
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "clangdiagnostictooltipwidget.h"
|
|
|
|
|
#include "clangfixitoperation.h"
|
|
|
|
|
|
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2016-01-29 17:17:18 +01:00
|
|
|
#include <utils/tooltip/tooltip.h>
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QDesktopWidget>
|
2016-01-29 17:17:18 +01:00
|
|
|
#include <QFileInfo>
|
2016-10-18 18:01:57 +02:00
|
|
|
#include <QHash>
|
2016-01-29 17:17:18 +01:00
|
|
|
#include <QLabel>
|
2016-10-18 18:01:57 +02:00
|
|
|
|
|
|
|
|
using namespace ClangCodeModel;
|
|
|
|
|
using Internal::ClangDiagnosticWidget;
|
2016-01-29 17:17:18 +01:00
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const char LINK_ACTION_GOTO_LOCATION[] = "#gotoLocation";
|
|
|
|
|
const char LINK_ACTION_APPLY_FIX[] = "#applyFix";
|
|
|
|
|
|
|
|
|
|
QString fileNamePrefix(const QString &mainFilePath,
|
|
|
|
|
const ClangBackEnd::SourceLocationContainer &location)
|
|
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
const QString filePath = location.filePath.toString();
|
2016-01-29 17:17:18 +01:00
|
|
|
if (filePath != mainFilePath)
|
|
|
|
|
return QFileInfo(filePath).fileName() + QLatin1Char(':');
|
|
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString locationToString(const ClangBackEnd::SourceLocationContainer &location)
|
|
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
return QString::number(location.line)
|
2016-01-29 17:17:18 +01:00
|
|
|
+ QStringLiteral(":")
|
2018-04-04 18:25:23 +02:00
|
|
|
+ QString::number(location.column);
|
2016-01-29 17:17:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
void openEditorAt(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
2016-01-29 17:17:18 +01:00
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2018-04-04 18:25:23 +02:00
|
|
|
Core::EditorManager::openEditorAt(location.filePath.toString(),
|
|
|
|
|
int(location.line),
|
|
|
|
|
int(location.column - 1));
|
2016-01-29 17:17:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
void applyFixit(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
2016-02-12 16:41:45 +01:00
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
ClangCodeModel::ClangFixItOperation operation(Utf8String(), diagnostic.fixIts);
|
2016-10-18 18:01:57 +02:00
|
|
|
|
|
|
|
|
operation.perform();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class WidgetFromDiagnostics
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
struct DisplayHints {
|
|
|
|
|
bool showCategoryAndEnableOption;
|
|
|
|
|
bool showFileNameInMainDiagnostic;
|
|
|
|
|
bool enableClickableFixits;
|
|
|
|
|
bool limitWidth;
|
|
|
|
|
bool hideTooltipAfterLinkActivation;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static QWidget *create(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
|
|
|
|
const DisplayHints &displayHints)
|
|
|
|
|
{
|
|
|
|
|
WidgetFromDiagnostics converter(displayHints);
|
|
|
|
|
return converter.createWidget(diagnostics);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
enum class IndentMode { Indent, DoNotIndent };
|
|
|
|
|
|
|
|
|
|
WidgetFromDiagnostics(const DisplayHints &displayHints)
|
|
|
|
|
: m_displayHints(displayHints)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
|
|
|
|
|
{
|
|
|
|
|
const QString text = htmlText(diagnostics);
|
|
|
|
|
|
|
|
|
|
auto *label = new QLabel;
|
|
|
|
|
label->setTextFormat(Qt::RichText);
|
|
|
|
|
label->setText(text);
|
|
|
|
|
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
2017-03-23 13:30:11 +01:00
|
|
|
|
|
|
|
|
if (m_displayHints.limitWidth) {
|
|
|
|
|
const int limit = widthLimit();
|
|
|
|
|
// Using "setWordWrap(true)" alone will wrap the text already for small
|
|
|
|
|
// widths, so do not require word wrapping until we hit limits.
|
|
|
|
|
if (label->sizeHint().width() > limit) {
|
|
|
|
|
label->setMaximumWidth(limit);
|
|
|
|
|
label->setWordWrap(true);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2016-10-18 18:01:57 +02:00
|
|
|
label->setWordWrap(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TargetIdToDiagnosticTable table = m_targetIdsToDiagnostics;
|
|
|
|
|
const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation;
|
|
|
|
|
QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation]
|
|
|
|
|
(const QString &action) {
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action);
|
|
|
|
|
QTC_ASSERT(diagnostic != ClangBackEnd::DiagnosticContainer(), return);
|
|
|
|
|
|
|
|
|
|
if (action.startsWith(LINK_ACTION_APPLY_FIX))
|
|
|
|
|
applyFixit(diagnostic);
|
|
|
|
|
else
|
|
|
|
|
openEditorAt(diagnostic);
|
|
|
|
|
|
|
|
|
|
if (hideToolTipAfterLinkActivation)
|
|
|
|
|
Utils::ToolTip::hideImmediately();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString htmlText(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics)
|
|
|
|
|
{
|
|
|
|
|
// For debugging, add: style='border-width:1px;border-color:black'
|
2017-03-23 13:30:11 +01:00
|
|
|
QString text = "<table cellspacing='0' cellpadding='0' width='100%'>";
|
2016-10-18 18:01:57 +02:00
|
|
|
|
|
|
|
|
foreach (const ClangBackEnd::DiagnosticContainer &diagnostic, diagnostics)
|
|
|
|
|
text.append(tableRows(diagnostic));
|
|
|
|
|
|
|
|
|
|
text.append("</table>");
|
|
|
|
|
|
2016-02-12 16:41:45 +01:00
|
|
|
return text;
|
2016-10-18 18:01:57 +02:00
|
|
|
}
|
2016-02-12 16:41:45 +01:00
|
|
|
|
2018-05-11 12:47:54 +02:00
|
|
|
class DiagnosticTextInfo
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DiagnosticTextInfo(const QString &text)
|
|
|
|
|
: m_text(text)
|
|
|
|
|
, m_squareBracketStartIndex(text.lastIndexOf('['))
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
QString textWithoutOption() const
|
|
|
|
|
{
|
|
|
|
|
if (m_squareBracketStartIndex == -1)
|
|
|
|
|
return m_text;
|
|
|
|
|
|
|
|
|
|
return m_text.mid(0, m_squareBracketStartIndex - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString option() const
|
|
|
|
|
{
|
|
|
|
|
if (m_squareBracketStartIndex == -1)
|
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
|
|
const int index = m_squareBracketStartIndex + 1;
|
|
|
|
|
return m_text.mid(index, m_text.count() - index - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString category() const
|
|
|
|
|
{
|
|
|
|
|
if (m_squareBracketStartIndex == -1)
|
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
|
|
const int index = m_squareBracketStartIndex + 1;
|
|
|
|
|
if (m_text.midRef(index).startsWith("-Wclazy"))
|
|
|
|
|
return QCoreApplication::translate("ClangDiagnosticWidget", "Clazy Issue");
|
|
|
|
|
else
|
|
|
|
|
return QCoreApplication::translate("ClangDiagnosticWidget", "Clang-Tidy Issue");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const QString m_text;
|
|
|
|
|
const int m_squareBracketStartIndex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Diagnostics from clazy/tidy do not have any category or option set but
|
|
|
|
|
// we will conclude them from the diagnostic message.
|
|
|
|
|
//
|
|
|
|
|
// Ideally, libclang should provide the correct category/option by default.
|
|
|
|
|
// However, tidy and clazy diagnostics use "custom diagnostic ids" and
|
|
|
|
|
// clang's static diagnostic table does not know anything about them.
|
|
|
|
|
//
|
|
|
|
|
// For clazy/tidy diagnostics, we expect something like "some text [some option]", e.g.:
|
|
|
|
|
// * clazy: "Use the static QFileInfo::exists() instead. It's documented to be faster. [-Wclazy-qfileinfo-exists]"
|
|
|
|
|
// * tidy: "use emplace_back instead of push_back [modernize-use-emplace]"
|
|
|
|
|
static ClangBackEnd::DiagnosticContainer supplementedDiagnostic(
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
|
|
|
|
if (!diagnostic.category.isEmpty() && !diagnostic.enableOption.isEmpty())
|
|
|
|
|
return diagnostic; // OK, diagnostics from clang have this set.
|
|
|
|
|
|
|
|
|
|
ClangBackEnd::DiagnosticContainer supplementedDiagnostic = diagnostic;
|
|
|
|
|
|
|
|
|
|
DiagnosticTextInfo info(diagnostic.text);
|
|
|
|
|
supplementedDiagnostic.enableOption = info.option();
|
|
|
|
|
supplementedDiagnostic.category = info.category();
|
|
|
|
|
supplementedDiagnostic.text = info.textWithoutOption();
|
|
|
|
|
|
|
|
|
|
for (auto &child : supplementedDiagnostic.children)
|
|
|
|
|
child.text = DiagnosticTextInfo(diagnostic.text.toString()).textWithoutOption();
|
|
|
|
|
|
|
|
|
|
return supplementedDiagnostic;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString tableRows(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
|
|
|
|
m_mainFilePath = m_displayHints.showFileNameInMainDiagnostic
|
|
|
|
|
? Utf8String()
|
2018-04-04 18:25:23 +02:00
|
|
|
: diagnostic.location.filePath;
|
2016-10-18 18:01:57 +02:00
|
|
|
|
2018-05-11 12:47:54 +02:00
|
|
|
const ClangBackEnd::DiagnosticContainer diag = supplementedDiagnostic(diagnostic);
|
2016-10-18 18:01:57 +02:00
|
|
|
|
2018-05-11 12:47:54 +02:00
|
|
|
QString text;
|
|
|
|
|
if (m_displayHints.showCategoryAndEnableOption)
|
|
|
|
|
text.append(diagnosticCategoryAndEnableOptionRow(diag));
|
|
|
|
|
text.append(diagnosticRow(diag, IndentMode::DoNotIndent));
|
|
|
|
|
text.append(diagnosticRowsForChildren(diag));
|
2016-02-12 16:41:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return text;
|
2016-02-12 16:41:45 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
static QString diagnosticCategoryAndEnableOptionRow(
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
|
|
|
|
const QString text = QString::fromLatin1(
|
|
|
|
|
" <tr>"
|
|
|
|
|
" <td align='left'><b>%1</b></td>"
|
2017-03-23 12:43:02 +01:00
|
|
|
" <td align='right'> <font color='gray'>%2</font></td>"
|
2016-10-18 18:01:57 +02:00
|
|
|
" </tr>")
|
2018-04-04 18:25:23 +02:00
|
|
|
.arg(diagnostic.category, diagnostic.enableOption);
|
2016-02-12 16:41:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return text;
|
|
|
|
|
}
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString diagnosticText(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
|
|
|
|
const bool hasFixit = m_displayHints.enableClickableFixits
|
2018-04-04 18:25:23 +02:00
|
|
|
&& !diagnostic.fixIts.isEmpty();
|
|
|
|
|
const QString diagnosticText = diagnostic.text.toString().toHtmlEscaped();
|
2017-03-23 12:23:22 +01:00
|
|
|
const QString text = QString::fromLatin1("%1: %2")
|
2016-10-18 18:01:57 +02:00
|
|
|
.arg(clickableLocation(diagnostic, m_mainFilePath),
|
|
|
|
|
clickableFixIt(diagnostic, diagnosticText, hasFixit));
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return text;
|
|
|
|
|
}
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString diagnosticRow(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
|
|
|
|
IndentMode indentMode)
|
|
|
|
|
{
|
|
|
|
|
const QString text = QString::fromLatin1(
|
|
|
|
|
" <tr>"
|
|
|
|
|
" <td colspan='2' align='left' style='%1'>%2</td>"
|
|
|
|
|
" </tr>")
|
|
|
|
|
.arg(indentModeToHtmlStyle(indentMode),
|
|
|
|
|
diagnosticText(diagnostic));
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return text;
|
|
|
|
|
}
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString diagnosticRowsForChildren(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer> &children = diagnostic.children;
|
2016-10-18 18:01:57 +02:00
|
|
|
QString text;
|
|
|
|
|
|
|
|
|
|
if (children.size() <= 10) {
|
|
|
|
|
text += diagnosticRowsForChildren(children.begin(), children.end());
|
|
|
|
|
} else {
|
|
|
|
|
text += diagnosticRowsForChildren(children.begin(), children.begin() + 7);
|
|
|
|
|
text += ellipsisRow();
|
|
|
|
|
text += diagnosticRowsForChildren(children.end() - 3, children.end());
|
|
|
|
|
}
|
2016-02-12 16:41:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return text;
|
|
|
|
|
}
|
2016-02-12 16:41:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString diagnosticRowsForChildren(
|
|
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator first,
|
|
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator last)
|
2016-01-29 17:17:18 +01:00
|
|
|
{
|
2016-10-18 18:01:57 +02:00
|
|
|
QString text;
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
for (auto it = first; it != last; ++it)
|
|
|
|
|
text.append(diagnosticRow(*it, IndentMode::Indent));
|
|
|
|
|
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString clickableLocation(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
|
|
|
|
const QString &mainFilePath)
|
|
|
|
|
{
|
2018-04-04 18:25:23 +02:00
|
|
|
const ClangBackEnd::SourceLocationContainer &location = diagnostic.location;
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
const QString filePrefix = fileNamePrefix(mainFilePath, location);
|
|
|
|
|
const QString lineColumn = locationToString(location);
|
|
|
|
|
const QString linkText = filePrefix + lineColumn;
|
|
|
|
|
const QString targetId = generateTargetId(LINK_ACTION_GOTO_LOCATION, diagnostic);
|
2016-10-04 16:23:42 +02:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return wrapInLink(linkText, targetId);
|
|
|
|
|
}
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString clickableFixIt(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
|
|
|
|
const QString &text,
|
|
|
|
|
bool hasFixIt)
|
|
|
|
|
{
|
|
|
|
|
if (!hasFixIt)
|
|
|
|
|
return text;
|
|
|
|
|
|
|
|
|
|
QString clickableText = text;
|
|
|
|
|
QString nonClickableCategory;
|
|
|
|
|
const int colonPosition = text.indexOf(QStringLiteral(": "));
|
|
|
|
|
|
|
|
|
|
if (colonPosition != -1) {
|
|
|
|
|
nonClickableCategory = text.mid(0, colonPosition + 2);
|
|
|
|
|
clickableText = text.mid(colonPosition + 2);
|
2016-10-04 16:23:42 +02:00
|
|
|
}
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
const QString targetId = generateTargetId(LINK_ACTION_APPLY_FIX, diagnostic);
|
2016-01-29 17:17:18 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
return nonClickableCategory + wrapInLink(clickableText, targetId);
|
2016-01-29 17:17:18 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QString generateTargetId(const QString &targetPrefix,
|
|
|
|
|
const ClangBackEnd::DiagnosticContainer &diagnostic)
|
|
|
|
|
{
|
|
|
|
|
const QString idAsString = QString::number(++m_targetIdCounter);
|
|
|
|
|
const QString targetId = targetPrefix + idAsString;
|
|
|
|
|
m_targetIdsToDiagnostics.insert(targetId, diagnostic);
|
|
|
|
|
|
|
|
|
|
return targetId;
|
2016-10-04 16:23:42 +02:00
|
|
|
}
|
2016-02-10 14:05:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
static QString wrapInLink(const QString &text, const QString &target)
|
|
|
|
|
{
|
|
|
|
|
return QStringLiteral("<a href='%1' style='text-decoration:none'>%2</a>").arg(target, text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static QString ellipsisRow()
|
|
|
|
|
{
|
|
|
|
|
return QString::fromLatin1(
|
|
|
|
|
" <tr>"
|
|
|
|
|
" <td colspan='2' align='left' style='%1'>...</td>"
|
|
|
|
|
" </tr>")
|
|
|
|
|
.arg(indentModeToHtmlStyle(IndentMode::Indent));
|
|
|
|
|
}
|
2016-02-10 14:05:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
static QString indentModeToHtmlStyle(IndentMode indentMode)
|
|
|
|
|
{
|
|
|
|
|
return indentMode == IndentMode::Indent
|
|
|
|
|
? QString("padding-left:10px")
|
|
|
|
|
: QString();
|
|
|
|
|
}
|
2016-02-10 14:05:45 +01:00
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
static int widthLimit()
|
|
|
|
|
{
|
|
|
|
|
return QApplication::desktop()->availableGeometry(QCursor::pos()).width() / 2;
|
2016-02-10 14:05:45 +01:00
|
|
|
}
|
2016-10-18 18:01:57 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const DisplayHints m_displayHints;
|
|
|
|
|
|
|
|
|
|
using TargetIdToDiagnosticTable = QHash<QString, ClangBackEnd::DiagnosticContainer>;
|
|
|
|
|
TargetIdToDiagnosticTable m_targetIdsToDiagnostics;
|
|
|
|
|
unsigned m_targetIdCounter = 0;
|
|
|
|
|
|
|
|
|
|
QString m_mainFilePath;
|
|
|
|
|
};
|
2016-02-10 14:05:45 +01:00
|
|
|
|
2016-01-29 17:17:18 +01:00
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
namespace ClangCodeModel {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2016-10-18 18:01:57 +02:00
|
|
|
QWidget *ClangDiagnosticWidget::create(
|
|
|
|
|
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
|
|
|
|
const Destination &destination)
|
2016-01-29 17:17:18 +01:00
|
|
|
{
|
2016-10-18 18:01:57 +02:00
|
|
|
WidgetFromDiagnostics::DisplayHints hints;
|
|
|
|
|
|
|
|
|
|
if (destination == ToolTip) {
|
|
|
|
|
hints.showCategoryAndEnableOption = true;
|
|
|
|
|
hints.showFileNameInMainDiagnostic = false;
|
|
|
|
|
hints.enableClickableFixits = true;
|
|
|
|
|
hints.limitWidth = true;
|
|
|
|
|
hints.hideTooltipAfterLinkActivation = true;
|
|
|
|
|
} else { // Info Bar
|
|
|
|
|
hints.showCategoryAndEnableOption = false;
|
|
|
|
|
hints.showFileNameInMainDiagnostic = true;
|
|
|
|
|
// Clickable fixits might change toolchain headers, so disable.
|
|
|
|
|
hints.enableClickableFixits = false;
|
|
|
|
|
hints.limitWidth = false;
|
|
|
|
|
hints.hideTooltipAfterLinkActivation = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return WidgetFromDiagnostics::create(diagnostics, hints);
|
2016-01-29 17:17:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace ClangCodeModel
|