From b3cc0b5be422be07980bc97b4a0b855dc9f1bdc6 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 11 Dec 2019 12:54:50 -0800 Subject: [PATCH] Made callstack aware of outer types vs namespaces. Colorized classview --- IDE/src/IDEUtils.bf | 271 +++++++++++++++++++ IDE/src/ui/CallStackPanel.bf | 202 +------------- IDE/src/ui/ClassViewPanel.bf | 55 +++- IDE/src/ui/ThreadPanel.bf | 2 +- IDEHelper/Compiler/BfAst.cpp | 8 + IDEHelper/Compiler/BfAst.h | 1 + IDEHelper/DbgModule.cpp | 491 +++++++++++++++++++++++------------ IDEHelper/DbgModule.h | 4 +- IDEHelper/WinDebugger.cpp | 4 +- 9 files changed, 662 insertions(+), 376 deletions(-) diff --git a/IDE/src/IDEUtils.bf b/IDE/src/IDEUtils.bf index 645c98b8..ee93d925 100644 --- a/IDE/src/IDEUtils.bf +++ b/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]); + } + } } } diff --git a/IDE/src/ui/CallStackPanel.bf b/IDE/src/ui/CallStackPanel.bf index bea2ffe6..30cea0c6 100644 --- a/IDE/src/ui/CallStackPanel.bf +++ b/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; diff --git a/IDE/src/ui/ClassViewPanel.bf b/IDE/src/ui/ClassViewPanel.bf index 9cafca3c..19abbec7 100644 --- a/IDE/src/ui/ClassViewPanel.bf +++ b/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 partialRefs = scope List(); + 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; + } } } diff --git a/IDE/src/ui/ThreadPanel.bf b/IDE/src/ui/ThreadPanel.bf index 0e1944f5..04cf1adc 100644 --- a/IDE/src/ui/ThreadPanel.bf +++ b/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); diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index f8d8caa5..df7457f2 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/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(); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index ec235658..4b4e15d0 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/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(); diff --git a/IDEHelper/DbgModule.cpp b/IDEHelper/DbgModule.cpp index 8c67c34c..efd516bc 100644 --- a/IDEHelper/DbgModule.cpp +++ b/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); } - - if (mTypeParam == NULL) - return "const"; - return "const " + mTypeParam->ToString(language); + return; } + + 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; + } - return mTypeParam->ToString(language) + "*"; - } + 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; + } + + 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; } - case DbgType_Unspecified: - return mTypeName; - case DbgType_SizedArray: - { - String name; - auto checkType = this; - while (checkType->mTypeCode == DbgType_SizedArray) - { - 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; + if (mTypeParam == NULL) + { + str += "&&"; + return; } - case DbgType_Union: + mTypeParam->ToString(str, language, allowDirectBfObject, internalName); + str += "&&"; + return; + } + case DbgType_Unspecified: + str += mTypeName; + return; + case DbgType_SizedArray: + { + StringT<128> name; + auto checkType = this; + while (checkType->mTypeCode == DbgType_SizedArray) { - if (mTypeName != NULL) - return String("union ") + mTypeName; - return "union"; - } - case DbgType_Single: - return "float"; - case DbgType_Double: - return "double"; - case DbgType_Null: - return "void"; - case DbgType_Subroutine: - { - String str; - str += mTypeParam->ToString(language); - str += " ("; - int paramIdx = 0; - for (auto param : mBlockParam->mVariables) + intptr innerSize = checkType->mTypeParam->GetStride(); + intptr arrSize = 0; + if (innerSize > 0) { - if (paramIdx > 0) - str += ", "; - str += param->mType->ToString(language); - paramIdx++; + arrSize = checkType->GetStride() / innerSize; } - str += ")"; - return str; + name += StrFormat("[%lld]", arrSize); + checkType = checkType->mTypeParam; } - case DbgType_VTable: - return "@vtable"; - case DbgType_Enum: - return "@enum"; - case DbgType_Namespace: - { - // Anonymous - return "`anon`"; - } - case DbgType_PtrToMember: - return "@ptrToMember"; - case DbgType_Bitfield: + checkType->ToString(str, language, allowDirectBfObject, internalName); + str += name; + return; + } + case DbgType_Union: + { + str += "union"; + if (mTypeParam != NULL) { - auto dbgBitfieldType = (DbgBitfieldType*)this; - return mTypeParam->ToString(language) + StrFormat("{%d:%d}", dbgBitfieldType->mPosition, dbgBitfieldType->mLength); + str += " "; + mTypeParam->ToString(str, language, allowDirectBfObject, internalName); } + return; + } + case DbgType_Single: + str += "float"; + return; + case DbgType_Double: + str += "double"; + return; + case DbgType_Null: + str += "void"; + return; + case DbgType_Subroutine: + { + mTypeParam->ToString(str, language, allowDirectBfObject, internalName); + str += " ("; + int paramIdx = 0; + for (auto param : mBlockParam->mVariables) + { + if (paramIdx > 0) + str += ", "; + param->mType->ToString(str, language, allowDirectBfObject, internalName); + paramIdx++; + } + str += ")"; + return; + } + case DbgType_VTable: + str += "@vtable"; + return; + case DbgType_Enum: + str += "@enum"; + return; + case DbgType_Namespace: + { + // Anonymous + str += "`anon`"; + return; + } + case DbgType_PtrToMember: + str += "@ptrToMember"; + return; + case DbgType_Bitfield: + { + 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) diff --git a/IDEHelper/DbgModule.h b/IDEHelper/DbgModule.h index db0f9781..ce403997 100644 --- a/IDEHelper/DbgModule.h +++ b/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(); diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index 76803fd2..700935a9 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/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;