Quellcode durchsuchen

Made callstack aware of outer types vs namespaces. Colorized classview

Brian Fiete vor 5 Jahren
Ursprung
Commit
b3cc0b5be4

+ 271 - 0
IDE/src/IDEUtils.bf

@@ -8,6 +8,7 @@ using Beefy.utils;
 using Beefy;
 using Beefy.gfx;
 using Beefy.theme.dark;
+using IDE.ui;
 
 namespace IDE
 {
@@ -288,6 +289,276 @@ namespace IDE
 				g.Draw(DarkTheme.sDarkTheme.GetImage(.LockIcon), x, y);
 			}
 		}
+
+		public static void InsertColorChange(String str, int idx, uint32 color)
+		{
+			char8* insertChars = scope char8[5]*;
+			insertChars[0] = (char8)1;
+			*(uint32*)(insertChars + 1) = (color >> 1) & 0x7F7F7F7F;
+			str.Insert(idx, scope String(insertChars, 5));
+		}
+
+		public static void ModifyColorChange(String str, int idx, uint32 color)
+		{
+			char8* insertPos = str.Ptr + idx;
+			*(uint32*)(insertPos + 1) = (color >> 1) & 0x7F7F7F7F;
+		}
+
+		public enum CodeKind
+		{
+			Callstack,
+			Method,
+			Field,
+			Type
+		}
+
+		public static void ColorizeCodeString(String label, CodeKind codeKind)
+		{
+			//int q = 98;
+
+			int prevTypeColor = -1;
+			int prevStart = -1;
+			bool foundOpenParen = codeKind != .Callstack;
+			// Check to see if this is just a Mixin name, don't mistake for the bang that separates module name 
+			bool awaitingBang = label.Contains('!') && !label.EndsWith("!"); 
+			bool awaitingParamName = false;
+			int chevronCount = 0;
+			int parenCount = 0;
+
+			int lastTopStart = -1;
+			int lastTopEnd = -1;
+
+			bool inSubtype = false;
+
+			bool IsIdentifierChar(char8 c)
+			{
+				return (c.IsLetterOrDigit) || (c == '_') || (c == '$') || (c == '@');
+			}
+
+			bool IsIdentifierStart(char8 c)
+			{
+				return (c.IsLetter) || (c == '_');
+			}
+
+			for (int32 i = 0; i < label.Length; i++)
+			{
+				char8 c = label[i];
+				if ((c == '0') && (i == 0))
+					break; // Don't colorize addresses
+
+				if ((c == '<') && (i == 0))
+				{
+					uint32 color = 0xFFA0A0A0;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
+					InsertColorChange(label, 0, color);
+					label.Append('\x02');
+					break;
+				}
+
+				if (awaitingBang)
+				{
+					if ((c == ':') || (c == '<'))
+					{
+		                awaitingBang = false;
+						i = -1;
+						continue;
+					}
+
+					if (c == '!')
+					{
+						bool endNow = false;
+
+						if (i + 1 < label.Length)
+						{
+		                    char16 nextC = label[i + 1];
+							if ((nextC == '(') || (nextC == '='))
+							{
+								awaitingBang = false;
+								i = -1;
+								continue;
+							}
+							else if ((nextC == '0') || (nextC == '<'))
+							{
+								endNow = true; // Just a raw string
+							}
+						}
+
+						uint32 color = 0xFFA0A0A0;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
+						InsertColorChange(label, 0, color);
+						awaitingBang = false;
+
+						i += 5;
+						label.Insert(i, '\x02');
+
+						if (endNow)
+						{
+							InsertColorChange(label, i + 2, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method]);
+		                    break;
+						}
+					}
+				}
+				else if (c == '$')
+				{
+					uint32 color = 0xFF80A080;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
+					InsertColorChange(label, i, color);
+					i += 5;
+				}
+				else if (IsIdentifierChar(c))
+				{					
+					if ((prevStart == -1) && (!awaitingParamName))
+						prevStart = i;
+				}
+				else
+				{
+					int setNamespaceIdx = -1;
+
+					if ((!inSubtype) && (prevTypeColor != -1))
+					{
+						setNamespaceIdx = prevTypeColor;
+					}
+
+					bool isSubtypeSplit = false;
+					char8 nextC = (i < label.Length - 1) ? label[i + 1] : 0;
+
+					// Check for internal '+' subtype encoding
+					if ((c == '+') && (IsIdentifierStart(nextC)))
+					{
+						isSubtypeSplit = true;
+						inSubtype = true;
+						label[i] = '.';
+					}
+
+					if (prevStart != -1)
+					{
+						//label.Insert(prevStart, SourceEditWidgetContent.sTextColors[(int)SourceElementType.TypeRef]);
+						/*uint32 color = SourceEditWidgetContent.sTextColors[
+							inSubtype ? (int32)SourceElementType.TypeRef : (int32)SourceElementType.Namespace
+							];*/
+
+						uint32 color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.TypeRef];
+
+						/*if ((c == '+') || (c == '('))
+						{
+							foundOpenParen = true;
+							color = SourceEditWidgetContent.sTextColors[(int)SourceElementType.Method];
+						}*/
+
+						if (chevronCount == 0)
+						{
+							lastTopStart = prevStart;
+							lastTopEnd = i;
+						}
+
+						prevTypeColor = prevStart;
+						InsertColorChange(label, prevStart, color);
+						i += 5;
+
+						label.Insert(i, '\x02');
+						prevStart = -1;
+						awaitingParamName = false;
+
+						i++;
+					}
+
+					
+
+					if (c == ',')
+						awaitingParamName = false;
+
+					if ((c == ')') && (parenCount > 0))
+						parenCount--;
+
+					if ((c != '+') && (c != '.'))
+					{
+						inSubtype = false;
+						prevTypeColor = -1;
+					}
+
+					if ((c == '(') || ((c == '+') && (!isSubtypeSplit)))
+						setNamespaceIdx = -1;
+
+					if (setNamespaceIdx != -1)
+						ModifyColorChange(label, setNamespaceIdx, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Namespace]);
+
+					if (isSubtypeSplit)
+					{
+						// Handled
+					}
+					else if ((c == '(') && ((i == 0) || (chevronCount > 0)))
+					{
+						parenCount++;
+					}
+					else if ((c == '(') || (c == '+'))
+					{
+						foundOpenParen = true;
+						if (lastTopStart != -1)
+						{
+							char8* insertChars = label.CStr() + lastTopStart;
+							uint32 color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method];
+							*(uint32*)(insertChars + 1) = (color >> 1) & 0x7F7F7F7F;
+						}
+						else
+						{
+							int checkIdx = i - 1;
+							while (checkIdx > 0)
+							{
+								char8 checkC = label[checkIdx];
+								if (checkC == ':')
+								{
+									checkIdx++;
+		                            break;
+								}
+								checkIdx--;
+							}
+							if (checkIdx >= 0)
+							{
+		                        InsertColorChange(label, checkIdx, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method]);
+								i += 5;
+							}
+						}
+					}
+
+					if ((foundOpenParen) && (!awaitingParamName) && (chevronCount == 0))
+					{
+						if (c == ' ')
+						{							
+							bool nextIsName = true;
+							int32 spaceCount = 0;
+							for (int32 checkIdx = i + 1; checkIdx < label.Length; checkIdx++)
+							{
+								char8 checkC = label[checkIdx];
+								if (checkC == ' ')
+								{
+									spaceCount++;
+									if (spaceCount > 1)
+										nextIsName = false;
+								}
+								if ((checkC == '<') || (checkC == '*') || (checkC == '['))
+									nextIsName = false;
+								if ((checkC == ',') || (checkC == ')'))
+								{
+									if (spaceCount > 0)
+										nextIsName = false;
+									break;
+								}
+							}
+
+							if (nextIsName)
+								awaitingParamName = true;
+						}						
+					}
+				}
+
+				if (c == '<')
+					chevronCount++;
+				else if (c == '>')
+					chevronCount--;
+			}
+
+			if ((prevStart != -1) && (codeKind == .Type))
+			{
+				InsertColorChange(label, prevStart, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Type]);
+			}
+		}
     }
 }
 

+ 4 - 198
IDE/src/ui/CallStackPanel.bf

@@ -47,203 +47,6 @@ namespace IDE.ui
 			return new CallStackListViewItem();
 		}
 
-		static void InsertColorChange(String str, int idx, uint32 color)
-		{
-			char8* insertChars = scope char8[5]*;
-			insertChars[0] = (char8)1;
-			*(uint32*)(insertChars + 1) = (color >> 1) & 0x7F7F7F7F;
-			str.Insert(idx, scope String(insertChars, 5));
-		}
-
-		public static void ColorizeLocationString(String label, int line = -1)
-		{
-			int prevStart = -1;
-			bool foundOpenParen = false;
-			// Check to see if this is just a Mixin name, don't mistake for the bang that separates module name 
-			bool awaitingBang = label.Contains('!') && !label.EndsWith("!"); 
-			bool awaitingParamName = false;
-			int chevronCount = 0;
-			int parenCount = 0;
-
-			int lastTopStart = -1;
-			int lastTopEnd = -1;
-
-			for (int32 i = 0; i < label.Length; i++)
-			{
-				char8 c = label[i];
-				if ((c == '0') && (i == 0))
-					break; // Don't colorize addresses
-
-				if ((c == '<') && (i == 0))
-				{
-					uint32 color = 0xFFA0A0A0;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
-					InsertColorChange(label, 0, color);
-					label.Append('\x02');
-					break;
-				}
-
-				if (awaitingBang)
-				{
-					if ((c == ':') || (c == '<'))
-					{
-                        awaitingBang = false;
-						i = -1;
-						continue;
-					}
-
-					if (c == '!')
-					{
-						bool endNow = false;
-
-						if (i + 1 < label.Length)
-						{
-                            char16 nextC = label[i + 1];
-							if ((nextC == '(') || (nextC == '='))
-							{
-								awaitingBang = false;
-								i = -1;
-								continue;
-							}
-							else if ((nextC == '0') || (nextC == '<'))
-							{
-								endNow = true; // Just a raw string
-							}
-						}
-
-						uint32 color = 0xFFA0A0A0;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
-						InsertColorChange(label, 0, color);
-						awaitingBang = false;
-
-						i += 5;
-						label.Insert(i, '\x02');
-
-						if (endNow)
-						{
-							InsertColorChange(label, i + 2, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method]);
-                            break;
-						}
-					}
-				}
-				else if (c == '$')
-				{
-					uint32 color = 0xFF80A080;//SourceEditWidgetContent.sTextColors[(int)SourceElementType.Comment];
-					InsertColorChange(label, i, color);
-					i += 5;
-				}
-				else if ((c.IsLetterOrDigit) || (c == '_') || (c == '$') || (c == '@') /*|| (c == '>') || (c == '<') || (c == ':') || (c == '[') || (c == ']')*/)
-				{					
-					if ((prevStart == -1) && (!awaitingParamName))
-						prevStart = i;
-				}
-				else
-				{
-					if (prevStart != -1)
-					{
-						//label.Insert(prevStart, SourceEditWidgetContent.sTextColors[(int)SourceElementType.TypeRef]);
-						uint32 color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.TypeRef];
-						/*if ((c == '+') || (c == '('))
-						{
-							foundOpenParen = true;
-							color = SourceEditWidgetContent.sTextColors[(int)SourceElementType.Method];
-						}*/
-
-						if (chevronCount == 0)
-						{
-							lastTopStart = prevStart;
-							lastTopEnd = i;
-						}
-
-						InsertColorChange(label, prevStart, color);
-						i += 5;
-
-						label.Insert(i, '\x02');
-						prevStart = -1;
-						awaitingParamName = false;
-
-						i++;
-					}
-
-					if (c == ',')
-						awaitingParamName = false;
-
-					if ((c == ')') && (parenCount > 0))
-						parenCount--;
-
-					if ((c == '(') && ((i == 0) || (chevronCount > 0)))
-					{
-						parenCount++;
-					}
-					else if ((c == '(') || (c == '+'))
-					{
-						foundOpenParen = true;
-						if (lastTopStart != -1)
-						{
-							char8* insertChars = label.CStr() + lastTopStart;
-							uint32 color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method];
-							*(uint32*)(insertChars + 1) = (color >> 1) & 0x7F7F7F7F;
-						}
-						else
-						{
-							int checkIdx = i - 1;
-							while (checkIdx > 0)
-							{
-								char8 checkC = label[checkIdx];
-								if (checkC == ':')
-								{
-									checkIdx++;
-                                    break;
-								}
-								checkIdx--;
-							}
-							if (checkIdx >= 0)
-							{
-                                InsertColorChange(label, checkIdx, SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Method]);
-								i += 5;
-							}
-						}
-					}
-
-					if ((foundOpenParen) && (!awaitingParamName) && (chevronCount == 0))
-					{
-						if (c == ' ')
-						{							
-							bool nextIsName = true;
-							int32 spaceCount = 0;
-							for (int32 checkIdx = i + 1; checkIdx < label.Length; checkIdx++)
-							{
-								char8 checkC = label[checkIdx];
-								if (checkC == ' ')
-								{
-									spaceCount++;
-									if (spaceCount > 1)
-										nextIsName = false;
-								}
-								if ((checkC == '<') || (checkC == '*') || (checkC == '['))
-									nextIsName = false;
-								if ((checkC == ',') || (checkC == ')'))
-								{
-									if (spaceCount > 0)
-										nextIsName = false;
-									break;
-								}
-							}
-
-							if (nextIsName)
-								awaitingParamName = true;
-						}						
-					}
-				}
-
-				if (c == '<')
-					chevronCount++;
-				else if (c == '>')
-					chevronCount--;
-			}
-
-			if (line != -1)
-			    label.AppendF(" Line {0}", (int32)(line + 1));
-		}
-
         public override void PopulateVirtualItem(DarkVirtualListViewItem listViewItem)
         {
             base.PopulateVirtualItem(listViewItem);
@@ -267,7 +70,10 @@ namespace IDE.ui
             String label = scope String(256);
 			DebugManager.FrameFlags frameFlags;
             gApp.mDebugger.GetStackFrameInfo(listViewItem.mVirtualIdx, label, out addr, file, out hotIdx, out defLineStart, out defLineEnd, out line, out column, out language, out stackSize, out frameFlags);
-			ColorizeLocationString(label, line);
+			IDEUtils.ColorizeCodeString(label, .Callstack);
+			if (line != -1)
+				label.AppendF(" Line {0}", (int32)(line + 1));
+
             listViewItem.Label = label;
 
 

+ 50 - 5
IDE/src/ui/ClassViewPanel.bf

@@ -19,6 +19,7 @@ namespace IDE.ui
 		    public Object mRefObject;
 			public DataKind mKind;
 			public PendingEntry mMemberInfo ~ delete _;
+			public bool mProcessedLabel;
 
 		    protected override float GetLabelOffset()
 		    {
@@ -44,7 +45,36 @@ namespace IDE.ui
 
 		    public override void Draw(Graphics g)
 		    {
+				if ((!mProcessedLabel) && (mLabel != null))
+				{
+					uint32 color = 0;
+					switch (mMemberInfo.mKind)
+					{
+					case .Globals:
+						/*color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Identifier];
+						color = Color.Mult(color, Color.Get(0.8f));*/
+					case .Namespace:
+						color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Namespace];
+					case .Interface,
+						 .Class,
+						 .ValueType:
+						IDEUtils.ColorizeCodeString(mLabel, .Type);
+					case .Field,
+						 .Property:
+						IDEUtils.ColorizeCodeString(mLabel, .Field);
+					case .Method:
+						IDEUtils.ColorizeCodeString(mLabel, .Method);
+					default:
+					}
+
+					if (color != 0)
+						IDEUtils.InsertColorChange(mLabel, 0, color);
+						
+					mProcessedLabel = true;
+				}
+
 		        base.Draw(g);
+
 		        if (mRefObject != null)
 		        {
 		            bool hasChanged = false;
@@ -203,8 +233,13 @@ namespace IDE.ui
 			{
 				if (((Object)val1 == null) || ((Object)val2 == null))
 					return ((Object)val1 == null) && ((Object)val2 == null);
-				if ((val1.mKind != val2.mKind) && ((val1.mKind != .Namespace) && (val2.mKind != .Namespace)))
-					return false;
+				if (val1.mKind != val2.mKind)
+				{
+					if ((val1.mKind == .Project) || (val2.mKind == .Project))
+						return false;
+					if ((val1.mKind != .Namespace) && (val2.mKind != .Namespace))
+						return false;
+				}
 				return (val1.mName == val2.mName);
 			}
 
@@ -598,6 +633,8 @@ namespace IDE.ui
 
 			List<PendingEntry> partialRefs = scope List<PendingEntry>();
 
+			char8[] seps = scope char8[] ('.', '+');
+
 			for (var subStrRef in str.Split('\n'))
 			{
 				String param = scope String();
@@ -656,6 +693,8 @@ namespace IDE.ui
 						kind = .Interface;
 					else if (cmd == 'c')
 						kind = .Class;
+					else if (cmd == 'g')
+						kind = .Globals;
 
 					if (parentEntry != null)
 					{
@@ -677,7 +716,7 @@ namespace IDE.ui
 					}
 
 					int nameIdx = 0;
-					for (var subName in param.Split('.'))
+					for (var subName in param.Split(seps))
 					{
 						if (nameIdx < addIdx)
 						{
@@ -687,10 +726,13 @@ namespace IDE.ui
 
 						String subNameStr = scope String();
 
+						bool isLast = subName.Ptr + subName.Length == param.Ptr + param.Length;
+
 						if (nameIdx == addIdx)
 						{
+							DataKind insertKind = isLast ? kind : .Namespace;
 							subNameStr.Reference(StringView(param, 0, @subName.MatchPos));
-							curEntry = mPendingInfo.mPendingRoot.AddChild(kind, subNameStr);
+							curEntry = mPendingInfo.mPendingRoot.AddChild(insertKind, subNameStr);
 							curEntry.mParent = curProject;
 							Debug.Assert(curProject != (Object)curEntry);
 							partialRefs.Add(curEntry);
@@ -700,7 +742,6 @@ namespace IDE.ui
 						}
 
 						DataKind insertKind = kind;
-						bool isLast = subName.Ptr + subName.Length == param.Ptr + param.Length;
 						if (!isLast)
 						{
 							char8 nextChar = subName.Ptr[subName.Length];
@@ -803,6 +844,7 @@ namespace IDE.ui
 					childListViewItem.mRefObject = pendingEntry.mRefObject;
 					childListViewItem.mOpenOnDoubleClick = false;
 					childListViewItem.mKind = child.mKind;
+					childListViewItem.mProcessedLabel = false;
 					DeleteAndNullify!(childListViewItem.mMemberInfo);
 					//if (child.mFile != null)
 					{
@@ -940,7 +982,10 @@ namespace IDE.ui
 			if (mWorkWait == -1)
 			{
 				if (mWantsSubmit)
+				{
 					mTypeLV.KeyDown(.Return, false);
+					mWantsSubmit = false;
+				}
 			}
 		}
 

+ 1 - 1
IDE/src/ui/ThreadPanel.bf

@@ -447,7 +447,7 @@ namespace IDE.ui
 			    subItem = (ThreadListViewItem)listViewItem.CreateSubItem(2);
 				label.Clear();
 				label.Append(elementData[2]);
-				CallStackListView.ColorizeLocationString(label);
+				IDEUtils.ColorizeCodeString(label, .Callstack);
 			    subItem.Label = label;
 			    subItem.mOnMouseDown.Add(new => ValueClicked);
 

+ 8 - 0
IDEHelper/Compiler/BfAst.cpp

@@ -892,6 +892,14 @@ BfSourceData* BfAstNode::GetSourceData()
 #endif
 }
 
+BfParserData* BfAstNode::GetParserData()
+{
+	BfSourceData* sourceData = GetSourceData();
+	if (sourceData == NULL)
+		return NULL;
+	return sourceData->ToParserData();
+}
+
 BfParser* BfAstNode::GetParser()
 {
 	BfSourceData* sourceData = GetSourceData();

+ 1 - 0
IDEHelper/Compiler/BfAst.h

@@ -1025,6 +1025,7 @@ public:
 	bool IsTemporary();
 	int GetStartCharId();
 	BfSourceData* GetSourceData();
+	BfParserData* GetParserData();
 	BfParser* GetParser();
 	bool IsFromParser(BfParser* parser);
 	String ToString();

+ 310 - 159
IDEHelper/DbgModule.cpp

@@ -389,15 +389,13 @@ NS_BF_DBG_END
 
 //////////////////////////////////////////////////////////////////////////
 
-String DbgSubprogram::ToString()
+void DbgSubprogram::ToString(StringImpl& str, bool internalName)
 {
 	if ((mInlineeInfo != NULL) && (mInlineeInfo->mInlineeId != 0))
 		mCompileUnit->mDbgModule->FixupInlinee(this);
 
 	PopulateSubprogram();
-	
-	String str;
-
+		
 	if (mCheckedKind == BfCheckedKind_Checked)
 		str += "[Checked] ";
 	else if (mCheckedKind == BfCheckedKind_Unchecked)
@@ -407,14 +405,17 @@ String DbgSubprogram::ToString()
 	if (mName == NULL)
 	{		
 		if (mLinkName[0] == '<')
-			return mLinkName;
+		{
+			str += mLinkName;
+			return;
+		}
 		str = BfDemangler::Demangle(StringImpl::MakeRef(mLinkName), language);
 		// Strip off the params since we need to generate those ourselves		
 		int parenPos = (int)str.IndexOf('(');
 		if (parenPos != -1)
 			str = str.Substring(0, parenPos);
 	}
-	else if (mHasQualifiedName)
+	else if ((mHasQualifiedName) && (!internalName))
 	{
 		const char* cPtr = mName;
 		if (strncmp(cPtr, "_bf::", 5) == 0)
@@ -458,48 +459,64 @@ String DbgSubprogram::ToString()
 			str += mName;
 	}
 	else
-	{		
+	{
 		if (mParentType != NULL)
 		{
-			str += mParentType->ToString();
+			mParentType->ToString(str, language, true, internalName);
 			if (!str.empty())
 			{
 				if (language == DbgLanguage_Beef)
 					str += ".";
 				else
 					str += "::";
+			}			
+		}
+
+		const char* name = mName;
+		if (mHasQualifiedName)
+		{
+			const char* cPtr = name;
+			for (; true; cPtr++)
+			{
+				char c = *cPtr;
+				if (c == 0)
+					break;				
+				if ((c == ':') && (cPtr[1] == ':'))
+				{
+					name = cPtr + 2;
+				}				
 			}
 		}
 
-		if ((language == DbgLanguage_Beef) && (mParentType != NULL) && (mParentType->mTypeName != NULL) && (strcmp(mName, mParentType->mTypeName) == 0))
+		if ((language == DbgLanguage_Beef) && (mParentType != NULL) && (mParentType->mTypeName != NULL) && (strcmp(name, mParentType->mTypeName) == 0))
 			str += "this";
-		else if ((language == DbgLanguage_Beef) && (mName[0] == '~'))
+		else if ((language == DbgLanguage_Beef) && (name[0] == '~'))
 			str += "~this";
-		else if (strncmp(mName, "_bf::", 5) == 0)
-			str += mName + 5;
+		else if (strncmp(name, "_bf::", 5) == 0)
+			str += name + 5;
 		else
 		{
 			bool handled = false;
-			if ((language == DbgLanguage_Beef) && (mName[0] == '_'))
+			if ((language == DbgLanguage_Beef) && (name[0] == '_'))
 			{
-				if (strcmp(mName, "__BfCtor") == 0)
+				if (strcmp(name, "__BfCtor") == 0)
 				{
 					str += "this";
 					handled = true;
 				}
-				else if (strcmp(mName, "__BfStaticCtor") == 0)				
+				else if (strcmp(name, "__BfStaticCtor") == 0)
 				{
 					str += "this";
 					handled = true;
 				}
-				else if (strcmp(mName, "__BfCtorClear") == 0)				
+				else if (strcmp(name, "__BfCtorClear") == 0)
 				{
 					str += "this$clear";
 					handled = true;
 				}
 			}
 			if (!handled)
-				str += mName;
+				str += name;
 		}
 	}
 
@@ -538,7 +555,7 @@ String DbgSubprogram::ToString()
 				BF_ASSERT(varType->IsPointer());
 				varType = varType->mTypeParam;
 			}
-			str += varType->ToString(language);
+			varType->ToString(str, language, false, internalName);
 			if (variable->mName != NULL)
 				str += " ";
 		}
@@ -547,7 +564,13 @@ String DbgSubprogram::ToString()
 		showedParam = true;
 		i++;
 	}
-	str += ")";
+	str += ")";	
+}
+
+String DbgSubprogram::ToString()
+{
+	String str;
+	ToString(str, false);
 	return str;
 }
 
@@ -1503,8 +1526,8 @@ String DbgType::ToStringRaw(DbgLanguage language)
 	return ToString(language);
 }
 
-String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
-{
+void DbgType::ToString(StringImpl& str, DbgLanguage language, bool allowDirectBfObject, bool internalName)
+{	
 	if (language == DbgLanguage_Unknown)
 		language = GetLanguage();
 
@@ -1513,27 +1536,38 @@ String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
 		switch (mTypeCode)
 		{
 		case DbgType_UChar:
-			return "char8";
+			str += "char8";
+			return;
 		case DbgType_UChar16:
-			return "char16";
+			str += "char16";
+			return;
 		case DbgType_UChar32:
-			return "char32";
+			str += "char32";
+			return;
 		case DbgType_i8:
-			return "int8";
+			str += "int8";
+			return;
 		case DbgType_u8:
-			return "uint8";
+			str += "uint8";
+			return;
 		case DbgType_i16:
-			return "int16";
+			str += "int16";
+			return;
 		case DbgType_u16:
-			return "uint16";
+			str += "uint16";
+			return;
 		case DbgType_i32:
-			return "int32";
+			str += "int32";
+			return;
 		case DbgType_u32:
-			return "uint32";
+			str += "uint32";
+			return;
 		case DbgType_i64:
-			return "int64";
+			str += "int64";
+			return;
 		case DbgType_u64:
-			return "uint64";		
+			str += "uint64";
+			return;
 		}
 	}
 	else
@@ -1541,50 +1575,78 @@ String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
 		switch (mTypeCode)
 		{
 		case DbgType_SChar:
-			return "char";
-		case DbgType_SChar16:		
-			return "wchar_t";
+			str += "char";
+			return;
+		case DbgType_SChar16:
+			str += "wchar_t";
+			return;
 		case DbgType_SChar32:
-			return "int32_t";
+			str += "int32_t";
+			return;
 		case DbgType_UChar:
-			return "uint8_t";
+			str += "uint8_t";
+			return;
 		case DbgType_UChar16:
-			return "uint16_t";
+			str += "uint16_t";
+			return;
 		case DbgType_UChar32:
-			return "uint32_t";
+			str += "uint32_t";
+			return;
 		case DbgType_i8:
-			return "char";
+			str += "char";
+			return;
 		case DbgType_u8:
-			return "uint8_t";
+			str += "uint8_t";
+			return;
 		case DbgType_i16:
-			return "short";
+			str += "short";
+			return;
 		case DbgType_u16:
-			return "uint16_t";
+			str += "uint16_t";
+			return;
 		case DbgType_i32:
-			return "int";
+			str += "int";
+			return;
 		case DbgType_u32:
-			return "uint32_t";
+			str += "uint32_t";
+			return;
 		case DbgType_i64:
-			return "int64_t";
+			str += "int64_t";
+			return;
 		case DbgType_u64:
-			return "uint64_t";
+			str += "uint64_t";
+			return;
 		}
 	}
 
+	if (mTypeCode == DbgType_Namespace)
+		internalName = false;
+
+	auto parent = mParent;
+	if ((parent == NULL) && (internalName))
+	{
+		auto primaryType = GetPrimaryType();
+		parent = primaryType->mParent;
+	}
+
 	if (mTypeName != NULL)
 	{
 		if ((!allowDirectBfObject) && (IsBfObject()))
 		{
 			// Only use the '#' for testing
 			//return ToString(true) + "#";
-			return ToString(DbgLanguage_Unknown, true);
+			ToString(str, DbgLanguage_Unknown, true, internalName);
+			return;
 		}
 
 		if (IsGlobalsContainer())
 		{
 			if (mParent != NULL)
-				return mParent->ToString(language);
-			return "";
+			{
+				mParent->ToString(str, language, false, internalName);
+				return;
+			}
+			return;
 		}
 
 		char* nameP = (char*)mTypeName;
@@ -1599,182 +1661,271 @@ String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
 		if ((!mFixedName) && (language == DbgLanguage_Beef))
 		{
 			FixName();
-		}
+		}		
 
-		if (mParent == NULL)
-		{			
+		if (parent == NULL)
+		{
 			if (strncmp(nameP, "Box<", 4) == 0)
-				return String(nameP + 4, nameP + strlen(nameP) - 1) + "^";
+			{
+				str += String(nameP + 4, nameP + strlen(nameP) - 1);
+				str += "^";
+				return;
+			}
 
 			// For declarations, may also include namespaces
-			return mName;			
+			str += mName;
+			return;
 		}
 
 		if (GetLanguage() == DbgLanguage_Beef)
-			return mParent->ToString(language) + "." + nameP;
+		{
+			parent->ToString(str, language, allowDirectBfObject, internalName);
+			if ((internalName) && (parent->mTypeCode != DbgType_Namespace))
+				str += "+";
+			else
+				str += ".";			
+			str += nameP;
+		}
 		else
-			return mParent->ToString(language) + "::" + nameP;
-	}
-	
+		{			
+			parent->ToString(str, language, allowDirectBfObject, internalName);
+			if ((internalName) && (parent->mTypeCode != DbgType_Namespace))
+				str += "+";
+			else
+				str += "::";			
+			str += nameP;
+		}
+		return;
+	}	
 
 	switch (mTypeCode)
 	{
 	case DbgType_Struct:
+	{
+		if ((mTypeName == NULL) && (parent != NULL))
 		{
-			if ((mTypeName == NULL) && (mParent != NULL))
-				return mParent->ToString(language);
-			return "@struct";
+			parent->ToString(str, language, allowDirectBfObject, internalName);
+			return;
 		}
+		str += "@struct";
+		return;
+	}
 	case DbgType_Class:
-		{
-			return "@class";
-		}
+	{
+		str += "@class";
+		return;
+	}
 	case DbgType_TypeDef:
-		{
-			return "@typedef";
-		}		
+	{
+		str += "@typedef";
+		return;
+	}
 	case DbgType_Const:
+	{
+		if (language == DbgLanguage_Beef)
 		{
-			if (language == DbgLanguage_Beef)
+			str += "readonly";
+			if (mTypeParam != NULL)
 			{
-				if (mTypeParam == NULL)
-					return "readonly";
-				return "readonly " + mTypeParam->ToString(language);
+				str += " ";
+				mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 			}
+			return;
+		}
 
-			if (mTypeParam == NULL)
-				return "const";
-			return "const " + mTypeParam->ToString(language);
+		str += "const";
+		if (mTypeParam != NULL)
+		{
+			str += " ";
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 		}
+		return;
+	}
 	case DbgType_Volatile:
+	{
+		str += "volatile";
+		if (mTypeParam != NULL)
 		{
-			if (mTypeParam == NULL)
-				return "volatile";
-			return "volatile " + mTypeParam->ToString(language);
+			str += " ";
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 		}
+		return;
+	}
 	case DbgType_Unaligned:
+	{
+		str += "unaligned";
+		if (mTypeParam != NULL)
 		{
-			if (mTypeParam == NULL)
-				return "unaligned";
-			return "unaligned " + mTypeParam->ToString(language);
+			str += " ";
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 		}
+	}
 	case DbgType_Restrict:
+	{
+		str += "restrict";
+		if (mTypeParam != NULL)
 		{
-			if (mTypeParam == NULL)
-				return "restrict";
-			return "restrict " + mTypeParam->ToString(language);
+			str += " ";
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 		}
+	}
 	case DbgType_Ptr:
+	{
+		if (mTypeParam == NULL)
 		{
-			if (mTypeParam == NULL)
-				return "void*";
-	
-			if (mTypeParam->IsBfObject())
-				return mTypeParam->ToString(DbgLanguage_Unknown, true);
-	
-			// Don't put a "*" on the end of a function type, it's implicit
-			if (mTypeParam->mTypeCode == DbgType_Subroutine)
-				return mTypeParam->ToString(language);
+			str += "void*";
+			return;
+		}
+
+		if (mTypeParam->IsBfObject())
+		{
+			mTypeParam->ToString(str, DbgLanguage_Unknown, true, internalName);
+			return;
+		}
+
+		// Don't put a "*" on the end of a function type, it's implicit
+		if (mTypeParam->mTypeCode == DbgType_Subroutine)
+		{
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+			return;
+		}
 
-			return mTypeParam->ToString(language) + "*";
-		}	
+		mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		str += "*";
+		return;
+	}
 	case DbgType_Ref:
+	{
+		if (language == DbgLanguage_Beef)
 		{
-			if (language == DbgLanguage_Beef)
+			str += "ref";
+			if (mTypeParam != NULL)
 			{
-				if (mTypeParam == NULL)
-					return "ref";
-				return "ref " + mTypeParam->ToString(language);
+				str += " ";
+				mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
 			}
-			if (mTypeParam == NULL)
-				return "&";
-			return mTypeParam->ToString(language) + "&";
 		}
+		if (mTypeParam == NULL)
+		{
+			str += "&";
+			return;
+		}
+		mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		str += "&";
+		return;
+	}
 	case DbgType_RValueReference:
+	{
+		if (language == DbgLanguage_Beef)
 		{
-			if (language == DbgLanguage_Beef)
-			{
-				// Ignore this - this is used for passing structs when we're not using the 'byval' attribute
-				return mTypeParam->ToString(language);
-			}
-	
-			if (mTypeParam == NULL)
-				return "&&";
-			return mTypeParam->ToString(language) + "&&";
+			// Ignore this - this is used for passing structs when we're not using the 'byval' attribute
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+			return;
 		}
+
+		if (mTypeParam == NULL)
+		{
+			str += "&&";
+			return;
+		}
+		mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		str += "&&";
+		return;
+	}
 	case DbgType_Unspecified:
-		return mTypeName;
+		str += mTypeName;
+		return;
 	case DbgType_SizedArray:
+	{
+		StringT<128> name;
+		auto checkType = this;
+		while (checkType->mTypeCode == DbgType_SizedArray)
 		{
-			String name;
-			auto checkType = this;
-			while (checkType->mTypeCode == DbgType_SizedArray)			
+			intptr innerSize = checkType->mTypeParam->GetStride();
+			intptr arrSize = 0;
+			if (innerSize > 0)
 			{
-				intptr innerSize = checkType->mTypeParam->GetStride();
-				intptr arrSize = 0;
-				if (innerSize > 0)
-				{
-					arrSize = checkType->GetStride() / innerSize;
-				}
-				name += StrFormat("[%lld]", arrSize);
-				checkType = checkType->mTypeParam;
-			}			 
-			name = checkType->ToString(language) + name;
-
-			return name;
+				arrSize = checkType->GetStride() / innerSize;
+			}
+			name += StrFormat("[%lld]", arrSize);
+			checkType = checkType->mTypeParam;
 		}
+		checkType->ToString(str, language, allowDirectBfObject, internalName);
+		str += name;
+		return;
+	}
 	case DbgType_Union:
+	{
+		str += "union";
+		if (mTypeParam != NULL)
 		{
-			if (mTypeName != NULL)
-				return String("union ") + mTypeName;
-			return "union";
-		}	
+			str += " ";
+			mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		}
+		return;
+	}
 	case DbgType_Single:
-		return "float";
+		str += "float";
+		return;
 	case DbgType_Double:
-		return "double";
+		str += "double";
+		return;
 	case DbgType_Null:
-		return "void";
+		str += "void";
+		return;
 	case DbgType_Subroutine:
+	{		
+		mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		str += " (";
+		int paramIdx = 0;
+		for (auto param : mBlockParam->mVariables)
 		{
-			String str;			
-			str += mTypeParam->ToString(language);
-			str += " (";
-			int paramIdx = 0;
-			for (auto param : mBlockParam->mVariables)
-			{
-				if (paramIdx > 0)
-					str += ", ";
-				str += param->mType->ToString(language);
-				paramIdx++;
-			}
-			str += ")";
-			return str;
+			if (paramIdx > 0)
+				str += ", ";
+			param->mType->ToString(str, language, allowDirectBfObject, internalName);
+			paramIdx++;
 		}
+		str += ")";
+		return;
+	}
 	case DbgType_VTable:
-		return "@vtable";
+		str += "@vtable";
+		return;
 	case DbgType_Enum:
-		return "@enum";	
+		str += "@enum";
+		return;
 	case DbgType_Namespace:
-		{		
-			// Anonymous
-			return "`anon`";
-		}
+	{
+		// Anonymous
+		str += "`anon`";
+		return;
+	}
 	case DbgType_PtrToMember:
-		return "@ptrToMember";
+		str += "@ptrToMember";
+		return;
 	case DbgType_Bitfield:
-		{
-			auto dbgBitfieldType = (DbgBitfieldType*)this;
-			return mTypeParam->ToString(language) + StrFormat("{%d:%d}", dbgBitfieldType->mPosition, dbgBitfieldType->mLength);
-		}
+	{
+		auto dbgBitfieldType = (DbgBitfieldType*)this;
+		mTypeParam->ToString(str, language, allowDirectBfObject, internalName);
+		str += StrFormat("{%d:%d}", dbgBitfieldType->mPosition, dbgBitfieldType->mLength);
+		return;
+	}
 	default:
 		break;
 	}
 
 	BF_FATAL("Unhandled type");
-	return "???";
+	str += "???";
+}
+
+String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
+{
+	String str;
+	ToString(str, language, allowDirectBfObject, false);
+	return str;
 }
 
+
 intptr DbgType::GetByteCount()
 {	
 	if (!mSizeCalculated)

+ 3 - 1
IDEHelper/DbgModule.h

@@ -433,7 +433,8 @@ public:
 
 	~DbgSubprogram();	
 		
-	String ToString();		
+	void ToString(StringImpl& str, bool internalName);
+	String ToString();
 	DbgLineData* FindClosestLine(addr_target addr, DbgSubprogram** inlinedSubprogram = NULL, DbgSrcFile** srcFile = NULL, int* outLineIdx = NULL);	
 	DbgType* GetParent();
 	DbgType* GetTargetType(); // usually mParentType except for closures
@@ -636,6 +637,7 @@ public:
 	DbgType* GetRootBaseType();
 	DbgType* RemoveModifiers(bool* hadRef = NULL);	
 	String ToStringRaw(DbgLanguage language = DbgLanguage_Unknown);
+	void ToString(StringImpl& str, DbgLanguage language, bool allowDirectBfObject, bool internalName);
 	String ToString(DbgLanguage language = DbgLanguage_Unknown, bool allowDirectBfObject = false);
 	intptr GetByteCount();
 	intptr GetStride();

+ 3 - 1
IDEHelper/WinDebugger.cpp

@@ -10766,7 +10766,9 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 			}
 		}
 		if (demangledName.IsEmpty())
-			demangledName = dwSubprogram->ToString();
+		{
+			dwSubprogram->ToString(demangledName, true);
+		}
 		
 		DbgSrcFile* dwSrcFile = NULL;
 		DbgLineData* dwLineData = NULL;