diff --git a/kdevclangtidy.json b/kdevclangtidy.json
index 2d816889b6..4cd7103d1e 100644
--- a/kdevclangtidy.json
+++ b/kdevclangtidy.json
@@ -1,66 +1,66 @@
{
- "GenericName": "clang-tidy Support",
- "GenericName[bs]": "Provjera sintakse",
- "GenericName[ca@valencia]": "Comprova la sintaxi",
- "GenericName[ca]": "Comprova la sintaxi",
- "GenericName[cs]": "Kontrola syntaxe",
- "GenericName[de]": "Syntaxprüfung",
- "GenericName[es]": "Comprobación de sintaxis",
- "GenericName[fr]": "Vérification de la syntaxe",
- "GenericName[hu]": "Szintaxis-ellenőrzés",
- "GenericName[nl]": "Controle op syntaxis",
- "GenericName[pl]": "Sprawdzanie składni",
- "GenericName[pt]": "Verificação de sintaxe",
- "GenericName[pt_BR]": "Verificação de sintaxe",
- "GenericName[sk]": "Kontrola syntaxe",
- "GenericName[sv]": "Syntaxkontroll",
- "GenericName[uk]": "Перевірка синтаксису",
+ "GenericName": "Clang-Tidy Support",
+ "GenericName[bs]": "Provjera sintakse",
+ "GenericName[ca@valencia]": "Comprova la sintaxi",
+ "GenericName[ca]": "Comprova la sintaxi",
+ "GenericName[cs]": "Kontrola syntaxe",
+ "GenericName[de]": "Syntaxprüfung",
+ "GenericName[es]": "Comprobación de sintaxis",
+ "GenericName[fr]": "Vérification de la syntaxe",
+ "GenericName[hu]": "Szintaxis-ellenőrzés",
+ "GenericName[nl]": "Controle op syntaxis",
+ "GenericName[pl]": "Sprawdzanie składni",
+ "GenericName[pt]": "Verificação de sintaxe",
+ "GenericName[pt_BR]": "Verificação de sintaxe",
+ "GenericName[sk]": "Kontrola syntaxe",
+ "GenericName[sv]": "Syntaxkontroll",
+ "GenericName[uk]": "Перевірка синтаксису",
"GenericName[x-test]": "xxclang-tidy Supportxx",
"KPlugin": {
"Authors": [
{
- "Name": "Carlos Nihelton",
+ "Name": "Carlos Nihelton",
"Name[x-test]": "xxCarlos Niheltonxx"
}
- ],
+ ],
"Category": "Analyzers",
"Description": "clang-tidy provides an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. http://clang.llvm.org/extra/clang-tidy/",
"Description[es]": "clang-tidy proporciona un marco extensible para el diagnóstico y fijación de los errores típicos de la programación, como violaciónes de estilo, el mal uso de la interfaz, o errores que se pueden deducir a través de análisis estático. http://clang.llvm.org/extra/clang-tidy/",
"Description[pt]": "clang-tidy fornece uma estrutura extensível para o diagnóstico e correção de erros de programação típicos, como violações de estilo, uso indevido de interface, ou bugs que podem ser deduzidos através da análise estática. http://clang.llvm.org/extra/clang-tidy/",
"Description[pt_BR]": "clang-tidy fornece uma estrutura extensível para o diagnóstico e correção de erros de programação típicos, como violações de estilo, uso indevido de interface, ou bugs que podem ser deduzidos através da análise estática. http://clang.llvm.org/extra/clang-tidy/",
"Description[x-test]": "xxclang-tidy provides an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. http://clang.llvm.org/extra/clang-tidy/xx",
- "Icon": "kdevelop",
- "Id": "kdevclangtidy",
- "License": "GPL",
- "Name": "clang-tidy Support",
- "Name[ast]": "Sofitu clang-tidy",
- "Name[bs]": "clang-tidy podrška",
- "Name[ca@valencia]": "Implementació del clang-tidy",
- "Name[ca]": "Implementació del clang-tidy",
- "Name[cs]": "Podpora clang-tidy",
- "Name[de]": "clang-tidy-Unterstützung",
- "Name[es]": "Uso de clang-tidy",
- "Name[fi]": "clang-tidy-tuki",
- "Name[fr]": "Prise en charge de clang-tidy",
- "Name[gl]": "Integración de clang-tidy",
- "Name[hu]": "clang-tidy támogatás",
- "Name[nl]": "Ondersteuning van clang-tidy",
- "Name[pl]": "Obsługa clang-tidy",
- "Name[pt]": "Suporte para o clang-tidy",
- "Name[pt_BR]": "Suporte ao clang-tidy",
- "Name[sk]": "Podpora clang-tidy",
- "Name[sv]": "Stöd för clang-tidy",
- "Name[tr]": "clang-tidy Desteği",
- "Name[uk]": "Підтримка clang-tidy",
- "Name[x-test]": "xxclang-tidy Supportxx",
- "Name[zh_CN]": "clang-tidy 支持",
+ "Icon": "kdevelop",
+ "Id": "kdevclangtidy",
+ "License": "GPL",
+ "Name": "Clang-Tidy Support",
+ "Name[ast]": "Sofitu clang-tidy",
+ "Name[bs]": "clang-tidy podrška",
+ "Name[ca@valencia]": "Implementació del clang-tidy",
+ "Name[ca]": "Implementació del clang-tidy",
+ "Name[cs]": "Podpora clang-tidy",
+ "Name[de]": "clang-tidy-Unterstützung",
+ "Name[es]": "Uso de clang-tidy",
+ "Name[fi]": "clang-tidy-tuki",
+ "Name[fr]": "Prise en charge de clang-tidy",
+ "Name[gl]": "Integración de clang-tidy",
+ "Name[hu]": "clang-tidy támogatás",
+ "Name[nl]": "Ondersteuning van clang-tidy",
+ "Name[pl]": "Obsługa clang-tidy",
+ "Name[pt]": "Suporte para o clang-tidy",
+ "Name[pt_BR]": "Suporte ao clang-tidy",
+ "Name[sk]": "Podpora clang-tidy",
+ "Name[sv]": "Stöd för clang-tidy",
+ "Name[tr]": "clang-tidy Desteği",
+ "Name[uk]": "Підтримка clang-tidy",
+ "Name[x-test]": "xxclang-tidy Supportxx",
+ "Name[zh_CN]": "clang-tidy 支持",
"ServiceTypes": [
"KDevelop/Plugin"
]
- },
- "X-KDevelop-Category": "Global",
+ },
+ "X-KDevelop-Category": "Global",
"X-KDevelop-IRequired": [
"org.kdevelop.IExecutePlugin"
],
"X-KDevelop-Mode": "GUI"
}
diff --git a/kdevclangtidy.qrc b/kdevclangtidy.qrc
index b25c95c075..826e009144 100644
--- a/kdevclangtidy.qrc
+++ b/kdevclangtidy.qrc
@@ -1,9 +1,6 @@
kdevclangtidy.rc
-
-
-
diff --git a/src/plugin.cpp b/src/plugin.cpp
index 89ddc52243..0d1a669ff0 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -1,326 +1,325 @@
/*
* This file is part of KDevelop
*
* Copyright 2016 Carlos Nihelton
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "plugin.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "config/clangtidypreferences.h"
#include "config/perprojectconfigpage.h"
#include "job.h"
using namespace KDevelop;
K_PLUGIN_FACTORY_WITH_JSON(ClangTidyFactory, "kdevclangtidy.json", registerPlugin();)
namespace ClangTidy
{
Plugin::Plugin(QObject* parent, const QVariantList& /*unused*/)
: IPlugin("kdevclangtidy", parent)
, m_model(new KDevelop::ProblemModel(parent))
{
setXMLFile("kdevclangtidy.rc");
- actionCollection()->setComponentDisplayName(i18n("Clang-Tidy Analyzer"));
QAction* act_checkfile;
act_checkfile = actionCollection()->addAction("clangtidy_file", this, SLOT(runClangTidyFile()));
act_checkfile->setStatusTip(i18n("Launches clang-tidy for current file"));
act_checkfile->setText(i18n("Clang-Tidy (Current File)"));
/* TODO: Uncomment this only when discover a safe way to run clang-tidy on
the whole project.
// QAction* act_check_all_files;
// act_check_all_files = actionCollection()->addAction ( "clangtidy_all",
this, SLOT ( runClangTidyAll() ) );
// act_check_all_files->setStatusTip ( i18n ( "Launches clangtidy for all
translation "
// "units of current project" ) );
// act_check_all_files->setText ( i18n ( "clang-tidy (all)" ) );
*/
IExecutePlugin* iface = KDevelop::ICore::self()
->pluginController()
->pluginForExtension("org.kdevelop.IExecutePlugin")
->extension();
Q_ASSERT(iface);
ProblemModelSet* pms = core()->languageController()->problemModelSet();
pms->addModel(QStringLiteral("ClangTidy"), i18n("Clang-Tidy"), m_model.data());
m_config = KSharedConfig::openConfig()->group("ClangTidy");
auto clangTidyPath = m_config.readEntry(ConfigGroup::ExecutablePath);
if (clangTidyPath.isEmpty()) {
clangTidyPath = QStandardPaths::findExecutable("clang-tidy");
}
collectAllAvailableChecks(clangTidyPath);
m_config.writeEntry(ConfigGroup::AdditionalParameters, "");
for (auto check : m_allChecks) {
bool enable = check.contains("cert") || check.contains("-core.") || check.contains("-cplusplus")
|| check.contains("-deadcode") || check.contains("-security") || check.contains("cppcoreguide");
if (enable) {
m_activeChecks << check;
} else {
m_activeChecks.removeAll(check);
}
}
m_activeChecks.removeDuplicates();
m_config.writeEntry(ConfigGroup::EnabledChecks, m_activeChecks.join(','));
}
void Plugin::unload()
{
ProblemModelSet* pms = core()->languageController()->problemModelSet();
pms->removeModel(QStringLiteral("ClangTidy"));
}
void Plugin::collectAllAvailableChecks(QString clangTidyPath)
{
m_allChecks.clear();
KProcess tidy;
tidy << clangTidyPath << QLatin1String("-checks=*") << QLatin1String("--list-checks");
tidy.setOutputChannelMode(KProcess::OnlyStdoutChannel);
tidy.start();
if (!tidy.waitForStarted()) {
qCDebug(KDEV_CLANGTIDY) << "Unable to execute clang-tidy.";
return;
}
tidy.closeWriteChannel();
if (!tidy.waitForFinished()) {
qCDebug(KDEV_CLANGTIDY) << "Failed during clang-tidy execution.";
return;
}
QTextStream ios(&tidy);
QString each;
while (ios.readLineInto(&each)) {
m_allChecks.append(each.trimmed());
}
if (m_allChecks.size() > 3) {
m_allChecks.removeAt(m_allChecks.length() - 1);
m_allChecks.removeAt(0);
}
m_allChecks.removeDuplicates();
}
void Plugin::runClangTidy(bool allFiles)
{
auto doc = core()->documentController()->activeDocument();
if (doc == nullptr) {
QMessageBox::critical(nullptr, i18n("Error starting clang-tidy"),
i18n("No suitable active file, unable to deduce project."));
return;
}
runClangTidy(doc->url(), allFiles);
}
void Plugin::runClangTidy(const QUrl& url, bool allFiles)
{
KDevelop::IProject* project = core()->projectController()->findProjectForUrl(url);
if (project == nullptr) {
QMessageBox::critical(nullptr, i18n("Error starting clang-tidy"), i18n("Active file isn't in a project"));
return;
}
m_config = project->projectConfiguration()->group("ClangTidy");
if (!m_config.isValid()) {
QMessageBox::critical(nullptr, i18n("Error starting clang-tidy"),
i18n("Can't load parameters. They must be set in the "
"project settings."));
return;
}
ConfigGroup configGroup = KSharedConfig::openConfig()->group("ClangTidy");
auto clangTidyPath = configGroup.readEntry(ConfigGroup::ExecutablePath);
Job::Parameters params;
params.projectRootDir = project->path().toLocalFile();
if (clangTidyPath.isEmpty()) {
params.executablePath = QStandardPaths::findExecutable("clang-tidy");
} else {
params.executablePath = clangTidyPath;
}
if (allFiles) {
params.filePath = project->path().toUrl().toLocalFile();
} else {
params.filePath = url.toLocalFile();
}
if (const auto buildSystem = project->buildSystemManager()) {
params.buildDir = buildSystem->buildDirectory(project->projectItem()).toLocalFile();
}
params.additionalParameters = m_config.readEntry(ConfigGroup::AdditionalParameters);
params.analiseTempDtors = m_config.readEntry(ConfigGroup::AnaliseTempDtors);
params.enabledChecks = m_activeChecks.join(',');
params.useConfigFile = m_config.readEntry(ConfigGroup::UseConfigFile);
params.dumpConfig = m_config.readEntry(ConfigGroup::DumpConfig);
params.enableChecksProfile = m_config.readEntry(ConfigGroup::EnableChecksProfile);
params.exportFixes = m_config.readEntry(ConfigGroup::ExportFixes);
params.extraArgs = m_config.readEntry(ConfigGroup::ExtraArgs);
params.extraArgsBefore = m_config.readEntry(ConfigGroup::ExtraArgsBefore);
params.autoFix = m_config.readEntry(ConfigGroup::AutoFix);
params.headerFilter = m_config.readEntry(ConfigGroup::HeaderFilter);
params.lineFilter = m_config.readEntry(ConfigGroup::LineFilter);
params.listChecks = m_config.readEntry(ConfigGroup::ListChecks);
params.checkSystemHeaders = m_config.readEntry(ConfigGroup::CheckSystemHeaders);
if (!params.dumpConfig.isEmpty()) {
auto job = new ClangTidy::Job(params, this);
core()->runController()->registerJob(job);
params.dumpConfig = QString();
}
auto job2 = new ClangTidy::Job(params, this);
connect(job2, SIGNAL(finished(KJob*)), this, SLOT(result(KJob*)));
core()->runController()->registerJob(job2);
m_runningJob = job2;
}
bool Plugin::isRunning() const
{
return !m_runningJob.isNull();
}
void Plugin::runClangTidyFile()
{
bool allFiles = false;
runClangTidy(allFiles);
}
void Plugin::runClangTidyAll()
{
bool allFiles = true;
runClangTidy(allFiles);
}
void Plugin::loadOutput()
{
}
void Plugin::result(KJob* job)
{
Job* aj = dynamic_cast(job);
if (aj == nullptr) {
return;
}
if (aj->status() == KDevelop::OutputExecuteJob::JobStatus::JobSucceeded) {
m_model->setProblems(aj->problems());
core()->uiController()->findToolView(i18nd("kdevproblemreporter", "Problems"), nullptr,
KDevelop::IUiController::FindFlags::Raise);
}
}
KDevelop::ContextMenuExtension Plugin::contextMenuExtension(KDevelop::Context* context)
{
ContextMenuExtension extension = KDevelop::IPlugin::contextMenuExtension(context);
if (context->hasType(KDevelop::Context::EditorContext) && !isRunning()) {
IDocument* doc = core()->documentController()->activeDocument();
const auto mime = doc->mimeType().name();
if (mime == QLatin1String("text/x-c++src") || mime == QLatin1String("text/x-csrc")) {
auto action = new QAction(QIcon::fromTheme("dialog-ok"), i18n("Clang-Tidy"), this);
connect(action, &QAction::triggered, this, &Plugin::runClangTidyFile);
extension.addAction(KDevelop::ContextMenuExtension::AnalyzeGroup, action);
}
}
if (context->hasType(KDevelop::Context::ProjectItemContext) && !isRunning()) {
auto pContext = dynamic_cast(context);
if (pContext->items().size() != 1)
return extension;
auto item = pContext->items().first();
switch (item->type()) {
case KDevelop::ProjectBaseItem::File:
break;
default:
return extension;
}
auto action = new QAction(QIcon::fromTheme("dialog-ok"), i18n("Clang-Tidy"), this);
connect(action, &QAction::triggered, this, [this, item]() {
runClangTidy(item->path().toUrl());
});
extension.addAction(KDevelop::ContextMenuExtension::AnalyzeGroup, action);
}
return extension;
}
KDevelop::ConfigPage* Plugin::perProjectConfigPage(int number, const ProjectConfigOptions& options, QWidget* parent)
{
if (number != 0) {
return nullptr;
}
auto config = new PerProjectConfigPage(options.project, parent);
config->setActiveChecksReceptorList(&m_activeChecks);
config->setList(m_allChecks);
return config;
}
KDevelop::ConfigPage* Plugin::configPage(int number, QWidget* parent)
{
if (number != 0) {
return nullptr;
}
return new ClangTidyPreferences(this, parent);
}
} // namespace ClangTidy
#include "plugin.moc"