private static String ToTypeStringWorker(this IDiaSymbol parameterType, IDiaSession session, int recursionLevel, out bool isValueTypeOrByRef) { int hr; isValueTypeOrByRef = false; // Block runaway recursions. if (recursionLevel++ > 10) return "?"; SymTagEnum symTag; hr = parameterType.GetSymTag(out symTag); if (hr != S_OK) return "?"; if (symTag == SymTagEnum.SymTagPointerType) { bool isReference; hr = parameterType.GetReference(out isReference); if (hr != S_OK) return "?"; if (isReference) { // An isReference pointer can mean one of two things: // 1. ELEMENT_TYPE_BYREF // 2. An indication that the UDT that follows is actually a class, not a struct. // isValueTypeOrByRef = true; IDiaSymbol targetType; hr = parameterType.GetType(out targetType); if (hr != S_OK) return "?"; bool targetIsValueTypeOrByRef; String targetTypeString = targetType.ToTypeStringWorker(session, recursionLevel, out targetIsValueTypeOrByRef); if (targetIsValueTypeOrByRef) return targetTypeString + "&"; else return targetTypeString; } else { // A non-isReference pointer means an ELEMENT_TYPE_PTR IDiaSymbol targetType; hr = parameterType.GetType(out targetType); if (hr != S_OK) return "?"; bool ignore; return targetType.ToTypeStringWorker(session, recursionLevel, out ignore) + "*"; } } else if (symTag == SymTagEnum.SymTagArrayType) { // Note: We don't actually hit this case in NUTC-generated PDB's as NUTC emits arrays as if they were UDT's with square brackets in the name. // But just in case NUTC ever changes its PDB emission, we'll print out the most obvious interpretation and hope we're right. IDiaSymbol elementType; hr = parameterType.GetType(out elementType); if (hr != S_OK) return "?"; bool ignore; return elementType.ToTypeStringWorker(session, recursionLevel, out ignore) + "[]"; } else if (symTag == SymTagEnum.SymTagUDT || symTag == SymTagEnum.SymTagEnum) { // Need to figure out whether this is a value type as our recursive caller needs to know whether the "byref pointer" that wrapped this // is a true managed byref or just the "byref pointer" that wraps all non-valuetypes. if (symTag == SymTagEnum.SymTagEnum) { isValueTypeOrByRef = true; } else { IDiaEnumSymbols baseClasses; hr = session.FindChildren(parameterType, SymTagEnum.SymTagBaseClass, null, 0, out baseClasses); if (hr != S_OK) return "?"; int count; hr = baseClasses.Count(out count); if (hr != S_OK) return "?"; for (int i = 0; i < count; i++) { IDiaSymbol baseClass; if (S_OK == baseClasses.Item(i, out baseClass)) { String baseClassName; if (S_OK == baseClass.GetName(out baseClassName)) { if (baseClassName == "System::ValueType") isValueTypeOrByRef = true; } } } } String name; hr = parameterType.GetName(out name); if (hr != S_OK) return "?"; return name.RemoveNamespaces().Demanglify(); } else if (symTag == SymTagEnum.SymTagBaseType) { // Certain "primitive" types are encoded specially. BasicType basicType; hr = parameterType.GetBaseType(out basicType); if (hr != S_OK) return "?"; long length; hr = parameterType.GetLength(out length); if (hr != S_OK) return "?"; return ConvertBasicTypeToTypeString(basicType, length, out isValueTypeOrByRef); } else { return "?"; } }
// // Create the method parameter list. // private static String CreateParameterListString(IDiaSession session, IDiaSymbol symbol) { StringBuilder sb = new StringBuilder("("); // find the parameters IDiaEnumSymbols dataSymbols; int hr = session.FindChildren(symbol, SymTagEnum.SymTagData, null, NameSearchOptions.nsNone, out dataSymbols); if (hr == S_OK) { int count; hr = dataSymbols.Count(out count); if (hr == S_OK) { for (int i = 0, iParam = 0; i < count; i++) { IDiaSymbol dataSym; hr = dataSymbols.Item(i, out dataSym); if (hr != S_OK) continue; DataKind dataKind; hr = dataSym.GetDataKind(out dataKind); if (hr != S_OK || dataKind != DataKind.DataIsParam) continue; string paramName; hr = dataSym.GetName(out paramName); if (hr != S_OK) { continue; } //this approximates the way C# displays methods by not including these hidden arguments if (paramName == "InstParam" || paramName == "this") { continue; } IDiaSymbol parameterType; hr = dataSym.GetType(out parameterType); if (hr != S_OK) { continue; } if (iParam++ != 0) sb.Append(", "); sb.Append(parameterType.ToTypeString(session)); sb.Append(' '); sb.Append(paramName); } } } sb.Append(')'); return sb.ToString(); }