OSDN Git Service

Debugger[New CDB]: Fix flag handling and expanding of list children.
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Wed, 15 Dec 2010 13:07:48 +0000 (14:07 +0100)
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>
Wed, 15 Dec 2010 13:09:37 +0000 (14:09 +0100)
Suppress repetitive invocation of dumper evaluation.
Use parseWatchData() as does gdb.

src/libs/qtcreatorcdbext/common.h
src/libs/qtcreatorcdbext/containers.cpp
src/libs/qtcreatorcdbext/symbolgroup.cpp
src/libs/qtcreatorcdbext/symbolgroupnode.cpp
src/libs/qtcreatorcdbext/symbolgroupnode.h
src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
src/plugins/debugger/cdb2/cdbengine2.cpp

index 198cb1e..6ee1f03 100644 (file)
@@ -73,4 +73,12 @@ ULONG currentThreadId(CIDebugClient *client);
 ULONG currentProcessId(IDebugSystemObjects *sysObjects);
 ULONG currentProcessId(CIDebugClient *client);
 
+#ifdef QTC_TRACE
+#  define QTC_TRACE_IN dprintf(">%s\n", __FUNCTION__);
+#  define QTC_TRACE_OUT dprintf("<%s\n", __FUNCTION__);
+#else
+#  define QTC_TRACE_IN
+#  define QTC_TRACE_OUT
+#endif
+
 #endif // COMMON_H
index aa2ec26..bcb8508 100644 (file)
@@ -39,9 +39,12 @@ typedef AbstractSymbolGroupNode::AbstractSymbolGroupNodePtrVector AbstractSymbol
 // Return size of container or -1
 int containerSize(KnownType kt, SymbolGroupNode *n, const SymbolGroupValueContext &ctx)
 {
+    QTC_TRACE_IN
     if ((kt & KT_ContainerType) == 0)
         return -1;
-    return containerSize(kt, SymbolGroupValue(n, ctx));
+    const int ct = containerSize(kt, SymbolGroupValue(n, ctx));
+    QTC_TRACE_OUT
+    return ct;
 }
 
 // Return size from an STL vector (last/first iterators).
index c2510c7..e1d6bc3 100644 (file)
@@ -185,6 +185,9 @@ static inline std::string msgNotFound(const std::string &nodeName)
 std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
                               const DumpParameters &p) const
 {
+    QTC_TRACE_IN
+    if (symbolGroupDebug)
+        DebugPrint() << "<SymbolGroup::dump()";
     std::ostringstream str;
     DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
     if (p.humanReadable())
@@ -192,6 +195,9 @@ std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
     str << '[';
     accept(visitor);
     str << ']';
+    QTC_TRACE_OUT
+    if (symbolGroupDebug)
+        DebugPrint() << "<SymbolGroup::dump()";
     return str.str();
 }
 
@@ -201,6 +207,9 @@ std::string SymbolGroup::dump(const std::string &iname,
                               const DumpParameters &p,
                               std::string *errorMessage)
 {
+    if (symbolGroupDebug)
+        DebugPrint() << ">SymbolGroup::dump(" << iname << ")";
+    QTC_TRACE_IN
     AbstractSymbolGroupNode *const aNode = find(iname);
     if (!aNode) {
         *errorMessage = msgNotFound(iname);
@@ -208,7 +217,7 @@ std::string SymbolGroup::dump(const std::string &iname,
     }
 
     // Real nodes: Expand and complex dumpers
-    if (SymbolGroupNode *node = aNode->asSymbolGroupNode()) {
+    if (SymbolGroupNode *node = aNode->resolveReference()->asSymbolGroupNode()) {
         if (node->isExpanded()) { // Mark expand request by watch model
             node->clearFlags(SymbolGroupNode::ExpandedByDumper);
         } else {
@@ -227,6 +236,9 @@ std::string SymbolGroup::dump(const std::string &iname,
     str << '[';
     aNode->accept(visitor, SymbolGroupNodeVisitor::parentIname(iname), 0, 0);
     str << ']';
+    QTC_TRACE_OUT
+    if (symbolGroupDebug)
+        DebugPrint() << "<SymbolGroup::dump(" << iname << ")";
     return str.str();
 }
 
@@ -291,6 +303,8 @@ static inline InamePathEntrySet expandEntrySet(const std::vector<std::string> &n
 // Expand a node list "locals.i1,locals.i2"
 unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::string *errorMessage)
 {
+    if (symbolGroupDebug)
+        DebugPrint() << ">SymbolGroup::expandList" << nodes.size();
     if (nodes.empty())
         return 0;
     // Create a set with a key <level, name>. Also required for 1 node (see above).
@@ -307,6 +321,8 @@ unsigned SymbolGroup::expandList(const std::vector<std::string> &nodes, std::str
                 errorMessage->append(", ");
             errorMessage->append(nodeError);
         }
+    if (symbolGroupDebug)
+        DebugPrint() << "<SymbolGroup::expandList returns " << succeeded;
     return succeeded;
 }
 
@@ -314,6 +330,9 @@ unsigned SymbolGroup::expandListRunComplexDumpers(const std::vector<std::string>
                                      const SymbolGroupValueContext &ctx,
                                      std::string *errorMessage)
 {
+    if (symbolGroupDebug)
+        DebugPrint() << ">SymbolGroup::expandListRunComplexDumpers" << nodes.size();
+    QTC_TRACE_IN
     if (nodes.empty())
         return 0;
     // Create a set with a key <level, name>. Also required for 1 node (see above).
@@ -330,6 +349,9 @@ unsigned SymbolGroup::expandListRunComplexDumpers(const std::vector<std::string>
                 errorMessage->append(", ");
             errorMessage->append(nodeError);
         }
+    QTC_TRACE_OUT
+    if (symbolGroupDebug)
+            DebugPrint() << "<SymbolGroup::expandListRunComplexDumpers returns " << succeeded;
     return succeeded;
 }
 
index 7948388..1c78a72 100644 (file)
@@ -36,8 +36,6 @@
 
 #include <algorithm>
 
-enum { debug = 0 };
-
 typedef std::vector<int>::size_type VectorIndexType;
 typedef std::vector<std::string> StringVector;
 
@@ -49,6 +47,43 @@ static inline void indentStream(std::ostream &str, unsigned depth)
         str << "  ";
 }
 
+static inline void debugNodeFlags(std::ostream &str, unsigned f)
+{
+    if (!f)
+        return;
+    str << " node-flags=" << f;
+    if (f & SymbolGroupNode::Uninitialized)
+        str << " UNINITIALIZED";
+    if (f & SymbolGroupNode::SimpleDumperNotApplicable)
+        str << " DumperNotApplicable";
+    if (f & SymbolGroupNode::SimpleDumperOk)
+        str << " DumperOk";
+    if (f & SymbolGroupNode::SimpleDumperFailed)
+        str << " DumperFailed";
+    if (f & SymbolGroupNode::ExpandedByDumper)
+        str << " ExpandedByDumper";
+    if (f & SymbolGroupNode::AdditionalSymbol)
+        str << " AdditionalSymbol";
+    if (f & SymbolGroupNode::Obscured)
+        str << " Obscured";
+    if (f & SymbolGroupNode::ComplexDumperOk)
+        str << " ComplexDumperOk";
+    str << ' ';
+}
+
+// Some helper to conveniently dump flags to a stream
+struct DebugNodeFlags
+{
+    DebugNodeFlags(unsigned f) : m_f(f) {}
+    const unsigned m_f;
+};
+
+inline std::ostream &operator<<(std::ostream &str, const DebugNodeFlags &f)
+{
+    debugNodeFlags(str, f.m_f);
+    return str;
+}
+
 // -------------- AbstractSymbolGroupNode
 
 AbstractSymbolGroupNode::AbstractSymbolGroupNode(const std::string &name,
@@ -704,9 +739,13 @@ std::wstring SymbolGroupNode::symbolGroupFixedValue() const
 // Complex dumpers: Get container/fake children
 void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
 {
+    if (symbolGroupDebug)
+        DebugPrint() << "SymbolGroupNode::runComplexDumpers "  << name() << '/'
+                        << absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
+
     if (m_dumperContainerSize <= 0 || (testFlags(ComplexDumperOk) || !testFlags(SimpleDumperOk)))
         return;
-    setFlags(ComplexDumperOk);
+    addFlags(ComplexDumperOk);
     const AbstractSymbolGroupNodePtrVector ctChildren =
             containerChildren(this, m_dumperType, m_dumperContainerSize, ctx);
     m_dumperContainerSize = int(ctChildren.size()); // Just in case...
@@ -726,19 +765,31 @@ void SymbolGroupNode::runComplexDumpers(const SymbolGroupValueContext &ctx)
 }
 
 // Run dumpers, format simple in-line dumper value and retrieve fake children
+bool SymbolGroupNode::runSimpleDumpers(const SymbolGroupValueContext &ctx)
+{
+    if (symbolGroupDebug)
+        DebugPrint() << "SymbolGroupNode::runSimpleDumpers "  << name() << '/'
+                        << absoluteFullIName() << ' ' << m_index << DebugNodeFlags(flags());
+    if (testFlags(Uninitialized))
+        return false;
+    if (testFlags(SimpleDumperOk))
+        return true;
+    if (testFlags(SimpleDumperMask))
+        return false;
+    addFlags(dumpSimpleType(this , ctx, &m_dumperValue,
+                            &m_dumperType, &m_dumperContainerSize));
+    if (symbolGroupDebug)
+        DebugPrint() << "-> '" << wStringToString(m_dumperValue) << "' Type="
+                     << m_dumperType << ' ' << DebugNodeFlags(flags());
+    return testFlags(SimpleDumperOk);
+}
+
 std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx)
 {
     if (testFlags(Uninitialized))
         return L"<not in scope>";
-    if (testFlags(SimpleDumperOk))
+    if (runSimpleDumpers(ctx))
         return m_dumperValue;
-    if ((flags() & SimpleDumperMask) == 0) {
-        const unsigned dumperFlags = dumpSimpleType(this , ctx, &m_dumperValue,
-                                                    &m_dumperType, &m_dumperContainerSize);
-        setFlags(dumperFlags);
-        if (testFlags(SimpleDumperOk))
-            return m_dumperValue;
-    }
     return symbolGroupFixedValue();
 }
 
@@ -814,28 +865,7 @@ void SymbolGroupNode::debug(std::ostream &str,
     str << "\",index=" << m_index;
     if (const VectorIndexType childCount = children().size())
         str << ", Children=" << childCount;
-    str << ' ' << m_parameters;
-    const unsigned f = flags();
-    if (f) {
-        str << " node-flags=" << f;
-        if (f & Uninitialized)
-            str << " UNINITIALIZED";
-        if (f & SimpleDumperNotApplicable)
-            str << " DumperNotApplicable";
-        if (f & SimpleDumperOk)
-            str << " DumperOk";
-        if (f & SimpleDumperFailed)
-            str << " DumperFailed";
-        if (f & ExpandedByDumper)
-            str << " ExpandedByDumper";
-        if (f & AdditionalSymbol)
-            str << " AdditionalSymbol";
-        if (f & Obscured)
-            str << " Obscured";
-        if (f & ComplexDumperOk)
-            str << " ComplexDumperOk";
-        str << ' ';
-    }
+    str << ' ' << m_parameters << DebugNodeFlags(flags());
     if (verbosity) {
         str << ",name=\"" << name() << "\", Address=0x" << std::hex << address() << std::dec
             << " Type=\"" << type() << '"';
@@ -848,7 +878,7 @@ void SymbolGroupNode::debug(std::ostream &str,
             if (m_dumperType & KT_ContainerType)
                 str << " container(" << m_dumperContainerSize << ')';
         }
-        if (!(f & Uninitialized))
+        if (!testFlags(Uninitialized))
             str << " Value=\"" << gdbmiWStringFormat(symbolGroupRawValue()) << '"';
         str << '\n'; // Potentially multiline
     }
@@ -869,8 +899,10 @@ static inline std::string msgCannotCast(const std::string &nodeName,
 // Expand!
 bool SymbolGroupNode::expand(std::string *errorMessage)
 {
-    if (::debug > 1)
-        DebugPrint() << "SymbolGroupNode::expand "  << name() << ' ' << m_index;
+    if (symbolGroupDebug)
+        DebugPrint() << "SymbolGroupNode::expand "  << name()
+                     <<'/' << absoluteFullIName() << ' '
+                    << m_index << DebugNodeFlags(flags());
     if (isExpanded()) {
         // Clear the flag indication dumper expansion on a second, explicit request
         clearFlags(ExpandedByDumper);
@@ -912,8 +944,8 @@ bool SymbolGroupNode::expandRunComplexDumpers(const SymbolGroupValueContext &ctx
         return true;
     if (!expand(errorMessage))
         return false;
-    simpleDumpValue(ctx); // Run simple dumpers to obtain type and run complex dumpers
-    if (testFlags(SimpleDumperOk))
+    // Run simple dumpers to obtain type and run complex dumpers
+    if (runSimpleDumpers(ctx) && testFlags(SimpleDumperOk))
         runComplexDumpers(ctx);
     return true;
 }
index 8ef34ec..82446ac 100644 (file)
@@ -37,6 +37,8 @@
 #include <map>
 #include <iosfwd>
 
+enum { symbolGroupDebug = 0 };
+
 std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
 
 class SymbolGroupNodeVisitor;
@@ -100,7 +102,6 @@ public:
 
     unsigned flags() const           { return m_flags; }
     bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
-    void setFlags(unsigned f)        { m_flags = f; }
     void addFlags(unsigned f)        { m_flags |= f; }
     void clearFlags(unsigned f)      { m_flags &= ~f; }
 
@@ -249,6 +250,7 @@ private:
     bool isArrayElement() const;
     // Notify about expansion of a node, shift indexes
     bool notifyExpanded(ULONG index, ULONG insertedCount);
+    bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
     std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
 
     SymbolGroup *const m_symbolGroup;
index 0089540..c13f962 100644 (file)
@@ -1086,6 +1086,7 @@ unsigned dumpSimpleType(SymbolGroupNode  *n, const SymbolGroupValueContext &ctx,
                         std::wstring *s, int *knownTypeIn /* = 0 */,
                         int *containerSizeIn /* = 0 */)
 {
+    QTC_TRACE_IN
     if (containerSizeIn)
         *containerSizeIn = -1;
     // Check for class types and strip pointer types (references appear as pointers as well)
@@ -1094,8 +1095,10 @@ unsigned dumpSimpleType(SymbolGroupNode  *n, const SymbolGroupValueContext &ctx,
     if (knownTypeIn)
         *knownTypeIn = kt;
 
-    if (kt == KT_Unknown)
+    if (kt == KT_Unknown) {
+        QTC_TRACE_OUT
         return SymbolGroupNode::SimpleDumperNotApplicable;
+    }
 
     const SymbolGroupValue v(n, ctx);
     // Simple dump of size for containers
@@ -1175,5 +1178,6 @@ unsigned dumpSimpleType(SymbolGroupNode  *n, const SymbolGroupValueContext &ctx,
     }
     if (rc == SymbolGroupNode::SimpleDumperOk)
         *s = str.str();
+    QTC_TRACE_OUT
     return rc;
 }
index a13f1fc..e110e39 100644 (file)
@@ -1189,20 +1189,26 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
 {
     if (reply->success) {
         QList<Debugger::Internal::WatchData> watchData;
-        if (Debugger::Internal::QtDumperHelper::parseValue(reply->reply.constData(), &watchData)) {
-            for (int i = 0; i < watchData.size(); i++)
-                watchData[i].setAllUnneeded();
-            if (debug > 1) {
-                QDebug nsp = qDebug().nospace();
-                nsp << "Obtained " << watchData.size() << " items:\n";
-                foreach (const Debugger::Internal::WatchData &wd, watchData)
-                    nsp << wd.toString() <<'\n';
-            }
-            watchHandler()->insertBulkData(watchData);
-            watchHandler()->endCycle();
-        } else {
-            showMessage(QString::fromLatin1("Parse error in locals response."), LogError);
-            qWarning("Parse error in locals response:\n%s", reply->reply.constData());
+        GdbMi root;
+        root.fromString(reply->reply);
+        QTC_ASSERT(root.isList(), return ; )
+        if (debugLocals) {
+            qDebug() << root.toString(true, 4);
+        }
+        // Courtesy of GDB engine
+        foreach (const GdbMi &child, root.children()) {
+            WatchData dummy;
+            dummy.iname = child.findChild("iname").data();
+            dummy.name = QLatin1String(child.findChild("name").data());
+            parseWatchData(watchHandler()->expandedINames(), dummy, child, &watchData);
+        }
+        watchHandler()->insertBulkData(watchData);
+        watchHandler()->endCycle();
+        if (debugLocals) {
+            QDebug nsp = qDebug().nospace();
+            nsp << "Obtained " << watchData.size() << " items:\n";
+            foreach (const Debugger::Internal::WatchData &wd, watchData)
+                nsp << wd.toString() <<'\n';
         }
     } else {
         showMessage(QString::fromLatin1(reply->errorMessage), LogError);