File indexing completed on 2024-05-12 04:40:07
0001 /* 0002 SPDX-FileCopyrightText: 2016 Aetf <aetf@unlimitedcodeworks.xyz> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "variable.h" 0008 0009 #include "debuglog.h" 0010 #include "debugsession.h" 0011 #include "mi/micommand.h" 0012 #include "stringhelpers.h" 0013 0014 #include <QString> 0015 0016 using namespace KDevelop; 0017 using namespace KDevMI::LLDB; 0018 using namespace KDevMI::MI; 0019 0020 LldbVariable::LldbVariable(DebugSession *session, TreeModel *model, TreeItem *parent, 0021 const QString& expression, const QString& display) 0022 : MIVariable(session, model, parent, expression, display) 0023 { 0024 } 0025 0026 void LldbVariable::refetch() 0027 { 0028 if (!topLevel() || varobj().isEmpty()) { 0029 return; 0030 } 0031 0032 if (!sessionIsAlive()) { 0033 return; 0034 } 0035 0036 // update the value itself 0037 QPointer<LldbVariable> guarded_this(this); 0038 m_debugSession->addCommand(VarEvaluateExpression, varobj(), [guarded_this](const ResultRecord &r){ 0039 if (guarded_this && r.reason == QLatin1String("done") && r.hasField(QStringLiteral("value"))) { 0040 guarded_this->setValue(guarded_this->formatValue(r[QStringLiteral("value")].literal())); 0041 } 0042 }); 0043 0044 // update children 0045 // remove all children first, this will cause some gliches in the UI, but there's no good way 0046 // that we can know if there's anything changed 0047 if (isExpanded() || !childCount()) { 0048 deleteChildren(); 0049 fetchMoreChildren(); 0050 } 0051 } 0052 0053 void LldbVariable::handleRawUpdate(const ResultRecord& r) 0054 { 0055 qCDebug(DEBUGGERLLDB) << "handleRawUpdate for variable" << varobj(); 0056 const Value& changelist = r[QStringLiteral("changelist")]; 0057 Q_ASSERT_X(changelist.size() <= 1, "LldbVariable::handleRawUpdate", 0058 "should only be used with one variable VarUpdate"); 0059 if (changelist.size() == 1) 0060 handleUpdate(changelist[0]); 0061 } 0062 0063 void LldbVariable::formatChanged() 0064 { 0065 if(childCount()) 0066 { 0067 for (TreeItem* item : qAsConst(childItems)) { 0068 Q_ASSERT(qobject_cast<MIVariable*>(item)); 0069 if (auto* var = qobject_cast<MIVariable*>(item)) { 0070 var->setFormat(format()); 0071 } 0072 } 0073 } 0074 else 0075 { 0076 if (sessionIsAlive()) { 0077 QPointer<LldbVariable> guarded_this(this); 0078 m_debugSession->addCommand( 0079 VarSetFormat, 0080 QStringLiteral(" %1 %2 ").arg(varobj(), format2str(format())), 0081 [guarded_this](const ResultRecord &r){ 0082 if(guarded_this && r.hasField(QStringLiteral("changelist"))) { 0083 if (r[QStringLiteral("changelist")].size() > 0) { 0084 guarded_this->handleRawUpdate(r); 0085 } 0086 } 0087 }); 0088 } 0089 } 0090 } 0091 0092 QString LldbVariable::formatValue(const QString& value) const 0093 { 0094 // Data formatter emits value with unicode escape sequence for string and char, 0095 // translate them back. 0096 // Only check with first char is enough, as unquote will do the rest check 0097 if (value.startsWith(QLatin1Char('"'))) { 0098 return Utils::quote(Utils::unquote(value, true)); 0099 } else if (value.startsWith(QLatin1Char('\''))) { 0100 return Utils::quote(Utils::unquote(value, true, QLatin1Char('\'')), QLatin1Char('\'')); 0101 } else if (value.startsWith(QLatin1Char('b'))) { 0102 // this is a byte array, don't translate unicode, simply return without 'b' prefix 0103 return value.mid(1); 0104 } 0105 return value; 0106 } 0107 0108 #include "moc_variable.cpp"