QmakePM: Do a "sorted insert" when adding files

Don't blindly append to the end of the list, but try to put files into
the right place with regards to lexicographical order.
We do not re-sort existing file lists, nor do we attempt to be fancy
with strangely formatted project files. But lists conforming to our own
style will stay sorted, in particular lists that have only ever been
touched by Qt Creator.

Fixes: QTCREATORBUG-553
Fixes: QTCREATORBUG-21807
Change-Id: I15db0e867a2d477fcf95e008f98ba468dcd83e45
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Christian Kandeler
2019-01-23 17:30:52 +01:00
parent 809416c993
commit a420374976
3 changed files with 69 additions and 16 deletions

View File

@@ -542,6 +542,7 @@ bool QmakePriFile::addFiles(const QStringList &filePaths, QStringList *notAdded)
if (!m_recursiveEnumerateFiles.contains(FileName::fromString(file)))
uniqueFilePaths.append(file);
}
uniqueFilePaths.sort();
changeFiles(type, uniqueFilePaths, &failedFiles, AddToProFile);
if (notAdded)

View File

@@ -244,23 +244,38 @@ bool ProWriter::locateVarValues(const ushort *tokPtr, const ushort *tokPtrEnd,
return false;
}
struct LineInfo
{
int continuationPos = 0;
bool hasComment = false;
};
static LineInfo lineInfo(const QString &line)
{
LineInfo li;
li.continuationPos = line.length();
const int idx = line.indexOf('#');
li.hasComment = idx >= 0;
if (li.hasComment)
li.continuationPos = idx;
for (int i = idx - 1; i >= 0 && (line.at(i) == ' ' || line.at(i) == '\t'); --i)
--li.continuationPos;
return li;
}
static int skipContLines(QStringList *lines, int lineNo, bool addCont)
{
for (; lineNo < lines->count(); lineNo++) {
QString line = lines->at(lineNo);
int idx = line.indexOf(QLatin1Char('#'));
if (idx >= 0)
line.truncate(idx);
while (line.endsWith(QLatin1Char(' ')) || line.endsWith(QLatin1Char('\t')))
line.chop(1);
if (line.isEmpty()) {
if (idx >= 0)
const QString line = lines->at(lineNo);
LineInfo li = lineInfo(line);
if (li.continuationPos == 0) {
if (li.hasComment)
continue;
break;
}
if (!line.endsWith(QLatin1Char('\\'))) {
if (line.at(li.continuationPos - 1) != '\\') {
if (addCont)
(*lines)[lineNo].insert(line.length(), QLatin1String(" \\"));
(*lines)[lineNo].insert(li.continuationPos, " \\");
lineNo++;
break;
}
@@ -287,12 +302,21 @@ void ProWriter::putVarValues(ProFile *profile, QStringList *lines,
foreach (const QString &v, values)
line += ((flags & MultiLine) ? QLatin1String(" \\\n ") + indent : QString::fromLatin1(" ")) + v;
} else {
lineNo = skipContLines(lines, lineNo, true);
QString added;
foreach (const QString &v, values)
added += QLatin1String(" ") + indent + v + QLatin1String(" \\\n");
added.chop(3);
lines->insert(lineNo, added);
int endLineNo = skipContLines(lines, lineNo, false);
for (const QString &v : values) {
int curLineNo = lineNo + 1;
while (curLineNo < endLineNo && v >= lines->at(curLineNo).trimmed())
++curLineNo;
QString newLine = " " + indent + v;
if (curLineNo == endLineNo) {
QString &oldLastLine = (*lines)[endLineNo - 1];
oldLastLine.insert(lineInfo(oldLastLine).continuationPos, " \\");
} else {
newLine += " \\";
}
lines->insert(curLineNo, newLine);
++endLineNo;
}
}
} else {
// Create & append new variable item

View File

@@ -206,6 +206,34 @@ void tst_ProFileWriter::adds_data()
"SOURCES = some files \\\n"
" foo"
},
{
PW::AppendValues|PW::AppendOperator|PW::MultiLine,
"insert at end", f_foo_bar, 0,
"SOURCES = some files",
"SOURCES = some files \\\n"
" bar \\\n"
" foo"
},
{
PW::AppendValues|PW::AppendOperator|PW::MultiLine,
"insert into empty", f_foo_bar, 0,
"SOURCES =",
"SOURCES = \\\n"
" bar \\\n"
" foo"
},
{
PW::AppendValues|PW::AppendOperator|PW::MultiLine,
"insert into middle", f_foo_bar, 0,
"SOURCES = some files \\\n"
" aargh \\\n"
" zoo",
"SOURCES = some files \\\n"
" aargh \\\n"
" bar \\\n"
" foo \\\n"
" zoo"
},
{
PW::AppendValues|PW::AppendOperator|PW::MultiLine,
"add to existing after comment (wrong operator)", f_foo, 0,