summaryrefslogtreecommitdiff
path: root/src/plugins/cppcheck/cppchecktrigger.cpp
diff options
context:
space:
mode:
authorSergey Morozov <dev@gres.biz>2018-07-30 21:42:47 +0300
committerSergey Morozov <dev@gres.biz>2018-09-18 19:07:12 +0000
commit31b595314c0963cad42ed4cd18d7dc78502479e0 (patch)
tree670ab7ccac2a0d738cfb59ef47752ee22b26e371 /src/plugins/cppcheck/cppchecktrigger.cpp
parent20f3c8d65432bffaa1ba6ca9d2512ce3f3e3ce12 (diff)
downloadqt-creator-31b595314c0963cad42ed4cd18d7dc78502479e0.tar.gz
Cppcheck: Add cppcheck static analysis tool
Automatically checks currently opened documents and displays results via text marks/annotations. CppcheckTrigger detects when to check files or clear results. CppcheckTextMarkManager stores/clears text marks with checks' results. CppcheckTool generates run arguments and parses output. CppcheckRunner runs cppcheck binary. CppcheckOptions configures CppcheckTool. Task-number: QTCREATORBUG-20418 Change-Id: I8eafeac7af6137d2c9061ae75d4a56c85b3b5a2d Reviewed-by: Alessandro Portale <alessandro.portale@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'src/plugins/cppcheck/cppchecktrigger.cpp')
-rw-r--r--src/plugins/cppcheck/cppchecktrigger.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/plugins/cppcheck/cppchecktrigger.cpp b/src/plugins/cppcheck/cppchecktrigger.cpp
new file mode 100644
index 0000000000..b9ce34448c
--- /dev/null
+++ b/src/plugins/cppcheck/cppchecktrigger.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Sergey Morozov
+** 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 "cppchecktextmarkmanager.h"
+#include "cppchecktool.h"
+#include "cppchecktrigger.h"
+
+#include <cpptools/cppmodelmanager.h>
+
+#include <utils/qtcassert.h>
+
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+
+#include <projectexplorer/project.h>
+#include <projectexplorer/session.h>
+
+namespace Cppcheck {
+namespace Internal {
+
+CppcheckTrigger::CppcheckTrigger(CppcheckTextMarkManager &marks, CppcheckTool &tool) :
+ m_marks(marks),
+ m_tool(tool)
+{
+ using EditorManager = Core::EditorManager;
+ using SessionManager = ProjectExplorer::SessionManager;
+ using CppModelManager = CppTools::CppModelManager;
+
+ connect(EditorManager::instance(), &EditorManager::editorOpened,
+ this, [this](Core::IEditor *editor) {checkEditors({editor});});
+ connect(EditorManager::instance(), &EditorManager::editorsClosed,
+ this, &CppcheckTrigger::removeEditors);
+ connect(EditorManager::instance(), &EditorManager::aboutToSave,
+ this, &CppcheckTrigger::checkChangedDocument);
+
+ connect(SessionManager::instance(), &SessionManager::startupProjectChanged,
+ this, &CppcheckTrigger::changeCurrentProject);
+
+ connect(CppModelManager::instance(), &CppModelManager::projectPartsUpdated,
+ this, &CppcheckTrigger::updateProjectFiles);
+}
+
+CppcheckTrigger::~CppcheckTrigger() = default;
+
+void CppcheckTrigger::recheck()
+{
+ removeEditors();
+ checkEditors();
+}
+
+void CppcheckTrigger::checkEditors(const QList<Core::IEditor *> &editors)
+{
+ if (!m_currentProject)
+ return;
+
+ using CppModelManager = CppTools::CppModelManager;
+ const auto info = CppModelManager::instance()->projectInfo(m_currentProject);
+ if (!info.isValid())
+ return;
+
+ const auto editorList = !editors.isEmpty()
+ ? editors : Core::DocumentModel::editorsForOpenedDocuments();
+
+ Utils::FileNameList toCheck;
+ for (const auto editor: editorList) {
+ QTC_ASSERT(editor, continue);
+ const auto document = editor->document();
+ QTC_ASSERT(document, continue);
+ const auto &path = document->filePath();
+ QTC_ASSERT(!path.isEmpty(), continue);
+
+ if (m_checkedFiles.contains(path))
+ continue;
+
+ if (!m_currentProject->isKnownFile(path))
+ continue;
+
+ const auto &pathString = path.toString();
+ if (!info.sourceFiles().contains(pathString))
+ continue;
+
+ connect(document, &Core::IDocument::aboutToReload,
+ this, [this, document]{checkChangedDocument(document);});
+ connect(document, &Core::IDocument::contentsChanged,
+ this, [this, document] {
+ if (!document->isModified())
+ checkChangedDocument(document);
+ });
+
+ m_checkedFiles.insert(path, QDateTime::currentDateTime());
+ toCheck.push_back(path);
+ }
+
+ if (!toCheck.isEmpty()) {
+ remove(toCheck);
+ check(toCheck);
+ }
+}
+
+void CppcheckTrigger::removeEditors(const QList<Core::IEditor *> &editors)
+{
+ if (!m_currentProject)
+ return;
+
+ const auto editorList = !editors.isEmpty()
+ ? editors : Core::DocumentModel::editorsForOpenedDocuments();
+
+ Utils::FileNameList toRemove;
+ for (const auto editor: editorList) {
+ QTC_ASSERT(editor, return);
+ const auto document = editor->document();
+ QTC_ASSERT(document, return);
+ const auto &path = document->filePath();
+ QTC_ASSERT(!path.isEmpty(), return);
+
+ if (!m_checkedFiles.contains(path))
+ continue;
+
+ disconnect(document, nullptr, this, nullptr);
+ m_checkedFiles.remove(path);
+ toRemove.push_back(path);
+ }
+
+ if (!toRemove.isEmpty())
+ remove(toRemove);
+}
+
+void CppcheckTrigger::checkChangedDocument(Core::IDocument *document)
+{
+ QTC_ASSERT(document, return);
+
+ if (!m_currentProject)
+ return;
+
+ const auto &path = document->filePath();
+ QTC_ASSERT(!path.isEmpty(), return);
+ if (!m_checkedFiles.contains(path))
+ return;
+
+ remove({path});
+ check({path});
+}
+
+void CppcheckTrigger::changeCurrentProject(ProjectExplorer::Project *project)
+{
+ m_currentProject = project;
+ m_checkedFiles.clear();
+ remove({});
+ m_tool.setProject(project);
+ checkEditors(Core::DocumentModel::editorsForOpenedDocuments());
+}
+
+void CppcheckTrigger::updateProjectFiles(ProjectExplorer::Project *project)
+{
+ if (project != m_currentProject)
+ return;
+
+ m_checkedFiles.clear();
+ remove({});
+ m_tool.setProject(project);
+ checkEditors(Core::DocumentModel::editorsForOpenedDocuments());
+}
+
+void CppcheckTrigger::check(const Utils::FileNameList &files)
+{
+ m_tool.check(files);
+}
+
+void CppcheckTrigger::remove(const Utils::FileNameList &files)
+{
+ m_marks.clearFiles(files);
+ m_tool.stop(files);
+}
+
+} // namespace Internal
+} // namespace Cppcheck