Add hooks that enable NSSet, NSDictionary and NSString formatting to apply to other types beyond the well-known ones

This is meant to support languages that can do some sort of bridging from<-->to these ObjC types via types that statically vend themselves as Cocoa types, but dynamically have an implementation that does not match any of our well-known types, but where an introspecting formatter can be vended by the bridged language

llvm-svn: 249185
diff --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 113e05d..1c3758b 100644
--- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Cocoa.h"
+#include "NSSet.h"
 
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Core/Error.h"
@@ -24,6 +24,20 @@
 using namespace lldb_private;
 using namespace lldb_private::formatters;
 
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSSet_Additionals::GetAdditionalSummaries ()
+{
+    static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+    return g_map;
+}
+
+std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+NSSet_Additionals::GetAdditionalSynthetics ()
+{
+    static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
+    return g_map;
+}
+
 namespace lldb_private {
     namespace formatters {
         class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
@@ -208,7 +222,8 @@
     
     uint64_t value = 0;
     
-    const char* class_name = descriptor->GetClassName().GetCString();
+    ConstString class_name_cs = descriptor->GetClassName();
+    const char* class_name = class_name_cs.GetCString();
     
     if (!class_name || !*class_name)
         return false;
@@ -252,6 +267,10 @@
     }*/
     else
     {
+        auto& map(NSSet_Additionals::GetAdditionalSummaries());
+        auto iter = map.find(class_name_cs), end = map.end();
+        if (iter != end)
+            return iter->second(valobj, stream, options);
         if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
             return false;
     }
@@ -264,7 +283,7 @@
     return true;
 }
 
-SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
 {
     lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
     if (!process_sp)
@@ -286,7 +305,8 @@
     if (!descriptor.get() || !descriptor->IsValid())
         return NULL;
     
-    const char* class_name = descriptor->GetClassName().GetCString();
+    ConstString class_name_cs = descriptor->GetClassName();
+    const char* class_name = class_name_cs.GetCString();
     
     if (!class_name || !*class_name)
         return NULL;
@@ -305,6 +325,10 @@
     }
     else
     {
+        auto& map(NSSet_Additionals::GetAdditionalSynthetics());
+        auto iter = map.find(class_name_cs), end = map.end();
+        if (iter != end)
+            return iter->second(synth, valobj_sp);
         return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
     }
 }