Commit 78c70776 authored by David Schulz's avatar David Schulz

Cpp: Adjust includes when files are renamed.

Change-Id: Ie6aaaa5d99ba3823d9d42331f45b2dcab397e1cd
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent b210294c
......@@ -798,6 +798,19 @@ QSet<QString> Snapshot::allIncludesForDocument(const QString &fileName) const
return result;
}
QList<Snapshot::IncludeLocation> Snapshot::includeLocationsOfDocument(const QString &fileName) const
{
QList<IncludeLocation> result;
for (const_iterator cit = begin(), citEnd = end(); cit != citEnd; ++cit) {
const Document::Ptr doc = cit.value();
foreach (const Document::Include &includeFile, doc->resolvedIncludes()) {
if (includeFile.resolvedFileName() == fileName)
result.append(qMakePair(doc, includeFile.line()));
}
}
return result;
}
QStringList Snapshot::filesDependingOn(const QString &fileName) const
{
updateDependencyTable();
......
......@@ -400,6 +400,7 @@ public:
typedef Base::const_iterator iterator;
typedef Base::const_iterator const_iterator;
typedef QPair<Document::Ptr, unsigned> IncludeLocation;
int size() const; // ### remove
bool isEmpty() const;
......@@ -424,6 +425,7 @@ public:
const QString &fileName) const;
QSet<QString> allIncludesForDocument(const QString &fileName) const;
QList<IncludeLocation> includeLocationsOfDocument(const QString &fileName) const;
QStringList filesDependingOn(const QString &fileName) const;
void updateDependencyTable() const;
......
......@@ -36,11 +36,13 @@
#include "cppfindreferences.h"
#include "cppindexingsupport.h"
#include "cppmodelmanagersupportinternal.h"
#include "cpprefactoringchanges.h"
#include "cppsourceprocessor.h"
#include "cpptoolsconstants.h"
#include "cpptoolsplugin.h"
#include "editordocumenthandle.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/projectexplorer.h>
......@@ -297,6 +299,8 @@ CppModelManager::CppModelManager(QObject *parent)
this, SLOT(onAboutToLoadSession()));
connect(sessionManager, SIGNAL(aboutToUnloadSession(QString)),
this, SLOT(onAboutToUnloadSession()));
connect(Core::DocumentManager::instance(), &Core::DocumentManager::allDocumentsRenamed,
this, &CppModelManager::renameIncludes);
connect(Core::ICore::instance(), SIGNAL(coreAboutToClose()),
this, SLOT(onCoreAboutToClose()));
......@@ -862,6 +866,35 @@ void CppModelManager::onAboutToUnloadSession()
} while (0);
}
void CppModelManager::renameIncludes(const QString &oldFileName, const QString &newFileName)
{
if (oldFileName.isEmpty() || newFileName.isEmpty())
return;
const QFileInfo oldFileInfo(oldFileName);
const QFileInfo newFileInfo(newFileName);
// We just want to handle renamings so return when the file was actually moved.
if (oldFileInfo.absoluteDir() != newFileInfo.absoluteDir())
return;
const TextEditor::RefactoringChanges changes;
foreach (Snapshot::IncludeLocation loc, snapshot().includeLocationsOfDocument(oldFileName)) {
TextEditor::RefactoringFilePtr file = changes.file(loc.first->fileName());
const QTextBlock &block = file->document()->findBlockByLineNumber(loc.second - 1);
const int replaceStart = block.text().indexOf(oldFileInfo.fileName());
if (replaceStart > -1) {
Utils::ChangeSet changeSet;
changeSet.replace(block.position() + replaceStart,
block.position() + replaceStart + oldFileInfo.fileName().length(),
newFileInfo.fileName());
file->setChangeSet(changeSet);
file->apply();
}
}
}
void CppModelManager::onCoreAboutToClose()
{
d->m_enableGC = false;
......
......@@ -179,6 +179,7 @@ private slots:
// This should be executed in the GUI thread.
void onAboutToLoadSession();
void onAboutToUnloadSession();
void renameIncludes(const QString &oldFileName, const QString &newFileName);
void onProjectAdded(ProjectExplorer::Project *project);
void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onSourceFilesRefreshed() const;
......
......@@ -35,6 +35,7 @@
#include "modelmanagertesthelper.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/testdatadir.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
......@@ -44,6 +45,7 @@
#include <QDebug>
#include <QFileInfo>
#include <QTemporaryDir>
#include <QtTest>
using namespace CppTools::Internal;
......@@ -1037,3 +1039,48 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName);
}
}
void CppToolsPlugin::test_modelmanager_renameIncludes()
{
struct ModelManagerGCHelper {
~ModelManagerGCHelper() { CppModelManager::instance()->GC(); }
} GCHelper;
QTemporaryDir tmpDir;
QVERIFY(tmpDir.isValid());
const QDir workingDir(tmpDir.path());
const QStringList fileNames = QStringList() << _("foo.h") << _("foo.cpp") << _("main.cpp");
const QString oldHeader(workingDir.filePath(_("foo.h")));
const QString newHeader(workingDir.filePath(_("bar.h")));
CppModelManager *modelManager = CppModelManager::instance();
const MyTestDataDir testDir(_("testdata_project1"));
// Copy test files to a temporary directory
QSet<QString> sourceFiles;
foreach (const QString &fileName, fileNames) {
const QString &file = workingDir.filePath(fileName);
QVERIFY(QFile::copy(testDir.file(fileName), file));
// Saving source file names for the model manager update,
// so we can update just the relevant files.
if (ProjectFile::classify(file) == ProjectFile::CXXSource)
sourceFiles.insert(file);
}
// Update the c++ model manager and check for the old includes
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
CPlusPlus::Snapshot snapshot = modelManager->snapshot();
foreach (const QString &sourceFile, sourceFiles)
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << oldHeader);
// Renaming the header
QVERIFY(Core::FileUtils::renameFile(oldHeader, newHeader));
// Update the c++ model manager again and check for the new includes
modelManager->updateSourceFiles(sourceFiles).waitForFinished();
QCoreApplication::processEvents();
snapshot = modelManager->snapshot();
foreach (const QString &sourceFile, sourceFiles)
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << newHeader);
}
......@@ -151,6 +151,7 @@ private slots:
void test_modelmanager_defines_per_project();
void test_modelmanager_defines_per_editor();
void test_modelmanager_precompiled_headers();
void test_modelmanager_renameIncludes();
void test_cpplocatorfilters_CppLocatorFilter();
void test_cpplocatorfilters_CppLocatorFilter_data();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment