1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 Sergey Morozov
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "cppcheckplugin.h"
27 #include "cppcheckconstants.h"
28 #include "cppcheckdiagnosticview.h"
29 #include "cppchecktextmarkmanager.h"
30 #include "cppchecktool.h"
31 #include "cppchecktrigger.h"
32 #include "cppcheckdiagnosticsmodel.h"
33 #include "cppcheckmanualrundialog.h"
34
35 #include <projectexplorer/session.h>
36 #include <projectexplorer/projectexplorer.h>
37 #include <projectexplorer/project.h>
38 #include <projectexplorer/kitinformation.h>
39 #include <projectexplorer/target.h>
40
41 #include <coreplugin/actionmanager/actioncontainer.h>
42 #include <coreplugin/actionmanager/actionmanager.h>
43
44 #include <debugger/analyzer/analyzerconstants.h>
45 #include <debugger/debuggermainwindow.h>
46
47 #include <utils/qtcassert.h>
48 #include <utils/utilsicons.h>
49
50 namespace Cppcheck {
51 namespace Internal {
52
53 class CppcheckPluginPrivate final : public QObject
54 {
55 public:
56 explicit CppcheckPluginPrivate();
57 CppcheckTextMarkManager marks;
58 CppcheckTool tool;
59 CppcheckTrigger trigger;
60 CppcheckOptionsPage options;
61 DiagnosticsModel manualRunModel;
62 CppcheckTool manualRunTool;
63 Utils::Perspective perspective{Constants::PERSPECTIVE_ID, CppcheckPlugin::tr("Cppcheck")};
64 QAction *manualRunAction;
65
66 void startManualRun();
67 void updateManualRunAction();
68 };
69
CppcheckPluginPrivate()70 CppcheckPluginPrivate::CppcheckPluginPrivate() :
71 tool(marks, Constants::CHECK_PROGRESS_ID),
72 trigger(marks, tool),
73 options(tool, trigger),
74 manualRunTool(manualRunModel, Constants::MANUAL_CHECK_PROGRESS_ID)
75 {
76 manualRunTool.updateOptions(tool.options());
77
78 auto manualRunView = new DiagnosticView;
79 manualRunView->setModel(&manualRunModel);
80 perspective.addWindow(manualRunView, Utils::Perspective::SplitVertical, nullptr);
81
82 {
83 // Go to previous diagnostic
84 auto action = new QAction(this);
85 action->setEnabled(false);
86 action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
87 action->setToolTip(CppcheckPlugin::tr("Go to previous diagnostic."));
88 connect(action, &QAction::triggered,
89 manualRunView, &Debugger::DetailedErrorView::goBack);
90 connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
91 action, &QAction::setEnabled);
92 perspective.addToolBarAction(action);
93 }
94
95 {
96 // Go to next diagnostic
97 auto action = new QAction(this);
98 action->setEnabled(false);
99 action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
100 action->setToolTip(CppcheckPlugin::tr("Go to next diagnostic."));
101 connect(action, &QAction::triggered,
102 manualRunView, &Debugger::DetailedErrorView::goNext);
103 connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
104 action, &QAction::setEnabled);
105 perspective.addToolBarAction(action);
106 }
107
108 {
109 // Clear data
110 auto action = new QAction(this);
111 action->setEnabled(false);
112 action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
113 action->setToolTip(CppcheckPlugin::tr("Clear"));
114 connect(action, &QAction::triggered,
115 &manualRunModel, &DiagnosticsModel::clear);
116 connect (&manualRunModel, &DiagnosticsModel::hasDataChanged,
117 action, &QAction::setEnabled);
118 perspective.addToolBarAction(action);
119 }
120 }
121
startManualRun()122 void CppcheckPluginPrivate::startManualRun() {
123 auto project = ProjectExplorer::SessionManager::startupProject();
124 if (!project)
125 return;
126
127 ManualRunDialog dialog(manualRunTool.options(), project);
128 if (dialog.exec() == ManualRunDialog::Rejected)
129 return;
130
131 manualRunModel.clear();
132
133 const auto files = dialog.filePaths();
134 if (files.isEmpty())
135 return;
136
137 manualRunTool.setProject(project);
138 manualRunTool.updateOptions(dialog.options());
139 manualRunTool.check(files);
140 perspective.select();
141 }
142
updateManualRunAction()143 void CppcheckPluginPrivate::updateManualRunAction()
144 {
145 using namespace ProjectExplorer;
146 const Project *project = SessionManager::startupProject();
147 const Target *target = SessionManager::startupTarget();
148 const Utils::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
149 const bool canRun = target && project->projectLanguages().contains(cxx)
150 && ToolChainKitAspect::cxxToolChain(target->kit());
151 manualRunAction->setEnabled(canRun);
152 }
153
154 CppcheckPlugin::CppcheckPlugin() = default;
155
156 CppcheckPlugin::~CppcheckPlugin() = default;
157
initialize(const QStringList & arguments,QString * errorString)158 bool CppcheckPlugin::initialize(const QStringList &arguments, QString *errorString)
159 {
160 Q_UNUSED(arguments)
161 Q_UNUSED(errorString)
162
163 d.reset(new CppcheckPluginPrivate);
164
165 using namespace Core;
166 ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
167
168 {
169 auto action = new QAction(tr("Cppcheck..."), this);
170 menu->addAction(ActionManager::registerAction(action, Constants::MANUAL_RUN_ACTION),
171 Debugger::Constants::G_ANALYZER_TOOLS);
172 connect(action, &QAction::triggered,
173 d.get(), &CppcheckPluginPrivate::startManualRun);
174 d->manualRunAction = action;
175 }
176
177 using ProjectExplorer::ProjectExplorerPlugin;
178 connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::runActionsUpdated,
179 d.get(), &CppcheckPluginPrivate::updateManualRunAction);
180 d->updateManualRunAction();
181
182 return true;
183 }
184
185 } // namespace Internal
186 } // namespace Cppcheck
187