Commit b9f9eb7a authored by Nikolai Kosjar's avatar Nikolai Kosjar Committed by Eike Ziller

Import Clang Static Analyzer plugin

This plugin adds "Clang Static Analyzer" to the Analyze mode, which
processes all implementation/source project files of the current
project. For this, it will call the clang executable for each file.

The found diagnostics will be displayed in a view similar to the one
used in "Valgrind Memory Analyzer".

The user can specify the clang executable to use and the number of
concurrent processes to launch in Menu: Tools > Options > Analyzer >
Clang Static Analyzer.

Main TODOs:

 * Fiddle around the appropriate command line options, currently only
   defines and include paths are passed on.

 * Tests on Windows / OS X.

 * Remove dependency to clangcodemodel by moving the functions that
   create command line arguments to CppTools. Mostly they are not even
   specific to clang (but would also work with gcc).

 * Maybe limit to a range of tested clang versions.

 * How to deal with directory containing all the log files after the
   user starts a new run or Creator is shut down? (delete it? leave it
   there? make it configurable?).

 * Find out how to properly integrate the tests.

Imaginable future additions:

 * Adding a button to load result/log files from a directory, e.g. if
   the user used the 'scan-build' approach.

 * Adding a button with a filter menu in order to display only
   diagnostics from certain categories, similar to "Valgrind Memory
   Analyzer".

Change-Id: I6aeb5dfdbdfa239a06c03dd8759a983df71b77ea
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent b3e07a53
*.pro.user
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += plugins/clangstaticanalyzer
QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency
{
\"Name\" : \"ClangStaticAnalyzer\",
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Vendor\" : \"Digia Plc\",
\"Copyright\" : \"(C) 2014 Digia Plc\",
\"License\" : [ \"Commercial Usage\",
\"\",
\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.\"
],
\"Category\" : \"Code Analyzer\",
\"Description\" : \"ClangStaticAnalyzer Plugin.\",
\"Url\" : \"http://qt.digia.com\",
$$dependencyList
}
TARGET = ClangStaticAnalyzer
TEMPLATE = lib
PROVIDER = Digia
include(../../qtcreatorplugin.pri)
include(clangstaticanalyzer_dependencies.pri)
SOURCES += \
clangstaticanalyzerconfigwidget.cpp \
clangstaticanalyzerdiagnostic.cpp \
clangstaticanalyzerdiagnosticmodel.cpp \
clangstaticanalyzerdiagnosticview.cpp \
clangstaticanalyzerlogfilereader.cpp \
clangstaticanalyzerplugin.cpp \
clangstaticanalyzerruncontrol.cpp \
clangstaticanalyzerruncontrolfactory.cpp \
clangstaticanalyzerrunner.cpp \
clangstaticanalyzersettings.cpp \
clangstaticanalyzertool.cpp \
clangstaticanalyzerutils.cpp
HEADERS += \
clangstaticanalyzerconfigwidget.h \
clangstaticanalyzerconstants.h \
clangstaticanalyzerdiagnostic.h \
clangstaticanalyzerdiagnosticmodel.h \
clangstaticanalyzerdiagnosticview.h \
clangstaticanalyzer_global.h \
clangstaticanalyzerlogfilereader.h \
clangstaticanalyzerplugin.h \
clangstaticanalyzerruncontrolfactory.h \
clangstaticanalyzerruncontrol.h \
clangstaticanalyzerrunner.h \
clangstaticanalyzersettings.h \
clangstaticanalyzertool.h \
clangstaticanalyzerutils.h
FORMS += \
clangstaticanalyzerconfigwidget.ui
DISTFILES += \
tests/tests.pri
QTC_PLUGIN_NAME = ClangStaticAnalyzer
QTC_LIB_DEPENDS += \
extensionsystem \
utils
QTC_PLUGIN_DEPENDS += \
analyzerbase \
clangcodemodel \
cpptools \
licensechecker
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise Qt Quick Profiler Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#ifndef CLANGSTATICANALYZER_GLOBAL_H
#define CLANGSTATICANALYZER_GLOBAL_H
#include <QtGlobal>
#if defined(CLANGSTATICANALYZER_LIBRARY)
# define CLANGSTATICANALYZER_EXPORT Q_DECL_EXPORT
#else
# define CLANGSTATICANALYZER_EXPORT Q_DECL_IMPORT
#endif
#endif // CLANGSTATICANALYZER_GLOBAL_H
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#include "clangstaticanalyzerconfigwidget.h"
#include "ui_clangstaticanalyzerconfigwidget.h"
#include <QThread>
namespace ClangStaticAnalyzer {
namespace Internal {
ClangStaticAnalyzerConfigWidget::ClangStaticAnalyzerConfigWidget(
ClangStaticAnalyzerSettings *settings,
QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::ClangStaticAnalyzerConfigWidget)
, m_settings(settings)
{
m_ui->setupUi(this);
m_ui->clangExecutableChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_ui->clangExecutableChooser->setHistoryCompleter(
QLatin1String("ClangStaticAnalyzer.ClangCommand.History"));
m_ui->clangExecutableChooser->setPromptDialogTitle(tr("Clang Command"));
m_ui->clangExecutableChooser->setPath(settings->clangExecutable());
connect(m_ui->clangExecutableChooser, &Utils::PathChooser::changed,
m_settings, &ClangStaticAnalyzerSettings::setClangExecutable);
m_ui->simultaneousProccessesSpinBox->setValue(settings->simultaneousProcesses());
m_ui->simultaneousProccessesSpinBox->setMinimum(1);
m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
connect(m_ui->simultaneousProccessesSpinBox,
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
m_settings, &ClangStaticAnalyzerSettings::setSimultaneousProcesses);
}
ClangStaticAnalyzerConfigWidget::~ClangStaticAnalyzerConfigWidget()
{
delete m_ui;
}
} // namespace Internal
} // namespace ClangStaticAnalyzer
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#ifndef CLANGSTATICANALYZERCONFIGWIDGET_H
#define CLANGSTATICANALYZERCONFIGWIDGET_H
#include "clangstaticanalyzersettings.h"
#include <QWidget>
namespace ClangStaticAnalyzer {
namespace Internal {
namespace Ui { class ClangStaticAnalyzerConfigWidget; }
class ClangStaticAnalyzerConfigWidget : public QWidget
{
Q_OBJECT
public:
explicit ClangStaticAnalyzerConfigWidget(ClangStaticAnalyzerSettings *settings,
QWidget *parent = 0);
~ClangStaticAnalyzerConfigWidget();
private:
Ui::ClangStaticAnalyzerConfigWidget *m_ui;
ClangStaticAnalyzerSettings *m_settings;
};
} // namespace Internal
} // namespace ClangStaticAnalyzer
#endif // CLANGSTATICANALYZERCONFIGWIDGET_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ClangStaticAnalyzer::Internal::ClangStaticAnalyzerConfigWidget</class>
<widget class="QWidget" name="ClangStaticAnalyzer::Internal::ClangStaticAnalyzerConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>General</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Clang executable:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="Utils::PathChooser" name="clangExecutableChooser" native="true"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Simultaneous processes:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="simultaneousProccessesSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>32</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>183</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise Qt LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#ifndef CLANGSTATICANALYZERCONSTANTS_H
#define CLANGSTATICANALYZERCONSTANTS_H
namespace ClangStaticAnalyzer {
namespace Constants {
const char CLANG_EXECUTABLE_BASE_NAME[] = "clang";
const char SETTINGS_ID[] = "ClangStaticAnalyzer";
} // Constants
} // ClangStaticAnalyzer
#endif // CLANGSTATICANALYZERCONSTANTS_H
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#include "clangstaticanalyzerdiagnostic.h"
namespace ClangStaticAnalyzer {
namespace Internal {
Location::Location()
: line(0), column(0)
{
}
Location::Location(const QString &filePath, int line, int column)
: filePath(filePath), line(line), column(column)
{
}
bool Location::isValid() const
{
return !filePath.isEmpty() && line >= 0 && column >= 0;
}
ExplainingStep::ExplainingStep()
: depth(0)
{
}
bool ExplainingStep::isValid() const
{
return location.isValid() && !ranges.isEmpty() && !message.isEmpty();
}
} // namespace Internal
} // namespace ClangStaticAnalyzer
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#ifndef CLANGSTATICANALZYERDIAGNOSTIC_H
#define CLANGSTATICANALZYERDIAGNOSTIC_H
#include <QList>
#include <QMetaType>
#include <QString>
namespace ClangStaticAnalyzer {
namespace Internal {
class Location
{
public:
Location();
Location(const QString &filePath, int line, int column);
bool isValid() const;
QString filePath;
int line;
int column;
};
class ExplainingStep
{
public:
ExplainingStep();
bool isValid() const;
QString message;
QString extendedMessage;
Location location;
QList<Location> ranges;
int depth;
};
class Diagnostic
{
public:
QString description;
QString category;
QString type;
QString issueContextKind;
QString issueContext;
Location location;
QList<ExplainingStep> explainingSteps;
};
} // namespace Internal
} // namespace ClangStaticAnalyzer
Q_DECLARE_METATYPE(ClangStaticAnalyzer::Internal::Diagnostic)
#endif // CLANGSTATICANALZYERDIAGNOSTIC_H
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#include "clangstaticanalyzerdiagnosticmodel.h"
#include "clangstaticanalyzerutils.h"
#include <QCoreApplication>
namespace ClangStaticAnalyzer {
namespace Internal {
ClangStaticAnalyzerDiagnosticModel::ClangStaticAnalyzerDiagnosticModel(QObject *parent)
: QAbstractListModel(parent)
{
}
void ClangStaticAnalyzerDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
{
beginInsertRows(QModelIndex(), m_diagnostics.size(),
m_diagnostics.size() + diagnostics.size() - 1 );
m_diagnostics += diagnostics;
endInsertRows();
}
void ClangStaticAnalyzerDiagnosticModel::clear()
{
beginResetModel();
m_diagnostics.clear();
endResetModel();
}
int ClangStaticAnalyzerDiagnosticModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_diagnostics.count();
}
static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
{
typedef QPair<QString, QString> StringPair;
QList<StringPair> lines;
if (!diagnostic.category.isEmpty()) {
lines << qMakePair(
QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Category:"),
diagnostic.category);
}
if (!diagnostic.type.isEmpty()) {
lines << qMakePair(
QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Type:"),
diagnostic.type);
}
if (!diagnostic.issueContext.isEmpty() && !diagnostic.issueContextKind.isEmpty()) {
lines << qMakePair(
QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Context:"),
diagnostic.issueContextKind + QLatin1Char(' ') + diagnostic.issueContext);
}
lines << qMakePair(
QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Location:"),
createFullLocationString(diagnostic.location));
QString html = QLatin1String("<html>"
"<head>"
"<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
"<body><dl>");
foreach (const StringPair &pair, lines) {
html += QLatin1String("<dt>");
html += pair.first;
html += QLatin1String("</dt><dd>");
html += pair.second;
html += QLatin1String("</dd>\n");
}
html += QLatin1String("</dl></body></html>");
return html;
}
QVariant ClangStaticAnalyzerDiagnosticModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.parent().isValid())
return QVariant();
const int row = index.row();
if (row < 0 || row >= m_diagnostics.size())
return QVariant();
const Diagnostic diagnostic = m_diagnostics.at(row);
if (role == Qt::DisplayRole)
return QString(QLatin1String("Some specific diagnostic")); // TODO: Remove?
else if (role == Qt::ToolTipRole)
return createDiagnosticToolTipString(diagnostic);
else if (role == Qt::UserRole)
return QVariant::fromValue<Diagnostic>(diagnostic);
return QVariant();
}
} // namespace Internal
} // namespace ClangStaticAnalyzer
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#ifndef CLANGSTATICANALYZERDIAGNOSTICMODEL_H
#define CLANGSTATICANALYZERDIAGNOSTICMODEL_H
#include "clangstaticanalyzerlogfilereader.h"
#include <QAbstractListModel>
namespace ClangStaticAnalyzer {
namespace Internal {
class ClangStaticAnalyzerDiagnosticModel : public QAbstractListModel
{
Q_OBJECT
public:
ClangStaticAnalyzerDiagnosticModel(QObject *parent = 0);
void addDiagnostics(const QList<Diagnostic> &diagnostics);
void clear();
// QAbstractListModel interface
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
private:
QList<Diagnostic> m_diagnostics;
};
} // namespace Internal
} // namespace ClangStaticAnalyzer
#endif // CLANGSTATICANALYZERDIAGNOSTICMODEL_H
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use contact form at http://qt.digia.com <http://qt.digia.com/>
**
** This file is part of the Qt Enterprise LicenseChecker Add-on.
**
** Licensees holding valid Qt Enterprise licenses may use this file in
** accordance with the Qt Enterprise License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.
**
** If you have questions regarding the use of this file, please use
** contact form at http://qt.digia.com <http://qt.digia.com/>
**
****************************************************************************/
#include "clangstaticanalyzerdiagnosticview.h"
#include "clangstaticanalyzerlogfilereader.h"
#include "clangstaticanalyzerutils.h"
#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QDebug>