aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--abstractmetabuilder.cpp31
-rw-r--r--tests/testenum.cpp73
-rw-r--r--tests/testenum.h1
3 files changed, 99 insertions, 6 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index 47c8e4843..75190a87a 100644
--- a/abstractmetabuilder.cpp
+++ b/abstractmetabuilder.cpp
@@ -707,14 +707,16 @@ AbstractMetaClass* AbstractMetaBuilder::traverseNamespace(NamespaceModelItem nam
struct Operator
{
- enum Type { Plus, ShiftLeft, None };
+ enum Type { Complement, Plus, ShiftRight, ShiftLeft, None };
Operator() : type(None) {}
int calculate(int x)
{
switch (type) {
+ case Complement: return ~value;
case Plus: return x + value;
+ case ShiftRight: return x >> value;
case ShiftLeft: return x << value;
case None: return x;
}
@@ -730,7 +732,9 @@ struct Operator
Operator findOperator(QString* s)
{
const char *names[] = {
+ "~",
"+",
+ ">>",
"<<"
};
@@ -738,14 +742,21 @@ Operator findOperator(QString* s)
QString name = QLatin1String(names[i]);
QString str = *s;
int splitPoint = str.indexOf(name);
- if (splitPoint > 0) {
+ if (splitPoint > -1) {
bool ok;
QString right = str.mid(splitPoint + name.length());
Operator op;
+
op.value = right.toInt(&ok);
+ if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u'))
+ op.value = right.left(right.length() - 1).toUInt(&ok, 0);
+
if (ok) {
op.type = Operator::Type(i);
- *s = str.left(splitPoint).trimmed();
+ if (splitPoint > 0)
+ *s = str.left(splitPoint).trimmed();
+ else
+ *s = QString();
return op;
}
}
@@ -777,16 +788,16 @@ int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
v = s.toUInt(&ok, 0);
+ else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u'))
+ v = s.left(s.length() - 1).toUInt(&ok, 0);
else
v = s.toInt(&ok);
- if (ok) {
+ if (ok || s.isEmpty()) {
matched = true;
-
} else if (m_enumValues.contains(s)) {
v = m_enumValues[s]->value();
matched = true;
-
} else {
if (metaEnum) {
v = findOutValueFromString(s, matched);
@@ -2089,6 +2100,14 @@ int AbstractMetaBuilder::findOutValueFromString(const QString& stringValue, bool
return (stringValue == "true");
}
+ // This is a very lame way to handle expression evaluation,
+ // but it is not critical and will do for the time being.
+ static QRegExp variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$");
+ if (!variableNameRegExp.exactMatch(stringValue)) {
+ ok = true;
+ return 0;
+ }
+
AbstractMetaEnumValue* enumValue = m_metaClasses.findEnumValue(stringValue);
if (enumValue) {
ok = true;
diff --git a/tests/testenum.cpp b/tests/testenum.cpp
index 698efa8d6..62c43c6c8 100644
--- a/tests/testenum.cpp
+++ b/tests/testenum.cpp
@@ -255,6 +255,79 @@ void TestEnum::testEnumValueFromNeighbourEnum()
QCOMPARE(enumValueB1->stringValue(), QString("ValueA0"));
}
+void TestEnum::testEnumValueFromExpression()
+{
+ const char* cppCode ="\
+ struct A {\
+ enum EnumA {\
+ ValueA0 = 3u,\
+ ValueA1 = ~3u,\
+ ValueA2 = ~3,\
+ ValueA3 = 0xf0,\
+ ValueA4 = 8 |ValueA3,\
+ ValueA5 = ValueA3|32,\
+ ValueA6 = ValueA3 >> 1,\
+ ValueA7 = ValueA3 << 1\
+ };\
+ };\
+ ";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\"> \
+ <value-type name='A'> \
+ <enum-type name='EnumA'/>\
+ </value-type> \
+ </typesystem>";
+
+ TestUtil t(cppCode, xmlCode, false);
+
+ AbstractMetaClass* classA = t.builder()->classes().findClass("A");
+ QVERIFY(classA);
+
+ AbstractMetaEnum* enumA = classA->findEnum("EnumA");
+ QVERIFY(enumA);
+ QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QString("A::EnumA"));
+
+ AbstractMetaEnumValue* valueA0 = enumA->values().at(0);
+ QCOMPARE(valueA0->name(), QString("ValueA0"));
+ QCOMPARE(valueA0->stringValue(), QString("3u"));
+ QCOMPARE(valueA0->value(), (int) 3u);
+
+ AbstractMetaEnumValue* valueA1 = enumA->values().at(1);
+ QCOMPARE(valueA1->name(), QString("ValueA1"));
+ QCOMPARE(valueA1->stringValue(), QString("~3u"));
+ QCOMPARE(valueA1->value(), (int) ~3u);
+
+ AbstractMetaEnumValue* valueA2 = enumA->values().at(2);
+ QCOMPARE(valueA2->name(), QString("ValueA2"));
+ QCOMPARE(valueA2->stringValue(), QString("~3"));
+ QCOMPARE(valueA2->value(), ~3);
+
+ AbstractMetaEnumValue* valueA3 = enumA->values().at(3);
+ QCOMPARE(valueA3->name(), QString("ValueA3"));
+ QCOMPARE(valueA3->stringValue(), QString("0xf0"));
+ QCOMPARE(valueA3->value(), 0xf0);
+
+ AbstractMetaEnumValue* valueA4 = enumA->values().at(4);
+ QCOMPARE(valueA4->name(), QString("ValueA4"));
+ QCOMPARE(valueA4->stringValue(), QString("8|ValueA3"));
+ QCOMPARE(valueA4->value(), 8|0xf0);
+
+ AbstractMetaEnumValue* valueA5 = enumA->values().at(5);
+ QCOMPARE(valueA5->name(), QString("ValueA5"));
+ QCOMPARE(valueA5->stringValue(), QString("ValueA3|32"));
+ QCOMPARE(valueA5->value(), 0xf0|32);
+
+ AbstractMetaEnumValue* valueA6 = enumA->values().at(6);
+ QCOMPARE(valueA6->name(), QString("ValueA6"));
+ QCOMPARE(valueA6->stringValue(), QString("ValueA3>>1"));
+ QCOMPARE(valueA6->value(), 0xf0 >> 1);
+
+ AbstractMetaEnumValue* valueA7 = enumA->values().at(7);
+ QCOMPARE(valueA7->name(), QString("ValueA7"));
+ QCOMPARE(valueA7->stringValue(), QString("ValueA3<<1"));
+ QCOMPARE(valueA7->value(), 0xf0 << 1);
+}
+
void TestEnum::testPrivateEnum()
{
const char* cppCode ="\
diff --git a/tests/testenum.h b/tests/testenum.h
index e4aaa1368..7bf3a9eb5 100644
--- a/tests/testenum.h
+++ b/tests/testenum.h
@@ -34,6 +34,7 @@ private slots:
void testAnonymousEnum();
void testGlobalEnums();
void testEnumValueFromNeighbourEnum();
+ void testEnumValueFromExpression();
void testPrivateEnum();
};