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 m_parseState = ParseStateASSEMSPEC;
583 if (szAssemblySpec && *szAssemblySpec)
587 if (m_instNesting > 0)
589 EscapeEmbeddedAssemblyName(szAssemblySpec);
593 EscapeAssemblyName(szAssemblySpec);
596 m_bHasAssemblySpec = TRUE;
603 HRESULT TypeNameBuilder::ToString(BSTR* pszStringRepresentation)
607 if (!CheckParseState(ParseStateNAME | ParseStateGENARGS | ParseStatePTRARR | ParseStateBYREF | ParseStateASSEMSPEC))
613 *pszStringRepresentation = SysAllocString(m_pStr->GetUnicode());
618 HRESULT TypeNameBuilder::Clear()
622 THROWS; // TypeNameBuilder::Stack::Clear might throw.
632 m_bNestedName = FALSE;
634 m_bFirstInstArg = FALSE;
635 m_parseState = ParseStateSTART;
636 m_bHasAssemblySpec = FALSE;
637 m_bUseAngleBracketsForGenerics = FALSE;
645 // Append the name of the type td to the string
646 // The following flags in the FormatFlags argument are significant: FormatNamespace
647 void TypeString::AppendTypeDef(SString& ss, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
658 TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
659 AppendTypeDef(tnb, pImport, td, format);
666 void TypeString::AppendTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
673 PRECONDITION(CheckPointer(pImport));
674 PRECONDITION(TypeFromToken(td) == mdtTypeDef);
680 IfFailThrow(pImport->GetNameOfTypeDef(td, &szName, &szNameSpace));
682 const WCHAR *wszNameSpace = NULL;
684 InlineSString<128> ssName(SString::Utf8, szName);
685 InlineSString<128> ssNameSpace;
687 if (format & FormatNamespace)
689 ssNameSpace.SetUTF8(szNameSpace);
690 wszNameSpace = ssNameSpace.GetUnicode();
693 tnb.AddName(ssName.GetUnicode(), wszNameSpace);
698 void TypeString::AppendNestedTypeDef(TypeNameBuilder& tnb, IMDInternalImport *pImport, mdTypeDef td, DWORD format)
705 PRECONDITION(CheckPointer(pImport));
706 PRECONDITION(TypeFromToken(td) == mdtTypeDef);
711 IfFailThrow(pImport->GetTypeDefProps(td, &dwAttr, NULL));
713 StackSArray<mdTypeDef> arNames;
715 if (format & FormatNamespace && IsTdNested(dwAttr))
717 while (SUCCEEDED(pImport->GetNestedClassProps(td, &td)))
721 for(SCOUNT_T i = arNames.GetCount() - 1; i >= 0; i --)
722 AppendTypeDef(tnb, pImport, arNames[i], format);
727 // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s
728 // and enclose each parameter in square brackets to disambiguate the commas
729 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
730 void TypeString::AppendInst(SString& ss, Instantiation inst, DWORD format)
735 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
741 TypeNameBuilder tnb(&ss, TypeNameBuilder::ParseStateNAME);
742 if ((format & FormatAngleBrackets) != 0)
743 tnb.SetUseAngleBracketsForGenerics(TRUE);
744 AppendInst(tnb, inst, format);
750 void TypeString::AppendInst(TypeNameBuilder& tnb, Instantiation inst, DWORD format)
756 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
757 PRECONDITION(!inst.IsEmpty());
761 tnb.OpenGenericArguments();
763 for (DWORD i = 0; i < inst.GetNumArgs(); i++)
765 tnb.OpenGenericArgument();
767 TypeHandle thArg = inst[i];
769 if ((format & FormatFullInst) != 0 && !thArg.IsGenericVariable())
771 AppendType(tnb, thArg, Instantiation(), format | FormatNamespace | FormatAssembly);
775 AppendType(tnb, thArg, Instantiation(), format & (FormatNamespace | FormatAngleBrackets
782 tnb.CloseGenericArgument();
785 tnb.CloseGenericArguments();
790 void TypeString::AppendParamTypeQualifier(TypeNameBuilder& tnb, CorElementType kind, DWORD rank)
797 PRECONDITION(CorTypeInfo::IsModifier(kind));
803 case ELEMENT_TYPE_BYREF :
806 case ELEMENT_TYPE_PTR :
809 case ELEMENT_TYPE_SZARRAY :
812 case ELEMENT_TYPE_ARRAY :
820 // Append a representation of the type t to the string s
821 // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion
823 void TypeString::AppendType(SString& ss, TypeHandle ty, DWORD format)
828 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
833 AppendType(ss, ty, Instantiation(), format);
838 void TypeString::AppendType(SString& ss, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
843 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
849 TypeNameBuilder tnb(&ss);
850 if ((format & FormatAngleBrackets) != 0)
851 tnb.SetUseAngleBracketsForGenerics(TRUE);
852 AppendType(tnb, ty, typeInstantiation, format);
858 void TypeString::AppendType(TypeNameBuilder& tnb, TypeHandle ty, Instantiation typeInstantiation, DWORD format)
864 /* This method calls Assembly::GetDisplayName. Since that function
865 uses Fusion which takes some Crsts in some places, it is GC_TRIGGERS.
866 It could be made GC_NOTRIGGER by factoring out Assembly::GetDisplayName.
867 However, its better to leave stuff as GC_TRIGGERS unless really needed,
868 as GC_NOTRIGGER ties your hands up. */
869 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
874 BOOL bToString = (format & (FormatNamespace|FormatFullInst|FormatAssembly)) == FormatNamespace;
879 tnb.AddName(W("(null)"));
882 // It's not restored yet!
883 if (ty.IsEncodedFixup())
885 tnb.AddName(W("(fixup)"));
889 // It's an array, with format
890 // element_ty[] (1-d, SZARRAY)
891 // element_ty[*] (1-d, ARRAY)
892 // element_ty[,] (2-d, ARRAY) etc
893 // or a pointer (*) or byref (&)
894 if (ty.HasTypeParam() || (!ty.IsTypeDesc() && ty.AsMethodTable()->IsArray()))
896 if (ty.GetSignatureCorElementType() != ELEMENT_TYPE_VALUETYPE)
900 if (ty.HasTypeParam())
902 rank = ty.IsArray() ? ty.AsArray()->GetRank() : 0;
903 elemType = ty.GetTypeParam();
907 MethodTable *pMT = ty.GetMethodTable();
908 PREFIX_ASSUME(pMT != NULL);
909 rank = pMT->GetRank();
910 elemType = pMT->GetApproxArrayElementTypeHandle();
913 _ASSERTE(!elemType.IsNull());
914 AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
915 AppendParamTypeQualifier(tnb, ty.GetSignatureCorElementType(), rank);
919 tnb.Append(W("VALUETYPE"));
920 TypeHandle elemType = ty.GetTypeParam();
921 AppendType(tnb, elemType, Instantiation(), format & ~FormatAssembly);
925 // ...or type parameter
926 else if (ty.IsGenericVariable())
928 PTR_TypeVarTypeDesc tyvar = dac_cast<PTR_TypeVarTypeDesc>(ty.AsTypeDesc());
930 mdGenericParam token = tyvar->GetToken();
932 LPCSTR szName = NULL;
935 IfFailThrow(ty.GetModule()->GetMDImport()->GetGenericParamProps(token, NULL, NULL, &mdOwner, NULL, &szName));
937 _ASSERTE(TypeFromToken(mdOwner) == mdtTypeDef || TypeFromToken(mdOwner) == mdtMethodDef);
940 if (!(format & FormatGenericParam))
942 else if (TypeFromToken(mdOwner) == mdtTypeDef)
947 SmallStackSString pName(SString::Utf8, szPrefix);
948 pName.AppendUTF8(szName);
949 tnb.AddName(pName.GetUnicode());
951 format &= ~FormatAssembly;
954 // ...or function pointer
955 else if (ty.IsFnPtrType())
957 // Don't attempt to format this currently, it may trigger GC due to fixups.
958 tnb.AddName(W("(fnptr)"));
961 // ...otherwise it's just a plain type def or an instantiated type
964 // Get the TypeDef token and attributes
965 IMDInternalImport *pImport = ty.GetMethodTable()->GetMDImport();
966 mdTypeDef td = ty.GetCl();
967 if (IsNilToken(td)) {
968 // This type does not exist in metadata. Simply append "dynamicClass".
969 tnb.AddName(W("(dynamicClass)"));
974 if (format & FormatDebug)
976 WCHAR wzAddress[128];
977 _snwprintf_s(wzAddress, 128, _TRUNCATE, W("(%p)"), dac_cast<TADDR>(ty.AsPtr()));
978 tnb.AddName(wzAddress);
981 AppendNestedTypeDef(tnb, pImport, td, format);
984 // Append the instantiation
985 if ((format & (FormatNamespace|FormatAssembly)) && ty.HasInstantiation() && (!ty.IsGenericTypeDefinition() || bToString))
987 if (typeInstantiation.IsEmpty())
988 AppendInst(tnb, ty.GetInstantiation(), format);
990 AppendInst(tnb, typeInstantiation, format);
994 // Now append the assembly
995 if (format & FormatAssembly)
997 Assembly* pAssembly = ty.GetAssembly();
998 _ASSERTE(pAssembly != NULL);
1000 StackSString pAssemblyName;
1001 #ifdef DACCESS_COMPILE
1002 pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1004 pAssembly->GetDisplayName(pAssemblyName,
1005 ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1006 (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1009 tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1016 void TypeString::AppendMethod(SString& s, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1023 PRECONDITION(CheckPointer(pMD));
1024 PRECONDITION(pMD->IsRestored_NoLogging());
1025 PRECONDITION(s.Check());
1029 AppendMethodImpl(s, pMD, typeInstantiation, format);
1032 void TypeString::AppendMethodInternal(SString& s, MethodDesc *pMD, const DWORD format)
1040 PRECONDITION(CheckPointer(pMD));
1041 PRECONDITION(pMD->IsRestored_NoLogging());
1042 PRECONDITION(s.Check());
1046 AppendMethodImpl(s, pMD, Instantiation(), format);
1049 void TypeString::AppendMethodImpl(SString& ss, MethodDesc *pMD, Instantiation typeInstantiation, const DWORD format)
1057 PRECONDITION(CheckPointer(pMD));
1058 PRECONDITION(pMD->IsRestored_NoLogging());
1059 PRECONDITION(ss.Check());
1066 if (pMD->IsDynamicMethod())
1068 if (pMD->IsLCGMethod())
1070 SString sss(SString::Literal, "DynamicClass");
1073 else if (pMD->IsILStub())
1075 SString sss(SString::Literal, ILStubResolver::GetStubClassName(pMD));
1081 th = TypeHandle(pMD->GetMethodTable());
1082 AppendType(ss, th, typeInstantiation, format);
1085 SString sss1(SString::Literal, NAMESPACE_SEPARATOR_STR);
1087 SString sss2(SString::Utf8, pMD->GetName());
1090 if (pMD->HasMethodInstantiation() && !pMD->IsGenericMethodDefinition())
1092 AppendInst(ss, pMD->GetMethodInstantiation(), format);
1095 if (format & FormatSignature)
1097 // @TODO: The argument list should be formatted nicely using AppendType()
1099 SigFormat sigFormatter(pMD, th);
1100 const char* sigStr = sigFormatter.GetCStringParmsOnly();
1101 SString sss(SString::Utf8, sigStr);
1105 if (format & FormatStubInfo) {
1106 if (pMD->IsInstantiatingStub())
1108 SString sss(SString::Literal, "{inst-stub}");
1111 if (pMD->IsUnboxingStub())
1113 SString sss(SString::Literal, "{unbox-stub}");
1116 if (pMD->IsSharedByGenericMethodInstantiations())
1118 SString sss(SString::Literal, "{method-shared}");
1121 else if (pMD->IsSharedByGenericInstantiations())
1123 SString sss(SString::Literal, "{shared}");
1126 if (pMD->RequiresInstMethodTableArg())
1128 SString sss(SString::Literal, "{requires-mt-arg}");
1131 if (pMD->RequiresInstMethodDescArg())
1133 SString sss(SString::Literal, "{requires-mdesc-arg}");
1140 void TypeString::AppendField(SString& s, FieldDesc *pFD, Instantiation typeInstantiation, const DWORD format /* = FormatNamespace */)
1147 PRECONDITION(CheckPointer(pFD));
1148 PRECONDITION(s.Check());
1153 TypeHandle th(pFD->GetApproxEnclosingMethodTable());
1154 AppendType(s, th, typeInstantiation, format);
1156 s.AppendUTF8(NAMESPACE_SEPARATOR_STR);
1157 s.AppendUTF8(pFD->GetName());
1162 void TypeString::AppendMethodDebug(SString& ss, MethodDesc *pMD)
1169 PRECONDITION(CheckPointer(pMD));
1170 PRECONDITION(pMD->IsRestored_NoLogging());
1171 PRECONDITION(ss.Check());
1175 #ifndef DACCESS_COMPILE
1178 AppendMethodInternal(ss, pMD, FormatSignature | FormatNamespace);
1182 // This function is only used as diagnostic aid in debug builds.
1183 // If we run out of memory or hit some other problem,
1184 // tough luck for the debugger.
1186 // Should we set ss to Empty
1188 EX_END_CATCH(SwallowAllExceptions);
1192 void TypeString::AppendTypeDebug(SString& ss, TypeHandle t)
1199 PRECONDITION(CheckPointer(t));
1200 PRECONDITION(ss.Check());
1204 #ifndef DACCESS_COMPILE
1208 AppendType(ss, t, FormatNamespace | FormatDebug);
1212 // This function is only used as diagnostic aid in debug builds.
1213 // If we run out of memory or hit some other problem,
1214 // tough luck for the debugger.
1216 EX_END_CATCH(SwallowAllExceptions);
1221 void TypeString::AppendTypeKeyDebug(SString& ss, TypeKey *pTypeKey)
1228 PRECONDITION(CheckPointer(pTypeKey));
1229 PRECONDITION(ss.Check());
1233 #ifndef DACCESS_COMPILE
1237 AppendTypeKey(ss, pTypeKey, FormatNamespace | FormatDebug);
1241 // This function is only used as diagnostic aid in debug builds.
1242 // If we run out of memory or hit some other problem,
1243 // tough luck for the debugger.
1245 EX_END_CATCH(SwallowAllExceptions);
1253 void TypeString::AppendTypeKey(TypeNameBuilder& tnb, TypeKey *pTypeKey, DWORD format)
1259 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1260 PRECONDITION(CheckPointer(pTypeKey));
1264 Module *pModule = NULL;
1266 // It's an array, with format
1267 // element_ty[] (1-d, SZARRAY)
1268 // element_ty[*] (1-d, ARRAY)
1269 // element_ty[,] (2-d, ARRAY) etc
1270 // or a pointer (*) or byref (&)
1271 CorElementType kind = pTypeKey->GetKind();
1272 if (CorTypeInfo::IsModifier(kind))
1275 TypeHandle elemType = pTypeKey->GetElementType();
1276 if (CorTypeInfo::IsArray(kind))
1278 rank = pTypeKey->GetRank();
1281 AppendType(tnb, elemType, Instantiation(), format);
1282 AppendParamTypeQualifier(tnb, kind, rank);
1283 pModule = elemType.GetModule();
1285 else if (kind == ELEMENT_TYPE_VALUETYPE)
1287 tnb.Append(W("VALUETYPE"));
1288 TypeHandle elemType = pTypeKey->GetElementType();
1289 AppendType(tnb, elemType, Instantiation(), format);
1290 pModule = elemType.GetModule();
1292 else if (kind == ELEMENT_TYPE_FNPTR)
1297 // ...otherwise it's just a plain type def or an instantiated type
1300 // Get the TypeDef token and attributes
1301 pModule = pTypeKey->GetModule();
1302 if (pModule != NULL)
1304 IMDInternalImport *pImport = pModule->GetMDImport();
1305 mdTypeDef td = pTypeKey->GetTypeToken();
1306 _ASSERTE(!IsNilToken(td));
1308 AppendNestedTypeDef(tnb, pImport, td, format);
1310 // Append the instantiation
1311 if ((format & (FormatNamespace|FormatAssembly)) && pTypeKey->HasInstantiation())
1312 AppendInst(tnb, pTypeKey->GetInstantiation(), format);
1317 // Now append the assembly
1318 if (pModule != NULL && (format & FormatAssembly))
1320 Assembly* pAssembly = pModule->GetAssembly();
1321 _ASSERTE(pAssembly != NULL);
1323 StackSString pAssemblyName;
1324 #ifdef DACCESS_COMPILE
1325 pAssemblyName.SetUTF8(pAssembly->GetSimpleName());
1327 pAssembly->GetDisplayName(pAssemblyName,
1328 ASM_DISPLAYF_PUBLIC_KEY_TOKEN | ASM_DISPLAYF_CONTENT_TYPE |
1329 (format & FormatNoVersion ? 0 : ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE));
1331 tnb.AddAssemblySpec(pAssemblyName.GetUnicode());
1337 void TypeString::AppendTypeKey(SString& ss, TypeKey *pTypeKey, DWORD format)
1342 if (format & (FormatAssembly|FormatFullInst)) GC_TRIGGERS; else GC_NOTRIGGER;
1344 PRECONDITION(CheckPointer(pTypeKey));
1349 TypeNameBuilder tnb(&ss);
1350 AppendTypeKey(tnb, pTypeKey, format);
1357 void TypeString::EscapeSimpleTypeName(SString* ssTypeName, SString* ssEscapedTypeName)
1359 SString::Iterator itr = ssTypeName->Begin();
1361 while ((c = *itr++) != W('\0'))
1363 if (IsTypeNameReservedChar(c))
1364 ssEscapedTypeName->Append(W("\\"));
1366 ssEscapedTypeName->Append(c);
1371 bool TypeString::ContainsReservedChar(LPCWSTR pTypeName)
1381 while ((c = * pTypeName++) != W('\0'))
1383 if (IsTypeNameReservedChar(c))