CppFindReferences: Fix file name case sensitivity on class renaming

Utils::matchCaseReplacement searches for common prefix and suffix
between old and new file name und leaves them unchanged. This leads
to unexpected new file names.

E.g. when renaming MainWindow to MyMainWindow, this function computes
the prefix "m", the suffix "ainwindow.h" and only considers "yM" as
the middle part that is actually renamed.

Use a better algorithm to determine the new base name, and for
unclear cases fall back to the "Lower case file names" option
from Tools -> Options -> C++ -> File Naming.

Task-number: QTCREATORBUG-18592
Change-Id: I818f7d372102eb6e266123b2b4b6355f6fa28d64
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Andre Hartmann
2017-07-20 20:40:19 +02:00
committed by André Hartmann
parent 2c5186253f
commit c78ea5a7ea

View File

@@ -25,6 +25,7 @@
#include "cppfindreferences.h" #include "cppfindreferences.h"
#include "cppfilesettingspage.h"
#include "cpptoolsconstants.h" #include "cpptoolsconstants.h"
#include "cppmodelmanager.h" #include "cppmodelmanager.h"
#include "cppworkingcopy.h" #include "cppworkingcopy.h"
@@ -384,6 +385,11 @@ void CppFindReferences::findAll_helper(SearchResult *search, Symbol *symbol,
connect(progress, &FutureProgress::clicked, search, &SearchResult::popup); connect(progress, &FutureProgress::clicked, search, &SearchResult::popup);
} }
static bool isAllLowerCase(const QString &text)
{
return text.toLower() == text;
}
void CppFindReferences::onReplaceButtonClicked(const QString &text, void CppFindReferences::onReplaceButtonClicked(const QString &text,
const QList<SearchResultItem> &items, const QList<SearchResultItem> &items,
bool preserveCase) bool preserveCase)
@@ -405,21 +411,40 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text,
if (!renameFilesCheckBox || !renameFilesCheckBox->isChecked()) if (!renameFilesCheckBox || !renameFilesCheckBox->isChecked())
return; return;
CppFileSettings settings;
settings.fromSettings(Core::ICore::settings());
const QStringList newPaths = const QStringList newPaths =
Utils::transform<QList>(parameters.filesToRename, Utils::transform<QList>(parameters.filesToRename,
[&parameters, text](const Node *node) -> QString { [&parameters, text, &settings](const Node *node) -> QString {
const QFileInfo fi = node->filePath().toFileInfo(); const QFileInfo fi = node->filePath().toFileInfo();
const QString fileName = fi.fileName(); const QString oldSymbolName = parameters.prettySymbolName;
QString newName = fileName; const QString oldBaseName = fi.baseName();
newName.replace(parameters.prettySymbolName, text, Qt::CaseInsensitive); const QString newSymbolName = text;
QString newBaseName = newSymbolName;
if (newName != fileName) { // 1) new symbol lowercase: new base name lowercase
newName = Utils::matchCaseReplacement(fileName, newName); if (isAllLowerCase(newSymbolName)) {
newBaseName = newSymbolName;
return fi.absolutePath() + "/" + newName; // 2) old base name mixed case: new base name is verbatim symbol name
} else if (!isAllLowerCase(oldBaseName)) {
newBaseName = newSymbolName;
// 3) old base name lowercase, old symbol mixed case: new base name lowercase
} else if (!isAllLowerCase(oldSymbolName)) {
newBaseName = newSymbolName.toLower();
// 4) old base name lowercase, old symbol lowercase, new symbol mixed case:
// use the preferences setting for new base name case
} else if (settings.lowerCaseFiles) {
newBaseName = newSymbolName.toLower();
} }
if (newBaseName == oldBaseName)
return QString(); return QString();
return fi.absolutePath() + "/" + newBaseName + '.' + fi.completeSuffix();
}); });
for (int i = 0; i < parameters.filesToRename.size(); ++i) { for (int i = 0; i < parameters.filesToRename.size(); ++i) {