diff --git a/config/projectconfigpage.ui b/config/projectconfigpage.ui index 19d449b..fb2d7bd 100644 --- a/config/projectconfigpage.ui +++ b/config/projectconfigpage.ui @@ -1,203 +1,188 @@ verapp::ProjectConfigPage 0 0 917 848 0 0 Built-in Rules 0 0 QTabWidget::North 0 F L T 1-7 T 8-14 T 15-19 - - - File Filter - - - - - - - - - - - &Extra parameters: kcfg_extraParameters - + <html><head/><body><p>Defines additional parameters for vera++ (see documentation).</p><p>You can use the following placeholders:</p><p>%p - Gets replaced by the URL of the project's root directory.</p><p>%b - Gets replaced by the URL of the project's build directory.</p></body></html> Command line &Filter: commandLineFilter false Break lines false true true false tabWidget - kcfg_fileFilter kcfg_extraParameters commandLineFilter commandLineBreaks commandLine commandLineBreaks toggled(bool) commandLineFilter setEnabled(bool) 901 513 772 518 commandLineBreaks toggled(bool) commandLineFilterLabel setEnabled(bool) 901 513 54 518 diff --git a/config/projectsettings.kcfg b/config/projectsettings.kcfg index 3a37b97..e8b09b5 100644 --- a/config/projectsettings.kcfg +++ b/config/projectsettings.kcfg @@ -1,57 +1,53 @@ "parameters.h" F001 F002 L001 L002 L003 L004 L005 L006 T001 T002 T003 T004 T005 T006 T007 T008 T009 T010 T011 T012 T013 T014 T015 T016 T017 T018 T019 defaults::isRuleEnabled((rules::Type)$(Idx)) - - ::defaults::fileFilter() - - diff --git a/parameters.cpp b/parameters.cpp index 4e1277c..9aa74ea 100644 --- a/parameters.cpp +++ b/parameters.cpp @@ -1,231 +1,224 @@ /* This file is part of KDevelop Copyright 2016 Anton Anikin 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "parameters.h" #include "globalsettings.h" #include "projectsettings.h" #include "rules.h" +#include "utils.h" #include #include #include #include #include #include #include #include #include #include #include namespace verapp { namespace defaults { QString executablePath() { QString path = QStandardPaths::findExecutable(QStringLiteral("vera++")); return path.isEmpty() ? QStringLiteral("vera++") : path; } bool hideOutputView() { return true; } -QString fileFilter() -{ - return QStringLiteral("*.h,*.hxx,*.hpp,*.hh,*.h++,*.H,*.tlh,*.cpp,*.cc,*.C,*.c++,*.cxx,*.ocl,*.inl,*.idl,*.c,*.m,*.mm,*.M,*.y,*.ypp,*.yxx,*.y++,*.l"); -} - } Parameters::Parameters(KDevelop::IProject* project) : m_project(project) { executablePath = KDevelop::Path(GlobalSettings::executablePath()).toLocalFile(); hideOutputView = GlobalSettings::hideOutputView(); if (!project) { for (int intType = rules::Type::FIRST; intType <= rules::Type::LAST; ++intType) { rules::Type ruleType = static_cast(intType); m_ruleEnabled[ruleType] = defaults::isRuleEnabled(ruleType); } - fileFilter = defaults::fileFilter(); return; } ProjectSettings projectSettings; projectSettings.setSharedConfig(project->projectConfiguration()); projectSettings.load(); for (int intType = rules::Type::FIRST; intType <= rules::Type::LAST; ++intType) { rules::Type ruleType = static_cast(intType); m_ruleEnabled[ruleType] = projectSettings.rule(intType); } extraParameters = projectSettings.extraParameters(); - fileFilter = projectSettings.fileFilter(); m_projectRootPath = m_project->path(); m_projectBuildPath = m_project->buildSystemManager()->buildDirectory(m_project->projectItem()); } QStringList Parameters::commandLine() const { QStringList arguments; arguments << executablePath; arguments << QStringLiteral("--show-rule"); arguments << QStringLiteral("--no-duplicate"); for (int intType = rules::Type::FIRST; intType <= rules::Type::LAST; ++intType) { rules::Type ruleType = static_cast(intType); if (m_ruleEnabled[ruleType]) { arguments << "-R"; arguments << rules::name(ruleType); } } if (!extraParameters.isEmpty()) { arguments << KShell::splitArgs(applyPlaceholders(extraParameters)); } return arguments; } QString Parameters::buildRunScript() const { QSet projectFiles; QString scriptPath; if (!checkPath.isEmpty() && QFileInfo(checkPath).isFile()) { projectFiles.insert(KDevelop::IndexedString(checkPath)); } else if (m_project) { projectFiles = m_project->fileSet(); - QStringList filters = fileFilter.split(',', QString::SkipEmptyParts); QMutableSetIterator i(projectFiles); while (i.hasNext()) { QString projectFile = i.next().str(); if (!projectFile.startsWith(checkPath)) { i.remove(); continue; } - if (!QDir::match(filters, projectFile)) { + if (!isSupportedFile(projectFile)) { i.remove(); } } } QString tempDir = QStandardPaths::standardLocations(QStandardPaths::TempLocation).first(); scriptPath = tempDir + "/kdevverapp"; if (m_project) { scriptPath += "_" + m_project->name(); } #ifdef Q_OS_WIN scriptPath += ".bat"; #else scriptPath += ".sh"; #endif QFile scriptFile(scriptPath); if (!scriptFile.open(QIODevice::WriteOnly)) { QMessageBox::critical( nullptr, i18n("Vera++ Error"), i18n("Unable to open file '%1' to write", scriptPath)); return scriptPath; } QTextStream scriptStream(&scriptFile); QString veraCommand = commandLine().join(' '); int fileNumber = 0; int filesCount = projectFiles.size(); foreach (const KDevelop::IndexedString& projectFile, projectFiles) { scriptStream << QString("echo Checking %1 ...\n").arg(projectFile.str()); scriptStream << QString("%1 %2\n").arg(veraCommand).arg(projectFile.str()); int progress = (++fileNumber)/(double)filesCount * 100.0; scriptStream << QString("echo %1/%2 files checked %3% done\n").arg(fileNumber).arg(filesCount).arg(progress); } scriptFile.setPermissions( QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner); scriptFile.close(); return scriptPath; } bool Parameters::isRuleEnabled(rules::Type type) const { return m_ruleEnabled[type]; } void Parameters::setRuleEnabled(rules::Type type, bool value) { m_ruleEnabled[type] = value; } QString Parameters::applyPlaceholders(const QString& text) const { QString result(text); if (m_project) { result.replace("%p", m_projectRootPath.toLocalFile()); result.replace("%b", m_projectBuildPath.toLocalFile()); } return result; } namespace defaults { bool isRuleEnabled(rules::Type type) { // default Vera++ profile if (type == rules::F002 || type == rules::T014) { return false; } return true; } } } diff --git a/parameters.h b/parameters.h index 3b2a41b..f1b95db 100644 --- a/parameters.h +++ b/parameters.h @@ -1,83 +1,80 @@ /* This file is part of KDevelop Copyright 2016 Anton Anikin 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef VERAPP_PARAMETERS_H #define VERAPP_PARAMETERS_H #include "rules.h" #include namespace KDevelop { class IProject; } namespace verapp { namespace defaults { QString executablePath(); bool hideOutputView(); -QString fileFilter(); - bool isRuleEnabled(rules::Type type); } class Parameters { public: explicit Parameters(KDevelop::IProject* project = nullptr); QStringList commandLine() const; QString buildRunScript() const; // global settings QString executablePath; bool hideOutputView; // project settings bool isRuleEnabled(rules::Type type) const; void setRuleEnabled(rules::Type type, bool value); - QString fileFilter; QString extraParameters; QString checkPath; private: QString applyPlaceholders(const QString& text) const; KDevelop::IProject* m_project; KDevelop::Path m_projectRootPath; KDevelop::Path m_projectBuildPath; bool m_ruleEnabled[rules::Type::COUNT]; }; } #endif diff --git a/plugin.cpp b/plugin.cpp index 84c6664..615c83f 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -1,290 +1,301 @@ /* This file is part of KDevelop Copyright 2016 Anton Anikin 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "plugin.h" #include "config/globalconfigpage.h" #include "config/projectconfigpage.h" #include "debug.h" #include "problemmodel.h" #include "rules.h" +#include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(VerappFactory, "kdevverapp.json", registerPlugin();) namespace verapp { Plugin::Plugin(QObject* parent, const QVariantList&) : IPlugin("kdevverapp", parent) , m_job(nullptr) , m_project(nullptr) , m_model(new ProblemModel(this)) { qCDebug(KDEV_VERAPP) << "setting kdevverapp.rc file"; setXMLFile("kdevverapp.rc"); rules::init(); m_menuActionFile = new QAction(i18n("Analyze Current File with Vera++"), this); connect(m_menuActionFile, &QAction::triggered, [this](){ runVerapp(false); }); actionCollection()->addAction("verapp_file", m_menuActionFile); m_contextActionFile = new QAction(i18n("Vera++"), this); connect(m_contextActionFile, &QAction::triggered, [this]() { runVerapp(false); }); m_menuActionProject = new QAction(i18n("Analyze Current Project with Vera++"), this); connect(m_menuActionProject, &QAction::triggered, [this](){ runVerapp(true); }); actionCollection()->addAction("verapp_project", m_menuActionProject); m_contextActionProject = new QAction(i18n("Vera++"), this); connect(m_contextActionProject, &QAction::triggered, [this]() { runVerapp(true); }); m_contextActionProjectItem = new QAction("Vera++", this); connect(core()->documentController(), &KDevelop::IDocumentController::documentClosed, this, &Plugin::updateActions); connect(core()->documentController(), &KDevelop::IDocumentController::documentActivated, this, &Plugin::updateActions); connect(core()->projectController(), &KDevelop::IProjectController::projectOpened, this, &Plugin::updateActions); connect(core()->projectController(), &KDevelop::IProjectController::projectClosed, this, &Plugin::projectClosed); updateActions(); } Plugin::~Plugin() { killVerapp(); } bool Plugin::isRunning() { return m_job; } void Plugin::killVerapp() { if (m_job) { m_job->kill(KJob::EmitResult); } } void Plugin::raiseProblemsView() { m_model->show(); } void Plugin::raiseOutputView() { core()->uiController()->findToolView( i18ndc("kdevstandardoutputview", "@title:window", "Test"), nullptr, KDevelop::IUiController::FindFlags::Raise); } void Plugin::updateActions() { m_project = nullptr; m_menuActionFile->setEnabled(false); m_menuActionProject->setEnabled(false); if (isRunning()) { return; } auto activeDocument = core()->documentController()->activeDocument(); if (!activeDocument) { return; } m_project = core()->projectController()->findProjectForUrl(activeDocument->url()); if (!m_project) { return; } m_menuActionFile->setEnabled(true); m_menuActionProject->setEnabled(true); } void Plugin::projectClosed(KDevelop::IProject* project) { if (project != m_model->project()) { return; } killVerapp(); m_model->reset(); } void Plugin::runVerapp(bool checkProject) { auto doc = core()->documentController()->activeDocument(); Q_ASSERT(doc); if (checkProject) { runVerapp(m_project, m_project->path().toUrl().toLocalFile()); } else { runVerapp(m_project, doc->url().toLocalFile()); } } void Plugin::runVerapp(KDevelop::IProject* project, const QString& path) { Parameters params(project); params.checkPath = path; m_model->reset(project, path); if (!QFile::exists(params.executablePath)) { QString errorMessage; errorMessage += i18n("Failed to start vera++ from \"%1\".", params.executablePath); errorMessage += QStringLiteral("\n\n"); errorMessage += i18n("Check your settings and install the vera++ if necessary."); KMessageBox::error(qApp->activeWindow(), errorMessage, i18n("Vera++ Error")); return; } m_job = new Job(params); connect(m_job, &Job::problemsDetected, m_model.data(), &ProblemModel::addProblems); connect(m_job, &Job::finished, this, &Plugin::result); core()->uiController()->registerStatus(new KDevelop::JobStatus(m_job, "vera++")); core()->runController()->registerJob(m_job); if (params.hideOutputView) { raiseProblemsView(); } else { raiseOutputView(); } updateActions(); } void Plugin::result(KJob*) { if (!core()->projectController()->projects().contains(m_model->project())) { m_model->reset(); } else { m_model->setProblems(); if (m_job->status() == KDevelop::OutputExecuteJob::JobStatus::JobSucceeded || m_job->status() == KDevelop::OutputExecuteJob::JobStatus::JobCanceled) { raiseProblemsView(); } else { raiseOutputView(); } } m_job = nullptr; // job is automatically deleted later updateActions(); } KDevelop::ContextMenuExtension Plugin::contextMenuExtension(KDevelop::Context* context, QWidget* parent) { Q_UNUSED(parent); KDevelop::ContextMenuExtension extension; if (context->hasType(KDevelop::Context::EditorContext) && m_project && !isRunning()) { - extension.addAction(KDevelop::ContextMenuExtension::AnalyzeFileGroup, m_contextActionFile); + auto eContext = static_cast(context); + if (isSupportedUrl(eContext->url())) + { + extension.addAction(KDevelop::ContextMenuExtension::AnalyzeFileGroup, m_contextActionFile); + } + extension.addAction(KDevelop::ContextMenuExtension::AnalyzeProjectGroup, m_contextActionProject); } 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: + case KDevelop::ProjectBaseItem::File: { + if (!isSupportedUrl(item->path().toUrl())) { + return extension; + } + break; + } case KDevelop::ProjectBaseItem::Folder: case KDevelop::ProjectBaseItem::BuildFolder: break; default: return extension; } m_contextActionProjectItem->disconnect(); connect(m_contextActionProjectItem, &QAction::triggered, [this, item](){ runVerapp(item->project(), item->path().toLocalFile()); }); extension.addAction(KDevelop::ContextMenuExtension::AnalyzeProjectGroup, m_contextActionProjectItem); } return extension; } KDevelop::ConfigPage* Plugin::perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent) { if (number) { return nullptr; } return new ProjectConfigPage(this, options.project, parent); } KDevelop::ConfigPage* Plugin::configPage(int number, QWidget* parent) { if (number) { return nullptr; } return new GlobalConfigPage(this, parent); } } #include "plugin.moc" diff --git a/utils.cpp b/utils.cpp index 02e2161..a9e2d92 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,36 +1,58 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "utils.h" #include #include +#include + namespace verapp { QString prettyPathName(const QString& path) { return KDevelop::ICore::self()->projectController()->prettyFileName( QUrl::fromLocalFile(path), KDevelop::IProjectController::FormatPlain); } +bool isSupportedMimeType(const QMimeType& mimeType) +{ + const QString mimeName = mimeType.name(); + return (mimeName == QLatin1String("text/x-c++src") || + mimeName == QLatin1String("text/x-c++hdr") || + mimeName == QLatin1String("text/x-chdr") || + mimeName == QLatin1String("text/x-csrc")); +} + +bool isSupportedFile(const QString& fileName) +{ + return isSupportedMimeType(QMimeDatabase().mimeTypeForFile(fileName)); +} + +bool isSupportedUrl(const QUrl& url) +{ + return isSupportedMimeType(QMimeDatabase().mimeTypeForUrl(url)); +} + + } diff --git a/utils.h b/utils.h index 45f8629..d4b2625 100644 --- a/utils.h +++ b/utils.h @@ -1,30 +1,35 @@ /* This file is part of KDevelop Copyright 2017 Anton Anikin 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #pragma once #include +class QUrl; + namespace verapp { QString prettyPathName(const QString& path); +bool isSupportedFile(const QString& fileName); +bool isSupportedUrl(const QUrl& url); + }