diff options
author | Sergey Morozov <dev@gres.biz> | 2018-07-30 21:42:47 +0300 |
---|---|---|
committer | Sergey Morozov <dev@gres.biz> | 2018-09-18 19:07:12 +0000 |
commit | 31b595314c0963cad42ed4cd18d7dc78502479e0 (patch) | |
tree | 670ab7ccac2a0d738cfb59ef47752ee22b26e371 /src/plugins/cppcheck/cppchecktrigger.cpp | |
parent | 20f3c8d65432bffaa1ba6ca9d2512ce3f3e3ce12 (diff) | |
download | qt-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.cpp | 198 |
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 |