ClangCodeModel: Show value in tool tips, if possible

When hovering over a constant expression, it's probably helpful
to show that value to the user.
Requires clang 11 to fully work. For now, it only shows the value for
variable initializations.

Fixes: QTCREATORBUG-23967
Change-Id: I6b844231bac50993c2fa2fa82c552ad9cef590df
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Christian Kandeler
2020-05-18 17:40:19 +02:00
parent 227904d4a6
commit 949bb0e67b
7 changed files with 61 additions and 1 deletions

View File

@@ -28,6 +28,8 @@
#include <utf8string.h>
#include <utf8stringvector.h>
#include <QVariant>
namespace ClangBackEnd {
class ToolTipInfo
@@ -54,6 +56,7 @@ public:
out << message.qdocIdCandidates;
out << message.qdocMark;
out << static_cast<quint8>(message.qdocCategory);
out << message.value;
out << message.sizeInBytes;
return out;
@@ -68,6 +71,7 @@ public:
in >> message.qdocIdCandidates;
in >> message.qdocMark;
in >> qdocCategory;
in >> message.value;
in >> message.sizeInBytes;
message.qdocCategory = static_cast<QdocCategory>(qdocCategory);
@@ -82,6 +86,7 @@ public:
&& first.qdocIdCandidates == second.qdocIdCandidates
&& first.qdocMark == second.qdocMark
&& first.qdocCategory == second.qdocCategory
&& first.value == second.value
&& first.sizeInBytes == second.sizeInBytes;
}
@@ -92,6 +97,7 @@ public:
Utf8StringVector qdocIdCandidates;
Utf8String qdocMark;
QdocCategory qdocCategory = Unknown;
QVariant value;
// For class definition and for class fields.
Utf8String sizeInBytes;

View File

@@ -339,7 +339,7 @@ static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates);
info.qDocMark = backendInfo.qdocMark;
info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory);
info.value = backendInfo.value;
info.sizeInBytes = backendInfo.sizeInBytes;
return info;

View File

@@ -181,6 +181,22 @@ void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info)
if (!info.sizeInBytes.isEmpty())
text.append("\n\n" + tr("%1 bytes").arg(info.sizeInBytes));
if (info.value.isValid()) {
text.append("\n\n" + tr("Value: "));
switch (info.value.type()) {
case static_cast<QVariant::Type>(QMetaType::LongLong):
text.append(QString::number(info.value.toLongLong()));
break;
case static_cast<QVariant::Type>(QMetaType::ULongLong):
text.append(QString::number(info.value.toULongLong()));
break;
case static_cast<QVariant::Type>(QMetaType::Double):
text.append(QString::number(info.value.toDouble()));
break;
default:
QTC_CHECK(false);
}
}
setToolTip(text);
m_reportPriority(priority());

View File

@@ -41,6 +41,8 @@
#include <QTextEdit>
#include <QVariant>
#include <functional>
namespace TextEditor {
@@ -57,6 +59,7 @@ struct CPPTOOLS_EXPORT ToolTipInfo {
QStringList qDocIdCandidates;
QString qDocMark;
Core::HelpItem::Category qDocCategory;
QVariant value;
QString sizeInBytes;
};

View File

@@ -149,6 +149,28 @@ Utf8String sizeInBytes(const Cursor &cursor)
return Utf8String();
}
QVariant value(const Cursor &cursor)
{
if (!clang_isDeclaration(cursor.cx().kind) && !clang_isExpression(cursor.cx().kind))
return {};
const CXEvalResult evalResult = clang_Cursor_Evaluate(cursor.cx());
QVariant v;
switch (clang_EvalResult_getKind(evalResult)) {
case CXEval_Int:
v = clang_EvalResult_isUnsignedInt(evalResult)
? QVariant::fromValue(clang_EvalResult_getAsUnsigned(evalResult))
: QVariant::fromValue(clang_EvalResult_getAsLongLong(evalResult));
break;
case CXEval_Float:
v = QVariant::fromValue(clang_EvalResult_getAsDouble(evalResult));
break;
default:
break;
}
clang_EvalResult_dispose(evalResult);
return v;
}
Cursor referencedCursor(const Cursor &cursor)
{
// Query the referenced cursor directly instead of first testing with cursor.isReference().
@@ -503,6 +525,7 @@ ToolTipInfo ToolTipInfoCollector::collect(uint line, uint column) const
ToolTipInfo info;
info.text = text(cursor, referenced);
info.briefComment = referenced.briefComment();
info.value = value(cursor);
{
ToolTipInfo qDocToolTipInfo = qDocInfo(referenced);

View File

@@ -385,6 +385,15 @@ TEST_F(ToolTipInfo, SizeForUnion)
ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("1"));
}
TEST_F(ToolTipInfo, constexprValue)
{
// CLANG-UPGRADE-CHECK: Adapt the values below
ASSERT_THAT(tooltip(204, 12).value.toInt(), 4);
ASSERT_THAT(tooltip(204, 27).value.toInt(), 4); // 3 in clang 11
ASSERT_THAT(tooltip(204, 30).value.toInt(), 4);
ASSERT_THAT(tooltip(204, 32).value.toInt(), 4); // 1 in clang 11
}
TEST_F(ToolTipInfo, Namespace)
{
::ToolTipInfo expected(Utf8StringLiteral("X"));

View File

@@ -199,3 +199,6 @@ Nuu **pointers(Nuu **p1)
{
return p1;
}
static constexpr int calcValue() { return 1 + 2; }
const auto val = calcValue() + sizeof(char);