forked from qt-creator/qt-creator
Clang: Show info bar for parse errors in header files
...because those errors can lead to a substantial performance/functional regression. The actual diagnostics (possibly with children) are shown as details in the info bar. The info bar can be hidden with the "Do Not Show Again" button. Re-enabling the info bar is possible with the new editor tool bar button. Change-Id: I03394ff8e3c84127946b0b791930b28a385f5a46 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -182,7 +182,9 @@ void IpcReceiver::documentAnnotationsChanged(const DocumentAnnotationsChangedMes
|
||||
const QString documentProjectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
|
||||
if (projectPartId == documentProjectPartId) {
|
||||
const quint32 documentRevision = message.fileContainer().documentRevision();
|
||||
processor->updateCodeWarnings(message.diagnostics(), documentRevision);
|
||||
processor->updateCodeWarnings(message.diagnostics(),
|
||||
message.firstHeaderErrorDiagnostic(),
|
||||
documentRevision);
|
||||
processor->updateHighlighting(message.highlightingMarks(),
|
||||
message.skippedPreprocessorRanges(),
|
||||
documentRevision);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <utils/proxyaction.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTextBlock>
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -129,9 +129,10 @@ enum IndentType { IndentDiagnostic, DoNotIndentDiagnostic };
|
||||
|
||||
QWidget *createDiagnosticLabel(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||
const QString &mainFilePath,
|
||||
IndentType indentType = DoNotIndentDiagnostic)
|
||||
IndentType indentType = DoNotIndentDiagnostic,
|
||||
bool enableClickableFixits = true)
|
||||
{
|
||||
const bool hasFixit = !diagnostic.fixIts().isEmpty();
|
||||
const bool hasFixit = enableClickableFixits ? !diagnostic.fixIts().isEmpty() : false;
|
||||
const QString diagnosticText = diagnostic.text().toString().toHtmlEscaped();
|
||||
const QString text = clickableLocation(mainFilePath, diagnostic.location())
|
||||
+ QStringLiteral(": ")
|
||||
@@ -159,25 +160,35 @@ class MainDiagnosticWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainDiagnosticWidget(const ClangBackEnd::DiagnosticContainer &diagnostic)
|
||||
MainDiagnosticWidget(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||
const ClangCodeModel::Internal::DisplayHints &displayHints)
|
||||
{
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
auto *mainLayout = createLayout<QVBoxLayout>();
|
||||
|
||||
// Set up header row: category + responsible option
|
||||
const QString category = diagnostic.category();
|
||||
const QString responsibleOption = diagnostic.enableOption();
|
||||
const ClangBackEnd::SourceLocationContainer location = diagnostic.location();
|
||||
|
||||
auto *headerLayout = createLayout<QHBoxLayout>();
|
||||
headerLayout->addWidget(new QLabel(wrapInBoldTags(category)), 1);
|
||||
// Set up header row: category + responsible option
|
||||
if (displayHints.showMainDiagnosticHeader) {
|
||||
const QString category = diagnostic.category();
|
||||
const QString responsibleOption = diagnostic.enableOption();
|
||||
|
||||
auto *responsibleOptionLabel = new QLabel(wrapInColor(responsibleOption, "gray"));
|
||||
headerLayout->addWidget(responsibleOptionLabel, 0);
|
||||
mainLayout->addLayout(headerLayout);
|
||||
auto *headerLayout = createLayout<QHBoxLayout>();
|
||||
headerLayout->addWidget(new QLabel(wrapInBoldTags(category)), 1);
|
||||
|
||||
auto *responsibleOptionLabel = new QLabel(wrapInColor(responsibleOption, "gray"));
|
||||
headerLayout->addWidget(responsibleOptionLabel, 0);
|
||||
mainLayout->addLayout(headerLayout);
|
||||
}
|
||||
|
||||
// Set up main row: diagnostic text
|
||||
mainLayout->addWidget(createDiagnosticLabel(diagnostic, location.filePath()));
|
||||
const Utf8String mainFilePath = displayHints.showFileNameInMainDiagnostic
|
||||
? Utf8String()
|
||||
: location.filePath();
|
||||
mainLayout->addWidget(createDiagnosticLabel(diagnostic,
|
||||
mainFilePath,
|
||||
DoNotIndentDiagnostic,
|
||||
displayHints.enableClickableFixits));
|
||||
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
@@ -186,26 +197,35 @@ public:
|
||||
void addChildrenToLayout(const QString &mainFilePath,
|
||||
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator first,
|
||||
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator last,
|
||||
bool enableClickableFixits,
|
||||
QLayout &boxLayout)
|
||||
{
|
||||
for (auto it = first; it != last; ++it)
|
||||
boxLayout.addWidget(createDiagnosticLabel(*it, mainFilePath, IndentDiagnostic));
|
||||
for (auto it = first; it != last; ++it) {
|
||||
boxLayout.addWidget(createDiagnosticLabel(*it,
|
||||
mainFilePath,
|
||||
IndentDiagnostic,
|
||||
enableClickableFixits));
|
||||
}
|
||||
}
|
||||
|
||||
void setupChildDiagnostics(const QString &mainFilePath,
|
||||
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
bool enableClickableFixits,
|
||||
QLayout &boxLayout)
|
||||
{
|
||||
if (diagnostics.size() <= 10) {
|
||||
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.end(), boxLayout);
|
||||
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.end(),
|
||||
enableClickableFixits, boxLayout);
|
||||
} else {
|
||||
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.begin() + 7, boxLayout);
|
||||
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.begin() + 7,
|
||||
enableClickableFixits, boxLayout);
|
||||
|
||||
auto ellipsisLabel = new QLabel(QStringLiteral("..."));
|
||||
ellipsisLabel->setContentsMargins(childIndentationOnTheLeftInPixel, 0, 0, 0);
|
||||
boxLayout.addWidget(ellipsisLabel);
|
||||
|
||||
addChildrenToLayout(mainFilePath, diagnostics.end() - 3, diagnostics.end(), boxLayout);
|
||||
addChildrenToLayout(mainFilePath, diagnostics.end() - 3, diagnostics.end(),
|
||||
enableClickableFixits, boxLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,13 +234,18 @@ void setupChildDiagnostics(const QString &mainFilePath,
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic, QLayout *target)
|
||||
void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||
QLayout *target,
|
||||
const DisplayHints &displayHints)
|
||||
{
|
||||
// Set up header and text row for main diagnostic
|
||||
target->addWidget(new MainDiagnosticWidget(diagnostic));
|
||||
target->addWidget(new MainDiagnosticWidget(diagnostic, displayHints));
|
||||
|
||||
// Set up child rows for notes
|
||||
setupChildDiagnostics(diagnostic.location().filePath(), diagnostic.children(), *target);
|
||||
setupChildDiagnostics(diagnostic.location().filePath(),
|
||||
diagnostic.children(),
|
||||
displayHints.enableClickableFixits,
|
||||
*target);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -34,7 +34,15 @@ QT_END_NAMESPACE
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
|
||||
void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic, QLayout *target);
|
||||
struct DisplayHints {
|
||||
bool showMainDiagnosticHeader = true;
|
||||
bool showFileNameInMainDiagnostic = false;
|
||||
bool enableClickableFixits = true;
|
||||
};
|
||||
|
||||
void addToolTipToLayout(const ClangBackEnd::DiagnosticContainer &diagnostic,
|
||||
QLayout *target,
|
||||
const DisplayHints &displayHints = DisplayHints());
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ClangCodeModel
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#include <utils/runextensions.h>
|
||||
|
||||
#include <QTextBlock>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
namespace ClangCodeModel {
|
||||
namespace Internal {
|
||||
@@ -167,14 +169,21 @@ void ClangEditorDocumentProcessor::clearProjectPart()
|
||||
m_projectPart.clear();
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
uint documentRevision)
|
||||
void ClangEditorDocumentProcessor::updateCodeWarnings(
|
||||
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
|
||||
uint documentRevision)
|
||||
{
|
||||
if (documentRevision == revision()) {
|
||||
m_diagnosticManager.processNewDiagnostics(diagnostics);
|
||||
const auto codeWarnings = m_diagnosticManager.takeExtraSelections();
|
||||
const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers();
|
||||
emit codeWarningsUpdated(revision(), codeWarnings, fixitAvailableMarkers);
|
||||
const auto creator = creatorForHeaderErrorDiagnosticWidget(firstHeaderErrorDiagnostic);
|
||||
|
||||
emit codeWarningsUpdated(revision(),
|
||||
codeWarnings,
|
||||
creator,
|
||||
fixitAvailableMarkers);
|
||||
}
|
||||
}
|
||||
namespace {
|
||||
@@ -333,6 +342,38 @@ void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &pro
|
||||
m_ipcCommunicator.requestDocumentAnnotations(fileContainer);
|
||||
}
|
||||
|
||||
static Internal::DisplayHints displayHintsForInfoBar()
|
||||
{
|
||||
Internal::DisplayHints displayHints;
|
||||
displayHints.showMainDiagnosticHeader = false;
|
||||
displayHints.showFileNameInMainDiagnostic = true;
|
||||
displayHints.enableClickableFixits = false; // Tool chain headers might be changed, so disable.
|
||||
|
||||
return displayHints;
|
||||
}
|
||||
|
||||
CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator
|
||||
ClangEditorDocumentProcessor::creatorForHeaderErrorDiagnosticWidget(
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic)
|
||||
{
|
||||
if (firstHeaderErrorDiagnostic.text().isEmpty())
|
||||
return CppTools::BaseEditorDocumentProcessor::HeaderErrorDiagnosticWidgetCreator();
|
||||
|
||||
return [firstHeaderErrorDiagnostic]() {
|
||||
auto vbox = new QVBoxLayout;
|
||||
vbox->setMargin(0);
|
||||
vbox->setContentsMargins(10, 0, 0, 2);
|
||||
vbox->setSpacing(2);
|
||||
|
||||
addToolTipToLayout(firstHeaderErrorDiagnostic, vbox, displayHintsForInfoBar());
|
||||
|
||||
auto widget = new QWidget;
|
||||
widget->setLayout(vbox);
|
||||
|
||||
return widget;
|
||||
};
|
||||
}
|
||||
|
||||
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
|
||||
{
|
||||
if (projectPart)
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
void clearProjectPart();
|
||||
|
||||
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
|
||||
uint documentRevision);
|
||||
void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
|
||||
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
|
||||
@@ -96,6 +97,8 @@ private:
|
||||
void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
|
||||
void updateTranslationUnitIfProjectPartExists();
|
||||
void requestDocumentAnnotations(const QString &projectpartId);
|
||||
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
|
||||
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
|
||||
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
|
||||
ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const;
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ void ClangTextMark::setIcon(ClangBackEnd::DiagnosticSeverity severity)
|
||||
|
||||
bool ClangTextMark::addToolTipContent(QLayout *target)
|
||||
{
|
||||
Internal::addToolTipToLayout(m_diagnostic, target);
|
||||
Internal::addToolTipToLayout(m_diagnostic, target, Internal::DisplayHints());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user