diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-09-30 10:57:29 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-09 19:10:11 -0300 |
commit | 128c833f6b51a3709a2b0162f639121981389af2 (patch) | |
tree | 8b3b341147011fa6113f5e57ae1214568fa8b6e6 | |
parent | f1987763b81d4a73063ebbd494dd3d09fef6383d (diff) |
Added a better support for resolution of enum value attribution.
Plus tests.
Reviewed by Luciano Wolf <luciano.wolf@openbossa.org>
Reviewed by Renato Araújo <renato.filho@openbossa.org>
-rw-r--r-- | abstractmetabuilder.cpp | 31 | ||||
-rw-r--r-- | tests/testenum.cpp | 73 | ||||
-rw-r--r-- | tests/testenum.h | 1 |
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(); }; |