forked from qt-creator/qt-creator
ClangTools: Show also diagnostics from project's header files
Fixes: QTCREATORBUG-21452 Change-Id: I73c85224e142f4f1d08c9ada75fe8359ebf0f984 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
@@ -407,7 +407,7 @@ void ClangTidyClazyTool::updateRunActions()
|
|||||||
m_startAction->setToolTip(toolTip);
|
m_startAction->setToolTip(toolTip);
|
||||||
m_startAction->setEnabled(canRun);
|
m_startAction->setEnabled(canRun);
|
||||||
m_stopAction->setEnabled(false);
|
m_stopAction->setEnabled(false);
|
||||||
m_clear->setEnabled(m_diagnosticModel->diagnosticsCount());
|
m_clear->setEnabled(m_diagnosticModel->diagnostics().count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +418,7 @@ void ClangTidyClazyTool::handleStateUpdate()
|
|||||||
QTC_ASSERT(m_diagnosticModel, return);
|
QTC_ASSERT(m_diagnosticModel, return);
|
||||||
QTC_ASSERT(m_diagnosticFilterModel, return);
|
QTC_ASSERT(m_diagnosticFilterModel, return);
|
||||||
|
|
||||||
const int issuesFound = m_diagnosticModel->diagnosticsCount();
|
const int issuesFound = m_diagnosticModel->diagnostics().count();
|
||||||
const int issuesVisible = m_diagnosticFilterModel->rowCount();
|
const int issuesVisible = m_diagnosticFilterModel->rowCount();
|
||||||
m_goBack->setEnabled(issuesVisible > 1);
|
m_goBack->setEnabled(issuesVisible > 1);
|
||||||
m_goNext->setEnabled(issuesVisible > 1);
|
m_goNext->setEnabled(issuesVisible > 1);
|
||||||
@@ -439,10 +439,11 @@ void ClangTidyClazyTool::handleStateUpdate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> ClangTidyClazyTool::read(const QString &filePath,
|
QList<Diagnostic> ClangTidyClazyTool::read(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const
|
QString *errorMessage) const
|
||||||
{
|
{
|
||||||
return readSerializedDiagnostics(filePath, logFilePath, errorMessage);
|
return readSerializedDiagnostics(filePath, projectRootDir, logFilePath, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -54,6 +54,7 @@ public:
|
|||||||
void startTool(bool askUserForFileSelection) final;
|
void startTool(bool askUserForFileSelection) final;
|
||||||
|
|
||||||
QList<Diagnostic> read(const QString &filePath,
|
QList<Diagnostic> read(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const final;
|
QString *errorMessage) const final;
|
||||||
|
|
||||||
|
@@ -135,7 +135,7 @@ void ClangTool::initDiagnosticView()
|
|||||||
m_diagnosticView->setAutoScroll(false);
|
m_diagnosticView->setAutoScroll(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> ClangTool::diagnostics() const
|
QSet<Diagnostic> ClangTool::diagnostics() const
|
||||||
{
|
{
|
||||||
return m_diagnosticModel->diagnostics();
|
return m_diagnosticModel->diagnostics();
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include <cpptools/projectinfo.h>
|
#include <cpptools/projectinfo.h>
|
||||||
|
|
||||||
namespace Debugger { class DetailedErrorView; }
|
namespace Debugger { class DetailedErrorView; }
|
||||||
|
namespace Utils { class FileName; }
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -49,6 +50,7 @@ public:
|
|||||||
virtual void startTool(bool askUserForFileSelection) = 0;
|
virtual void startTool(bool askUserForFileSelection) = 0;
|
||||||
|
|
||||||
virtual QList<Diagnostic> read(const QString &filePath,
|
virtual QList<Diagnostic> read(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
QString *errorMessage) const = 0;
|
QString *errorMessage) const = 0;
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ public:
|
|||||||
bool askUserForFileSelection) const;
|
bool askUserForFileSelection) const;
|
||||||
|
|
||||||
// For testing.
|
// For testing.
|
||||||
QList<Diagnostic> diagnostics() const;
|
QSet<Diagnostic> diagnostics() const;
|
||||||
|
|
||||||
const QString &name() const;
|
const QString &name() const;
|
||||||
|
|
||||||
|
@@ -387,13 +387,24 @@ void ClangToolRunControl::analyzeNextFile()
|
|||||||
Utils::StdOutFormat);
|
Utils::StdOutFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Utils::FileName cleanPath(const Utils::FileName &filePath)
|
||||||
|
{
|
||||||
|
return Utils::FileName::fromString(QDir::cleanPath(filePath.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath)
|
void ClangToolRunControl::onRunnerFinishedWithSuccess(const QString &filePath)
|
||||||
{
|
{
|
||||||
const QString logFilePath = qobject_cast<ClangToolRunner *>(sender())->logFilePath();
|
const QString logFilePath = qobject_cast<ClangToolRunner *>(sender())->logFilePath();
|
||||||
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << logFilePath;
|
qCDebug(LOG) << "onRunnerFinishedWithSuccess:" << logFilePath;
|
||||||
|
|
||||||
|
QTC_ASSERT(m_projectInfo.project(), return);
|
||||||
|
const Utils::FileName projectRootDir = cleanPath(m_projectInfo.project()->projectDirectory());
|
||||||
|
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
const QList<Diagnostic> diagnostics = tool()->read(filePath, logFilePath, &errorMessage);
|
const QList<Diagnostic> diagnostics = tool()->read(filePath,
|
||||||
|
projectRootDir,
|
||||||
|
logFilePath,
|
||||||
|
&errorMessage);
|
||||||
QFile::remove(logFilePath); // Clean-up.
|
QFile::remove(logFilePath); // Clean-up.
|
||||||
|
|
||||||
if (!errorMessage.isEmpty()) {
|
if (!errorMessage.isEmpty()) {
|
||||||
|
@@ -38,5 +38,13 @@ bool Diagnostic::isValid() const
|
|||||||
return !description.isEmpty();
|
return !description.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint32 qHash(const Diagnostic &diagnostic)
|
||||||
|
{
|
||||||
|
return qHash(diagnostic.description)
|
||||||
|
^ qHash(diagnostic.location.filePath)
|
||||||
|
^ diagnostic.location.line
|
||||||
|
^ diagnostic.location.column;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
@@ -66,6 +66,8 @@ public:
|
|||||||
bool hasFixits = false;
|
bool hasFixits = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
quint32 qHash(const Diagnostic &diagnostic);
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
|
||||||
|
@@ -35,9 +35,12 @@
|
|||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
static Q_LOGGING_CATEGORY(LOG, "qtc.clangtools.model", QtWarningMsg)
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -60,6 +63,19 @@ ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
|
|||||||
connectFileWatcher();
|
connectFileWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, const Diagnostic &d)
|
||||||
|
{
|
||||||
|
return debug << "category:" << d.category
|
||||||
|
<< "type:" << d.type
|
||||||
|
<< "context:" << d.issueContext
|
||||||
|
<< "contextKind:" << d.issueContextKind
|
||||||
|
<< "hasFixits:" << d.hasFixits
|
||||||
|
<< "explainingSteps:" << d.explainingSteps.size()
|
||||||
|
<< "location:" << d.location
|
||||||
|
<< "description:" << d.description
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
|
void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
|
||||||
{
|
{
|
||||||
const auto onFixitStatusChanged = [this](FixitStatus newStatus) {
|
const auto onFixitStatusChanged = [this](FixitStatus newStatus) {
|
||||||
@@ -70,28 +86,28 @@ void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnost
|
|||||||
emit fixItsToApplyCountChanged(m_fixItsToApplyCount);
|
emit fixItsToApplyCountChanged(m_fixItsToApplyCount);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!diagnostics.empty())
|
for (const Diagnostic &d : diagnostics) {
|
||||||
addWatchedPath(diagnostics.front().location.filePath);
|
const int previousItemCount = m_diagnostics.count();
|
||||||
|
m_diagnostics.insert(d);
|
||||||
|
if (m_diagnostics.count() == previousItemCount) {
|
||||||
|
qCDebug(LOG) << "Not adding duplicate diagnostic:" << d;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const Diagnostic &d : diagnostics)
|
qCDebug(LOG) << "Adding diagnostic:" << d;
|
||||||
|
addWatchedPath(d.location.filePath);
|
||||||
rootItem()->appendChild(new DiagnosticItem(d, onFixitStatusChanged, this));
|
rootItem()->appendChild(new DiagnosticItem(d, onFixitStatusChanged, this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> ClangToolsDiagnosticModel::diagnostics() const
|
QSet<Diagnostic> ClangToolsDiagnosticModel::diagnostics() const
|
||||||
{
|
{
|
||||||
QList<Diagnostic> diags;
|
return m_diagnostics;
|
||||||
for (const Utils::TreeItem * const item : *rootItem())
|
|
||||||
diags << static_cast<const DiagnosticItem *>(item)->diagnostic();
|
|
||||||
return diags;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ClangToolsDiagnosticModel::diagnosticsCount() const
|
|
||||||
{
|
|
||||||
return rootItem()->childCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangToolsDiagnosticModel::clear()
|
void ClangToolsDiagnosticModel::clear()
|
||||||
{
|
{
|
||||||
|
m_diagnostics.clear();
|
||||||
clearAndSetupCache();
|
clearAndSetupCache();
|
||||||
Utils::TreeModel<>::clear();
|
Utils::TreeModel<>::clear();
|
||||||
}
|
}
|
||||||
|
@@ -98,10 +98,8 @@ class ClangToolsDiagnosticModel : public Utils::TreeModel<>
|
|||||||
public:
|
public:
|
||||||
ClangToolsDiagnosticModel(QObject *parent = nullptr);
|
ClangToolsDiagnosticModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
virtual void addDiagnostics(const QList<Diagnostic> &diagnostics);
|
void addDiagnostics(const QList<Diagnostic> &diagnostics);
|
||||||
virtual QList<Diagnostic> diagnostics() const;
|
QSet<Diagnostic> diagnostics() const;
|
||||||
|
|
||||||
int diagnosticsCount() const;
|
|
||||||
|
|
||||||
enum ItemRole {
|
enum ItemRole {
|
||||||
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
|
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
|
||||||
@@ -121,6 +119,7 @@ private:
|
|||||||
void clearAndSetupCache();
|
void clearAndSetupCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QSet<Diagnostic> m_diagnostics;
|
||||||
std::map<QVector<ExplainingStep>, QVector<DiagnosticItem *>> stepsToItemsCache;
|
std::map<QVector<ExplainingStep>, QVector<DiagnosticItem *>> stepsToItemsCache;
|
||||||
std::unique_ptr<QFileSystemWatcher> m_filesWatcher;
|
std::unique_ptr<QFileSystemWatcher> m_filesWatcher;
|
||||||
int m_fixItsToApplyCount = 0;
|
int m_fixItsToApplyCount = 0;
|
||||||
|
@@ -59,6 +59,7 @@ static Debugger::DiagnosticLocation diagLocationFromSourceLocation(CXSourceLocat
|
|||||||
|
|
||||||
Debugger::DiagnosticLocation location;
|
Debugger::DiagnosticLocation location;
|
||||||
location.filePath = fromCXString(clang_getFileName(file));
|
location.filePath = fromCXString(clang_getFileName(file));
|
||||||
|
location.filePath = QDir::cleanPath(location.filePath); // Normalize to find duplicates later
|
||||||
location.line = line;
|
location.line = line;
|
||||||
location.column = column;
|
location.column = column;
|
||||||
return location;
|
return location;
|
||||||
@@ -118,7 +119,9 @@ static ExplainingStep buildFixIt(const CXDiagnostic cxDiagnostic, unsigned index
|
|||||||
return fixItStep;
|
return fixItStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic, const QString &nativeFilePath)
|
static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
|
const QString &nativeFilePath)
|
||||||
{
|
{
|
||||||
Diagnostic diagnostic;
|
Diagnostic diagnostic;
|
||||||
diagnostic.type = cxDiagnosticType(cxDiagnostic);
|
diagnostic.type = cxDiagnosticType(cxDiagnostic);
|
||||||
@@ -130,7 +133,13 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic, const QString
|
|||||||
return diagnostic;
|
return diagnostic;
|
||||||
|
|
||||||
diagnostic.location = diagLocationFromSourceLocation(cxLocation);
|
diagnostic.location = diagLocationFromSourceLocation(cxLocation);
|
||||||
if (diagnostic.location.filePath != nativeFilePath)
|
const auto diagnosticFilePath = Utils::FileName::fromString(diagnostic.location.filePath);
|
||||||
|
if (!diagnosticFilePath.isChildOf(projectRootDir))
|
||||||
|
return diagnostic;
|
||||||
|
|
||||||
|
// TODO: Introduce CppTools::ProjectFile::isGenerated to filter these out properly
|
||||||
|
const QString fileName = diagnosticFilePath.fileName();
|
||||||
|
if ((fileName.startsWith("ui_") && fileName.endsWith(".h")) || fileName.endsWith(".moc"))
|
||||||
return diagnostic;
|
return diagnostic;
|
||||||
|
|
||||||
CXDiagnosticSet cxChildDiagnostics = clang_getChildDiagnostics(cxDiagnostic);
|
CXDiagnosticSet cxChildDiagnostics = clang_getChildDiagnostics(cxDiagnostic);
|
||||||
@@ -165,6 +174,7 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic, const QString
|
|||||||
}
|
}
|
||||||
|
|
||||||
static QList<Diagnostic> readSerializedDiagnostics_helper(const QString &filePath,
|
static QList<Diagnostic> readSerializedDiagnostics_helper(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath)
|
const QString &logFilePath)
|
||||||
{
|
{
|
||||||
QList<Diagnostic> list;
|
QList<Diagnostic> list;
|
||||||
@@ -187,7 +197,7 @@ static QList<Diagnostic> readSerializedDiagnostics_helper(const QString &filePat
|
|||||||
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
||||||
clang_disposeDiagnostic(cxDiagnostic);
|
clang_disposeDiagnostic(cxDiagnostic);
|
||||||
});
|
});
|
||||||
const Diagnostic diagnostic = buildDiagnostic(cxDiagnostic, nativeFilePath);
|
const Diagnostic diagnostic = buildDiagnostic(cxDiagnostic, projectRootDir, nativeFilePath);
|
||||||
if (!diagnostic.isValid())
|
if (!diagnostic.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -213,13 +223,14 @@ static bool checkFilePath(const QString &filePath, QString *errorMessage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
|
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
QString *errorMessage)
|
QString *errorMessage)
|
||||||
{
|
{
|
||||||
if (!checkFilePath(logFilePath, errorMessage))
|
if (!checkFilePath(logFilePath, errorMessage))
|
||||||
return QList<Diagnostic>();
|
return QList<Diagnostic>();
|
||||||
|
|
||||||
return readSerializedDiagnostics_helper(filePath, logFilePath);
|
return readSerializedDiagnostics_helper(filePath, projectRootDir, logFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -35,6 +35,7 @@ namespace ClangTools {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
|
QList<Diagnostic> readSerializedDiagnostics(const QString &filePath,
|
||||||
|
const Utils::FileName &projectRootDir,
|
||||||
const QString &logFilePath,
|
const QString &logFilePath,
|
||||||
QString *errorMessage);
|
QString *errorMessage);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user