forked from qt-creator/qt-creator
AbstractMacroExpander: expand macros recursively
Started-by: Tobias Hunger <tobias.hunger@digia.com> Change-Id: Id2e88efbb475221cd7c0347f7d5e7009e4372eec Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Tobias Hunger
parent
1b11f9b3c0
commit
62da66a0aa
@@ -115,6 +115,40 @@ QTCREATOR_UTILS_EXPORT QString withTildeHomePath(const QString &path)
|
||||
return outPath;
|
||||
}
|
||||
|
||||
bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QString *ret)
|
||||
{
|
||||
QString varName;
|
||||
QChar prev;
|
||||
QChar c;
|
||||
|
||||
int i = *pos;
|
||||
int strLen = str.length();
|
||||
varName.reserve(strLen - i);
|
||||
for (; i < strLen; prev = c) {
|
||||
c = str.at(i++);
|
||||
if (c == QLatin1Char('}')) {
|
||||
if (varName.isEmpty()) { // replace "%{}" with "%"
|
||||
*ret = QString(QLatin1Char('%'));
|
||||
*pos = i;
|
||||
return true;
|
||||
}
|
||||
if (resolveMacro(varName, ret)) {
|
||||
*pos = i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else if (c == QLatin1Char('{') && prev == QLatin1Char('%')) {
|
||||
if (!expandNestedMacros(str, &i, ret))
|
||||
return false;
|
||||
varName.chop(1);
|
||||
varName += ret;
|
||||
} else {
|
||||
varName += c;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AbstractMacroExpander::findMacro(const QString &str, int *pos, QString *ret)
|
||||
{
|
||||
forever {
|
||||
@@ -122,22 +156,13 @@ int AbstractMacroExpander::findMacro(const QString &str, int *pos, QString *ret)
|
||||
if (openPos < 0)
|
||||
return 0;
|
||||
int varPos = openPos + 2;
|
||||
int closePos = str.indexOf(QLatin1Char('}'), varPos);
|
||||
if (closePos < 0)
|
||||
return 0;
|
||||
int varLen = closePos - varPos;
|
||||
if (varLen == 0) { // replace "%{}" with "%"
|
||||
if (expandNestedMacros(str, &varPos, ret)) {
|
||||
*pos = openPos;
|
||||
*ret = QString(QLatin1Char('%'));
|
||||
return 3;
|
||||
}
|
||||
if (resolveMacro(str.mid(varPos, varLen), ret)) {
|
||||
*pos = openPos;
|
||||
return varLen + 3;
|
||||
return varPos - openPos;
|
||||
}
|
||||
// An actual expansion may be nested into a "false" one,
|
||||
// so we continue right after the last %{.
|
||||
*pos = varPos;
|
||||
*pos = openPos + 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ public:
|
||||
//! \param ret Replacement string on output
|
||||
//! \return True if the expando was found
|
||||
virtual bool resolveMacro(const QString &name, QString *ret) = 0;
|
||||
private:
|
||||
bool expandNestedMacros(const QString &str, int *pos, QString *ret);
|
||||
};
|
||||
|
||||
QTCREATOR_UTILS_EXPORT void expandMacros(QString *str, AbstractMacroExpander *mx);
|
||||
|
||||
@@ -38,12 +38,20 @@ class TestMacroExpander : public Utils::AbstractMacroExpander
|
||||
public:
|
||||
virtual bool resolveMacro(const QString &name, QString *ret)
|
||||
{
|
||||
if (name == QLatin1String("foo")) {
|
||||
*ret = QLatin1String("a");
|
||||
return true;
|
||||
}
|
||||
if (name == QLatin1String("a")) {
|
||||
*ret = QLatin1String("hi");
|
||||
return true;
|
||||
}
|
||||
if (name == QLatin1String("foo")) {
|
||||
*ret = QLatin1String("a");
|
||||
if (name == QLatin1String("hi")) {
|
||||
*ret = QLatin1String("ho");
|
||||
return true;
|
||||
}
|
||||
if (name == QLatin1String("hihi")) {
|
||||
*ret = QLatin1String("bar");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -116,7 +124,15 @@ void tst_StringUtils::testMacroExpander_data()
|
||||
{ "%{a}text%{a}", "hitexthi" },
|
||||
{ "%{foo}%{a}text%{a}", "ahitexthi" },
|
||||
{ "%{}{a}", "%{a}" },
|
||||
{ "%{abc", "%{abc" }
|
||||
{ "%{}", "%" },
|
||||
{ "test%{}", "test%" },
|
||||
{ "%{}test", "%test" },
|
||||
{ "%{abc", "%{abc" },
|
||||
{ "%{%{a}", "%{hi" },
|
||||
{ "%{%{a}}", "ho" },
|
||||
{ "%{%{a}}}post", "ho}post" },
|
||||
{ "%{hi%{a}}", "bar" },
|
||||
{ "%{hi%{%{foo}}}", "bar" },
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(vals)/sizeof(vals[0]); i++)
|
||||
|
||||
Reference in New Issue
Block a user