forked from qt-creator/qt-creator
ClangTools: Add QuickFixes to the editor
Change-Id: I9862231f0aa8e8274e8529e57e80eac5ececded9 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -7,7 +7,7 @@ find_package(yaml-cpp QUIET MODULE)
|
|||||||
add_qtc_plugin(ClangTools
|
add_qtc_plugin(ClangTools
|
||||||
CONDITION TARGET yaml-cpp
|
CONDITION TARGET yaml-cpp
|
||||||
DEPENDS ClangSupport yaml-cpp
|
DEPENDS ClangSupport yaml-cpp
|
||||||
PLUGIN_DEPENDS Core Debugger CppTools ${TST_COMPONENT}
|
PLUGIN_DEPENDS Core Debugger CppTools CppEditor ${TST_COMPONENT}
|
||||||
PLUGIN_RECOMMENDS CppEditor
|
PLUGIN_RECOMMENDS CppEditor
|
||||||
INCLUDES ${CLANG_INCLUDE_DIRS}
|
INCLUDES ${CLANG_INCLUDE_DIRS}
|
||||||
SOURCES
|
SOURCES
|
||||||
@@ -33,6 +33,7 @@ add_qtc_plugin(ClangTools
|
|||||||
diagnosticconfigswidget.cpp diagnosticconfigswidget.h
|
diagnosticconfigswidget.cpp diagnosticconfigswidget.h
|
||||||
diagnosticmark.cpp diagnosticmark.h
|
diagnosticmark.cpp diagnosticmark.h
|
||||||
documentclangtoolrunner.cpp documentclangtoolrunner.h
|
documentclangtoolrunner.cpp documentclangtoolrunner.h
|
||||||
|
documentquickfixfactory.cpp documentquickfixfactory.h
|
||||||
executableinfo.cpp executableinfo.h
|
executableinfo.cpp executableinfo.h
|
||||||
filterdialog.cpp filterdialog.h filterdialog.ui
|
filterdialog.cpp filterdialog.h filterdialog.ui
|
||||||
runsettingswidget.cpp runsettingswidget.h runsettingswidget.ui
|
runsettingswidget.cpp runsettingswidget.h runsettingswidget.ui
|
||||||
|
@@ -31,6 +31,7 @@ SOURCES += \
|
|||||||
diagnosticconfigswidget.cpp \
|
diagnosticconfigswidget.cpp \
|
||||||
diagnosticmark.cpp \
|
diagnosticmark.cpp \
|
||||||
documentclangtoolrunner.cpp \
|
documentclangtoolrunner.cpp \
|
||||||
|
documentquickfixfactory.cpp \
|
||||||
executableinfo.cpp \
|
executableinfo.cpp \
|
||||||
filterdialog.cpp \
|
filterdialog.cpp \
|
||||||
runsettingswidget.cpp \
|
runsettingswidget.cpp \
|
||||||
@@ -59,6 +60,7 @@ HEADERS += \
|
|||||||
diagnosticconfigswidget.h \
|
diagnosticconfigswidget.h \
|
||||||
diagnosticmark.h \
|
diagnosticmark.h \
|
||||||
documentclangtoolrunner.h \
|
documentclangtoolrunner.h \
|
||||||
|
documentquickfixfactory.h \
|
||||||
executableinfo.h \
|
executableinfo.h \
|
||||||
filterdialog.h \
|
filterdialog.h \
|
||||||
runsettingswidget.h \
|
runsettingswidget.h \
|
||||||
|
@@ -8,6 +8,7 @@ QtcPlugin {
|
|||||||
Depends { name: "Core" }
|
Depends { name: "Core" }
|
||||||
Depends { name: "TextEditor" }
|
Depends { name: "TextEditor" }
|
||||||
Depends { name: "CppTools" }
|
Depends { name: "CppTools" }
|
||||||
|
Depends { name: "CppEditor" }
|
||||||
Depends { name: "ProjectExplorer" }
|
Depends { name: "ProjectExplorer" }
|
||||||
Depends { name: "QtSupport"; condition: qtc.testsEnabled }
|
Depends { name: "QtSupport"; condition: qtc.testsEnabled }
|
||||||
Depends { name: "QtcSsh" }
|
Depends { name: "QtcSsh" }
|
||||||
@@ -70,6 +71,8 @@ QtcPlugin {
|
|||||||
"diagnosticmark.h",
|
"diagnosticmark.h",
|
||||||
"documentclangtoolrunner.cpp",
|
"documentclangtoolrunner.cpp",
|
||||||
"documentclangtoolrunner.h",
|
"documentclangtoolrunner.h",
|
||||||
|
"documentquickfixfactory.cpp",
|
||||||
|
"documentquickfixfactory.h",
|
||||||
"executableinfo.cpp",
|
"executableinfo.cpp",
|
||||||
"executableinfo.h",
|
"executableinfo.h",
|
||||||
"filterdialog.cpp",
|
"filterdialog.cpp",
|
||||||
|
@@ -8,6 +8,7 @@ isEmpty(EXTERNAL_YAML_CPP_FOUND): QTC_LIB_DEPENDS += yaml-cpp
|
|||||||
|
|
||||||
QTC_PLUGIN_DEPENDS += \
|
QTC_PLUGIN_DEPENDS += \
|
||||||
debugger \
|
debugger \
|
||||||
|
cppeditor \
|
||||||
cpptools
|
cpptools
|
||||||
QTC_PLUGIN_RECOMMENDS += \
|
QTC_PLUGIN_RECOMMENDS += \
|
||||||
cppeditor
|
cppeditor
|
||||||
|
@@ -40,6 +40,10 @@ const char CLANGTIDYCLAZY_RUN_MODE[] = "ClangTidyClazy.RunMode";
|
|||||||
const char CLANG_TIDY_EXECUTABLE_NAME[] = "clang-tidy";
|
const char CLANG_TIDY_EXECUTABLE_NAME[] = "clang-tidy";
|
||||||
const char CLAZY_STANDALONE_EXECUTABLE_NAME[] = "clazy-standalone";
|
const char CLAZY_STANDALONE_EXECUTABLE_NAME[] = "clazy-standalone";
|
||||||
|
|
||||||
|
const char CLANG_TOOL_FIXIT_AVAILABLE_MARKER_ID[] = "ClangToolFixItAvailableMarker";
|
||||||
|
|
||||||
|
const char DIAGNOSTIC_MARK_ID[] = "ClangTool.DiagnosticMark";
|
||||||
|
|
||||||
const char DIAG_CONFIG_TIDY_AND_CLAZY[] = "Builtin.DefaultTidyAndClazy";
|
const char DIAG_CONFIG_TIDY_AND_CLAZY[] = "Builtin.DefaultTidyAndClazy";
|
||||||
|
|
||||||
} // Constants
|
} // Constants
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "clangtoolsprojectsettings.h"
|
#include "clangtoolsprojectsettings.h"
|
||||||
#include "clangtoolsprojectsettingswidget.h"
|
#include "clangtoolsprojectsettingswidget.h"
|
||||||
#include "documentclangtoolrunner.h"
|
#include "documentclangtoolrunner.h"
|
||||||
|
#include "documentquickfixfactory.h"
|
||||||
#include "settingswidget.h"
|
#include "settingswidget.h"
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
@@ -83,9 +84,24 @@ ProjectPanelFactory *projectPanelFactory()
|
|||||||
class ClangToolsPluginPrivate
|
class ClangToolsPluginPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ClangToolsPluginPrivate()
|
||||||
|
: quickFixFactory(
|
||||||
|
[this](const Utils::FilePath &filePath) { return runnerForFilePath(filePath); })
|
||||||
|
{}
|
||||||
|
|
||||||
|
DocumentClangToolRunner *runnerForFilePath(const Utils::FilePath &filePath)
|
||||||
|
{
|
||||||
|
for (DocumentClangToolRunner *runner : documentRunners) {
|
||||||
|
if (runner->filePath() == filePath)
|
||||||
|
return runner;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ClangTool clangTool;
|
ClangTool clangTool;
|
||||||
ClangToolsOptionsPage optionsPage;
|
ClangToolsOptionsPage optionsPage;
|
||||||
QMap<Core::IDocument *, DocumentClangToolRunner *> documentRunners;
|
QMap<Core::IDocument *, DocumentClangToolRunner *> documentRunners;
|
||||||
|
DocumentQuickFixFactory quickFixFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangToolsPlugin::~ClangToolsPlugin()
|
ClangToolsPlugin::~ClangToolsPlugin()
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "diagnosticmark.h"
|
#include "diagnosticmark.h"
|
||||||
|
|
||||||
|
#include "clangtoolsconstants.h"
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
|
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
@@ -35,7 +36,7 @@ namespace Internal {
|
|||||||
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
|
DiagnosticMark::DiagnosticMark(const Diagnostic &diagnostic)
|
||||||
: TextEditor::TextMark(Utils::FilePath::fromString(diagnostic.location.filePath),
|
: TextEditor::TextMark(Utils::FilePath::fromString(diagnostic.location.filePath),
|
||||||
diagnostic.location.line,
|
diagnostic.location.line,
|
||||||
Utils::Id("ClangTool.DiagnosticMark"))
|
Utils::Id(Constants::DIAGNOSTIC_MARK_ID))
|
||||||
, m_diagnostic(diagnostic)
|
, m_diagnostic(diagnostic)
|
||||||
{
|
{
|
||||||
if (diagnostic.type == "error" || diagnostic.type == "fatal")
|
if (diagnostic.type == "error" || diagnostic.type == "fatal")
|
||||||
@@ -67,6 +68,11 @@ bool DiagnosticMark::enabled() const
|
|||||||
return m_enabled;
|
return m_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Diagnostic DiagnosticMark::diagnostic() const
|
||||||
|
{
|
||||||
|
return m_diagnostic;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
|
||||||
|
@@ -41,6 +41,8 @@ public:
|
|||||||
void disable();
|
void disable();
|
||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
|
|
||||||
|
Diagnostic diagnostic() const;
|
||||||
|
|
||||||
QString source;
|
QString source;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -26,8 +26,10 @@
|
|||||||
#include "documentclangtoolrunner.h"
|
#include "documentclangtoolrunner.h"
|
||||||
|
|
||||||
#include "clangfileinfo.h"
|
#include "clangfileinfo.h"
|
||||||
|
#include "clangfixitsrefactoringchanges.h"
|
||||||
#include "clangtidyclazyrunner.h"
|
#include "clangtidyclazyrunner.h"
|
||||||
#include "clangtoolruncontrol.h"
|
#include "clangtoolruncontrol.h"
|
||||||
|
#include "clangtoolsconstants.h"
|
||||||
#include "clangtoolsprojectsettings.h"
|
#include "clangtoolsprojectsettings.h"
|
||||||
#include "clangtoolsutils.h"
|
#include "clangtoolsutils.h"
|
||||||
#include "diagnosticmark.h"
|
#include "diagnosticmark.h"
|
||||||
@@ -42,6 +44,7 @@
|
|||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/textmark.h>
|
#include <texteditor/textmark.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
@@ -85,10 +88,32 @@ DocumentClangToolRunner::~DocumentClangToolRunner()
|
|||||||
qDeleteAll(m_marks);
|
qDeleteAll(m_marks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::FilePath DocumentClangToolRunner::filePath() const
|
||||||
|
{
|
||||||
|
return m_document->filePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
Diagnostics DocumentClangToolRunner::diagnosticsAtLine(int lineNumber) const
|
||||||
|
{
|
||||||
|
Diagnostics diagnostics;
|
||||||
|
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(m_document)) {
|
||||||
|
for (auto mark : textDocument->marksAt(lineNumber)) {
|
||||||
|
if (mark->category() == Constants::DIAGNOSTIC_MARK_ID)
|
||||||
|
diagnostics << static_cast<DiagnosticMark *>(mark)->diagnostic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return diagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentClangToolRunner::scheduleRun()
|
void DocumentClangToolRunner::scheduleRun()
|
||||||
{
|
{
|
||||||
for (DiagnosticMark *mark : m_marks)
|
for (DiagnosticMark *mark : m_marks)
|
||||||
mark->disable();
|
mark->disable();
|
||||||
|
for (TextEditor::TextEditorWidget *editor : m_editorsWithMarkers) {
|
||||||
|
editor->setRefactorMarkers(
|
||||||
|
TextEditor::RefactorMarker::filterOutType(editor->refactorMarkers(),
|
||||||
|
Constants::CLANG_TOOL_FIXIT_AVAILABLE_MARKER_ID));
|
||||||
|
}
|
||||||
m_runTimer.start();
|
m_runTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,19 +258,27 @@ void DocumentClangToolRunner::runNext()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateLocation(Debugger::DiagnosticLocation &location)
|
||||||
|
{
|
||||||
|
location.filePath = vfso().originalFilePath(Utils::FilePath::fromString(location.filePath)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentClangToolRunner::onSuccess()
|
void DocumentClangToolRunner::onSuccess()
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
Utils::FilePath mappedPath = vfso().filePath(m_document);
|
Utils::FilePath mappedPath = vfso().autoSavedFilePath(m_document);
|
||||||
Diagnostics diagnostics = readExportedDiagnostics(
|
Diagnostics diagnostics = readExportedDiagnostics(
|
||||||
Utils::FilePath::fromString(m_currentRunner->outputFilePath()),
|
Utils::FilePath::fromString(m_currentRunner->outputFilePath()),
|
||||||
[&](const Utils::FilePath &path) { return path == mappedPath; },
|
[&](const Utils::FilePath &path) { return path == mappedPath; },
|
||||||
&errorMessage);
|
&errorMessage);
|
||||||
|
|
||||||
if (mappedPath != m_document->filePath()) {
|
for (Diagnostic &diag : diagnostics) {
|
||||||
const QString originalPath = m_document->filePath().toString();
|
updateLocation(diag.location);
|
||||||
for (Diagnostic &diag : diagnostics)
|
for (ExplainingStep &explainingStep : diag.explainingSteps) {
|
||||||
diag.location.filePath = originalPath;
|
updateLocation(explainingStep.location);
|
||||||
|
for (Debugger::DiagnosticLocation &rangeLocation : explainingStep.ranges)
|
||||||
|
updateLocation(rangeLocation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove outdated marks of the current runner
|
// remove outdated marks of the current runner
|
||||||
@@ -255,11 +288,41 @@ void DocumentClangToolRunner::onSuccess()
|
|||||||
m_marks = newMarks;
|
m_marks = newMarks;
|
||||||
qDeleteAll(toDelete);
|
qDeleteAll(toDelete);
|
||||||
|
|
||||||
m_marks << Utils::transform(diagnostics, [this](const Diagnostic &diagnostic) {
|
auto doc = qobject_cast<TextEditor::TextDocument *>(m_document);
|
||||||
|
|
||||||
|
TextEditor::RefactorMarkers markers;
|
||||||
|
|
||||||
|
for (const Diagnostic &diagnostic : diagnostics) {
|
||||||
auto mark = new DiagnosticMark(diagnostic);
|
auto mark = new DiagnosticMark(diagnostic);
|
||||||
mark->source = m_currentRunner->name();
|
mark->source = m_currentRunner->name();
|
||||||
return mark;
|
|
||||||
});
|
if (doc && Utils::anyOf(diagnostic.explainingSteps, &ExplainingStep::isFixIt)) {
|
||||||
|
TextEditor::RefactorMarker marker;
|
||||||
|
marker.tooltip = diagnostic.description;
|
||||||
|
QTextCursor cursor(doc->document());
|
||||||
|
cursor.setPosition(Utils::Text::positionInText(doc->document(),
|
||||||
|
diagnostic.location.line,
|
||||||
|
diagnostic.location.column));
|
||||||
|
cursor.movePosition(QTextCursor::EndOfLine);
|
||||||
|
marker.cursor = cursor;
|
||||||
|
marker.type = Constants::CLANG_TOOL_FIXIT_AVAILABLE_MARKER_ID;
|
||||||
|
marker.callback = [marker](TextEditor::TextEditorWidget *editor) {
|
||||||
|
editor->setTextCursor(marker.cursor);
|
||||||
|
editor->invokeAssist(TextEditor::QuickFix);
|
||||||
|
};
|
||||||
|
markers << marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_marks << mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto editor : TextEditor::BaseTextEditor::textEditorsForDocument(doc)) {
|
||||||
|
if (TextEditor::TextEditorWidget *widget = editor->editorWidget()) {
|
||||||
|
widget->setRefactorMarkers(markers + widget->refactorMarkers());
|
||||||
|
m_editorsWithMarkers << widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
runNext();
|
runNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "clangfileinfo.h"
|
#include "clangfileinfo.h"
|
||||||
|
#include "clangtoolsdiagnostic.h"
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
|
|
||||||
namespace Core { class IDocument; }
|
namespace Core { class IDocument; }
|
||||||
namespace CppTools { class ClangDiagnosticConfig; }
|
namespace CppTools { class ClangDiagnosticConfig; }
|
||||||
|
namespace TextEditor { class TextEditorWidget; }
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
|
|
||||||
@@ -50,6 +52,9 @@ public:
|
|||||||
DocumentClangToolRunner(Core::IDocument *doc);
|
DocumentClangToolRunner(Core::IDocument *doc);
|
||||||
~DocumentClangToolRunner();
|
~DocumentClangToolRunner();
|
||||||
|
|
||||||
|
Utils::FilePath filePath() const;
|
||||||
|
Diagnostics diagnosticsAtLine(int lineNumber) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void scheduleRun();
|
void scheduleRun();
|
||||||
void run();
|
void run();
|
||||||
@@ -62,6 +67,7 @@ private:
|
|||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
|
|
||||||
const CppTools::ClangDiagnosticConfig getDiagnosticConfig(ProjectExplorer::Project *project);
|
const CppTools::ClangDiagnosticConfig getDiagnosticConfig(ProjectExplorer::Project *project);
|
||||||
template<class T>
|
template<class T>
|
||||||
ClangToolRunner *createRunner(const CppTools::ClangDiagnosticConfig &config,
|
ClangToolRunner *createRunner(const CppTools::ClangDiagnosticConfig &config,
|
||||||
@@ -75,6 +81,7 @@ private:
|
|||||||
QList<DiagnosticMark *> m_marks;
|
QList<DiagnosticMark *> m_marks;
|
||||||
FileInfo m_fileInfo;
|
FileInfo m_fileInfo;
|
||||||
QMetaObject::Connection m_projectSettingsUpdate;
|
QMetaObject::Connection m_projectSettingsUpdate;
|
||||||
|
QSet<TextEditor::TextEditorWidget *> m_editorsWithMarkers;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
107
src/plugins/clangtools/documentquickfixfactory.cpp
Normal file
107
src/plugins/clangtools/documentquickfixfactory.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** 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 "documentquickfixfactory.h"
|
||||||
|
|
||||||
|
#include "clangfixitsrefactoringchanges.h"
|
||||||
|
#include "clangtoolsdiagnostic.h"
|
||||||
|
#include "documentclangtoolrunner.h"
|
||||||
|
|
||||||
|
#include <texteditor/refactoringchanges.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ClangToolQuickFixOperation : public TextEditor::QuickFixOperation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ClangToolQuickFixOperation(const Diagnostic &diagnostic)
|
||||||
|
: m_diagnostic(diagnostic)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString description() const override { return m_diagnostic.description; }
|
||||||
|
void perform() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Diagnostic m_diagnostic;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Range = TextEditor::RefactoringFile::Range;
|
||||||
|
using DiagnosticRange = QPair<Debugger::DiagnosticLocation, Debugger::DiagnosticLocation>;
|
||||||
|
|
||||||
|
static Range toRange(const QTextDocument *doc, DiagnosticRange locations)
|
||||||
|
{
|
||||||
|
Range range;
|
||||||
|
range.start = Utils::Text::positionInText(doc, locations.first.line, locations.first.column);
|
||||||
|
range.end = Utils::Text::positionInText(doc, locations.second.line, locations.second.column);
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolQuickFixOperation::perform()
|
||||||
|
{
|
||||||
|
TextEditor::RefactoringChanges changes;
|
||||||
|
QMap<QString, TextEditor::RefactoringFilePtr> refactoringFiles;
|
||||||
|
|
||||||
|
for (const ExplainingStep &step : m_diagnostic.explainingSteps) {
|
||||||
|
if (!step.isFixIt)
|
||||||
|
continue;
|
||||||
|
TextEditor::RefactoringFilePtr &refactoringFile = refactoringFiles[step.location.filePath];
|
||||||
|
if (refactoringFile.isNull())
|
||||||
|
refactoringFile = changes.file(step.location.filePath);
|
||||||
|
Utils::ChangeSet changeSet = refactoringFile->changeSet();
|
||||||
|
Range range = toRange(refactoringFile->document(), {step.ranges.first(), step.ranges.last()});
|
||||||
|
changeSet.replace(range, step.message);
|
||||||
|
refactoringFile->setChangeSet(changeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const TextEditor::RefactoringFilePtr &refactoringFile : qAsConst(refactoringFiles))
|
||||||
|
refactoringFile->apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentQuickFixFactory::DocumentQuickFixFactory(DocumentQuickFixFactory::RunnerCollector runnerCollector)
|
||||||
|
: m_runnerCollector(runnerCollector)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void DocumentQuickFixFactory::match(const CppEditor::Internal::CppQuickFixInterface &interface,
|
||||||
|
QuickFixOperations &result)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_runnerCollector, return );
|
||||||
|
if (DocumentClangToolRunner *runner = m_runnerCollector(interface.filePath())) {
|
||||||
|
const QTextBlock &block = interface.textDocument()->findBlock(interface.position());
|
||||||
|
if (!block.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int lineNumber = block.blockNumber() + 1;
|
||||||
|
|
||||||
|
for (Diagnostic diagnostic : runner->diagnosticsAtLine(lineNumber)) {
|
||||||
|
if (diagnostic.hasFixits)
|
||||||
|
result << new ClangToolQuickFixOperation(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
49
src/plugins/clangtools/documentquickfixfactory.h
Normal file
49
src/plugins/clangtools/documentquickfixfactory.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cppeditor/cppquickfix.h>
|
||||||
|
|
||||||
|
namespace ClangTools {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class DocumentClangToolRunner;
|
||||||
|
|
||||||
|
class DocumentQuickFixFactory : public CppEditor::CppQuickFixFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using RunnerCollector = std::function<DocumentClangToolRunner *(const Utils::FilePath &)>;
|
||||||
|
|
||||||
|
DocumentQuickFixFactory(RunnerCollector runnerCollector);
|
||||||
|
void match(const CppEditor::Internal::CppQuickFixInterface &interface,
|
||||||
|
QuickFixOperations &result) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RunnerCollector m_runnerCollector;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangTools
|
@@ -26,6 +26,7 @@
|
|||||||
#include "virtualfilesystemoverlay.h"
|
#include "virtualfilesystemoverlay.h"
|
||||||
|
|
||||||
#include <coreplugin/documentmanager.h>
|
#include <coreplugin/documentmanager.h>
|
||||||
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@@ -80,6 +81,9 @@ void VirtualFileSystemOverlay::update()
|
|||||||
qCDebug(LOG) << error;
|
qCDebug(LOG) << error;
|
||||||
}
|
}
|
||||||
m_saved = newSaved;
|
m_saved = newSaved;
|
||||||
|
m_mapping.clear();
|
||||||
|
for (auto it = m_saved.constBegin(), end = m_saved.constEnd(); it != end; ++it)
|
||||||
|
m_mapping[it.value().path] = it.key()->filePath();
|
||||||
|
|
||||||
auto toContent = [this](Core::IDocument *document) {
|
auto toContent = [this](Core::IDocument *document) {
|
||||||
QJsonObject content;
|
QJsonObject content;
|
||||||
@@ -112,7 +116,7 @@ void VirtualFileSystemOverlay::update()
|
|||||||
|
|
||||||
Utils::FilePath VirtualFileSystemOverlay::overlayFilePath() { return m_overlayFilePath; }
|
Utils::FilePath VirtualFileSystemOverlay::overlayFilePath() { return m_overlayFilePath; }
|
||||||
|
|
||||||
Utils::FilePath VirtualFileSystemOverlay::filePath(Core::IDocument *doc)
|
Utils::FilePath VirtualFileSystemOverlay::autoSavedFilePath(Core::IDocument *doc)
|
||||||
{
|
{
|
||||||
auto it = m_saved.find(doc);
|
auto it = m_saved.find(doc);
|
||||||
if (it != m_saved.end())
|
if (it != m_saved.end())
|
||||||
@@ -120,5 +124,10 @@ Utils::FilePath VirtualFileSystemOverlay::filePath(Core::IDocument *doc)
|
|||||||
return doc->filePath();
|
return doc->filePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::FilePath VirtualFileSystemOverlay::originalFilePath(const Utils::FilePath &file)
|
||||||
|
{
|
||||||
|
return m_mapping.value(file, file);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangTools
|
} // namespace ClangTools
|
||||||
|
@@ -43,7 +43,8 @@ public:
|
|||||||
void update();
|
void update();
|
||||||
|
|
||||||
Utils::FilePath overlayFilePath();
|
Utils::FilePath overlayFilePath();
|
||||||
Utils::FilePath filePath(Core::IDocument *doc);
|
Utils::FilePath autoSavedFilePath(Core::IDocument *doc);
|
||||||
|
Utils::FilePath originalFilePath(const Utils::FilePath &file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::TemporaryDirectory m_root;
|
Utils::TemporaryDirectory m_root;
|
||||||
@@ -55,6 +56,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QMap<Core::IDocument *, AutoSavedPath> m_saved;
|
QMap<Core::IDocument *, AutoSavedPath> m_saved;
|
||||||
|
QMap<Utils::FilePath, Utils::FilePath> m_mapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user