Commit 9e159d87 authored by Przemyslaw Gorszkowski's avatar Przemyslaw Gorszkowski
Browse files

C++: display enum value in tooltip for simplest case



If it is possible lets calculate enum value for the simplest case.
Example where it works:
enum
{
  enum_val1, // tooltip = "enum_val1 = 0"
  enum_val2 // tooltip = "enum_val2 = 1"
};

enum
{
  enum_val1=10, // tooltip = "enum_val1 = 10"
  enum_val2 // tooltip = "enum_val2 = 11"
};

enum
{
  enum_val1, // tooltip = "enum_val1 = 0"
  enum_val2=10, // tooltip = "enum_val2 = 10"
  enum_val3 // tooltip = "enum_val3 = 11"
};

Example where it does not work:
enum
{
  enum_val1=10+1, // tooltip = "enum_val1 = 10+1"
  enum_val2 // tooltip = "enum_val2"
};

Task-number: QTCREATORBUG-4529
Change-Id: Idd85ed7304018f73f2b068bf1ac28f1abde02f93
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent f66ee665
......@@ -33,7 +33,7 @@
#include <vector>
#include <string>
#include <memory>
#include <sstream>
using namespace CPlusPlus;
......@@ -459,6 +459,58 @@ bool Bind::visit(EnumeratorAST *ast)
return false;
}
namespace {
bool isInteger(const StringLiteral *stringLiteral)
{
const int size = stringLiteral->size();
const char *chars = stringLiteral->chars();
for (int i = 0; i < size; ++i) {
if (!isdigit(chars[i]))
return false;
}
return true;
}
bool stringLiteralToInt(const StringLiteral *stringLiteral, int *output)
{
if (!output)
return false;
if (!isInteger(stringLiteral)) {
*output = 0;
return false;
}
std::stringstream ss(std::string(stringLiteral->chars(), stringLiteral->size()));
const bool ok = ss >> *output;
if (!ok)
*output = 0;
return ok;
}
void calculateConstantValue(const Symbol *symbol, EnumeratorDeclaration *e, Control *control)
{
if (symbol) {
if (const Declaration *decl = symbol->asDeclaration()) {
if (const EnumeratorDeclaration *previousEnumDecl = decl->asEnumeratorDeclarator()) {
if (const StringLiteral *constantValue = previousEnumDecl->constantValue()) {
int constantValueAsInt = 0;
if (stringLiteralToInt(constantValue, &constantValueAsInt)) {
++constantValueAsInt;
const std::string buffer = std::to_string(constantValueAsInt);
e->setConstantValue(control->stringLiteral(buffer.c_str(),
unsigned(buffer.size())));
}
}
}
}
}
}
} // anonymous namespace
void Bind::enumerator(EnumeratorAST *ast, Enum *symbol)
{
(void) symbol;
......@@ -477,6 +529,10 @@ void Bind::enumerator(EnumeratorAST *ast, Enum *symbol)
if (ExpressionAST *expr = ast->expression)
e->setConstantValue(asStringLiteral(expr->firstToken(), expr->lastToken()));
else if (!symbol->isEmpty())
calculateConstantValue(*(symbol->lastMember()-1), e, control());
else
e->setConstantValue(control()->stringLiteral("0", 1));
symbol->addMember(e);
}
......
......@@ -456,7 +456,7 @@ CppEnumerator::CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration)
Overview overview;
Symbol *enumSymbol = declaration->enclosingScope()->asEnum();
Symbol *enumSymbol = declaration->enclosingScope();
const QString enumName = overview.prettyName(LookupContext::fullyQualifiedName(enumSymbol));
const QString enumeratorName = overview.prettyName(declaration->name());
QString enumeratorValue;
......
......@@ -184,6 +184,11 @@ private slots:
void lambda_2();
void diagnostic_error();
void enum_constantValue1();
void enum_constantValue2();
void enum_constantValue3();
void enum_constantValue4();
};
void tst_Semantic::function_declaration_1()
......@@ -783,5 +788,107 @@ void tst_Semantic::diagnostic_error()
QCOMPARE(doc->globals->memberCount(), 1U);
}
namespace {
void testEnumaratorDeclarator(Enum *e, int enumDeclIndex, const char *expectedConstantValue)
{
Declaration *enumMemberDeclaration = e->memberAt(enumDeclIndex)->asDeclaration();
QVERIFY(enumMemberDeclaration);
EnumeratorDeclaration *enumeratorDeclaration = enumMemberDeclaration->asEnumeratorDeclarator();
QVERIFY(enumeratorDeclaration);
if (const StringLiteral *constantValue = enumeratorDeclaration->constantValue())
QCOMPARE(constantValue->chars(), expectedConstantValue);
else
QVERIFY(!expectedConstantValue);
}
} // anonymous
void tst_Semantic::enum_constantValue1()
{
QSharedPointer<Document> doc = document("\n"
"enum {\n"
"E1,\n"
"E2,\n"
"E3\n"
"};\n"
);
QCOMPARE(doc->errorCount, 0U);
QCOMPARE(doc->globals->memberCount(), 1U);
Enum *e = doc->globals->memberAt(0)->asEnum();
QVERIFY(e);
QCOMPARE(e->memberCount(), 3U);
testEnumaratorDeclarator(e, 0, "0");
testEnumaratorDeclarator(e, 1, "1");
testEnumaratorDeclarator(e, 2, "2");
}
void tst_Semantic::enum_constantValue2()
{
QSharedPointer<Document> doc = document("\n"
"enum {\n"
"E1=10,\n"
"E2,\n"
"E3\n"
"};\n"
);
QCOMPARE(doc->errorCount, 0U);
QCOMPARE(doc->globals->memberCount(), 1U);
Enum *e = doc->globals->memberAt(0)->asEnum();
QVERIFY(e);
QCOMPARE(e->memberCount(), 3U);
testEnumaratorDeclarator(e, 0, "10");
testEnumaratorDeclarator(e, 1, "11");
testEnumaratorDeclarator(e, 2, "12");
}
void tst_Semantic::enum_constantValue3()
{
QSharedPointer<Document> doc = document("\n"
"enum {\n"
"E1,\n"
"E2=10,\n"
"E3\n"
"};\n"
);
QCOMPARE(doc->errorCount, 0U);
QCOMPARE(doc->globals->memberCount(), 1U);
Enum *e = doc->globals->memberAt(0)->asEnum();
QVERIFY(e);
QCOMPARE(e->memberCount(), 3U);
testEnumaratorDeclarator(e, 0, "0");
testEnumaratorDeclarator(e, 1, "10");
testEnumaratorDeclarator(e, 2, "11");
}
void tst_Semantic::enum_constantValue4()
{
QSharedPointer<Document> doc = document("\n"
"enum {\n"
"E1,\n"
"E2=E1+10,\n"
"E3,\n"
"E4=10,\n"
"E5\n"
"};\n"
);
QCOMPARE(doc->errorCount, 0U);
QCOMPARE(doc->globals->memberCount(), 1U);
Enum *e = doc->globals->memberAt(0)->asEnum();
QVERIFY(e);
QCOMPARE(e->memberCount(), 5U);
testEnumaratorDeclarator(e, 0, "0");
testEnumaratorDeclarator(e, 1, "E1+10");
testEnumaratorDeclarator(e, 2, NULL);
testEnumaratorDeclarator(e, 3, "10");
testEnumaratorDeclarator(e, 4, "11");
}
QTEST_MAIN(tst_Semantic)
#include "tst_semantic.moc"
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