1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // ---------------------------------------------------------------------------
6 // ---------------------------------------------------------------------------
10 // This module contains a helper function used to produce string
11 // representations of types, with options to control the appearance of
12 // namespace and assembly information. Its primary use is in
13 // reflection (Type.Name, Type.FullName, Type.ToString, etc) but over
14 // time it could replace the use of TypeHandle.GetName etc for
15 // diagnostic messages.
17 // See the header file for more details
18 // ---------------------------------------------------------------------------
23 #include "typehandle.h"
25 #include "sigformat.h"
26 #include "typeparse.h"
27 #include "typestring.h"
31 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
32 TypeNameBuilder * QCALLTYPE TypeNameBuilder::_CreateTypeNameBuilder()
36 TypeNameBuilder * retVal = NULL;
38 retVal = new TypeNameBuilder();
44 void QCALLTYPE TypeNameBuilder::_ReleaseTypeNameBuilder(TypeNameBuilder * pTnb)
53 void QCALLTYPE TypeNameBuilder::_ToString(TypeNameBuilder * pTnb, QCall::StringHandleOnStack retString)
58 retString.Set(*pTnb->GetString());
62 void QCALLTYPE TypeNameBuilder::_AddName(TypeNameBuilder * pTnb, LPCWSTR wszName)
67 pTnb->AddName(wszName);
71 void QCALLTYPE TypeNameBuilder::_AddAssemblySpec(TypeNameBuilder * pTnb, LPCWSTR wszAssemblySpec)
76 pTnb->AddAssemblySpec(wszAssemblySpec);
80 void QCALLTYPE TypeNameBuilder::_OpenGenericArguments(TypeNameBuilder * pTnb)
85 pTnb->OpenGenericArguments();
89 void QCALLTYPE TypeNameBuilder::_CloseGenericArguments(TypeNameBuilder * pTnb)
94 pTnb->CloseGenericArguments();
98 void QCALLTYPE TypeNameBuilder::_OpenGenericArgument(TypeNameBuilder * pTnb)
103 pTnb->OpenGenericArgument();
107 void QCALLTYPE TypeNameBuilder::_CloseGenericArgument(TypeNameBuilder * pTnb)
112 pTnb->CloseGenericArgument();
116 void QCALLTYPE TypeNameBuilder::_AddPointer(TypeNameBuilder * pTnb)
125 void QCALLTYPE TypeNameBuilder::_AddByRef(TypeNameBuilder * pTnb)
134 void QCALLTYPE TypeNameBuilder::_AddSzArray(TypeNameBuilder * pTnb)
143 void QCALLTYPE TypeNameBuilder::_AddArray(TypeNameBuilder * pTnb, DWORD dwRank)
148 pTnb->AddArray(dwRank);
152 void QCALLTYPE TypeNameBuilder::_Clear(TypeNameBuilder * pTnb)
166 TypeNameBuilder::TypeNameBuilder(SString* pStr, ParseState parseState /*= ParseStateSTART*/) :
178 m_parseState = parseState;
181 void TypeNameBuilder::PushOpenGenericArgument()
185 m_stack.Push(m_pStr->GetCount());
188 void TypeNameBuilder::PopOpenGenericArgument()
198 COUNT_T index = m_stack.Pop();
200 if (!m_bHasAssemblySpec)
201 m_pStr->Delete(m_pStr->Begin() + index - 1, 1);
203 m_bHasAssemblySpec = FALSE;
206 /* This method escapes szName and appends it to this TypeNameBuilder */
207 void TypeNameBuilder::EscapeName(LPCWSTR szName)
217 if (TypeString::ContainsReservedChar(szName))
221 WCHAR c = * szName ++;
223 if (IsTypeNameReservedChar(c))
235 void TypeNameBuilder::EscapeAssemblyName(LPCWSTR szName)
242 void TypeNameBuilder::EscapeEmbeddedAssemblyName(LPCWSTR szName)
252 LPCWSTR itr = szName;
253 bool bContainsReservedChar = false;
257 if (W(']') == *itr++)
259 bContainsReservedChar = true;
264 if (bContainsReservedChar)
282 HRESULT TypeNameBuilder::OpenGenericArgument()
292 if (!CheckParseState(ParseStateSTART))
295 if (m_instNesting == 0)
300 m_parseState = ParseStateSTART;
301 m_bNestedName = FALSE;
303 if (!m_bFirstInstArg)
306 m_bFirstInstArg = FALSE;
308 if (m_bUseAngleBracketsForGenerics)
312 PushOpenGenericArgument();
317 HRESULT TypeNameBuilder::AddName(LPCWSTR szName)
330 if (!CheckParseState(ParseStateSTART | ParseStateNAME))
335 m_parseState = ParseStateNAME;
340 m_bNestedName = TRUE;
347 HRESULT TypeNameBuilder::AddName(LPCWSTR szName, LPCWSTR szNamespace)
360 if (!CheckParseState(ParseStateSTART | ParseStateNAME))
365 m_parseState = ParseStateNAME;
370 m_bNestedName = TRUE;
372 if (szNamespace && *szNamespace)
374 EscapeName(szNamespace);
383 HRESULT TypeNameBuilder::OpenGenericArguments()
387 if (!CheckParseState(ParseStateNAME))
392 m_parseState = ParseStateSTART;
394 m_bFirstInstArg = TRUE;
396 if (m_bUseAngleBracketsForGenerics)
404 HRESULT TypeNameBuilder::CloseGenericArguments()
416 if (!CheckParseState(ParseStateSTART))
421 m_parseState = ParseStateGENARGS;
427 m_pStr->Truncate(m_pStr->End() - 1);
431 if (m_bUseAngleBracketsForGenerics)
440 HRESULT TypeNameBuilder::AddPointer()
444 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
447 m_parseState = ParseStatePTRARR;
454 HRESULT TypeNameBuilder::AddByRef()
458 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
461 m_parseState = ParseStateBYREF;
468 HRESULT TypeNameBuilder::AddSzArray()
472 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
475 m_parseState = ParseStatePTRARR;
482 HRESULT TypeNameBuilder::AddArray(DWORD rank)
492 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR))
495 m_parseState = ParseStatePTRARR;
504 // Only taken in an error path, runtime will not load arrays of more than 32 dimentions
506 _snwprintf_s(wzDim, 128, _TRUNCATE, W("[%d]"), rank);
511 WCHAR* wzDim = new (nothrow) WCHAR[rank+3];
513 if(wzDim == NULL) // allocation failed, do it the long way (each Append -> memory realloc)
516 for(COUNT_T i = 1; i < rank; i ++)
520 else // allocation OK, do it the fast way
522 WCHAR* pwz = wzDim+1;
524 for(COUNT_T i = 1; i < rank; i++, pwz++) *pwz=',';
535 HRESULT TypeNameBuilder::CloseGenericArgument()
545 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
548 if (m_instNesting == 0)
551 m_parseState = ParseStateSTART;
553 if (m_bHasAssemblySpec)
555 if (m_bUseAngleBracketsForGenerics)
561 PopOpenGenericArgument();
566 HRESULT TypeNameBuilder::AddAssemblySpec(LPCWSTR szAssemblySpec)
576 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF))
581 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
583 m_parseState = ParseStateASSEMSPEC;
585 if (szAssemblySpec && *szAssemblySpec)
589 if (m_instNesting > 0)
591 EscapeEmbeddedAssemblyName(szAssemblySpec);
595 EscapeAssemblyName(szAssemblySpec);
598 m_bHasAssemblySpec = TRUE;
602 END_SO_INTOLERANT_CODE;
607 HRESULT TypeNameBuilder::ToString(BSTR* pszStringRepresentation)
611 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
617 *pszStringRepresentation = SysAllocString(m_pStr->GetUnicode());
622 HRESULT TypeNameBuilder::Clear()
626 THROWS; // TypeNameBuilder::Stack::Clear might throw.
632 CONTRACT_VIOLATION(SOToleranceViolation);
638 m_bNestedName = FALSE;
640 m_bFirstInstArg = FALSE;
641 m_parseState = ParseStateSTART;
642 m_bHasAssemblySpec = FALSE;
643 m_bUseAngleBracketsForGenerics = FALSE;
651 // Append the name of the type td to the string
652 // The following flags in the FormatFlags argument are significant: FormatNamespace
653 void TypeString::AppendTypeDef(SString& ss, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
663 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
665 TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
666 AppendTypeDef(tnb, pImport, td, format);
668 END_SO_INTOLERANT_CODE;
674 void TypeString::AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
681 PRECONDITION(CheckPointer(pImport));
682 PRECONDITION(TypeFromToken(td) == mdtTypeDef);
688 IfFailThrow(pImport->GetNameOfTypeDef(td, &szName, &szNameSpace));
690 const WCHAR *wszNameSpace = NULL;
692 InlineSString<128> ssName(SString::Utf8, szName);
693 InlineSString<128> ssNameSpace;
695 if (format & FormatNamespace)
697 ssNameSpace.SetUTF8(szNameSpace);
698 wszNameSpace = ssNameSpace.GetUnicode();
701 tnb.AddName(ssName.GetUnicode(), wszNameSpace);
706 void TypeString::AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
713 PRECONDITION(CheckPointer(pImport));
714 PRECONDITION(TypeFromToken(td) == mdtTypeDef);
719 IfFailThrow(pImport->GetTypeDefProps(td, &dwAttr, NULL));
721 StackSArray<mdTypeDef> arNames;
723 if (format & FormatNamespace && IsTdNested(dwAttr))
725 while (SUCCEEDED(pImport->GetNestedClassProps(td, &td)))
729 for(SCOUNT_T i = arNames.GetCount() - 1; i >= 0; i --)
730 AppendTypeDef(tnb, pImport, arNames[i], format);
735 // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
736 // and enclose each parameter in square brackets to disambiguate the commas
737 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
738 void TypeString::AppendInst(SString& ss, Instantiation inst, DWORD format)
743 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
748 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
750 TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
751 if ((format & FormatAngleBrackets) != 0)
752 tnb.SetUseAngleBracketsForGenerics(TRUE);
753 AppendInst(tnb, inst, format);
755 END_SO_INTOLERANT_CODE;
760 void TypeString::AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format)
766 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
767 PRECONDITION(!inst.IsEmpty());
771 tnb.OpenGenericArguments();
773 for (DWORD i = 0; i < inst.GetNumArgs(); i++)
775 tnb.OpenGenericArgument();
777 TypeHandle thArg = inst[i];
779 if ((format & FormatFullInst) != 0 && !thArg.IsGenericVariable())
781 AppendType(tnb, thArg, Instantiation(), format | FormatNamespace | FormatAssembly);
785 AppendType(tnb, thArg, Instantiation(), format & (FormatNamespace | FormatAngleBrackets
792 tnb.CloseGenericArgument();
795 tnb.CloseGenericArguments();
800 void TypeString::AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank)
807 PRECONDITION(CorTypeInfo::IsModifier(kind));
813 case ELEMENT_TYPE_BYREF :
816 case ELEMENT_TYPE_PTR :
819 case ELEMENT_TYPE_SZARRAY :
822 case ELEMENT_TYPE_ARRAY :
830 // Append a representation of the type t to the string s
831 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
833 void TypeString::AppendType(SString& ss, TypeHandle ty, DWORD format)
838 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
843 AppendType(ss, ty, Instantiation(), format);
848 void TypeString::AppendType(SString& ss, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
853 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
858 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
860 TypeNameBuilder tnb(&ss);
861 if ((format & FormatAngleBrackets) != 0)
862 tnb.SetUseAngleBracketsForGenerics(TRUE);
863 AppendType(tnb, ty, typeInstantiation, format);
865 END_SO_INTOLERANT_CODE;
870 void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
876 /* This method calls Assembly::GetDisplayName. Since that function
877 uses Fusion which takes some Crsts in some places, it is GC_TRIGGERS.
878 It could be made GC_NOTRIGGER by factoring out Assembly::GetDisplayName.
879 However, its better to leave stuff as GC_TRIGGERS unless really needed,
880 as GC_NOTRIGGER ties your hands up. */
881 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
886 INTERIOR_STACK_PROBE_FOR_CHECK_THREAD(10);
888 BOOL bToString = (format & (FormatNamespace|FormatFullInst|FormatAssembly)) == FormatNamespace;
893 tnb.AddName(W("(null)"));
896 // It's not restored yet!
897 if (ty.IsEncodedFixup())
899 tnb.AddName(W("(fixup)"));
903 // It's an array, with format
904 // element_ty[] (1-d, SZARRAY)
905 // element_ty[*] (1-d, ARRAY)
906 // element_ty[,] (2-d, ARRAY) etc
907 // or a pointer (*) or byref (&)
908 if (ty.HasTypeParam() || (!ty.IsTypeDesc() && ty.AsMethodTable()->IsArray()))
910 if (ty.GetSignatureCorElementType() != ELEMENT_TYPE_VALUETYPE)
914 if (ty.HasTypeParam())
916 rank = ty.IsArray() ? ty.AsArray()->GetRank() : 0;
917 elemType = ty.GetTypeParam();
921 MethodTable *pMT = ty.GetMethodTable();
922 PREFIX_ASSUME(pMT != NULL);
923 rank = pMT->GetRank();
924 elemType = pMT->GetApproxArrayElementTypeHandle();
927 _ASSERTE(!elemType.IsNull());
928 AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
929 AppendParamTypeQualifier(tnb, ty.GetSignatureCorElementType(), rank);
933 tnb.Append(W("VALUETYPE"));
934 TypeHandle elemType = ty.GetTypeParam();
935 AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
939 // ...or type parameter
940 else if (ty.IsGenericVariable())
942 PTR_TypeVarTypeDesc tyvar = dac_cast<PTR_TypeVarTypeDesc>(ty.AsTypeDesc());
944 mdGenericParam token = tyvar->GetToken();
946 LPCSTR szName = NULL;
949 IfFailThrow(ty.GetModule()->GetMDImport()->GetGenericParamProps(token, NULL, NULL, &mdOwner, NULL, &szName));
951 _ASSERTE(TypeFromToken(mdOwner) == mdtTypeDef || TypeFromToken(mdOwner) == mdtMethodDef);
954 if (!(format & FormatGenericParam))
956 else if (TypeFromToken(mdOwner) == mdtTypeDef)
961 SmallStackSString pName(SString::Utf8, szPrefix);
962 pName.AppendUTF8(szName);
963 tnb.AddName(pName.GetUnicode());
965 format &= ~FormatAssembly;
968 // ...or function pointer
969 else if (ty.IsFnPtrType())
971 // Don't attempt to format this currently, it may trigger GC due to fixups.
972 tnb.AddName(W("(fnptr)"));
975 // ...otherwise it's just a plain type def or an instantiated type
978 // Get the TypeDef token and attributes
979 IMDInternalImport *pImport = ty.GetMethodTable()->GetMDImport();
980 mdTypeDef td = ty.GetCl();
981 if (IsNilToken(td)) {
982 // This type does not exist in metadata. Simply append "dynamicClass".
983 tnb.AddName(W("(dynamicClass)"));
988 if (format & FormatDebug)
990 WCHAR wzAddress[128];
991 _snwprintf_s(wzAddress, 128, _TRUNCATE, W("(%p)"), dac_cast<TADDR>(ty.AsPtr()));
992 tnb.AddName(wzAddress);
995 AppendNestedTypeDef(tnb, pImport, td, format);
998 // Append the instantiation
999 if ((format & (FormatNamespace|FormatAssembly)) && ty.HasInstantiation() && (!ty.IsGenericTypeDefinition() || bToString))
1001 if (typeInstantiation.IsEmpty())
1002 AppendInst(tnb, ty.GetInstantiation(), format);
1004 AppendInst(tnb, typeInstantiation, format);
1008 // Now append the assembly
1009 if (format & FormatAssembly)
1011 Assembly* pAssembly = ty.GetAssembly();
1012 _ASSERTE(pAssembly != NULL);
1014 StackSString pAssemblyName;
1015 #ifdef DACCESS_COMPILE
1016 pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1018 pAssembly->GetDisplayName(pAssemblyName,
1019 ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1020 (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1023 tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1027 END_INTERIOR_STACK_PROBE;
1033 void TypeString::AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1040 PRECONDITION(CheckPointer(pMD));
1041 PRECONDITION(pMD->IsRestored_NoLogging());
1042 PRECONDITION(s.Check());
1046 AppendMethodImpl(s, pMD, typeInstantiation, format);
1049 void TypeString::AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format)
1057 PRECONDITION(CheckPointer(pMD));
1058 PRECONDITION(pMD->IsRestored_NoLogging());
1059 PRECONDITION(s.Check());
1063 AppendMethodImpl(s, pMD, Instantiation(), format);
1066 void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1074 PRECONDITION(CheckPointer(pMD));
1075 PRECONDITION(pMD->IsRestored_NoLogging());
1076 PRECONDITION(ss.Check());
1080 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
1084 if (pMD->IsDynamicMethod())
1086 if (pMD->IsLCGMethod())
1088 SString sss(SString::Literal, "DynamicClass");
1091 else if (pMD->IsILStub())
1093 SString sss(SString::Literal, ILStubResolver::GetStubClassName(pMD));
1099 th = TypeHandle(pMD->GetMethodTable());
1100 AppendType(ss, th, typeInstantiation, format);
1103 SString sss1(SString::Literal, NAMESPACE_SEPARATOR_STR);
1105 SString sss2(SString::Utf8, pMD->GetName());
1108 if (pMD->HasMethodInstantiation() && !pMD->IsGenericMethodDefinition())
1110 AppendInst(ss, pMD->GetMethodInstantiation(), format);
1113 if (format & FormatSignature)
1115 // @TODO: The argument list should be formatted nicely using AppendType()
1117 SigFormat sigFormatter(pMD, th);
1118 const char* sigStr = sigFormatter.GetCStringParmsOnly();
1119 SString sss(SString::Utf8, sigStr);
1123 if (format & FormatStubInfo) {
1124 if (pMD->IsInstantiatingStub())
1126 SString sss(SString::Literal, "{inst-stub}");
1129 if (pMD->IsUnboxingStub())
1131 SString sss(SString::Literal, "{unbox-stub}");
1134 if (pMD->IsSharedByGenericMethodInstantiations())
1136 SString sss(SString::Literal, "{method-shared}");
1139 else if (pMD->IsSharedByGenericInstantiations())
1141 SString sss(SString::Literal, "{shared}");
1144 if (pMD->RequiresInstMethodTableArg())
1146 SString sss(SString::Literal, "{requires-mt-arg}");
1149 if (pMD->RequiresInstMethodDescArg())
1151 SString sss(SString::Literal, "{requires-mdesc-arg}");
1156 END_SO_INTOLERANT_CODE;
1159 void TypeString::AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format /* = FormatNamespace */)
1166 PRECONDITION(CheckPointer(pFD));
1167 PRECONDITION(s.Check());
1171 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
1173 TypeHandle th(pFD->GetApproxEnclosingMethodTable());
1174 AppendType(s, th, typeInstantiation, format);
1176 s.AppendUTF8(NAMESPACE_SEPARATOR_STR);
1177 s.AppendUTF8(pFD->GetName());
1179 END_SO_INTOLERANT_CODE;
1183 void TypeString::AppendMethodDebug(SString& ss, MethodDesc *pMD)
1190 PRECONDITION(CheckPointer(pMD));
1191 PRECONDITION(pMD->IsRestored_NoLogging());
1192 PRECONDITION(ss.Check());
1196 #ifndef DACCESS_COMPILE
1199 AppendMethodInternal(ss, pMD, FormatSignature | FormatNamespace);
1203 // This function is only used as diagnostic aid in debug builds.
1204 // If we run out of memory or hit some other problem,
1205 // tough luck for the debugger.
1207 // Should we set ss to Empty
1209 EX_END_CATCH(SwallowAllExceptions);
1213 void TypeString::AppendTypeDebug(SString& ss, TypeHandle t)
1220 PRECONDITION(CheckPointer(t));
1221 PRECONDITION(ss.Check());
1226 #ifndef DACCESS_COMPILE
1230 AppendType(ss, t, FormatNamespace | FormatDebug);
1234 // This function is only used as diagnostic aid in debug builds.
1235 // If we run out of memory or hit some other problem,
1236 // tough luck for the debugger.
1238 EX_END_CATCH(SwallowAllExceptions);
1243 void TypeString::AppendTypeKeyDebug(SString& ss, TypeKey *pTypeKey)
1250 PRECONDITION(CheckPointer(pTypeKey));
1251 PRECONDITION(ss.Check());
1256 #ifndef DACCESS_COMPILE
1260 AppendTypeKey(ss, pTypeKey, FormatNamespace | FormatDebug);
1264 // This function is only used as diagnostic aid in debug builds.
1265 // If we run out of memory or hit some other problem,
1266 // tough luck for the debugger.
1268 EX_END_CATCH(SwallowAllExceptions);
1276 void TypeString::AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format)
1282 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1283 PRECONDITION(CheckPointer(pTypeKey));
1288 Module *pModule = NULL;
1290 // It's an array, with format
1291 // element_ty[] (1-d, SZARRAY)
1292 // element_ty[*] (1-d, ARRAY)
1293 // element_ty[,] (2-d, ARRAY) etc
1294 // or a pointer (*) or byref (&)
1295 CorElementType kind = pTypeKey->GetKind();
1296 if (CorTypeInfo::IsModifier(kind))
1299 TypeHandle elemType = pTypeKey->GetElementType();
1300 if (CorTypeInfo::IsArray(kind))
1302 rank = pTypeKey->GetRank();
1305 AppendType(tnb, elemType, Instantiation(), format);
1306 AppendParamTypeQualifier(tnb, kind, rank);
1307 pModule = elemType.GetModule();
1309 else if (kind == ELEMENT_TYPE_VALUETYPE)
1311 tnb.Append(W("VALUETYPE"));
1312 TypeHandle elemType = pTypeKey->GetElementType();
1313 AppendType(tnb, elemType, Instantiation(), format);
1314 pModule = elemType.GetModule();
1316 else if (kind == ELEMENT_TYPE_FNPTR)
1321 // ...otherwise it's just a plain type def or an instantiated type
1324 // Get the TypeDef token and attributes
1325 pModule = pTypeKey->GetModule();
1326 if (pModule != NULL)
1328 IMDInternalImport *pImport = pModule->GetMDImport();
1329 mdTypeDef td = pTypeKey->GetTypeToken();
1330 _ASSERTE(!IsNilToken(td));
1332 AppendNestedTypeDef(tnb, pImport, td, format);
1334 // Append the instantiation
1335 if ((format & (FormatNamespace|FormatAssembly)) && pTypeKey->HasInstantiation())
1336 AppendInst(tnb, pTypeKey->GetInstantiation(), format);
1341 // Now append the assembly
1342 if (pModule != NULL && (format & FormatAssembly))
1344 Assembly* pAssembly = pModule->GetAssembly();
1345 _ASSERTE(pAssembly != NULL);
1347 StackSString pAssemblyName;
1348 #ifdef DACCESS_COMPILE
1349 pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1351 pAssembly->GetDisplayName(pAssemblyName,
1352 ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1353 (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1355 tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1361 void TypeString::AppendTypeKey(SString& ss, TypeKey *pTypeKey, DWORD format)
1366 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1368 PRECONDITION(CheckPointer(pTypeKey));
1372 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
1374 TypeNameBuilder tnb(&ss);
1375 AppendTypeKey(tnb, pTypeKey, format);
1377 END_SO_INTOLERANT_CODE;
1383 void TypeString::EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName)
1385 SString::Iterator itr = ssTypeName->Begin();
1387 while ((c = *itr++) != W('\0'))
1389 if (IsTypeNameReservedChar(c))
1390 ssEscapedTypeName->Append(W("\\"));
1392 ssEscapedTypeName->Append(c);
1397 bool TypeString::ContainsReservedChar(LPCWSTR pTypeName)
1407 while ((c = * pTypeName++) != W('\0'))
1409 if (IsTypeNameReservedChar(c))
1418 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::QueryInterface(REFIID riid, void **ppUnk)
1431 if (riid == IID_IUnknown)
1432 *ppUnk = (IUnknown *)this;
1433 else if (riid == IID_ITypeNameBuilder)
1434 *ppUnk = (ITypeNameBuilder*)this;
1436 return (E_NOINTERFACE);
1442 ULONG STDMETHODCALLTYPE TypeNameBuilderWrapper::AddRef()
1453 return InterlockedIncrement(&m_ref);
1456 ULONG STDMETHODCALLTYPE TypeNameBuilderWrapper::Release()
1464 SUPPORTS_DAC_HOST_ONLY;
1470 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1472 ref = InterlockedDecrement(&m_ref);
1476 END_SO_INTOLERANT_CODE;
1482 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::OpenGenericArguments()
1493 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1494 hr = m_tnb.OpenGenericArguments();
1495 END_SO_INTOLERANT_CODE;
1499 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::CloseGenericArguments()
1510 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1511 hr = m_tnb.CloseGenericArguments();
1512 END_SO_INTOLERANT_CODE;
1516 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::OpenGenericArgument()
1527 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1528 hr = m_tnb.OpenGenericArgument();
1529 END_SO_INTOLERANT_CODE;
1533 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::CloseGenericArgument()
1544 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1545 hr = m_tnb.CloseGenericArgument();
1546 END_SO_INTOLERANT_CODE;
1550 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddName(LPCWSTR szName)
1561 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1562 hr = m_tnb.AddName(szName);
1563 END_SO_INTOLERANT_CODE;
1567 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddPointer()
1578 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1579 hr = m_tnb.AddPointer();
1580 END_SO_INTOLERANT_CODE;
1584 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddByRef()
1595 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1596 hr = m_tnb.AddByRef();
1597 END_SO_INTOLERANT_CODE;
1601 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddSzArray()
1612 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1613 hr = m_tnb.AddSzArray();
1614 END_SO_INTOLERANT_CODE;
1618 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddArray(DWORD rank)
1629 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1630 hr = m_tnb.AddArray(rank);
1631 END_SO_INTOLERANT_CODE;
1635 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::AddAssemblySpec(LPCWSTR szAssemblySpec)
1646 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1647 hr = m_tnb.AddAssemblySpec(szAssemblySpec);
1648 END_SO_INTOLERANT_CODE;
1652 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::ToString(BSTR* pszStringRepresentation)
1654 WRAPPER_NO_CONTRACT;
1657 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1658 hr = m_tnb.ToString(pszStringRepresentation);
1659 END_SO_INTOLERANT_CODE;
1663 HRESULT STDMETHODCALLTYPE TypeNameBuilderWrapper::Clear()
1674 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
1676 END_SO_INTOLERANT_CODE;