diff --git a/languages/cpp/codegen/renameassistant.cpp b/languages/cpp/codegen/renameassistant.cpp
new file mode 100644
index 0000000..0a69780
--- /dev/null
+++ b/languages/cpp/codegen/renameassistant.cpp
@@ -0,0 +1,163 @@
+/*
+   Copyright 2010 Olivier de Gaalon <olivier.jg@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 version 2 as published by the Free Software Foundation.
+
+   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 "renameassistant.h"
+#include <language/duchain/duchainutils.h>
+#include <interfaces/icore.h>
+#include <interfaces/idocumentcontroller.h>
+#include <ktexteditor/document.h>
+#include <ktexteditor/view.h>
+#include <language/duchain/duchainlock.h>
+#include <language/duchain/duchain.h>
+#include <interfaces/ilanguagecontroller.h>
+#include <language/duchain/declaration.h>
+#include <klocalizedstring.h>
+#include <language/codegen/documentchangeset.h>
+#include <kmessagebox.h>
+#include <language/backgroundparser/parsejob.h>
+#include <language/backgroundparser/backgroundparser.h>
+
+using namespace  KDevelop;
+using namespace Cpp;
+
+typedef QMap<IndexedString, QList <RangeInRevision> > UsesList;
+
+class RenameAction : public KDevelop::IAssistantAction {
+public:
+  RenameAction(Identifier oldDeclarationName, QString newDeclarationName, UsesList oldDeclarationUses)
+  : m_oldDeclarationName(oldDeclarationName),
+    m_newDeclarationName(newDeclarationName),
+    m_oldDeclarationUses(oldDeclarationUses)
+  { }
+
+  virtual QString description() const {
+    return i18n("Rename \"%1\" to \"%2\"", m_oldDeclarationName.toString(), m_newDeclarationName);
+  }
+
+  virtual void execute() {
+    UsesList::iterator it;
+    DocumentChangeSet changes;
+    for (it = m_oldDeclarationUses.begin(); it != m_oldDeclarationUses.end(); ++it) {
+      foreach (RangeInRevision range, it.value()) {
+        DocumentChange useRename(it.key(), range.castToSimpleRange(), m_oldDeclarationName.toString(), m_newDeclarationName);
+        changes.addChange( useRename );
+        changes.setReplacementPolicy(DocumentChangeSet::WarnOnFailedChange);
+      }
+    }
+
+    DocumentChangeSet::ChangeResult result = changes.applyAllChanges();
+    if(!result)
+      KMessageBox::error(0, i18n("Failed to apply changes: %1", result.m_failureReason));
+  }
+private:
+  Identifier m_oldDeclarationName;
+  QString m_newDeclarationName;
+  UsesList m_oldDeclarationUses;
+};
+
+RenameAssistant::RenameAssistant(KTextEditor::View* view) : ITextAssistant(view)
+{
+connect(KDevelop::ICore::self()->languageController()->backgroundParser(), SIGNAL(parseJobFinished(KDevelop::ParseJob*)), SLOT(parseJobFinished(KDevelop::ParseJob*)));
+}
+
+void RenameAssistant::reset() {
+  m_oldDeclarationName = Identifier();
+  m_newDeclarationRange.clear();
+  m_oldDeclarationUses.clear();
+}
+
+bool RenameAssistant::isUseful()
+{
+  return m_editingDeclaration;
+}
+
+bool rangesConnect(const KTextEditor::Range &firstRange, const KTextEditor::Range& secondRange) {
+  KTextEditor::Range expanded = KTextEditor::Range(
+      secondRange.start().line(), secondRange.start().column() - 1,
+      secondRange.end().line(), secondRange.end().column() + 1
+  );
+  return !firstRange.intersect(expanded).isEmpty();
+}
+
+void RenameAssistant::textChanged(KTextEditor::Range invocationRange, QString removedText) {
+  m_documentUrl = IndexedString(view()->document()->url());
+  m_editingDeclaration = false;
+  KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock());
+
+  //If the inserted text isn't valid for a variable name, consider the editing ended
+  QRegExp validDeclName("^[0-9a-zA-Z_]*$");
+  if (removedText.isEmpty() && !validDeclName.exactMatch(view()->document()->text(invocationRange))) {
+    reset();
+    return;
+  }
+
+  //If we've stopped editing m_newDeclarationRange, reset and see if there's another declaration being edited
+  if (!m_newDeclarationRange.data() || !rangesConnect(m_newDeclarationRange->range().textRange(), invocationRange)) {
+    reset();
+
+    //What declaration is being edited, if any?
+    SimpleCursor cursor = SimpleRange(invocationRange).start;
+    Declaration* declUnderCursor = DUChainUtils::itemUnderCursor(m_documentUrl.toUrl(), cursor);
+    if (!declUnderCursor) //May be appending to the variable name...
+      declUnderCursor = DUChainUtils::itemUnderCursor(m_documentUrl.toUrl(), SimpleCursor(cursor.line, --cursor.column));
+
+    if (declUnderCursor) {
+      if (!rangesConnect(declUnderCursor->rangeInCurrentRevision().textRange(), invocationRange))
+        return; //This is a use for the declaration, not the actual declaration
+    } else return; //Not currently editing a declaration, and none under the cursor
+
+    if (declUnderCursor->uses().size() > 0) {
+      m_oldDeclarationName = declUnderCursor->identifier();
+      m_oldDeclarationUses = declUnderCursor->uses();
+      m_newDeclarationRange = PersistentMovingRange::Ptr(
+        new PersistentMovingRange(declUnderCursor->rangeInCurrentRevision(), m_documentUrl)
+      );
+    }
+    else
+      return; //new declaration is useless
+  }
+
+  //at this point we are known to be renaming a valid declaration with uses
+  //if we are appending text to either side of newDeclarationRange, we need to extend it accordingly
+  if (m_newDeclarationRange->range().textRange().intersect(invocationRange).isEmpty() && removedText.isEmpty()) {
+    m_newDeclarationRange.attach(
+      new PersistentMovingRange(
+        SimpleRange(m_newDeclarationRange->range().textRange().encompass(invocationRange)), m_documentUrl)
+    );
+  }
+
+  m_newDeclarationName = view()->document()->text(m_newDeclarationRange->range().textRange());
+
+  if (m_newDeclarationName == m_oldDeclarationName.toString())
+    return;
+
+  m_editingDeclaration = true;
+}
+
+void RenameAssistant::parseJobFinished(ParseJob* job)
+{
+  //The replace won't work until the parse job is finished
+  if(job->document() == m_documentUrl) {
+    clearActions();
+    if (m_editingDeclaration)
+      addAction(IAssistantAction::Ptr(new RenameAction(m_oldDeclarationName, m_newDeclarationName, m_oldDeclarationUses)));
+    emit actionsChanged();
+  }
+}
+
+#include "renameassistant.moc"
\ No newline at end of file
diff --git a/languages/cpp/codegen/renameassistant.h b/languages/cpp/codegen/renameassistant.h
new file mode 100644
index 0000000..533c8d0
--- /dev/null
+++ b/languages/cpp/codegen/renameassistant.h
@@ -0,0 +1,56 @@
+/*
+   Copyright 2010 Olivier de Gaalon <olivier.jg@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 version 2 as published by the Free Software Foundation.
+
+   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.
+*/
+
+#ifndef CPP_RENAMEEASSISTANT_H
+#define CPP_RENAMEEASSISTANT_H
+
+#include <interfaces/iassistant.h>
+#include <language/duchain/identifier.h>
+#include <language/duchain/topducontext.h>
+#include <language/duchain/types/indexedtype.h>
+#include <language/duchain/indexedstring.h>
+#include <language/duchain/declaration.h>
+
+
+namespace KDevelop {
+class ParseJob;
+}
+namespace Cpp {
+
+class RenameAssistant : public KDevelop::ITextAssistant {
+Q_OBJECT
+public:
+  RenameAssistant(KTextEditor::View* view);
+  void textChanged(KTextEditor::Range invocationRange, QString removedText = QString());
+  bool isUseful();
+
+private:
+  void reset();
+  KDevelop::Identifier m_oldDeclarationName;
+  QString m_newDeclarationName;
+  KDevelop::PersistentMovingRange::Ptr m_newDeclarationRange;
+  QMap <KDevelop::IndexedString, QList <KDevelop::RangeInRevision > > m_oldDeclarationUses;
+  KDevelop::IndexedString m_documentUrl;
+  bool m_editingDeclaration;
+private slots:
+  void parseJobFinished(KDevelop::ParseJob* job);
+};
+
+}
+
+#endif // CPP_RENAMEEASSISTANT_H
