forked from qt-creator/qt-creator
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:
@@ -28,6 +28,8 @@
|
|||||||
#include <utf8string.h>
|
#include <utf8string.h>
|
||||||
#include <utf8stringvector.h>
|
#include <utf8stringvector.h>
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class ToolTipInfo
|
class ToolTipInfo
|
||||||
@@ -54,6 +56,7 @@ public:
|
|||||||
out << message.qdocIdCandidates;
|
out << message.qdocIdCandidates;
|
||||||
out << message.qdocMark;
|
out << message.qdocMark;
|
||||||
out << static_cast<quint8>(message.qdocCategory);
|
out << static_cast<quint8>(message.qdocCategory);
|
||||||
|
out << message.value;
|
||||||
out << message.sizeInBytes;
|
out << message.sizeInBytes;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@@ -68,6 +71,7 @@ public:
|
|||||||
in >> message.qdocIdCandidates;
|
in >> message.qdocIdCandidates;
|
||||||
in >> message.qdocMark;
|
in >> message.qdocMark;
|
||||||
in >> qdocCategory;
|
in >> qdocCategory;
|
||||||
|
in >> message.value;
|
||||||
in >> message.sizeInBytes;
|
in >> message.sizeInBytes;
|
||||||
|
|
||||||
message.qdocCategory = static_cast<QdocCategory>(qdocCategory);
|
message.qdocCategory = static_cast<QdocCategory>(qdocCategory);
|
||||||
@@ -82,6 +86,7 @@ public:
|
|||||||
&& first.qdocIdCandidates == second.qdocIdCandidates
|
&& first.qdocIdCandidates == second.qdocIdCandidates
|
||||||
&& first.qdocMark == second.qdocMark
|
&& first.qdocMark == second.qdocMark
|
||||||
&& first.qdocCategory == second.qdocCategory
|
&& first.qdocCategory == second.qdocCategory
|
||||||
|
&& first.value == second.value
|
||||||
&& first.sizeInBytes == second.sizeInBytes;
|
&& first.sizeInBytes == second.sizeInBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +97,7 @@ public:
|
|||||||
Utf8StringVector qdocIdCandidates;
|
Utf8StringVector qdocIdCandidates;
|
||||||
Utf8String qdocMark;
|
Utf8String qdocMark;
|
||||||
QdocCategory qdocCategory = Unknown;
|
QdocCategory qdocCategory = Unknown;
|
||||||
|
QVariant value;
|
||||||
|
|
||||||
// For class definition and for class fields.
|
// For class definition and for class fields.
|
||||||
Utf8String sizeInBytes;
|
Utf8String sizeInBytes;
|
||||||
|
@@ -339,7 +339,7 @@ static CppTools::ToolTipInfo toToolTipInfo(const ToolTipMessage &message)
|
|||||||
info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates);
|
info.qDocIdCandidates = toStringList(backendInfo.qdocIdCandidates);
|
||||||
info.qDocMark = backendInfo.qdocMark;
|
info.qDocMark = backendInfo.qdocMark;
|
||||||
info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory);
|
info.qDocCategory = toHelpItemCategory(backendInfo.qdocCategory);
|
||||||
|
info.value = backendInfo.value;
|
||||||
info.sizeInBytes = backendInfo.sizeInBytes;
|
info.sizeInBytes = backendInfo.sizeInBytes;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
@@ -181,6 +181,22 @@ void ClangHoverHandler::processToolTipInfo(const CppTools::ToolTipInfo &info)
|
|||||||
|
|
||||||
if (!info.sizeInBytes.isEmpty())
|
if (!info.sizeInBytes.isEmpty())
|
||||||
text.append("\n\n" + tr("%1 bytes").arg(info.sizeInBytes));
|
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);
|
setToolTip(text);
|
||||||
m_reportPriority(priority());
|
m_reportPriority(priority());
|
||||||
|
@@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
@@ -57,6 +59,7 @@ struct CPPTOOLS_EXPORT ToolTipInfo {
|
|||||||
QStringList qDocIdCandidates;
|
QStringList qDocIdCandidates;
|
||||||
QString qDocMark;
|
QString qDocMark;
|
||||||
Core::HelpItem::Category qDocCategory;
|
Core::HelpItem::Category qDocCategory;
|
||||||
|
QVariant value;
|
||||||
|
|
||||||
QString sizeInBytes;
|
QString sizeInBytes;
|
||||||
};
|
};
|
||||||
|
@@ -149,6 +149,28 @@ Utf8String sizeInBytes(const Cursor &cursor)
|
|||||||
return Utf8String();
|
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)
|
Cursor referencedCursor(const Cursor &cursor)
|
||||||
{
|
{
|
||||||
// Query the referenced cursor directly instead of first testing with cursor.isReference().
|
// 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;
|
ToolTipInfo info;
|
||||||
info.text = text(cursor, referenced);
|
info.text = text(cursor, referenced);
|
||||||
info.briefComment = referenced.briefComment();
|
info.briefComment = referenced.briefComment();
|
||||||
|
info.value = value(cursor);
|
||||||
|
|
||||||
{
|
{
|
||||||
ToolTipInfo qDocToolTipInfo = qDocInfo(referenced);
|
ToolTipInfo qDocToolTipInfo = qDocInfo(referenced);
|
||||||
|
@@ -385,6 +385,15 @@ TEST_F(ToolTipInfo, SizeForUnion)
|
|||||||
ASSERT_THAT(actual.sizeInBytes, Utf8StringLiteral("1"));
|
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)
|
TEST_F(ToolTipInfo, Namespace)
|
||||||
{
|
{
|
||||||
::ToolTipInfo expected(Utf8StringLiteral("X"));
|
::ToolTipInfo expected(Utf8StringLiteral("X"));
|
||||||
|
@@ -199,3 +199,6 @@ Nuu **pointers(Nuu **p1)
|
|||||||
{
|
{
|
||||||
return p1;
|
return p1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr int calcValue() { return 1 + 2; }
|
||||||
|
const auto val = calcValue() + sizeof(char);
|
||||||
|
Reference in New Issue
Block a user