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"