File indexing completed on 2024-04-21 04:36:04
0001 /* 0002 * XDebug Debugger Support 0003 * 0004 * Copyright 2007 Hamish Rodda <rodda@kde.org> 0005 * Copyright 2008 Vladimir Prus <ghost@cs.msu.su> 0006 * Copyright 2009 Niko Sams <niko.sams@gmail.com> 0007 * 0008 * This program is free software; you can redistribute it and/or modify 0009 * it under the terms of the GNU General Public License as 0010 * published by the Free Software Foundation; either version 2 of the 0011 * License, or (at your option) any later version. 0012 * 0013 * This program is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0016 * GNU General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU General Public 0019 * License along with this program; if not, write to the 0020 * Free Software Foundation, Inc., 0021 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0022 */ 0023 0024 #include "variablecontroller.h" 0025 0026 #include <KTextEditor/Document> 0027 0028 #include <QDomElement> 0029 #include <QXmlStreamReader> 0030 0031 #include <debugger/variable/variablecollection.h> 0032 #include <debugger/breakpoint/breakpointmodel.h> 0033 #include <interfaces/icore.h> 0034 #include <interfaces/idebugcontroller.h> 0035 #include <debugger/interfaces/iframestackmodel.h> 0036 0037 #include "connection.h" 0038 #include "debugsession.h" 0039 #include "variable.h" 0040 #include "stringhelpers.h" 0041 0042 namespace XDebug { 0043 VariableController::VariableController(DebugSession* parent) 0044 : KDevelop::IVariableController(parent) 0045 { 0046 Q_ASSERT(parent); 0047 } 0048 0049 DebugSession* VariableController::debugSession() const 0050 { 0051 return static_cast<DebugSession*>(const_cast<QObject*>(QObject::parent())); 0052 } 0053 0054 void VariableController::update() 0055 { 0056 //if (autoUpdate() & UpdateWatches) { 0057 variableCollection()->watches()->reinstall(); 0058 //} 0059 // if (autoUpdate() & UpdateLocals) { 0060 updateLocals(); 0061 // } 0062 } 0063 0064 void VariableController::handleLocals(KDevelop::Locals* locals, const QDomDocument& xml) 0065 { 0066 Q_ASSERT(xml.documentElement().attribute("command") == "context_get"); 0067 0068 QStringList names; 0069 { 0070 QDomElement el = xml.documentElement().firstChildElement("property"); 0071 while (!el.isNull()) { 0072 names << el.attribute("fullname"); 0073 el = el.nextSiblingElement("property"); 0074 } 0075 } 0076 0077 { 0078 QList<KDevelop::Variable*> vars = locals->updateLocals(names); 0079 0080 QDomElement el = xml.documentElement().firstChildElement("property"); 0081 while (!el.isNull()) { 0082 QString name = el.attribute("fullname"); 0083 foreach (KDevelop::Variable* v, vars) { 0084 Q_ASSERT(dynamic_cast<Variable*>(v)); 0085 if (v->expression() == name) { 0086 static_cast<Variable*>(v)->handleProperty(el); 0087 break; 0088 } 0089 } 0090 0091 el = el.nextSiblingElement("property"); 0092 } 0093 } 0094 } 0095 void VariableController::handleContextNames(const QDomDocument& xml) 0096 { 0097 Q_ASSERT(xml.documentElement().attribute("command") == "context_names"); 0098 0099 QDomElement el = xml.documentElement().firstChildElement("context"); 0100 while (!el.isNull()) { 0101 QString name = el.attribute("name"); 0102 QString id = el.attribute("id"); 0103 QStringList args; 0104 args << QString("-c %0").arg(id); 0105 Q_ASSERT(debugSession()->frameStackModel()->currentFrame() != -1); 0106 args << QString("-d %0").arg(debugSession()->frameStackModel()->currentFrame()); 0107 KDevelop::Locals* locals = KDevelop::ICore::self()->debugController()->variableCollection()->locals(name); 0108 CallbackWithCookie<VariableController, KDevelop::Locals>* cb = 0109 new CallbackWithCookie<VariableController, KDevelop::Locals> 0110 (this, &VariableController::handleLocals, locals); 0111 debugSession()->connection()->sendCommand("context_get", args, QByteArray(), cb); 0112 el = el.nextSiblingElement("context"); 0113 } 0114 } 0115 0116 void VariableController::updateLocals() 0117 { 0118 if (debugSession()->frameStackModel()->currentFrame() == -1) { 0119 return; 0120 } 0121 0122 Callback<VariableController>* cb = new Callback<VariableController>(this, &VariableController::handleContextNames); 0123 QStringList args; 0124 args << QString("-d %0").arg(debugSession()->frameStackModel()->currentFrame()); 0125 debugSession()->connection()->sendCommand("context_names", args, QByteArray(), cb); 0126 } 0127 0128 KTextEditor::Range VariableController::expressionRangeUnderCursor(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor) 0129 { 0130 QString line = doc->line(cursor.line()); 0131 int index = cursor.column(); 0132 QChar c = line[index]; 0133 if (!c.isLetterOrNumber() && c != '_' && c != '$') { 0134 return {}; 0135 } 0136 0137 int start = Utils::expressionAt(line, index); 0138 int end = index; 0139 for (; end < line.size(); ++end) { 0140 QChar c = line[end]; 0141 if (!(c.isLetterOrNumber() || c == '_' || c == '$')) { 0142 break; 0143 } 0144 } 0145 0146 if (!(start < end)) { 0147 return {}; 0148 } 0149 0150 // TODO: Check whether this was ported correctly 0151 return { 0152 KTextEditor::Cursor { 0153 cursor.line(), start 0154 }, KTextEditor::Cursor { 0155 cursor.line(), end 0156 } 0157 }; 0158 } 0159 0160 void VariableController::addWatch(KDevelop::Variable* variable) 0161 { 0162 if (Variable* v = dynamic_cast<Variable*>(variable)) { 0163 variableCollection()->watches()->add(v->fullName()); 0164 } 0165 } 0166 0167 void VariableController::addWatchpoint(KDevelop::Variable* variable) 0168 { 0169 if (Variable* v = dynamic_cast<Variable*>(variable)) { 0170 KDevelop::ICore::self()->debugController()->breakpointModel()->addWatchpoint(v->fullName()); 0171 } 0172 } 0173 0174 KDevelop::Variable* VariableController:: 0175 createVariable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent, 0176 const QString& expression, const QString& display) 0177 { 0178 return new Variable(model, parent, expression, display); 0179 } 0180 0181 void VariableController::handleEvent(KDevelop::IDebugSession::event_t event) 0182 { 0183 IVariableController::handleEvent(event); 0184 } 0185 }