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:
Nikolai Kosjar
2016-10-04 16:23:42 +02:00
parent cb24872f43
commit 9d55d8485c
25 changed files with 458 additions and 44 deletions

View File

@@ -37,6 +37,7 @@ QDebug operator<<(QDebug debug, const DocumentAnnotationsChangedMessage &message
debug.nospace() << "DocumentAnnotationsChangedMessage(" debug.nospace() << "DocumentAnnotationsChangedMessage("
<< message.fileContainer() << message.fileContainer()
<< ", " << message.diagnostics().size() << ", " << message.diagnostics().size()
<< ", " << !message.firstHeaderErrorDiagnostic().text().isEmpty()
<< ", " << message.highlightingMarks().size() << ", " << message.highlightingMarks().size()
<< ", " << message.skippedPreprocessorRanges().size() << ", " << message.skippedPreprocessorRanges().size()
<< ")"; << ")";
@@ -49,6 +50,7 @@ void PrintTo(const DocumentAnnotationsChangedMessage &message, ::std::ostream* o
*os << "DocumentAnnotationsChangedMessage("; *os << "DocumentAnnotationsChangedMessage(";
PrintTo(message.fileContainer(), os); PrintTo(message.fileContainer(), os);
*os << "," << message.diagnostics().size(); *os << "," << message.diagnostics().size();
*os << "," << !message.firstHeaderErrorDiagnostic().text().isEmpty();
*os << "," << message.highlightingMarks().size(); *os << "," << message.highlightingMarks().size();
*os << "," << message.skippedPreprocessorRanges().size(); *os << "," << message.skippedPreprocessorRanges().size();
*os << ")"; *os << ")";

View File

@@ -41,10 +41,12 @@ public:
DocumentAnnotationsChangedMessage() = default; DocumentAnnotationsChangedMessage() = default;
DocumentAnnotationsChangedMessage(const FileContainer &fileContainer, DocumentAnnotationsChangedMessage(const FileContainer &fileContainer,
const QVector<DiagnosticContainer> &diagnostics, const QVector<DiagnosticContainer> &diagnostics,
const DiagnosticContainer &firstHeaderErrorDiagnostic_,
const QVector<HighlightingMarkContainer> &highlightingMarks, const QVector<HighlightingMarkContainer> &highlightingMarks,
const QVector<SourceRangeContainer> &skippedPreprocessorRanges) const QVector<SourceRangeContainer> &skippedPreprocessorRanges)
: fileContainer_(fileContainer), : fileContainer_(fileContainer),
diagnostics_(diagnostics), diagnostics_(diagnostics),
firstHeaderErrorDiagnostic_(firstHeaderErrorDiagnostic_),
highlightingMarks_(highlightingMarks), highlightingMarks_(highlightingMarks),
skippedPreprocessorRanges_(skippedPreprocessorRanges) skippedPreprocessorRanges_(skippedPreprocessorRanges)
{ {
@@ -60,6 +62,11 @@ public:
return diagnostics_; return diagnostics_;
} }
const DiagnosticContainer &firstHeaderErrorDiagnostic() const
{
return firstHeaderErrorDiagnostic_;
}
const QVector<HighlightingMarkContainer> &highlightingMarks() const const QVector<HighlightingMarkContainer> &highlightingMarks() const
{ {
return highlightingMarks_; return highlightingMarks_;
@@ -74,6 +81,7 @@ public:
{ {
out << message.fileContainer_; out << message.fileContainer_;
out << message.diagnostics_; out << message.diagnostics_;
out << message.firstHeaderErrorDiagnostic_;
out << message.highlightingMarks_; out << message.highlightingMarks_;
out << message.skippedPreprocessorRanges_; out << message.skippedPreprocessorRanges_;
@@ -84,6 +92,7 @@ public:
{ {
in >> message.fileContainer_; in >> message.fileContainer_;
in >> message.diagnostics_; in >> message.diagnostics_;
in >> message.firstHeaderErrorDiagnostic_;
in >> message.highlightingMarks_; in >> message.highlightingMarks_;
in >> message.skippedPreprocessorRanges_; in >> message.skippedPreprocessorRanges_;
@@ -95,6 +104,7 @@ public:
{ {
return first.fileContainer_ == second.fileContainer_ return first.fileContainer_ == second.fileContainer_
&& first.diagnostics_ == second.diagnostics_ && first.diagnostics_ == second.diagnostics_
&& first.firstHeaderErrorDiagnostic_ == second.firstHeaderErrorDiagnostic_
&& first.highlightingMarks_ == second.highlightingMarks_ && first.highlightingMarks_ == second.highlightingMarks_
&& first.skippedPreprocessorRanges_ == second.skippedPreprocessorRanges_; && first.skippedPreprocessorRanges_ == second.skippedPreprocessorRanges_;
} }
@@ -102,6 +112,7 @@ public:
private: private:
FileContainer fileContainer_; FileContainer fileContainer_;
QVector<DiagnosticContainer> diagnostics_; QVector<DiagnosticContainer> diagnostics_;
DiagnosticContainer firstHeaderErrorDiagnostic_;
QVector<HighlightingMarkContainer> highlightingMarks_; QVector<HighlightingMarkContainer> highlightingMarks_;
QVector<SourceRangeContainer> skippedPreprocessorRanges_; QVector<SourceRangeContainer> skippedPreprocessorRanges_;
}; };

View File

@@ -182,7 +182,9 @@ void IpcReceiver::documentAnnotationsChanged(const DocumentAnnotationsChangedMes
const QString documentProjectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath); const QString documentProjectPartId = CppTools::CppToolsBridge::projectPartIdForFile(filePath);
if (projectPartId == documentProjectPartId) { if (projectPartId == documentProjectPartId) {
const quint32 documentRevision = message.fileContainer().documentRevision(); const quint32 documentRevision = message.fileContainer().documentRevision();
processor->updateCodeWarnings(message.diagnostics(), documentRevision); processor->updateCodeWarnings(message.diagnostics(),
message.firstHeaderErrorDiagnostic(),
documentRevision);
processor->updateHighlighting(message.highlightingMarks(), processor->updateHighlighting(message.highlightingMarks(),
message.skippedPreprocessorRanges(), message.skippedPreprocessorRanges(),
documentRevision); documentRevision);

View File

@@ -41,6 +41,7 @@
#include <utils/proxyaction.h> #include <utils/proxyaction.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QFileInfo>
#include <QTextBlock> #include <QTextBlock>
namespace { namespace {

View File

@@ -129,9 +129,10 @@ enum IndentType { IndentDiagnostic, DoNotIndentDiagnostic };
QWidget *createDiagnosticLabel(const ClangBackEnd::DiagnosticContainer &diagnostic, QWidget *createDiagnosticLabel(const ClangBackEnd::DiagnosticContainer &diagnostic,
const QString &mainFilePath, 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 diagnosticText = diagnostic.text().toString().toHtmlEscaped();
const QString text = clickableLocation(mainFilePath, diagnostic.location()) const QString text = clickableLocation(mainFilePath, diagnostic.location())
+ QStringLiteral(": ") + QStringLiteral(": ")
@@ -159,15 +160,18 @@ class MainDiagnosticWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
MainDiagnosticWidget(const ClangBackEnd::DiagnosticContainer &diagnostic) MainDiagnosticWidget(const ClangBackEnd::DiagnosticContainer &diagnostic,
const ClangCodeModel::Internal::DisplayHints &displayHints)
{ {
setContentsMargins(0, 0, 0, 0); setContentsMargins(0, 0, 0, 0);
auto *mainLayout = createLayout<QVBoxLayout>(); auto *mainLayout = createLayout<QVBoxLayout>();
const ClangBackEnd::SourceLocationContainer location = diagnostic.location();
// Set up header row: category + responsible option // Set up header row: category + responsible option
if (displayHints.showMainDiagnosticHeader) {
const QString category = diagnostic.category(); const QString category = diagnostic.category();
const QString responsibleOption = diagnostic.enableOption(); const QString responsibleOption = diagnostic.enableOption();
const ClangBackEnd::SourceLocationContainer location = diagnostic.location();
auto *headerLayout = createLayout<QHBoxLayout>(); auto *headerLayout = createLayout<QHBoxLayout>();
headerLayout->addWidget(new QLabel(wrapInBoldTags(category)), 1); headerLayout->addWidget(new QLabel(wrapInBoldTags(category)), 1);
@@ -175,9 +179,16 @@ public:
auto *responsibleOptionLabel = new QLabel(wrapInColor(responsibleOption, "gray")); auto *responsibleOptionLabel = new QLabel(wrapInColor(responsibleOption, "gray"));
headerLayout->addWidget(responsibleOptionLabel, 0); headerLayout->addWidget(responsibleOptionLabel, 0);
mainLayout->addLayout(headerLayout); mainLayout->addLayout(headerLayout);
}
// Set up main row: diagnostic text // 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); setLayout(mainLayout);
} }
@@ -186,26 +197,35 @@ public:
void addChildrenToLayout(const QString &mainFilePath, void addChildrenToLayout(const QString &mainFilePath,
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator first, const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator first,
const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator last, const QVector<ClangBackEnd::DiagnosticContainer>::const_iterator last,
bool enableClickableFixits,
QLayout &boxLayout) QLayout &boxLayout)
{ {
for (auto it = first; it != last; ++it) for (auto it = first; it != last; ++it) {
boxLayout.addWidget(createDiagnosticLabel(*it, mainFilePath, IndentDiagnostic)); boxLayout.addWidget(createDiagnosticLabel(*it,
mainFilePath,
IndentDiagnostic,
enableClickableFixits));
}
} }
void setupChildDiagnostics(const QString &mainFilePath, void setupChildDiagnostics(const QString &mainFilePath,
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
bool enableClickableFixits,
QLayout &boxLayout) QLayout &boxLayout)
{ {
if (diagnostics.size() <= 10) { if (diagnostics.size() <= 10) {
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.end(), boxLayout); addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.end(),
enableClickableFixits, boxLayout);
} else { } else {
addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.begin() + 7, boxLayout); addChildrenToLayout(mainFilePath, diagnostics.begin(), diagnostics.begin() + 7,
enableClickableFixits, boxLayout);
auto ellipsisLabel = new QLabel(QStringLiteral("...")); auto ellipsisLabel = new QLabel(QStringLiteral("..."));
ellipsisLabel->setContentsMargins(childIndentationOnTheLeftInPixel, 0, 0, 0); ellipsisLabel->setContentsMargins(childIndentationOnTheLeftInPixel, 0, 0, 0);
boxLayout.addWidget(ellipsisLabel); 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 ClangCodeModel {
namespace Internal { 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 // 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 // Set up child rows for notes
setupChildDiagnostics(diagnostic.location().filePath(), diagnostic.children(), *target); setupChildDiagnostics(diagnostic.location().filePath(),
diagnostic.children(),
displayHints.enableClickableFixits,
*target);
} }
} // namespace Internal } // namespace Internal

View File

@@ -34,7 +34,15 @@ QT_END_NAMESPACE
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { 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 Internal
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -57,6 +57,8 @@
#include <utils/runextensions.h> #include <utils/runextensions.h>
#include <QTextBlock> #include <QTextBlock>
#include <QVBoxLayout>
#include <QWidget>
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
@@ -167,14 +169,21 @@ void ClangEditorDocumentProcessor::clearProjectPart()
m_projectPart.clear(); m_projectPart.clear();
} }
void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, void ClangEditorDocumentProcessor::updateCodeWarnings(
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision) uint documentRevision)
{ {
if (documentRevision == revision()) { if (documentRevision == revision()) {
m_diagnosticManager.processNewDiagnostics(diagnostics); m_diagnosticManager.processNewDiagnostics(diagnostics);
const auto codeWarnings = m_diagnosticManager.takeExtraSelections(); const auto codeWarnings = m_diagnosticManager.takeExtraSelections();
const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers(); const auto fixitAvailableMarkers = m_diagnosticManager.takeFixItAvailableMarkers();
emit codeWarningsUpdated(revision(), codeWarnings, fixitAvailableMarkers); const auto creator = creatorForHeaderErrorDiagnosticWidget(firstHeaderErrorDiagnostic);
emit codeWarningsUpdated(revision(),
codeWarnings,
creator,
fixitAvailableMarkers);
} }
} }
namespace { namespace {
@@ -333,6 +342,38 @@ void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &pro
m_ipcCommunicator.requestDocumentAnnotations(fileContainer); 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) static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
{ {
if (projectPart) if (projectPart)

View File

@@ -68,6 +68,7 @@ public:
void clearProjectPart(); void clearProjectPart();
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic,
uint documentRevision); uint documentRevision);
void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks, void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges, const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
@@ -96,6 +97,8 @@ private:
void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart); void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
void updateTranslationUnitIfProjectPartExists(); void updateTranslationUnitIfProjectPartExists();
void requestDocumentAnnotations(const QString &projectpartId); void requestDocumentAnnotations(const QString &projectpartId);
HeaderErrorDiagnosticWidgetCreator creatorForHeaderErrorDiagnosticWidget(
const ClangBackEnd::DiagnosticContainer &firstHeaderErrorDiagnostic);
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const; ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const; ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const;

View File

@@ -84,7 +84,7 @@ void ClangTextMark::setIcon(ClangBackEnd::DiagnosticSeverity severity)
bool ClangTextMark::addToolTipContent(QLayout *target) bool ClangTextMark::addToolTipContent(QLayout *target)
{ {
Internal::addToolTipToLayout(m_diagnostic, target); Internal::addToolTipToLayout(m_diagnostic, target, Internal::DisplayHints());
return true; return true;
} }

View File

@@ -44,6 +44,7 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/documentmodel.h> #include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/infobar.h>
#include <cpptools/cppchecksymbols.h> #include <cpptools/cppchecksymbols.h>
#include <cpptools/cppcodeformatter.h> #include <cpptools/cppcodeformatter.h>
@@ -77,6 +78,7 @@
#include <cplusplus/FastPreprocessor.h> #include <cplusplus/FastPreprocessor.h>
#include <cplusplus/MatchingText.h> #include <cplusplus/MatchingText.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/utilsicons.h>
#include <QApplication> #include <QApplication>
#include <QAction> #include <QAction>
@@ -126,9 +128,13 @@ public:
QSharedPointer<FunctionDeclDefLink> m_declDefLink; QSharedPointer<FunctionDeclDefLink> m_declDefLink;
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor; QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
QToolButton *m_preprocessorButton;
QToolButton *m_preprocessorButton = nullptr;
QToolButton *m_headerErrorsIndicatorButton = nullptr;
CppSelectionChanger m_cppSelectionChanger; CppSelectionChanger m_cppSelectionChanger;
CppEditorWidget::HeaderErrorDiagnosticWidgetCreator m_headerErrorDiagnosticWidgetCreator;
}; };
CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
@@ -139,7 +145,6 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q)
, m_useSelectionsUpdater(q) , m_useSelectionsUpdater(q)
, m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q)) , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q))
, m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q)) , m_followSymbolUnderCursor(new FollowSymbolUnderCursor(q))
, m_preprocessorButton(0)
, m_cppSelectionChanger() , m_cppSelectionChanger()
{ {
} }
@@ -224,7 +229,15 @@ void CppEditorWidget::finalizeInitialization()
connect(cmd, &Command::keySequenceChanged, this, &CppEditorWidget::updatePreprocessorButtonTooltip); connect(cmd, &Command::keySequenceChanged, this, &CppEditorWidget::updatePreprocessorButtonTooltip);
updatePreprocessorButtonTooltip(); updatePreprocessorButtonTooltip();
connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget); connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget);
d->m_headerErrorsIndicatorButton = new QToolButton(this);
d->m_headerErrorsIndicatorButton->setIcon(Utils::Icons::WARNING_TOOLBAR.pixmap());
connect(d->m_headerErrorsIndicatorButton, &QAbstractButton::clicked,
this, &CppEditorWidget::showHeaderErrorInfoBar);
d->m_headerErrorsIndicatorButton->setEnabled(false);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton); insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_headerErrorsIndicatorButton);
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget()); insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget());
} }
@@ -287,6 +300,7 @@ void CppEditorWidget::onCppDocumentUpdated()
void CppEditorWidget::onCodeWarningsUpdated(unsigned revision, void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
const QList<QTextEdit::ExtraSelection> selections, const QList<QTextEdit::ExtraSelection> selections,
const HeaderErrorDiagnosticWidgetCreator &creator,
const TextEditor::RefactorMarkers &refactorMarkers) const TextEditor::RefactorMarkers &refactorMarkers)
{ {
if (revision != documentRevision()) if (revision != documentRevision())
@@ -294,6 +308,9 @@ void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections); setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections);
setRefactorMarkers(refactorMarkersWithoutClangMarkers() + refactorMarkers); setRefactorMarkers(refactorMarkersWithoutClangMarkers() + refactorMarkers);
d->m_headerErrorDiagnosticWidgetCreator = creator;
updateHeaderErrorWidgets();
} }
void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision, void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
@@ -304,6 +321,24 @@ void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision,
setIfdefedOutBlocks(ifdefedOutBlocks); setIfdefedOutBlocks(ifdefedOutBlocks);
} }
void CppEditorWidget::updateHeaderErrorWidgets()
{
const Id id(Constants::ERRORS_IN_HEADER_FILES);
InfoBar *infoBar = textDocument()->infoBar();
infoBar->removeInfo(id);
if (d->m_headerErrorDiagnosticWidgetCreator) {
if (infoBar->canInfoBeAdded(id)) {
addHeaderErrorInfoBarEntryAndHideIndicator();
} else {
d->m_headerErrorsIndicatorButton->setEnabled(true);
}
} else {
d->m_headerErrorsIndicatorButton->setEnabled(false);
}
}
void CppEditorWidget::findUsages() void CppEditorWidget::findUsages()
{ {
if (!d->m_modelManager) if (!d->m_modelManager)
@@ -399,6 +434,25 @@ void CppEditorWidget::renameSymbolUnderCursorBuiltin()
renameUsages(); // Rename non-local symbol or macro renameUsages(); // Rename non-local symbol or macro
} }
void CppEditorWidget::addHeaderErrorInfoBarEntryAndHideIndicator() const
{
InfoBarEntry info(Constants::ERRORS_IN_HEADER_FILES,
tr("<b>Warning</b>: The code model could not parse an included file, "
"which might lead to slow or incorrect code completion and "
"highlighting, for example."),
InfoBarEntry::GlobalSuppressionEnabled);
info.setDetailsWidgetCreator(d->m_headerErrorDiagnosticWidgetCreator);
info.setShowDefaultCancelButton(false);
info.setSuppressionButtonInfo([this](){
d->m_headerErrorsIndicatorButton->setEnabled(true);
});
InfoBar *infoBar = textDocument()->infoBar();
infoBar->addInfo(info);
d->m_headerErrorsIndicatorButton->setEnabled(false);
}
namespace { namespace {
QList<ProjectPart::Ptr> fetchProjectParts(CppTools::CppModelManager *modelManager, QList<ProjectPart::Ptr> fetchProjectParts(CppTools::CppModelManager *modelManager,
@@ -970,5 +1024,14 @@ void CppEditorWidget::showPreProcessorWidget()
} }
} }
void CppEditorWidget::showHeaderErrorInfoBar()
{
const Id id(Constants::ERRORS_IN_HEADER_FILES);
QTC_CHECK(!textDocument()->infoBar()->canInfoBeAdded(id));
InfoBar::globallyUnsuppressInfo(id);
addHeaderErrorInfoBarEntryAndHideIndicator();
}
} // namespace Internal } // namespace Internal
} // namespace CppEditor } // namespace CppEditor

View File

@@ -31,6 +31,10 @@
#include <QScopedPointer> #include <QScopedPointer>
namespace Core {
class InfoBarEntry;
}
namespace CppTools { namespace CppTools {
class CppEditorOutline; class CppEditorOutline;
class RefactoringEngineInterface; class RefactoringEngineInterface;
@@ -87,6 +91,7 @@ public:
void switchDeclarationDefinition(bool inNextSplit); void switchDeclarationDefinition(bool inNextSplit);
void showPreProcessorWidget(); void showPreProcessorWidget();
void showHeaderErrorInfoBar();
void findUsages(); void findUsages();
void renameSymbolUnderCursor(); void renameSymbolUnderCursor();
@@ -108,6 +113,9 @@ protected:
void slotCodeStyleSettingsChanged(const QVariant &) override; void slotCodeStyleSettingsChanged(const QVariant &) override;
public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
private: private:
void updateFunctionDeclDefLink(); void updateFunctionDeclDefLink();
void updateFunctionDeclDefLinkNow(); void updateFunctionDeclDefLinkNow();
@@ -118,10 +126,12 @@ private:
void onCodeWarningsUpdated(unsigned revision, void onCodeWarningsUpdated(unsigned revision,
const QList<QTextEdit::ExtraSelection> selections, const QList<QTextEdit::ExtraSelection> selections,
const HeaderErrorDiagnosticWidgetCreator &creator,
const TextEditor::RefactorMarkers &refactorMarkers); const TextEditor::RefactorMarkers &refactorMarkers);
void onIfdefedOutBlocksUpdated(unsigned revision, void onIfdefedOutBlocksUpdated(unsigned revision,
const QList<TextEditor::BlockRange> ifdefedOutBlocks); const QList<TextEditor::BlockRange> ifdefedOutBlocks);
void updateHeaderErrorWidgets();
void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo, void updateSemanticInfo(const CppTools::SemanticInfo &semanticInfo,
bool updateUseSelectionSynchronously = false); bool updateUseSelectionSynchronously = false);
void updatePreprocessorButtonTooltip(); void updatePreprocessorButtonTooltip();
@@ -140,6 +150,8 @@ private:
void renameSymbolUnderCursorClang(); void renameSymbolUnderCursorClang();
void renameSymbolUnderCursorBuiltin(); void renameSymbolUnderCursorBuiltin();
void addHeaderErrorInfoBarEntryAndHideIndicator() const;
CppTools::ProjectPart *projectPart() const; CppTools::ProjectPart *projectPart() const;
private: private:

View File

@@ -36,6 +36,7 @@ const char OPEN_DECLARATION_DEFINITION_IN_NEXT_SPLIT[] = "CppEditor.OpenDeclarat
const char RENAME_SYMBOL_UNDER_CURSOR[] = "CppEditor.RenameSymbolUnderCursor"; const char RENAME_SYMBOL_UNDER_CURSOR[] = "CppEditor.RenameSymbolUnderCursor";
const char FIND_USAGES[] = "CppEditor.FindUsages"; const char FIND_USAGES[] = "CppEditor.FindUsages";
const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog"; const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog";
const char ERRORS_IN_HEADER_FILES[] = "CppEditor.ErrorsInHeaderFiles";
const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup"; const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup";
const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel"; const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel";
const char INSPECT_CPP_CODEMODEL[] = "CppEditor.InspectCppCodeModel"; const char INSPECT_CPP_CODEMODEL[] = "CppEditor.InspectCppCodeModel";

View File

@@ -59,9 +59,13 @@ public:
const QByteArray &defines); const QByteArray &defines);
void scheduleProcessDocument(); void scheduleProcessDocument();
public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
signals: signals:
void codeWarningsUpdated(unsigned contentsRevision, void codeWarningsUpdated(unsigned contentsRevision,
const QList<QTextEdit::ExtraSelection> selections, const QList<QTextEdit::ExtraSelection> selections,
const HeaderErrorDiagnosticWidgetCreator &creator,
const TextEditor::RefactorMarkers &refactorMarkers); const TextEditor::RefactorMarkers &refactorMarkers);
void ifdefedOutBlocksUpdated(unsigned contentsRevision, void ifdefedOutBlocksUpdated(unsigned contentsRevision,

View File

@@ -37,6 +37,8 @@
#include <QTextEdit> #include <QTextEdit>
#include <functional>
namespace TextEditor { namespace TextEditor {
class TextDocument; class TextDocument;
class QuickFixOperations; class QuickFixOperations;
@@ -69,10 +71,15 @@ public:
virtual void editorDocumentTimerRestarted(); virtual void editorDocumentTimerRestarted();
public:
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
signals: signals:
// Signal interface to implement // Signal interface to implement
void codeWarningsUpdated(unsigned revision, void codeWarningsUpdated(unsigned revision,
const QList<QTextEdit::ExtraSelection> selections, const QList<QTextEdit::ExtraSelection> selections,
const HeaderErrorDiagnosticWidgetCreator &creator,
const TextEditor::RefactorMarkers &refactorMarkers); const TextEditor::RefactorMarkers &refactorMarkers);
void ifdefedOutBlocksUpdated(unsigned revision, void ifdefedOutBlocksUpdated(unsigned revision,

View File

@@ -310,7 +310,10 @@ void BuiltinEditorDocumentProcessor::onCodeWarningsUpdated(
m_codeWarnings += toTextEditorSelections(codeWarnings, textDocument()); m_codeWarnings += toTextEditorSelections(codeWarnings, textDocument());
m_codeWarningsUpdated = true; m_codeWarningsUpdated = true;
emit codeWarningsUpdated(revision(), m_codeWarnings, TextEditor::RefactorMarkers()); emit codeWarningsUpdated(revision(),
m_codeWarnings,
HeaderErrorDiagnosticWidgetCreator(),
TextEditor::RefactorMarkers());
} }
SemanticInfo::Source BuiltinEditorDocumentProcessor::createSemanticInfoSource(bool force) const SemanticInfo::Source BuiltinEditorDocumentProcessor::createSemanticInfoSource(bool force) const

View File

@@ -40,7 +40,8 @@ static RequestDocumentAnnotationsJob::AsyncResult runAsyncHelper(
RequestDocumentAnnotationsJob::AsyncResult asyncResult; RequestDocumentAnnotationsJob::AsyncResult asyncResult;
translationUnit.extractDocumentAnnotations(asyncResult.diagnostics, translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
asyncResult.diagnostics,
asyncResult.highlightingMarks, asyncResult.highlightingMarks,
asyncResult.skippedSourceRanges); asyncResult.skippedSourceRanges);
@@ -83,6 +84,7 @@ void RequestDocumentAnnotationsJob::sendAnnotations(
{ {
const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer, const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer,
result.diagnostics, result.diagnostics,
result.firstHeaderErrorDiagnostic,
result.highlightingMarks, result.highlightingMarks,
result.skippedSourceRanges); result.skippedSourceRanges);

View File

@@ -36,6 +36,7 @@ namespace ClangBackEnd {
struct RequestDocumentAnnotationsJobResult struct RequestDocumentAnnotationsJobResult
{ {
ClangBackEnd::DiagnosticContainer firstHeaderErrorDiagnostic;
QVector<ClangBackEnd::DiagnosticContainer> diagnostics; QVector<ClangBackEnd::DiagnosticContainer> diagnostics;
QVector<HighlightingMarkContainer> highlightingMarks; QVector<HighlightingMarkContainer> highlightingMarks;
QVector<SourceRangeContainer> skippedSourceRanges; QVector<SourceRangeContainer> skippedSourceRanges;

View File

@@ -112,11 +112,12 @@ TranslationUnit::CodeCompletionResult TranslationUnit::complete(
} }
void TranslationUnit::extractDocumentAnnotations( void TranslationUnit::extractDocumentAnnotations(
QVector<DiagnosticContainer> &diagnostics, DiagnosticContainer &firstHeaderErrorDiagnostic,
QVector<DiagnosticContainer> &mainFileDiagnostics,
QVector<HighlightingMarkContainer> &highlightingMarks, QVector<HighlightingMarkContainer> &highlightingMarks,
QVector<SourceRangeContainer> &skippedSourceRanges) const QVector<SourceRangeContainer> &skippedSourceRanges) const
{ {
diagnostics = mainFileDiagnostics(); extractDiagnostics(firstHeaderErrorDiagnostic, mainFileDiagnostics);
highlightingMarks = this->highlightingMarks().toHighlightingMarksContainers(); highlightingMarks = this->highlightingMarks().toHighlightingMarksContainers();
skippedSourceRanges = this->skippedSourceRanges().toSourceRangeContainers(); skippedSourceRanges = this->skippedSourceRanges().toSourceRangeContainers();
} }
@@ -126,15 +127,6 @@ DiagnosticSet TranslationUnit::diagnostics() const
return DiagnosticSet(clang_getDiagnosticSetFromTU(m_cxTranslationUnit)); return DiagnosticSet(clang_getDiagnosticSetFromTU(m_cxTranslationUnit));
} }
QVector<DiagnosticContainer> TranslationUnit::mainFileDiagnostics() const
{
const auto isMainFileDiagnostic = [this](const Diagnostic &diagnostic) {
return diagnostic.location().filePath() == m_filePath;
};
return diagnostics().toDiagnosticContainers(isMainFileDiagnostic);
}
SourceLocation TranslationUnit::sourceLocationAt(uint line,uint column) const SourceLocation TranslationUnit::sourceLocationAt(uint line,uint column) const
{ {
return SourceLocation(m_cxTranslationUnit, m_filePath, line, column); return SourceLocation(m_cxTranslationUnit, m_filePath, line, column);
@@ -193,4 +185,35 @@ SkippedSourceRanges TranslationUnit::skippedSourceRanges() const
return SkippedSourceRanges(m_cxTranslationUnit, m_filePath.constData()); return SkippedSourceRanges(m_cxTranslationUnit, m_filePath.constData());
} }
static bool isMainFileDiagnostic(const Utf8String &mainFilePath, const Diagnostic &diagnostic)
{
return diagnostic.location().filePath() == mainFilePath;
}
static bool isHeaderErrorDiagnostic(const Utf8String &mainFilePath, const Diagnostic &diagnostic)
{
const bool isCritical = diagnostic.severity() == DiagnosticSeverity::Error
|| diagnostic.severity() == DiagnosticSeverity::Fatal;
return isCritical && diagnostic.location().filePath() != mainFilePath;
}
void TranslationUnit::extractDiagnostics(DiagnosticContainer &firstHeaderErrorDiagnostic,
QVector<DiagnosticContainer> &mainFileDiagnostics) const
{
mainFileDiagnostics.clear();
mainFileDiagnostics.reserve(int(diagnostics().size()));
bool hasFirstHeaderErrorDiagnostic = false;
for (const Diagnostic &diagnostic : diagnostics()) {
if (!hasFirstHeaderErrorDiagnostic && isHeaderErrorDiagnostic(m_filePath, diagnostic)) {
hasFirstHeaderErrorDiagnostic = true;
firstHeaderErrorDiagnostic = diagnostic.toDiagnosticContainer();
}
if (isMainFileDiagnostic(m_filePath, diagnostic))
mainFileDiagnostics.push_back(diagnostic.toDiagnosticContainer());
}
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -76,12 +76,14 @@ public:
CodeCompletionResult complete(UnsavedFiles &unsavedFiles, uint line, uint column) const; CodeCompletionResult complete(UnsavedFiles &unsavedFiles, uint line, uint column) const;
void extractDocumentAnnotations(QVector<DiagnosticContainer> &diagnostics, void extractDiagnostics(DiagnosticContainer &firstHeaderErrorDiagnostic,
QVector<DiagnosticContainer> &mainFileDiagnostics) const;
void extractDocumentAnnotations(DiagnosticContainer &firstHeaderErrorDiagnostic,
QVector<DiagnosticContainer> &mainFileDiagnostics,
QVector<HighlightingMarkContainer> &highlightingMarks, QVector<HighlightingMarkContainer> &highlightingMarks,
QVector<SourceRangeContainer> &skippedSourceRanges) const; QVector<SourceRangeContainer> &skippedSourceRanges) const;
DiagnosticSet diagnostics() const; DiagnosticSet diagnostics() const;
QVector<DiagnosticContainer> mainFileDiagnostics() const;
SourceLocation sourceLocationAt(uint line, uint column) const; SourceLocation sourceLocationAt(uint line, uint column) const;
SourceLocation sourceLocationAt(const Utf8String &filePath, uint line, uint column) const; SourceLocation sourceLocationAt(const Utf8String &filePath, uint line, uint column) const;

View File

@@ -45,7 +45,8 @@ static UpdateDocumentAnnotationsJob::AsyncResult runAsyncHelper(
asyncResult.updateResult = translationUnit.update(translationUnitUpdatInput); asyncResult.updateResult = translationUnit.update(translationUnitUpdatInput);
// Collect // Collect
translationUnit.extractDocumentAnnotations(asyncResult.diagnostics, translationUnit.extractDocumentAnnotations(asyncResult.firstHeaderErrorDiagnostic,
asyncResult.diagnostics,
asyncResult.highlightingMarks, asyncResult.highlightingMarks,
asyncResult.skippedSourceRanges); asyncResult.skippedSourceRanges);
@@ -95,6 +96,7 @@ void UpdateDocumentAnnotationsJob::sendAnnotations(const AsyncResult &result)
{ {
const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer, const DocumentAnnotationsChangedMessage message(m_pinnedFileContainer,
result.diagnostics, result.diagnostics,
result.firstHeaderErrorDiagnostic,
result.highlightingMarks, result.highlightingMarks,
result.skippedSourceRanges); result.skippedSourceRanges);

View File

@@ -39,6 +39,7 @@ struct UpdateDocumentAnnotationsJobResult
{ {
TranslationUnitUpdateResult updateResult; TranslationUnitUpdateResult updateResult;
ClangBackEnd::DiagnosticContainer firstHeaderErrorDiagnostic;
QVector<ClangBackEnd::DiagnosticContainer> diagnostics; QVector<ClangBackEnd::DiagnosticContainer> diagnostics;
QVector<HighlightingMarkContainer> highlightingMarks; QVector<HighlightingMarkContainer> highlightingMarks;
QVector<SourceRangeContainer> skippedSourceRanges; QVector<SourceRangeContainer> skippedSourceRanges;

View File

@@ -0,0 +1,197 @@
/****************************************************************************
**
** 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 <clangtranslationunit.h>
#include <clangtranslationunitupdater.h>
#include <diagnosticcontainer.h>
#include <utf8string.h>
#include <clang-c/Index.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
using ClangBackEnd::DiagnosticContainer;
using ClangBackEnd::TranslationUnit;
using ClangBackEnd::TranslationUnitUpdateInput;
using ClangBackEnd::TranslationUnitUpdateResult;
using testing::ContainerEq;
using testing::Eq;
namespace {
class TranslationUnit : public ::testing::Test
{
protected:
void SetUp() override;
void TearDown() override;
void parse();
void reparse();
DiagnosticContainer createDiagnostic(const QString &text,
ClangBackEnd::DiagnosticSeverity severity,
uint line,
uint column,
const QString &filePath) const;
QVector<DiagnosticContainer> diagnosticsFromMainFile() const;
QVector<DiagnosticContainer> errorDiagnosticsFromHeaders() const;
protected:
Utf8String sourceFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_source.cpp");
Utf8String headerFilePath = Utf8StringLiteral(TESTDATA_DIR"/diagnostic_erroneous_header.h");
CXIndex cxIndex = nullptr;
CXTranslationUnit cxTranslationUnit = nullptr;
::TranslationUnit translationUnit{Utf8String(), sourceFilePath, cxIndex, cxTranslationUnit};
DiagnosticContainer extractedFirstHeaderErrorDiagnostic;
QVector<DiagnosticContainer> extractedMainFileDiagnostics;
};
TEST_F(TranslationUnit, HasExpectedMainFileDiagnostics)
{
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
}
TEST_F(TranslationUnit, HasExpectedMainFileDiagnosticsAfterReparse)
{
reparse();
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedMainFileDiagnostics, ContainerEq(diagnosticsFromMainFile()));
}
TEST_F(TranslationUnit, HasErrorDiagnosticsInHeaders)
{
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
Eq(errorDiagnosticsFromHeaders().first()));
}
TEST_F(TranslationUnit, HasErrorDiagnosticsInHeadersAfterReparse)
{
reparse();
translationUnit.extractDiagnostics(extractedFirstHeaderErrorDiagnostic,
extractedMainFileDiagnostics);
ASSERT_THAT(extractedFirstHeaderErrorDiagnostic,
Eq(errorDiagnosticsFromHeaders().first()));
}
void TranslationUnit::SetUp()
{
parse();
}
void TranslationUnit::TearDown()
{
clang_disposeTranslationUnit(cxTranslationUnit);
clang_disposeIndex(cxIndex);
}
void TranslationUnit::parse()
{
TranslationUnitUpdateInput parseInput;
parseInput.filePath = sourceFilePath;
parseInput.parseNeeded = true;
const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
ASSERT_TRUE(parseResult.hasParsed());
}
void TranslationUnit::reparse()
{
TranslationUnitUpdateInput parseInput;
parseInput.filePath = sourceFilePath;
parseInput.reparseNeeded = true;
const TranslationUnitUpdateResult parseResult = translationUnit.update(parseInput);
ASSERT_TRUE(parseResult.hasReparsed());
}
DiagnosticContainer TranslationUnit::createDiagnostic(const QString &text,
ClangBackEnd::DiagnosticSeverity severity,
uint line,
uint column,
const QString &filePath) const
{
return DiagnosticContainer(
text,
Utf8StringLiteral(""),
{},
severity,
{filePath, line, column},
{},
{},
{}
);
}
QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::diagnosticsFromMainFile() const
{
return {
createDiagnostic(
QStringLiteral("warning: enumeration value 'Three' not handled in switch"),
ClangBackEnd::DiagnosticSeverity::Warning,
7,
13,
sourceFilePath),
createDiagnostic(
QStringLiteral("error: void function 'g' should not return a value"),
ClangBackEnd::DiagnosticSeverity::Error,
15,
5,
sourceFilePath),
createDiagnostic(
QStringLiteral("warning: using the result of an assignment as a condition without parentheses"),
ClangBackEnd::DiagnosticSeverity::Warning,
21,
11,
sourceFilePath),
};
}
QVector<ClangBackEnd::DiagnosticContainer> TranslationUnit::errorDiagnosticsFromHeaders() const
{
return {
createDiagnostic(
QStringLiteral("error: C++ requires a type specifier for all declarations"),
ClangBackEnd::DiagnosticSeverity::Error,
11,
1,
headerFilePath),
};
}
} // anonymous namespace

View File

@@ -277,6 +277,7 @@ TEST_F(ClientServerInProcess, SendDocumentAnnotationsChangedMessage)
ClangBackEnd::DocumentAnnotationsChangedMessage message(fileContainer, ClangBackEnd::DocumentAnnotationsChangedMessage message(fileContainer,
{diagnostic}, {diagnostic},
{},
{highlightingMark}, {highlightingMark},
QVector<SourceRangeContainer>()); QVector<SourceRangeContainer>());

View File

@@ -186,6 +186,7 @@ TEST_F(ReadAndWriteMessageBlock, CompareDocumentAnnotationsChangedMessage)
CompareMessage(ClangBackEnd::DocumentAnnotationsChangedMessage(fileContainer, CompareMessage(ClangBackEnd::DocumentAnnotationsChangedMessage(fileContainer,
{diagnostic}, {diagnostic},
{},
{highlightingMark}, {highlightingMark},
QVector<ClangBackEnd::SourceRangeContainer>())); QVector<ClangBackEnd::SourceRangeContainer>()));
} }

View File

@@ -61,6 +61,7 @@ SOURCES += \
clangrequestdocumentannotationsjob-test.cpp \ clangrequestdocumentannotationsjob-test.cpp \
clangsupportivetranslationunitinitializertest.cpp \ clangsupportivetranslationunitinitializertest.cpp \
clangstring-test.cpp \ clangstring-test.cpp \
clangtranslationunit-test.cpp \
clangtranslationunits-test.cpp \ clangtranslationunits-test.cpp \
clangupdatedocumentannotationsjob-test.cpp \ clangupdatedocumentannotationsjob-test.cpp \
codecompletionsextractor-test.cpp \ codecompletionsextractor-test.cpp \