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
This commit is contained in:
Oswald Buddenhagen
2011-05-13 20:20:41 +02:00
parent f5a37db6c4
commit 014571b602
3 changed files with 43 additions and 18 deletions

View File

@@ -222,7 +222,7 @@ public:
ProStringList values(const ProString &variableName) const; ProStringList values(const ProString &variableName) const;
QString propertyValue(const QString &val, bool complain) 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); bool isActiveConfig(const QString &config, bool regex = false);
ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false); ProStringList expandVariableReferences(const ProString &value, int *pos = 0, bool joined = false);
ProStringList expandVariableReferences(const ushort *&tokPtr, int sizeHint = 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. // FIXME: this should not build new strings for direct sections.
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy. // 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; QString build;
ProStringList ret; ProStringList ret;
@@ -570,6 +570,9 @@ ProStringList ProFileEvaluator::Private::split_value_list(const QString &vals)
const ushort DOUBLEQUOTE = '"'; const ushort DOUBLEQUOTE = '"';
const ushort BACKSLASH = '\\'; const ushort BACKSLASH = '\\';
if (!source)
source = currentProFile();
ushort unicode; ushort unicode;
const QChar *vals_data = vals.data(); const QChar *vals_data = vals.data();
const int vals_len = vals.length(); 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) { if (!parens && quote.isEmpty() && vals_data[x] == SPACE) {
ret << ProString(build, NoHash); ret << ProString(build, NoHash).setSource(source);
build.clear(); build.clear();
} else { } else {
build += vals_data[x]; build += vals_data[x];
} }
} }
if (!build.isEmpty()) if (!build.isEmpty())
ret << ProString(build, NoHash); ret << ProString(build, NoHash).setSource(source);
return ret; return ret;
} }
@@ -639,7 +642,7 @@ static void replaceInList(ProStringList *varlist,
if (val.isEmpty()) { if (val.isEmpty()) {
varit = varlist->erase(varit); varit = varlist->erase(varit);
} else { } else {
*varit = ProString(val); (*varit).setValue(val, NoHash);
++varit; ++varit;
} }
if (!global) if (!global)
@@ -762,7 +765,8 @@ void ProFileEvaluator::Private::evaluateExpression(
break; break;
case TokProperty: case TokProperty:
addStr(ProString(propertyValue( 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; break;
case TokEnvVar: case TokEnvVar:
addStrList(split_value_list(m_option->getEnv(getStr(tokPtr).toQString(m_tmp1))), addStrList(split_value_list(m_option->getEnv(getStr(tokPtr).toQString(m_tmp1))),
@@ -2145,12 +2149,12 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
QRegExp sepRx(sep); QRegExp sepRx(sep);
foreach (const ProString &str, values(map(var))) { foreach (const ProString &str, values(map(var))) {
const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end); 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 { } else {
foreach (const ProString &str, values(map(var))) { foreach (const ProString &str, values(map(var))) {
const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end); 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) if (args.count() == 4)
after = args[3]; after = args[3];
const ProStringList &var = values(map(args.at(0))); const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty()) if (!var.isEmpty()) {
ret.append(ProString(before + var.join(glue) + after, NoHash)); 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; break;
} }
@@ -2192,7 +2203,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep; 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 ProString &var, values(map(args.at(0))))
foreach (const QString &splt, var.toQString(m_tmp2).split(sep)) 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; break;
case E_MEMBER: case E_MEMBER:
@@ -2310,7 +2321,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
ret = ProStringList(ProString(tmp, NoHash)); ret = ProStringList(ProString(tmp, NoHash));
ProStringList lst; ProStringList lst;
foreach (const ProString &arg, args) 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; m_valuemapStack.top()[ret.at(0)] = lst;
break; } break; }
case E_FIND: 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; break;
case E_RE_ESCAPE: case E_RE_ESCAPE:
for (int i = 0; i < args.size(); ++i) { for (int i = 0; i < args.size(); ++i) {
const QString &rstr = QRegExp::escape(args.at(i).toQString(m_tmp1)); 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; break;
case E_UPPER: case E_UPPER:
@@ -2419,7 +2430,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
for (int i = 0; i < args.count(); ++i) { for (int i = 0; i < args.count(); ++i) {
QString rstr = args.at(i).toQString(m_tmp1); QString rstr = args.at(i).toQString(m_tmp1);
rstr = (func_t == E_UPPER) ? rstr.toUpper() : rstr.toLower(); 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; break;
case E_FILES: case E_FILES:
@@ -2459,7 +2470,7 @@ ProStringList ProFileEvaluator::Private::evaluateExpandFunction(
dirs.append(fname + QDir::separator()); dirs.append(fname + QDir::separator());
} }
if (regex.exactMatch(qdir[i])) 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 rstr = val.toQString(m_tmp1);
QString copy = rstr; // Force a detach on modify QString copy = rstr; // Force a detach on modify
rstr.replace(before, after); 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; break;

View File

@@ -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 uint ProString::updatedHash() const
{ {
return (m_hash = hash(m_string.constData() + m_offset, m_length)); return (m_hash = hash(m_string.constData() + m_offset, m_length));

View File

@@ -71,7 +71,10 @@ public:
ProString(const QString &str, int offset, int length); 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, uint hash);
ProString(const QString &str, int offset, int length, ProStringConstants::OmitPreHashing); 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; } const ProFile *sourceFile() const { return m_file; }
QString toQString() const; QString toQString() const;
QString &toQString(QString &tmp) const; QString &toQString(QString &tmp) const;