Commit 014571b6 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

improve value source tracking

- use the current file if a value is generated "out of nowhere"
- preserve source through function calls

Task-number: QTCREATORBUG-4897
parent f5a37db6
......@@ -222,7 +222,7 @@ public:
ProStringList values(const ProString &variableName) const;
QString propertyValue(const QString &val, bool complain) const;
static ProStringList split_value_list(const QString &vals);
ProStringList split_value_list(const QString &vals, const ProFile *source = 0);
bool isActiveConfig(const QString &config, bool regex = false);
ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 0, bool joined = false);
......@@ -557,7 +557,7 @@ void ProFileEvaluator::Private::skipHashStr(const ushort *&tokPtr)
// FIXME: this should not build new strings for direct sections.
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals, const ProFile *source)
{
QString build;
ProStringList ret;
......@@ -570,6 +570,9 @@ ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
const ushort DOUBLEQUOTE = '"';
const ushort BACKSLASH = '\\';
if (!source)
source = currentProFile();
ushort unicode;
const QChar *vals_data = vals.data();
const int vals_len = vals.length();
......@@ -589,14 +592,14 @@ ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
}
if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
ret << ProString(build, NoHash);
ret << ProString(build, NoHash).setSource(source);
build.clear();
} else {
build += vals_data[x];
}
}
if (!build.isEmpty())
ret << ProString(build, NoHash);
ret << ProString(build, NoHash).setSource(source);
return ret;
}
......@@ -639,7 +642,7 @@ static void replaceInList(ProStringList *varlist,
if (val.isEmpty()) {
varit = varlist->erase(varit);
} else {
*varit = ProString(val);
(*varit).setValue(val, NoHash);
++varit;
}
if (!global)
......@@ -762,7 +765,8 @@ void ProFileEvaluator::Private::evaluateExpression(
break;
case TokProperty:
addStr(ProString(propertyValue(
getStr(tokPtr).toQString(m_tmp1), true), NoHash), ret, pending, joined);
getStr(tokPtr).toQString(m_tmp1), true), NoHash).setSource(currentProFile()),
ret, pending, joined);
break;
case TokEnvVar:
addStrList(split_value_list(m_option->getEnv(getStr(tokPtr).toQString(m_tmp1))),
......@@ -2145,12 +2149,12 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
QRegExp sepRx(sep);
foreach (const ProString &str, values(map(var))) {
const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end);
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash));
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash).setSource(str));
}
} else {
foreach (const ProString &str, values(map(var))) {
const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end);
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash));
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr, NoHash).setSource(str));
}
}
}
......@@ -2180,8 +2184,15 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
if (args.count() == 4)
after = args[3];
const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty())
ret.append(ProString(before + var.join(glue) + after, NoHash));
if (!var.isEmpty()) {
const ProFile *src = currentProFile();
foreach (const ProString &v, var)
if (const ProFile *s = v.sourceFile()) {
src = s;
break;
}
ret.append(ProString(before + var.join(glue) + after, NoHash).setSource(src));
}
}
break;
}
......@@ -2192,7 +2203,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
foreach (const ProString &var, values(map(args.at(0))))
foreach (const QString &splt, var.toQString(m_tmp2).split(sep))
ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt, NoHash));
ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt, NoHash).setSource(var));
}
break;
case E_MEMBER:
......@@ -2310,7 +2321,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
ret = ProStringList(ProString(tmp, NoHash));
ProStringList lst;
foreach (const ProString &arg, args)
lst += split_value_list(arg.toQString(m_tmp1)); // Relies on deep copy
lst += split_value_list(arg.toQString(m_tmp1), arg.sourceFile()); // Relies on deep copy
m_valuemapStack.top()[ret.at(0)] = lst;
break; }
case E_FIND:
......@@ -2405,13 +2416,13 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
}
}
}
ret.append(ProString(QString(i_data, i_len), NoHash));
ret.append(ProString(QString(i_data, i_len), NoHash).setSource(args.at(i)));
}
break;
case E_RE_ESCAPE:
for (int i = 0; i < args.size(); ++i) {
const QString &rstr = QRegExp::escape(args.at(i).toQString(m_tmp1));
ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash));
ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash).setSource(args.at(i)));
}
break;
case E_UPPER:
......@@ -2419,7 +2430,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
for (int i = 0; i < args.count(); ++i) {
QString rstr = args.at(i).toQString(m_tmp1);
rstr = (func_t == E_UPPER) ? rstr.toUpper() : rstr.toLower();
ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash));
ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr, NoHash).setSource(args.at(i)));
}
break;
case E_FILES:
......@@ -2459,7 +2470,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
dirs.append(fname + QDir::separator());
}
if (regex.exactMatch(qdir[i]))
ret += ProString(fname, NoHash);
ret += ProString(fname, NoHash).setSource(currentProFile());
}
}
}
......@@ -2474,7 +2485,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
QString rstr = val.toQString(m_tmp1);
QString copy = rstr; // Force a detach on modify
rstr.replace(before, after);
ret << (rstr.isSharedWith(m_tmp1) ? val : ProString(rstr, NoHash));
ret << (rstr.isSharedWith(m_tmp1) ? val : ProString(rstr, NoHash).setSource(val));
}
}
break;
......
......@@ -105,6 +105,17 @@ ProString::ProString(const QString &str, int offset, int length, ProStringConsta
{
}
void ProString::setValue(const QString &str)
{
m_string = str, m_offset = 0, m_length = str.length();
updatedHash();
}
void ProString::setValue(const QString &str, OmitPreHashing)
{
m_string = str, m_offset = 0, m_length = str.length(), m_hash = 0x80000000;
}
uint ProString::updatedHash() const
{
return (m_hash = hash(m_string.constData() + m_offset, m_length));
......
......@@ -71,7 +71,10 @@ public:
ProString(const QString &str, int offset, int length);
ProString(const QString &str, int offset, int length, uint hash);
ProString(const QString &str, int offset, int length, ProStringConstants::OmitPreHashing);
void setSource(const ProFile *pro) { m_file = pro; }
void setValue(const QString &str);
void setValue(const QString &str, ProStringConstants::OmitPreHashing);
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
ProString &setSource(const ProFile *pro) { m_file = pro; return *this; }
const ProFile *sourceFile() const { return m_file; }
QString toQString() const;
QString &toQString(QString &tmp) const;
......
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