Changeset View
Changeset View
Standalone View
Standalone View
languages/clang/codegen/clangrefactoring.cpp
Show All 22 Lines | |||||
23 | 23 | | |||
24 | #include "clangrefactoring.h" | 24 | #include "clangrefactoring.h" | ||
25 | 25 | | |||
26 | #include <QAction> | 26 | #include <QAction> | ||
27 | #include <QIcon> | 27 | #include <QIcon> | ||
28 | 28 | | |||
29 | #include <interfaces/context.h> | 29 | #include <interfaces/context.h> | ||
30 | #include <interfaces/contextmenuextension.h> | 30 | #include <interfaces/contextmenuextension.h> | ||
31 | #include <language/duchain/classfunctiondeclaration.h> | ||||
31 | #include <language/duchain/duchain.h> | 32 | #include <language/duchain/duchain.h> | ||
32 | #include <language/duchain/duchainlock.h> | 33 | #include <language/duchain/duchainlock.h> | ||
33 | #include <language/duchain/functiondeclaration.h> | 34 | #include <language/duchain/functiondeclaration.h> | ||
34 | #include <language/duchain/functiondefinition.h> | 35 | #include <language/duchain/functiondefinition.h> | ||
35 | #include <language/duchain/types/functiontype.h> | 36 | #include <language/duchain/types/functiontype.h> | ||
36 | #include <language/interfaces/codecontext.h> | 37 | #include <language/interfaces/codecontext.h> | ||
37 | 38 | | |||
38 | #include <interfaces/icore.h> | 39 | #include <interfaces/icore.h> | ||
39 | #include <interfaces/ilanguagecontroller.h> | 40 | #include <interfaces/ilanguagecontroller.h> | ||
40 | #include <language/backgroundparser/backgroundparser.h> | 41 | #include <language/backgroundparser/backgroundparser.h> | ||
41 | 42 | | |||
42 | #include "duchain/clanghelpers.h" | 43 | #include "duchain/clanghelpers.h" | ||
43 | #include "duchain/documentfinderhelpers.h" | 44 | #include "duchain/documentfinderhelpers.h" | ||
44 | #include "duchain/duchainutils.h" | 45 | #include "duchain/duchainutils.h" | ||
45 | #include "sourcemanipulation.h" | 46 | #include "sourcemanipulation.h" | ||
46 | #include "util/clangdebug.h" | 47 | #include "util/clangdebug.h" | ||
47 | 48 | | |||
48 | using namespace KDevelop; | 49 | using namespace KDevelop; | ||
49 | 50 | | |||
51 | namespace { | ||||
52 | | ||||
53 | bool isDestructor(Declaration* decl) | ||||
54 | { | ||||
55 | if (auto functionDef = dynamic_cast<FunctionDefinition*>(decl)) { | ||||
56 | // we found a definition, e.g. "Foo::~Foo()" | ||||
57 | const auto functionDecl = functionDef->declaration(decl->topContext()); | ||||
58 | if (auto classFunctionDecl = dynamic_cast<ClassFunctionDeclaration*>(functionDecl)) { | ||||
59 | return classFunctionDecl->isDestructor(); | ||||
60 | } | ||||
61 | } | ||||
62 | else if (auto classFunctionDecl = dynamic_cast<ClassFunctionDeclaration*>(decl)) { | ||||
63 | // we found a declaration, e.g. "~Foo()" | ||||
64 | return classFunctionDecl->isDestructor(); | ||||
65 | } | ||||
66 | | ||||
67 | return false; | ||||
68 | } | ||||
69 | | ||||
70 | } | ||||
71 | | ||||
50 | ClangRefactoring::ClangRefactoring(QObject* parent) | 72 | ClangRefactoring::ClangRefactoring(QObject* parent) | ||
51 | : BasicRefactoring(parent) | 73 | : BasicRefactoring(parent) | ||
52 | { | 74 | { | ||
53 | qRegisterMetaType<IndexedDeclaration>(); | 75 | qRegisterMetaType<IndexedDeclaration>(); | ||
54 | } | 76 | } | ||
55 | 77 | | |||
56 | void ClangRefactoring::fillContextMenu(ContextMenuExtension& extension, Context* context) | 78 | void ClangRefactoring::fillContextMenu(ContextMenuExtension& extension, Context* context) | ||
57 | { | 79 | { | ||
Show All 37 Lines | 116 | { | |||
95 | if (!decl || !decl->isFunctionDeclaration() || !decl->type<FunctionType>()) { | 117 | if (!decl || !decl->isFunctionDeclaration() || !decl->type<FunctionType>()) { | ||
96 | return false; | 118 | return false; | ||
97 | } | 119 | } | ||
98 | 120 | | |||
99 | if (!decl->internalContext() || decl->internalContext()->type() != DUContext::Function) { | 121 | if (!decl->internalContext() || decl->internalContext()->type() != DUContext::Function) { | ||
100 | return false; | 122 | return false; | ||
101 | } | 123 | } | ||
102 | 124 | | |||
125 | if (dynamic_cast<FunctionDefinition*>(decl)) { | ||||
126 | return false; | ||||
127 | } | ||||
128 | | ||||
103 | auto childCtx = decl->internalContext()->childContexts(); | 129 | auto childCtx = decl->internalContext()->childContexts(); | ||
104 | if (childCtx.isEmpty()) { | 130 | if (childCtx.isEmpty()) { | ||
105 | return false; | 131 | return false; | ||
106 | } | 132 | } | ||
107 | 133 | | |||
108 | auto ctx = childCtx.first(); | 134 | auto ctx = childCtx.first(); | ||
109 | if (!ctx || ctx->type() != DUContext::Other) { | 135 | if (!ctx || ctx->type() != DUContext::Other) { | ||
110 | return false; | 136 | return false; | ||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Line(s) | 249 | if (!iDecl.isValid()) { | |||
224 | iDecl = declarationUnderCursor(false); | 250 | iDecl = declarationUnderCursor(false); | ||
225 | } | 251 | } | ||
226 | 252 | | |||
227 | const auto error = moveIntoSource(iDecl); | 253 | const auto error = moveIntoSource(iDecl); | ||
228 | if (!error.isEmpty()) { | 254 | if (!error.isEmpty()) { | ||
229 | KMessageBox::error(nullptr, error); | 255 | KMessageBox::error(nullptr, error); | ||
230 | } | 256 | } | ||
231 | } | 257 | } | ||
258 | | ||||
259 | DocumentChangeSet::ChangeResult ClangRefactoring::applyChangesToDeclarations(const QString& oldName, | ||||
260 | const QString& newName, | ||||
261 | DocumentChangeSet& changes, | ||||
262 | const QList<IndexedDeclaration>& declarations) | ||||
263 | { | ||||
264 | foreach (const IndexedDeclaration decl, declarations) { | ||||
265 | Declaration *declaration = decl.data(); | ||||
266 | if (!declaration) | ||||
267 | continue; | ||||
268 | | ||||
269 | if (declaration->range().isEmpty()) | ||||
270 | clangDebug() << "found empty declaration:" << declaration->toString(); | ||||
271 | | ||||
272 | // special handling for dtors, their name is not "Foo", but "~Foo" | ||||
273 | // see https://bugs.kde.org/show_bug.cgi?id=373452 | ||||
274 | QString fixedOldName = oldName; | ||||
275 | QString fixedNewName = newName; | ||||
276 | | ||||
277 | if (isDestructor(declaration)) { | ||||
278 | clangDebug() << "found destructor:" << declaration->toString() << "-- making sure we replace the identifier correctly"; | ||||
279 | fixedOldName = QLatin1Char('~') + oldName; | ||||
280 | fixedNewName = QLatin1Char('~') + newName; | ||||
281 | } | ||||
282 | | ||||
283 | TopDUContext *top = declaration->topContext(); | ||||
284 | DocumentChangeSet::ChangeResult result = changes.addChange(DocumentChange(top->url(), declaration->rangeInCurrentRevision(), fixedOldName, fixedNewName)); | ||||
285 | if (!result) | ||||
286 | return result; | ||||
287 | } | ||||
288 | | ||||
289 | return KDevelop::DocumentChangeSet::ChangeResult::successfulResult(); | ||||
290 | } |