[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdev-clang/wip/maciej/tooling] refactoring: Move all refactoring actions to background
From: Maciej Poleski <d82ks8djf82msd83hf8sc02lqb5gh5 () gmail ! com>
Date: 2015-08-01 1:16:58
Message-ID: E1ZLLQ2-0003gw-GS () scm ! kde ! org
[Download RAW message or body]
Git commit cf1679ce62ea927e4c1f006d477bd0a1577708bf by Maciej Poleski.
Committed on 01/08/2015 at 01:16.
Pushed by mpoleski into branch 'wip/maciej/tooling'.
Move all refactoring actions to background
By the way remove old interface.h
M +0 -1 refactoring/CMakeLists.txt
C +26 -18 refactoring/actionwatcher.cpp [from: refactoring/kdevrefactorings.cpp \
- 053% similarity] C +23 -12 refactoring/actionwatcher.h [from: \
refactoring/nooprefactoring.cpp - 064% similarity] M +22 -7 \
refactoring/changesignaturerefactoring.cpp M +11 -0 \
refactoring/changesignaturerefactoring.h M +20 -11 \
refactoring/contextmenumutator.cpp M +1 -1 \
refactoring/declarationcomparator.cpp M +0 -1 refactoring/documentcache.cpp
M +12 -6 refactoring/encapsulatefieldrefactoring.cpp
D +0 -117 refactoring/interface.cpp
D +0 -152 refactoring/interface.h
M +0 -1 refactoring/kdevrefactorings.cpp
M +0 -1 refactoring/kdevrefactorings.h
M +1 -1 refactoring/nooprefactoring.cpp
M +38 -3 refactoring/refactoring.cpp
M +14 -7 refactoring/refactoring.h
M +21 -0 refactoring/refactoringcontext.cpp
M +11 -4 refactoring/refactoringcontext.h
M +25 -15 refactoring/renamefielddeclrefactoring.cpp
M +8 -0 refactoring/renamefielddeclrefactoring.h
M +30 -17 refactoring/renamefielddeclturefactoring.cpp
M +8 -0 refactoring/renamefielddeclturefactoring.h
M +15 -17 refactoring/renamevardeclrefactoring.cpp
http://commits.kde.org/kdev-clang/cf1679ce62ea927e4c1f006d477bd0a1577708bf
diff --git a/refactoring/CMakeLists.txt b/refactoring/CMakeLists.txt
index c9b7e90..f916151 100644
--- a/refactoring/CMakeLists.txt
+++ b/refactoring/CMakeLists.txt
@@ -2,7 +2,6 @@
set(CMAKE_AUTOUIC ON)
set(SRCS
- interface.cpp
utils.cpp
documentcache.cpp
refactoring.cpp
diff --git a/refactoring/kdevrefactorings.cpp b/refactoring/actionwatcher.cpp
similarity index 53%
copy from refactoring/kdevrefactorings.cpp
copy to refactoring/actionwatcher.cpp
index 07ad6b6..9ac24fa 100644
--- a/refactoring/kdevrefactorings.cpp
+++ b/refactoring/actionwatcher.cpp
@@ -19,32 +19,40 @@
Boston, MA 02110-1301, USA.
*/
-// KDevelop
-#include <language/interfaces/editorcontext.h>
+#include <QAction>
-#include "kdevrefactorings.h"
-#include "refactoringcontext.h"
-#include "refactoringmanager.h"
-
-#include "../clangsupport.h"
+#include "actionwatcher.h"
+#include "debug.h"
+ActionWatcher::ActionWatcher(QAction *action)
+ : QObject(action)
+{
+ registerAssociatedWidgets();
+}
-using namespace KDevelop;
-using namespace Refactorings;
+QAction *ActionWatcher::parent()
+{
+ return static_cast<QAction *>(QObject::parent());
+}
-KDevRefactorings::KDevRefactorings(ClangSupport *parent)
- : QObject(parent)
- , m_refactoringsContext(new RefactoringContext(this))
- , m_refactoringManager(new RefactoringManager(this))
+void ActionWatcher::decreaseCount()
{
+ m_count--;
+ if (m_count == 0) {
+ registerAssociatedWidgets();
+ }
}
-void KDevRefactorings::fillContextMenu(ContextMenuExtension &extension, Context \
*context) +void ActionWatcher::registerAssociatedWidgets()
{
- if (EditorContext *ctx = dynamic_cast<EditorContext *>(context)) {
- m_refactoringManager->fillContextMenu(extension, ctx);
+ // Consider watching for ActionEvents - action may be removed from widget before \
destruction + const auto &widgets = parent()->associatedWidgets();
+ m_count = widgets.count();
+ if (m_count == 0) {
+ parent()->deleteLater();
} else {
- // I assume the above works anytime we ask for context menu for code
- Q_ASSERT(!context->hasType(Context::CodeContext));
+ for (QWidget *w : widgets) {
+ connect(w, &QObject::destroyed, this, &ActionWatcher::decreaseCount);
+ }
}
}
diff --git a/refactoring/nooprefactoring.cpp b/refactoring/actionwatcher.h
similarity index 64%
copy from refactoring/nooprefactoring.cpp
copy to refactoring/actionwatcher.h
index c62bece..6a12985 100644
--- a/refactoring/nooprefactoring.cpp
+++ b/refactoring/actionwatcher.h
@@ -19,20 +19,31 @@
Boston, MA 02110-1301, USA.
*/
-#include "nooprefactoring.h"
+#ifndef KDEV_CLANG_QACTIONWATCHER_H
+#define KDEV_CLANG_QACTIONWATCHER_H
-#include "documentcache.h"
+#include <QObject>
-#include "../util/clangdebug.h"
+class QAction;
-QString NoopRefactoring::name() const
+/**
+ * Watches associated widgets and deletes action when last associated widget is \
destroyed + */
+class ActionWatcher : public QObject
{
- return QStringLiteral("do nothing");
-}
+ Q_OBJECT;
+ Q_DISABLE_COPY(ActionWatcher);
+public:
+ ActionWatcher(QAction *action);
-llvm::ErrorOr<clang::tooling::Replacements> \
NoopRefactoring::invoke(RefactoringContext *ctx)
-{
- Q_UNUSED(ctx);
- clangDebug() << "Did nothing (dummy refactoring action)";
- return clang::tooling::Replacements();
-}
\ No newline at end of file
+private:
+ QAction *parent();
+ void decreaseCount();
+ void registerAssociatedWidgets();
+
+private:
+ int m_count;
+};
+
+
+#endif //KDEV_CLANG_QACTIONWATCHER_H
diff --git a/refactoring/changesignaturerefactoring.cpp \
b/refactoring/changesignaturerefactoring.cpp index 94bf79f..965c6e0 100644
--- a/refactoring/changesignaturerefactoring.cpp
+++ b/refactoring/changesignaturerefactoring.cpp
@@ -79,7 +79,7 @@ private:
ChangeSignatureRefactoring::ChangeSignatureRefactoring(const FunctionDecl \
*functionDecl) : Refactoring(nullptr)
- , m_infoPack(InfoPack::fromFunctionDecl(functionDecl))
+ , m_infoPack(InfoPack::fromFunctionDecl(functionDecl))
{
}
@@ -94,24 +94,39 @@ llvm::ErrorOr<clang::tooling::Replacements> \
ChangeSignatureRefactoring::invoke( return cancelledResult();
}
- auto &tool = ctx->cache->refactoringTool();
+ auto infoPack = dialog->infoPack(); // C++14...
+ auto changePack = dialog->changePack();
+ return ctx->scheduleRefactoring(
+ [infoPack, changePack](RefactoringTool &tool)
+ {
+ Refactorings::ChangeSignature::run(infoPack, changePack, tool);
+ return tool.getReplacements();
+ }
+ );
+}
+namespace Refactorings
+{
+namespace ChangeSignature
+{
+int run(const InfoPack *infoPack, const ChangePack *changePack, RefactoringTool \
&tool) +{
auto declRefExprMatcher = declRefExpr(to(functionDecl())).bind("DeclRefExpr");
auto memberExprMatcher = memberExpr().bind("MemberExpr");
auto functionDeclMatcher = functionDecl().bind("FunctionDecl");
auto functionCallMatcher = callExpr().bind("CallExpr");
- Translator translator(&m_infoPack->declarationComparator(), dialog->infoPack(),
- dialog->changePack(), tool.getReplacements());
+ Translator translator(&infoPack->declarationComparator(), infoPack, changePack,
+ tool.getReplacements());
MatchFinder finder;
finder.addMatcher(declRefExprMatcher, &translator);
finder.addMatcher(memberExprMatcher, &translator);
finder.addMatcher(functionDeclMatcher, &translator);
finder.addMatcher(functionCallMatcher, &translator);
- tool.run(newFrontendActionFactory(&finder).get());
-
- return tool.getReplacements();
+ return tool.run(newFrontendActionFactory(&finder).get());
+}
+}
}
QString ChangeSignatureRefactoring::name() const
diff --git a/refactoring/changesignaturerefactoring.h \
b/refactoring/changesignaturerefactoring.h index 36098e1..3e0488b 100644
--- a/refactoring/changesignaturerefactoring.h
+++ b/refactoring/changesignaturerefactoring.h
@@ -48,5 +48,16 @@ private:
std::unique_ptr<const InfoPack> m_infoPack;
};
+namespace Refactorings
+{
+namespace ChangeSignature
+{
+using InfoPack = ChangeSignatureRefactoring::InfoPack;
+using ChangePack = ChangeSignatureRefactoring::ChangePack;
+
+int run(const InfoPack *infoPack, const ChangePack *changePack,
+ clang::tooling::RefactoringTool &tool);
+}
+}
#endif //KDEV_CLANG_CHANGESIGNATUREREFACTORING_H
diff --git a/refactoring/contextmenumutator.cpp b/refactoring/contextmenumutator.cpp
index 5264a42..bb8f556 100644
--- a/refactoring/contextmenumutator.cpp
+++ b/refactoring/contextmenumutator.cpp
@@ -30,11 +30,18 @@
#include <interfaces/contextmenuextension.h>
#include <language/interfaces/editorcontext.h>
+// Clang
+#include <clang/Tooling/Core/Replacement.h>
+
#include "contextmenumutator.h"
#include "refactoringmanager.h"
#include "kdevrefactorings.h"
#include "actionwatcher.h"
+#include "refactoringcontext.h"
+#include "utils.h"
+using namespace clang;
+using namespace clang::tooling;
using namespace KDevelop;
ContextMenuMutator::ContextMenuMutator(ContextMenuExtension &extension, \
RefactoringManager *parent) @@ -89,21 +96,23 @@ QWidget \
*ContextMenuMutator::menuForWidget(QWidget *widget) void \
ContextMenuMutator::endFillingContextMenu(const QVector<Refactoring *> &refactorings) \
{ QList<QAction *> actions;
- auto refactoringContext = parent()->parent()->refactoringContext();
+ auto ctx = parent()->parent()->refactoringContext();
for (auto refactorAction : refactorings) {
QAction *action = new QAction(refactorAction->name(), parent());
refactorAction->setParent(action); // delete as necessary
- connect(action, &QAction::triggered, [this, refactoringContext, \
refactorAction]() + connect(action, &QAction::triggered, [this, ctx, \
refactorAction]() {
- // TODO: don't use refactorThis
- auto changes = Refactorings::refactorThis(refactoringContext, \
refactorAction,
- {}, {});
- // FIXME:
- // use background thread
- // ... provided with ability to show GUI
- // show busy indicator
-
- changes.applyAllChanges();
+ auto result = refactorAction->invoke(ctx);
+ if (!result) {
+ ctx->reportError(result.getError());
+ }
+ auto changes = toDocumentChangeSet(result.get(), ctx->cache,
+ \
ctx->cache->refactoringTool().getFiles()); + if (!changes) {
+ ctx->reportError(changes.getError());
+ } else {
+ changes.get().applyAllChanges();
+ }
});
actions.push_back(action);
}
diff --git a/refactoring/declarationcomparator.cpp \
b/refactoring/declarationcomparator.cpp index 5bec32b..957e694 100644
--- a/refactoring/declarationcomparator.cpp
+++ b/refactoring/declarationcomparator.cpp
@@ -21,4 +21,4 @@
#include "declarationcomparator.h"
-DeclarationComparator::~DeclarationComparator() = default;
\ No newline at end of file
+DeclarationComparator::~DeclarationComparator() = default;
diff --git a/refactoring/documentcache.cpp b/refactoring/documentcache.cpp
index 2fae5b7..e8c1016 100644
--- a/refactoring/documentcache.cpp
+++ b/refactoring/documentcache.cpp
@@ -28,7 +28,6 @@
#include "refactoringcontext.h"
#include "utils.h"
-#include "interface.h"
#include "../util/clangdebug.h"
using namespace KDevelop;
diff --git a/refactoring/encapsulatefieldrefactoring.cpp \
b/refactoring/encapsulatefieldrefactoring.cpp index 4fb397f..6f137a5 100644
--- a/refactoring/encapsulatefieldrefactoring.cpp
+++ b/refactoring/encapsulatefieldrefactoring.cpp
@@ -102,12 +102,18 @@ llvm::ErrorOr<clang::tooling::Replacements> \
EncapsulateFieldRefactoring::invoke( return cancelledResult();
}
- auto &tool = ctx->cache->refactoringTool();
-
- Refactorings::EncapsulateField::run(tool, m_changePack.get(), &m_declDispatcher,
- &m_recordDeclDispatcher, m_recordName);
-
- return tool.getReplacements();
+ const ChangePack *changePack = m_changePack.get(); // C++14...
+ auto declDispatcher = m_declDispatcher;
+ auto recordDeclDispatcher = m_recordDeclDispatcher;
+ auto recordName = m_recordName;
+ return ctx->scheduleRefactoring(
+ [changePack, declDispatcher, recordDeclDispatcher, \
recordName](RefactoringTool &tool) + {
+ Refactorings::EncapsulateField::run(tool, changePack, &declDispatcher,
+ &recordDeclDispatcher, recordName);
+ return tool.getReplacements();
+ }
+ );
}
namespace Refactorings
diff --git a/refactoring/interface.cpp b/refactoring/interface.cpp
deleted file mode 100644
index 63379bc..0000000
--- a/refactoring/interface.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- This file is part of KDevelop
-
- Copyright 2015 Maciej Poleski <d82ks8djf82msd83hf8sc02lqb5gh5@gmail.com>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "interface.h"
-
-// KF5
-#include <KI18n/klocalizedstring.h>
-
-// Clang
-#include <clang/Tooling/Refactoring.h>
-
-#include "utils.h"
-#include "refactoringcontext.h"
-#include "documentcache.h"
-#include "refactoringinfo.h"
-
-#include "nooprefactoring.h"
-#include "renamevardeclrefactoring.h"
-
-#include "../util/clangdebug.h"
-
-namespace Refactorings
-{
-
-//////////////////////// Compilation Database
-
-// Maybe skip this opaque pointer? (but would leak details...)
-struct CompilationDatabase_t
-{
- std::unique_ptr<clang::tooling::CompilationDatabase> database;
-};
-
-CompilationDatabase createCompilationDatabase(const std::string &buildPath, \
ProjectKind kind,
- QString &errorMessage)
-{
- if (kind != ProjectKind::CMAKE) {
- errorMessage = i18n("Only CMake projects are supported for now");
- return nullptr;
- }
- auto result = makeCompilationDatabaseFromCMake(buildPath, errorMessage);
- if (result == nullptr) {
- return nullptr;
- }
- return new CompilationDatabase_t{std::move(result)};
-};
-
-CompilationDatabase createCMakeCompilationDatabase(const std::string &buildPath)
-{
- QString error; // ignored, required by Clang API
- auto cd = makeCompilationDatabaseFromCMake(buildPath, error);
- if (cd == nullptr) {
- return nullptr;
- } else {
- return new CompilationDatabase_t{std::move(cd)};
- }
-}
-
-void releaseCompilationDatabase(CompilationDatabase db)
-{
- delete db;
-}
-
-///////////////// Refactoring Context
-
-KDevelop::DocumentChangeSet refactorThis(RefactoringsContext rc, RefactoringKind \
refactoringKind,
- const QUrl &sourceFile,
- const KTextEditor::Cursor &position)
-{
- Q_ASSERT(rc);
- Refactoring *refactoring = dynamic_cast<Refactoring *>(refactoringKind);
- Q_ASSERT(refactoring);
- // FIXME: introduce RefactoringManager to maintain pool of refactorings and such \
translations
-
- auto result = refactoring->invoke(rc);
- // TODO: introduce union type for {Location, What}
-
- if (!result) {
- // TODO: notify
- clangDebug() << "Refactoring failed: " << \
result.getError().message().c_str();
- return KDevelop::DocumentChangeSet();
- }
-
- auto changes = toDocumentChangeSet(result.get(), rc->cache, \
rc->cache->refactoringTool().getFiles());
- if (!changes) {
- // TODO: notify
- clangDebug() << "Translation Replacements to DocumentChangeSet failed " <<
- result.getError().message().c_str();
- return KDevelop::DocumentChangeSet();
- }
- return changes.get();
-}
-
-// TODO: consider removing this function
-std::vector<std::string> sources(CompilationDatabase db)
-{
- return db->database->getAllFiles();
-}
-
-};
diff --git a/refactoring/interface.h b/refactoring/interface.h
deleted file mode 100644
index 5ba386b..0000000
--- a/refactoring/interface.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- This file is part of KDevelop
-
- Copyright 2015 Maciej Poleski <d82ks8djf82msd83hf8sc02lqb5gh5@gmail.com>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-// This header file should be independent of any Clang libraries both
-// compile time and run time.
-// All of refactorings features will be accessible from here
-
-#ifndef KDEV_CLANG_INTERFACE_H
-#define KDEV_CLANG_INTERFACE_H
-
-// C++
-#include <vector>
-#include <string>
-#include <unordered_map>
-
-// Qt
-#include <QUrl>
-#include <QString>
-
-// KF5
-#include <KTextEditor/ktexteditor/cursor.h>
-
-// KDevelop
-#include <language/codegen/documentchangeset.h>
-
-namespace KDevelop
-{
-class IDocumentController;
-};
-
-class RefactoringInfo;
-class RefactoringContext;
-
-namespace Refactorings
-{
-
-struct CompilationDatabase_t;
-struct RefactoringsContext_t;
-
-// All std::strings appearing here may be replaced to something different
-// if necessary (QString, QUrl, ...)
-// All functions provided here get C linkage. These (few) functions as designed
-// to provide interoperability with KDevelop based on stable, predictable ABI.
-// It can bu used later to dlopen implementation, or as "engine" in standalone
-// executable.
-// Note: some types are not fully known now. typedefs will change soon
-
-
-// CompilationDatabase will be used internally, but needs initialization
-typedef CompilationDatabase_t *CompilationDatabase;
-
-// All data which can be required for any operation of this library.
-// It is CompilationDatabase, ClangTool (with virtual files), ...
-typedef RefactoringContext *RefactoringsContext;
-
-// Short information about one particular kind of refactoring.
-typedef RefactoringInfo *RefactoringKind;
-
-enum class ProjectKind
-{
- CMAKE, // CMake project are already nice
- NON_CMAKE, // Non CMake are nice after use of Bear
-}; // Where "nice" means prepared compile_commands.json file
-
-/**
- * Prepares and returns compilation database for given project build path.
- * Note: result of this operation is deprecated by any change in project
- * structure (adding new file, removing, renaming, changing flags, ...).
- * In such a case new object must be created using this function.
- *
- * @param buildPath build path for given project (ex. CMAKE_BINARY_DIR)
- * @param kind CMAKE if underlying project is a configured CMake project
- * with CMAKE_EXPORT_COMPILE_COMMANDS enabled, NON_CMAKE otherwise
- * @param errorMessage will be set to error message if any occurred
- * @return Compilation database for given project
- */
-CompilationDatabase createCompilationDatabase(const std::string &buildPath, \
ProjectKind kind,
- QString &errorMessage);
-
-/**
- * Simpler version of the above only for CMake projects as requested in
- * https://git.reviewboard.kde.org/r/123963/#comment55684 and
- * https://git.reviewboard.kde.org/r/123963/#comment55548
- *
- * @return nullptr on error
- */
-CompilationDatabase createCMakeCompilationDatabase(const std::string &buildPath);
-
-/**
- * Frees resources used by given compilation database.
- * NOTE: You mustn't release database given to @c createRefactoringsContext
- * as that function takes ownership of compilation database.
- *
- * @param db compilation database to be released
- */
-void releaseCompilationDatabase(CompilationDatabase db);
-
-// TODO: mergeCompilationDatabases - handle refactorings between projects
-
-/**
- * Returns list of all sources from given CompilationDatabase
- *
- * @note: dedicated to provide @c sources for @c createRefactoringsContext
- */
-std::vector<std::string> sources(CompilationDatabase db);
-
-/**
- * Invokes selected refactoring action on selected place in file.
- *
- * @param rc Initialized refactorings context
- * @param refactoring A refactoring kind we are going to apply here
- * @param sourceFile source file name (full path)
- * @param position position in source file which we are going to work on
- */
-KDevelop::DocumentChangeSet refactorThis(RefactoringsContext rc, RefactoringKind \
refactoring,
- const QUrl &sourceFile,
- const KTextEditor::Cursor &position);
-// NOTE: We have to cooperate with cache here (it is guaranteed that sourceFile is \
in cache,
-// as this file is already opened). Maybe it is more reasonable to provide Document* \
here?
-// Especially when DocumentCache middleware will be IDocumentController aware.
-// NOTE: position (Cursor) is not nice - will need translation to offset.
-// NOTE: We are going to need some GUI handle here. Probably something like QWidget* \
parent
-// will be introduced as additional parameter (but it will bind this interface to Qt \
Widgets).
-// NOTE: Can we block calling thread? I would say no. We are going to need Qt \
wrapper/continuation
-// here.
-
-
-// TODO: refactorThis(RefactoringsContext, RefactoringKind, Location, ...)
-// TODO: refactor(RefactoringsContext, RefactoringKind, What, ...)
-// ^^^^ will return DocumentChangeSet
-
-};
-
-#endif //KDEV_CLANG_INTERFACE_H
diff --git a/refactoring/kdevrefactorings.cpp b/refactoring/kdevrefactorings.cpp
index 07ad6b6..42e3d20 100644
--- a/refactoring/kdevrefactorings.cpp
+++ b/refactoring/kdevrefactorings.cpp
@@ -30,7 +30,6 @@
using namespace KDevelop;
-using namespace Refactorings;
KDevRefactorings::KDevRefactorings(ClangSupport *parent)
: QObject(parent)
diff --git a/refactoring/kdevrefactorings.h b/refactoring/kdevrefactorings.h
index f44d68d..d906854 100644
--- a/refactoring/kdevrefactorings.h
+++ b/refactoring/kdevrefactorings.h
@@ -34,7 +34,6 @@
#include <interfaces/context.h>
#include <interfaces/iproject.h>
-#include "interface.h"
#include "refactoring.h"
class ClangSupport;
diff --git a/refactoring/nooprefactoring.cpp b/refactoring/nooprefactoring.cpp
index c62bece..abd32ef 100644
--- a/refactoring/nooprefactoring.cpp
+++ b/refactoring/nooprefactoring.cpp
@@ -35,4 +35,4 @@ llvm::ErrorOr<clang::tooling::Replacements> \
NoopRefactoring::invoke(RefactoringC Q_UNUSED(ctx);
clangDebug() << "Did nothing (dummy refactoring action)";
return clang::tooling::Replacements();
-}
\ No newline at end of file
+}
diff --git a/refactoring/refactoring.cpp b/refactoring/refactoring.cpp
index 3644bfc..d529e7e 100644
--- a/refactoring/refactoring.cpp
+++ b/refactoring/refactoring.cpp
@@ -19,16 +19,51 @@
Boston, MA 02110-1301, USA.
*/
+// Qt
+#include <QDialog>
+#include <QLabel>
+#include <QVBoxLayout>
+
+// KF5
+#include <KLocalizedString>
+
+// Clang
#include <clang/Tooling/Core/Replacement.h>
#include "refactoring.h"
+using namespace clang;
+using namespace clang::tooling;
+
Refactoring::Refactoring(QObject *parent)
: QObject(parent)
{
}
-llvm::ErrorOr<clang::tooling::Replacements> Refactoring::cancelledResult()
+llvm::ErrorOr<Replacements> Refactoring::cancelledResult()
+{
+ return Replacements{};
+}
+
+QDialog *Refactoring::newBusyDialog()
{
- return clang::tooling::Replacements{};
-}
\ No newline at end of file
+ // Very simple placeholder
+ // TODO: progress bar and cancel button (this is not trivial task!)
+ QDialog *result = new QDialog();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QLabel *label = new QLabel(i18n("Refactoring..."));
+ layout->addWidget(label);
+ result->setLayout(layout);
+ return result;
+}
+
+std::function<void(Replacements)> Refactoring::uiLockerCallback(QDialog *uiLocker,
+ Replacements \
&result) +{
+ return [uiLocker, &result](Replacements repl)
+ {
+ result = std::move(repl);
+ uiLocker->accept();
+ // TODO: dialog probably can be closed anyway, detect and clear replacements
+ };
+}
diff --git a/refactoring/refactoring.h b/refactoring/refactoring.h
index caa49a1..3ef8bc7 100644
--- a/refactoring/refactoring.h
+++ b/refactoring/refactoring.h
@@ -22,21 +22,18 @@
#ifndef KDEV_CLANG_REFACTORING_H
#define KDEV_CLANG_REFACTORING_H
-#include "refactoringinfo.h"
-
// Qt
#include <QObject>
-#include <QUrl>
-
-// KF5
-#include <KTextEditor/ktexteditor/cursor.h>
// Clang
#include <clang/Tooling/Tooling.h>
#include <clang/Tooling/Core/Replacement.h>
#include <clang/Tooling/Refactoring.h>
-#include "interface.h"
+#include "refactoringinfo.h"
+#include "refactoringcontext.h"
+
+class QDialog;
class DocumentCache;
@@ -47,6 +44,10 @@ class Refactoring : public QObject, public RefactoringInfo
{
Q_OBJECT;
Q_DISABLE_COPY(Refactoring);
+
+ friend clang::tooling::Replacements RefactoringContext::scheduleRefactoring(
+ std::function<clang::tooling::Replacements(clang::tooling::RefactoringTool \
&)>); +
// TODO: interface as needed
public:
Refactoring(QObject *parent);
@@ -56,6 +57,12 @@ public:
protected:
static llvm::ErrorOr<clang::tooling::Replacements> cancelledResult(); // \
Returned on cancel + // TODO: Returned on interrupt (implement with care!)
+
+ /// GUI placeholder when refactoring action takes place and UI should be blocked
+ static QDialog *newBusyDialog();
+ static std::function<void(clang::tooling::Replacements)> uiLockerCallback(
+ QDialog *uiLocker, clang::tooling::Replacements &result);
};
diff --git a/refactoring/refactoringcontext.cpp b/refactoring/refactoringcontext.cpp
index 6ee38ac..472f588 100644
--- a/refactoring/refactoringcontext.cpp
+++ b/refactoring/refactoringcontext.cpp
@@ -19,8 +19,12 @@
Boston, MA 02110-1301, USA.
*/
+// Qt
+#include <QMessageBox>
+
// KF5
#include <KJob>
+#include <KLocalizedString>
// KDevelop
#include <interfaces/icore.h>
@@ -38,6 +42,8 @@
#include "debug.h"
using namespace KDevelop;
+using namespace clang;
+using namespace clang::tooling;
RefactoringContext::RefactoringContext(KDevRefactorings *parent)
: QObject(parent)
@@ -67,6 +73,11 @@ llvm::ErrorOr<unsigned> RefactoringContext::offset(const \
std::string &sourceFile
return toOffset(sourceFile, position, cache->refactoringTool(), cache);
}
+void RefactoringContext::reportError(const std::error_code &error)
+{
+ QMessageBox::critical(nullptr, i18n("Error occurred"), \
QString::fromStdString(error.message())); +}
+
void RefactoringContext::projectOpened(IProject *project)
{
Q_ASSERT(project);
@@ -106,6 +117,16 @@ void RefactoringContext::projectConfigured(IProject *project)
refactorDebug() << "RefactoringsContext sucessfully (re)generated!";
}
+Replacements RefactoringContext::scheduleRefactoring(
+ std::function<Replacements(RefactoringTool &)> task)
+{
+ QDialog *uiLocker = Refactoring::newBusyDialog();
+ Replacements result;
+ schedule(task, Refactoring::uiLockerCallback(uiLocker, result));
+ uiLocker->exec();
+ return result;
+}
+
void RefactoringContext::invokeCallback(std::function<void()> callback)
{
callback();
diff --git a/refactoring/refactoringcontext.h b/refactoring/refactoringcontext.h
index ce370b1..0e996f0 100644
--- a/refactoring/refactoringcontext.h
+++ b/refactoring/refactoringcontext.h
@@ -63,10 +63,17 @@ public:
llvm::ErrorOr<unsigned> offset(const std::string &sourceFile,
const KTextEditor::Cursor &position) const;
+ void reportError(const std::error_code &error);
+
template<typename Task, typename Callback>
void schedule(Task task, Callback callback);
template<typename Task, typename Callback>
void scheduleOnSingleFile(Task task, const std::string &filename, Callback \
callback); + // Convenience method on top of @c schedule
+ clang::tooling::Replacements scheduleRefactoring(
+ std::function<clang::tooling::Replacements(clang::tooling::RefactoringTool \
&)> task); +
+ // TODO: schedule refactoring (with ui locker, with Replacements as result)
private: // (slots)
// Only one project for now
@@ -79,7 +86,7 @@ private slots:
private:
template<typename Task, typename Callback>
- static std::function<void(clang::tooling::RefactoringTool &,
+ static std::function<void(clang::tooling::RefactoringTool,
std::function<void(std::function<void()>)>)> \
composeTask( Task task, Callback callback);
@@ -94,19 +101,19 @@ private:
Q_DECLARE_METATYPE(std::function<void()>);
template<typename Task, typename Callback>
-std::function<void(clang::tooling::RefactoringTool &,
+std::function<void(clang::tooling::RefactoringTool,
std::function<void(std::function<void()>)>)> \
RefactoringContext::composeTask( Task task, Callback callback)
{
return [task, callback](
- clang::tooling::RefactoringTool &tool,
+ clang::tooling::RefactoringTool tool,
std::function<void(std::function<void()>)> callbackScheduler)
{
auto result = task(tool);
// By value! (TODO C++14: move result to lambda instead of copying)
auto callbackInvoker = [callback, result]
{
- callback(result);
+ callback(std::move(result));
};
callbackScheduler(callbackInvoker);
};
diff --git a/refactoring/renamefielddeclrefactoring.cpp \
b/refactoring/renamefielddeclrefactoring.cpp index 4e80af9..e1ab321 100644
--- a/refactoring/renamefielddeclrefactoring.cpp
+++ b/refactoring/renamefielddeclrefactoring.cpp
@@ -48,8 +48,8 @@ class Renamer : public MatchFinder::MatchCallback
public:
Renamer(const std::string &oldQualName, const std::string &newName, Replacements \
&replacements) : m_oldQualName(oldQualName)
- , m_newName(newName)
- , m_replacements(replacements)
+ , m_newName(newName)
+ , m_replacements(replacements)
{
}
@@ -74,45 +74,55 @@ private:
RenameFieldDeclRefactoring::RenameFieldDeclRefactoring(const std::string &oldName,
std::string oldQualName)
: Refactoring(nullptr)
- , m_oldFieldDeclName(oldName)
- , m_oldQualName(std::move(oldQualName))
+ , m_oldFieldDeclName(oldName)
+ , m_oldQualName(std::move(oldQualName))
{
}
llvm::ErrorOr<clang::tooling::Replacements> RenameFieldDeclRefactoring::invoke(
RefactoringContext *ctx)
{
- auto &clangTool = ctx->cache->refactoringTool();
-
const QString oldName = QString::fromStdString(m_oldFieldDeclName);
const QString newName = QInputDialog::getText(nullptr, i18n("Rename field"),
i18n("Type new name of field"),
QLineEdit::Normal,
oldName);
if (newName.isEmpty() || newName == oldName) {
- return clangTool.getReplacements();
+ return cancelledResult();
}
- refactorDebug() << "Will rename" << m_oldFieldDeclName << "to:" << newName;
+ auto newNameS = newName.toStdString(); // C++14...
+ auto oldQualName = m_oldQualName;
+ return ctx->scheduleRefactoring(
+ [oldQualName, newNameS](RefactoringTool &tool)
+ {
+ Refactorings::RenameFieldDecl::run(oldQualName, newNameS, tool);
+ return tool.getReplacements();
+ });
+}
+namespace Refactorings
+{
+namespace RenameFieldDecl
+{
+int run(const std::string oldQualName, const std::string &newName, RefactoringTool \
&clangTool) +{
auto memberExprMatcher = memberExpr().bind("MemberExpr");
auto fieldDeclMatcher = fieldDecl().bind("FieldDecl");
- Renamer renamer(m_oldQualName, newName.toStdString(), \
clangTool.getReplacements()); + Renamer renamer(oldQualName, newName, \
clangTool.getReplacements()); MatchFinder finder;
finder.addMatcher(memberExprMatcher, &renamer);
finder.addMatcher(fieldDeclMatcher, &renamer);
- clangTool.run(tooling::newFrontendActionFactory(&finder).get());
-
- auto result = clangTool.getReplacements();
- clangTool.getReplacements().clear();
- return result;
+ return clangTool.run(tooling::newFrontendActionFactory(&finder).get());
+}
+}
}
QString RenameFieldDeclRefactoring::name() const
{
- return i18n("rename %1").arg(QString::fromStdString(m_oldQualName));
+ return i18n("rename [%1]").arg(QString::fromStdString(m_oldQualName));
}
void Renamer::run(const MatchFinder::MatchResult &result)
diff --git a/refactoring/renamefielddeclrefactoring.h \
b/refactoring/renamefielddeclrefactoring.h index 32b3a59..a39399d 100644
--- a/refactoring/renamefielddeclrefactoring.h
+++ b/refactoring/renamefielddeclrefactoring.h
@@ -39,5 +39,13 @@ private:
const std::string m_oldQualName;
};
+namespace Refactorings
+{
+namespace RenameFieldDecl
+{
+int run(const std::string oldQualName, const std::string &newName,
+ clang::tooling::RefactoringTool &clangTool);
+}
+}
#endif //KDEV_CLANG_RENAMEFIELDDECLREFACTORING_H
diff --git a/refactoring/renamefielddeclturefactoring.cpp \
b/refactoring/renamefielddeclturefactoring.cpp index b85024f..dea9198 100644
--- a/refactoring/renamefielddeclturefactoring.cpp
+++ b/refactoring/renamefielddeclturefactoring.cpp
@@ -50,9 +50,9 @@ public:
Renamer(const std::string &fileName, unsigned offset, const std::string \
&newName, Replacements &replacements)
: m_fileName(fileName)
- , m_fileOffset(offset)
- , m_newName(newName)
- , m_replacements(replacements)
+ , m_fileOffset(offset)
+ , m_newName(newName)
+ , m_replacements(replacements)
{
}
@@ -79,46 +79,59 @@ RenameFieldDeclTURefactoring::RenameFieldDeclTURefactoring(const \
std::string &fi
unsigned offset,
llvm::StringRef oldName)
: Refactoring(nullptr)
- , m_fileName(fileName)
- , m_fileOffset(offset)
- , m_oldFieldDeclName(oldName)
+ , m_fileName(fileName)
+ , m_fileOffset(offset)
+ , m_oldFieldDeclName(oldName)
{
}
llvm::ErrorOr<clang::tooling::Replacements> RenameFieldDeclTURefactoring::invoke(
RefactoringContext *ctx)
{
- auto &clangTool = ctx->cache->refactoringTool();
-
const QString oldName = QString::fromStdString(m_oldFieldDeclName);
const QString newName = QInputDialog::getText(nullptr, i18n("Rename field"),
i18n("Type new name of field"),
QLineEdit::Normal,
oldName);
if (newName.isEmpty() || newName == oldName) {
- return clangTool.getReplacements();
+ return cancelledResult();
}
- refactorDebug() << "Will rename" << m_oldFieldDeclName << "to:" << newName;
+ auto fileName = m_fileName; // C++14...
+ auto fileOffset = m_fileOffset;
+ auto newNameS = newName.toStdString();
+ return ctx->scheduleRefactoring(
+ [fileName, fileOffset, newNameS](RefactoringTool &tool)
+ {
+ Refactorings::RenameFieldTuDecl::run(fileName, fileOffset, newNameS, \
tool); + return tool.getReplacements();
+ }
+ );
+}
+namespace Refactorings
+{
+namespace RenameFieldTuDecl
+{
+int run(const std::string fileName, unsigned fileOffset, const std::string &newName,
+ clang::tooling::RefactoringTool &clangTool)
+{
auto memberExprMatcher = memberExpr().bind("MemberExpr");
auto fieldDeclMatcher = fieldDecl().bind("FieldDecl");
- Renamer renamer(m_fileName, m_fileOffset, newName.toStdString(), \
clangTool.getReplacements()); + Renamer renamer(fileName, fileOffset, newName, \
clangTool.getReplacements()); MatchFinder finder;
finder.addMatcher(memberExprMatcher, &renamer);
finder.addMatcher(fieldDeclMatcher, &renamer);
- clangTool.run(tooling::newFrontendActionFactory(&finder).get());
-
- auto result = clangTool.getReplacements();
- clangTool.getReplacements().clear();
- return result;
+ return clangTool.run(tooling::newFrontendActionFactory(&finder).get());
+}
+}
}
QString RenameFieldDeclTURefactoring::name() const
{
- return i18n("rename %1").arg(QString::fromStdString(m_oldFieldDeclName));
+ return i18n("rename [%1]").arg(QString::fromStdString(m_oldFieldDeclName));
}
void Renamer::run(const MatchFinder::MatchResult &result)
diff --git a/refactoring/renamefielddeclturefactoring.h \
b/refactoring/renamefielddeclturefactoring.h index abc4b8e..6a5cb8b 100644
--- a/refactoring/renamefielddeclturefactoring.h
+++ b/refactoring/renamefielddeclturefactoring.h
@@ -42,5 +42,13 @@ private:
const std::string m_oldFieldDeclName;
};
+namespace Refactorings
+{
+namespace RenameFieldTuDecl
+{
+int run(const std::string fileName, unsigned fileOffset, const std::string &newName,
+ clang::tooling::RefactoringTool &clangTool);
+}
+}
#endif //KDEV_CLANG_RENAMEFIELDDECLTUREFACTORING_H
diff --git a/refactoring/renamevardeclrefactoring.cpp \
b/refactoring/renamevardeclrefactoring.cpp index efb2661..e49eca7 100644
--- a/refactoring/renamevardeclrefactoring.cpp
+++ b/refactoring/renamevardeclrefactoring.cpp
@@ -19,8 +19,6 @@
Boston, MA 02110-1301, USA.
*/
-#include "renamevardeclrefactoring.h"
-
// Qt
#include <QInputDialog>
@@ -33,6 +31,7 @@
#include <clang/ASTMatchers/ASTMatchFinder.h>
#include <refactoringcontext.h>
+#include "renamevardeclrefactoring.h"
#include "documentcache.h"
#include "declarationcomparator.h"
#include "tudecldispatcher.h"
@@ -54,8 +53,8 @@ public:
Renamer(const DeclarationComparator *declComparator, const string &newName,
Replacements &replacements)
: m_declDispatcher(declComparator)
- , m_newName(newName)
- , m_replacements(replacements)
+ , m_newName(newName)
+ , m_replacements(replacements)
{
}
@@ -76,32 +75,31 @@ private:
RenameVarDeclRefactoring::RenameVarDeclRefactoring(unique_ptr<DeclarationComparator> \
declComparator,
const string &declName, QObject \
*parent) : Refactoring(parent)
- , m_declComparator(std::move(declComparator))
- , m_oldVarDeclName(declName)
+ , m_declComparator(std::move(declComparator))
+ , m_oldVarDeclName(declName)
{
}
-llvm::ErrorOr<clang::tooling::Replacements> RenameVarDeclRefactoring::invoke(
+llvm::ErrorOr<Replacements> RenameVarDeclRefactoring::invoke(
RefactoringContext *ctx)
{
- auto &clangTool = ctx->cache->refactoringTool();
-
const QString oldName = QString::fromStdString(m_oldVarDeclName);
const QString newName = QInputDialog::getText(nullptr, i18n("Rename variable"),
i18n("Type new name of variable"),
QLineEdit::Normal,
oldName);
if (newName.isEmpty() || newName == oldName) {
- return clangTool.getReplacements();
+ return cancelledResult();
}
- refactorDebug() << "Will rename" << m_oldVarDeclName << "to:" << newName;
-
- Refactorings::RenameVarDecl::run(m_declComparator.get(), newName.toStdString(), \
clangTool);
-
- auto result = clangTool.getReplacements();
- clangTool.getReplacements().clear();
- return result;
+ auto declCmp = m_declComparator.get();
+ auto name = newName.toStdString();
+ return ctx->scheduleRefactoring(
+ [declCmp, name](RefactoringTool &tool)
+ {
+ Refactorings::RenameVarDecl::run(declCmp, name, tool);
+ return tool.getReplacements();
+ });
}
namespace Refactorings
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic