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:
@@ -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 << ")";
|
||||||
|
@@ -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_;
|
||||||
};
|
};
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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:
|
||||||
|
@@ -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";
|
||||||
|
@@ -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,
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
197
tests/unit/unittest/clangtranslationunit-test.cpp
Normal file
197
tests/unit/unittest/clangtranslationunit-test.cpp
Normal 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
|
@@ -277,6 +277,7 @@ TEST_F(ClientServerInProcess, SendDocumentAnnotationsChangedMessage)
|
|||||||
|
|
||||||
ClangBackEnd::DocumentAnnotationsChangedMessage message(fileContainer,
|
ClangBackEnd::DocumentAnnotationsChangedMessage message(fileContainer,
|
||||||
{diagnostic},
|
{diagnostic},
|
||||||
|
{},
|
||||||
{highlightingMark},
|
{highlightingMark},
|
||||||
QVector<SourceRangeContainer>());
|
QVector<SourceRangeContainer>());
|
||||||
|
|
||||||
|
@@ -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>()));
|
||||||
}
|
}
|
||||||
|
@@ -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 \
|
||||||
|
Reference in New Issue
Block a user