forked from qt-creator/qt-creator
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: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
58
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
58
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -33,7 +33,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace CPlusPlus;
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
@@ -459,6 +459,58 @@ bool Bind::visit(EnumeratorAST *ast)
|
|||||||
return false;
|
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 Bind::enumerator(EnumeratorAST *ast, Enum *symbol)
|
||||||
{
|
{
|
||||||
(void) symbol;
|
(void) symbol;
|
||||||
@@ -477,6 +529,10 @@ void Bind::enumerator(EnumeratorAST *ast, Enum *symbol)
|
|||||||
|
|
||||||
if (ExpressionAST *expr = ast->expression)
|
if (ExpressionAST *expr = ast->expression)
|
||||||
e->setConstantValue(asStringLiteral(expr->firstToken(), expr->lastToken()));
|
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);
|
symbol->addMember(e);
|
||||||
}
|
}
|
||||||
|
@@ -456,7 +456,7 @@ CppEnumerator::CppEnumerator(CPlusPlus::EnumeratorDeclaration *declaration)
|
|||||||
|
|
||||||
Overview overview;
|
Overview overview;
|
||||||
|
|
||||||
Symbol *enumSymbol = declaration->enclosingScope()->asEnum();
|
Symbol *enumSymbol = declaration->enclosingScope();
|
||||||
const QString enumName = overview.prettyName(LookupContext::fullyQualifiedName(enumSymbol));
|
const QString enumName = overview.prettyName(LookupContext::fullyQualifiedName(enumSymbol));
|
||||||
const QString enumeratorName = overview.prettyName(declaration->name());
|
const QString enumeratorName = overview.prettyName(declaration->name());
|
||||||
QString enumeratorValue;
|
QString enumeratorValue;
|
||||||
|
@@ -184,6 +184,11 @@ private slots:
|
|||||||
void lambda_2();
|
void lambda_2();
|
||||||
|
|
||||||
void diagnostic_error();
|
void diagnostic_error();
|
||||||
|
|
||||||
|
void enum_constantValue1();
|
||||||
|
void enum_constantValue2();
|
||||||
|
void enum_constantValue3();
|
||||||
|
void enum_constantValue4();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Semantic::function_declaration_1()
|
void tst_Semantic::function_declaration_1()
|
||||||
@@ -783,5 +788,107 @@ void tst_Semantic::diagnostic_error()
|
|||||||
QCOMPARE(doc->globals->memberCount(), 1U);
|
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)
|
QTEST_MAIN(tst_Semantic)
|
||||||
#include "tst_semantic.moc"
|
#include "tst_semantic.moc"
|
||||||
|
Reference in New Issue
Block a user