/// <summary> /// Returns a C# string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { ValidateOptions(options); if (value == null) { throw new ArgumentNullException("value"); } var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var quote = useQuotes ? '"' : '\0'; PooledStringBuilder pooledBuilder = null; StringBuilder builder = null; if (useQuotes) { pooledBuilder = PooledStringBuilder.GetInstance(); builder = pooledBuilder.Builder; builder.Append(quote); } for (int i = 0; i < value.Length; i++) { FormatStringChar(ref pooledBuilder, value, i, value[i], quote, useLanguageSpecificEscapes: true, useUnicodeEscapes: true); } if (useQuotes) { builder.Append(quote); } return((pooledBuilder == null) ? value : pooledBuilder.ToStringAndFree()); }
private string FormatPrimitive( DkmClrValue value, ObjectDisplayOptions options, DkmInspectionContext inspectionContext ) { Debug.Assert(value != null); // check if HostObjectValue is null, since any of these types might actually be a synthetic value as well. if (value.HostObjectValue == null) { return(_hostValueNotFoundString); } // DateTime is primitive in VB but not in C#. object obj; if (value.Type.GetLmrType().IsDateTime()) { var dateDataValue = value.GetPropertyValue("Ticks", inspectionContext); obj = new DateTime((long)dateDataValue.HostObjectValue); } else { obj = value.HostObjectValue; } return(FormatPrimitiveObject(obj, options)); }
internal override string GetNamesForFlagsEnumValue( ArrayBuilder <EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt ) { var usedFields = ArrayBuilder <EnumField> .GetInstance(); FillUsedEnumFields(usedFields, fields, underlyingValue); if (usedFields.Count == 0) { return(null); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; for (int i = usedFields.Count - 1; i >= 0; i--) // Backwards to list smallest first. { AppendEnumTypeAndName(builder, typeToDisplayOpt, usedFields[i].Name); if (i > 0) { builder.Append(" | "); } } usedFields.Free(); return(pooled.ToStringAndFree()); }
/// <summary> /// Returns a C# string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { ValidateOptions(options); if (value == null) { throw new ArgumentNullException(nameof(value)); } var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var quote = useQuotes ? '"' : '\0'; if (!useQuotes && !ReplaceAny(value, quote)) { return(value); } var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; if (useQuotes) { builder.Append(quote); } foreach (var c in value) { FormatStringChar(builder, c, quote); } if (useQuotes) { builder.Append(quote); } return(pooledBuilder.ToStringAndFree()); }
#pragma warning disable CA1200 // Avoid using cref tags with a prefix /// <remarks> /// The corresponding native code is in EEUserStringBuilder::ErrTryAppendConstantEnum. /// The corresponding roslyn code is in /// <see cref="M:Microsoft.CodeAnalysis.SymbolDisplay.AbstractSymbolDisplayVisitor`1.AddEnumConstantValue(Microsoft.CodeAnalysis.INamedTypeSymbol, System.Object, System.Boolean)"/>. /// NOTE: no curlies for enum values. /// </remarks> #pragma warning restore CA1200 // Avoid using cref tags with a prefix private string GetEnumDisplayString(Type lmrType, DkmClrValue value, ObjectDisplayOptions options, bool includeTypeName, DkmInspectionContext inspectionContext) { Debug.Assert(lmrType.IsEnum); Debug.Assert(value != null); object underlyingValue = value.HostObjectValue; // check if HostObjectValue is null, since any of these types might actually be a synthetic value as well. if (underlyingValue == null) { return(_hostValueNotFoundString); } string displayString; var fields = ArrayBuilder <EnumField> .GetInstance(); FillEnumFields(fields, lmrType); // We will normalize/extend all enum values to ulong to ensure that we are always comparing the full underlying value. ulong valueForComparison = ConvertEnumUnderlyingTypeToUInt64(underlyingValue, Type.GetTypeCode(lmrType)); var typeToDisplayOpt = includeTypeName ? lmrType : null; if (valueForComparison != 0 && IsFlagsEnum(lmrType)) { displayString = GetNamesForFlagsEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } else { displayString = GetNameForEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } fields.Free(); return(displayString ?? FormatPrimitive(value, options, inspectionContext)); }
internal abstract string GetNameForEnumValue( ArrayBuilder <EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt );
/// <summary> /// Returns a string representation of an object of primitive type. /// </summary> /// <param name="obj">A value to display as a string.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string representation of an object of primitive type (or null if the type is not supported).</returns> /// <remarks> /// Handles <see cref="bool"/>, <see cref="string"/>, <see cref="double"/> and <c>null</c>. /// </remarks> public static string?FormatPrimitive(object?obj, ObjectDisplayOptions options) { if (obj is null) { return(NullLiteral); } var type = obj.GetType(); if (type.IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(string)) { return(FormatLiteral((string)obj, options)); } if (type == typeof(bool)) { return(FormatLiteral((bool)obj)); } if (type == typeof(double)) { return(FormatLiteral((double)obj, options)); } return(null); }
internal static bool IncludesOption( this ObjectDisplayOptions options, ObjectDisplayOptions flag ) { return((options & flag) == flag); }
#pragma warning disable RS0010 /// <remarks> /// The corresponding native code is in EEUserStringBuilder::ErrTryAppendConstantEnum. /// The corresponding roslyn code is in /// <see cref="M:Microsoft.CodeAnalysis.SymbolDisplay.AbstractSymbolDisplayVisitor`1.AddEnumConstantValue(Microsoft.CodeAnalysis.INamedTypeSymbol, System.Object, System.Boolean)"/>. /// NOTE: no curlies for enum values. /// </remarks> #pragma warning restore RS0010 private string GetEnumDisplayString(Type lmrType, DkmClrValue value, ObjectDisplayOptions options, bool includeTypeName) { Debug.Assert(lmrType.IsEnum); Debug.Assert(value != null); object underlyingValue = value.HostObjectValue; Debug.Assert(underlyingValue != null); string displayString; ArrayBuilder <EnumField> fields = ArrayBuilder <EnumField> .GetInstance(); FillEnumFields(fields, lmrType); // We will normalize/extend all enum values to ulong to ensure that we are always comparing the full underlying value. ulong valueForComparison = ConvertEnumUnderlyingTypeToUInt64(underlyingValue, Type.GetTypeCode(lmrType)); var typeToDisplayOpt = includeTypeName ? lmrType : null; if (valueForComparison != 0 && IsFlagsEnum(lmrType)) { displayString = GetNamesForFlagsEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } else { displayString = GetNameForEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } fields.Free(); return(displayString ?? FormatPrimitive(value, options)); }
internal static string FormatLiteral( ulong value, ObjectDisplayOptions options, CultureInfo cultureInfo = null ) { var pooledBuilder = PooledStringBuilder.GetInstance(); var sb = pooledBuilder.Builder; if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { sb.Append("0x"); sb.Append(value.ToString("x16")); } else { sb.Append(value.ToString(GetFormatCulture(cultureInfo))); } if (options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix)) { sb.Append("UL"); } return(pooledBuilder.ToStringAndFree()); }
internal abstract string GetArrayDisplayString( DkmClrAppDomain appDomain, Type lmrType, ReadOnlyCollection <int> sizes, ReadOnlyCollection <int> lowerBounds, ObjectDisplayOptions options );
/// <summary> /// Returns a C# string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Optionally escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { if (value == null) { throw new ArgumentNullException(nameof(value)); } const char quote = '"'; var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters); var isVerbatim = useQuotes && !escapeNonPrintable && ContainsNewLine(value); if (useQuotes) { if (isVerbatim) { builder.Append('@'); } builder.Append(quote); } foreach (var c in value) { string replaceWith; if (escapeNonPrintable && TryReplaceChar(c, out replaceWith)) { builder.Append(replaceWith); } else if (useQuotes && c == quote) { if (isVerbatim) { builder.Append(quote); builder.Append(quote); } else { builder.Append('\\'); builder.Append(quote); } } else { builder.Append(c); } } if (useQuotes) { builder.Append(quote); } return(pooledBuilder.ToStringAndFree()); }
internal static string FormatLiteral(decimal value, ObjectDisplayOptions options) { ValidateOptions(options); var result = value.ToString(CultureInfo.InvariantCulture); return(options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix) ? result + "M" : result); }
protected override string FormatLiteral( string value, bool useQuotes, bool escapeNonPrintable) { ObjectDisplayOptions objectDisplayOptions = ObjectFormatterHelpers.GetObjectDisplayOptions(useQuotes, escapeNonPrintable, false); return(ObjectDisplay.FormatLiteral(value, objectDisplayOptions)); }
internal override string GetArrayDisplayString(Type lmrType, ReadOnlyCollection<int> sizes, ReadOnlyCollection<int> lowerBounds, ObjectDisplayOptions options) { Debug.Assert(lmrType.IsArray); Type originalLmrType = lmrType; // Strip off all array types. We'll process them at the end. while (lmrType.IsArray) { lmrType = lmrType.GetElementType(); } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; builder.Append('{'); // We're showing the type of a value, so "dynamic" does not apply. bool unused; builder.Append(GetTypeName(new TypeAndCustomInfo(lmrType), escapeKeywordIdentifiers: false, sawInvalidIdentifier: out unused)); // NOTE: call our impl directly, since we're coupled anyway. var numSizes = sizes.Count; builder.Append('['); for (int i = 0; i < numSizes; i++) { if (i > 0) { builder.Append(", "); } var lowerBound = lowerBounds[i]; var size = sizes[i]; if (lowerBound == 0) { builder.Append(FormatLiteral(size, options)); } else { builder.Append(FormatLiteral(lowerBound, options)); builder.Append(".."); builder.Append(FormatLiteral(size + lowerBound - 1, options)); } } builder.Append(']'); lmrType = originalLmrType.GetElementType(); // Strip off one layer (already handled). while (lmrType.IsArray) { builder.Append('['); builder.Append(',', lmrType.GetArrayRank() - 1); builder.Append(']'); lmrType = lmrType.GetElementType(); } builder.Append('}'); return pooled.ToStringAndFree(); }
protected override string FormatLiteral( char c, bool useQuotes, bool escapeNonPrintable, bool includeCodePoints = false) { ObjectDisplayOptions objectDisplayOptions = ObjectFormatterHelpers.GetObjectDisplayOptions(useQuotes, escapeNonPrintable, includeCodePoints); return(ObjectDisplay.FormatLiteral(c, objectDisplayOptions)); }
internal static string FormatLiteral(int value, ObjectDisplayOptions options) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { return("0x" + value.ToString("x8")); } else { return(value.ToString(CultureInfo.InvariantCulture)); } }
internal static string FormatLiteral( short value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { return("0x" + (value >= 0 ? value.ToString("x4") : ((int)value).ToString("x8"))); } return(value.ToString(ObjectDisplay.GetFormatCulture(cultureInfo))); }
internal static string FormatLiteral(int value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { return("0x" + value.ToString("x8")); } else { return(value.ToString(GetFormatCulture(cultureInfo))); } }
/// <summary> /// Returns a C# string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { ValidateOptions(options); if (value == null) { throw new ArgumentNullException("value"); } return(FormatString(value, options.IncludesOption(ObjectDisplayOptions.UseQuotes) ? '"' : '\0', escapeNonPrintable: true)); }
internal override string FormatLiteral(int value, ObjectDisplayOptions options) { return(ObjectDisplay.FormatLiteral( value, options & ~( ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters ) )); }
/// <summary> /// Gets the string representation of a character literal without including the numeric code point. /// </summary> internal string GetValueStringForCharacter(DkmClrValue value, ObjectDisplayOptions options) { Debug.Assert(value.Type.GetLmrType().IsCharacter()); if (UsesHexadecimalNumbers(value)) { options |= ObjectDisplayOptions.UseHexadecimalNumbers; } var charTemp = FormatLiteral((char)value.HostObjectValue, options); Debug.Assert(charTemp != null); return(charTemp); }
internal static string FormatLiteral( decimal value, ObjectDisplayOptions options, CultureInfo cultureInfo = null ) { var result = value.ToString(GetFormatCulture(cultureInfo)); return(options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix) ? result + "M" : result); }
internal static string FormatLiteral( Decimal value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { string str = value.ToString(ObjectDisplay.GetFormatCulture(cultureInfo)); if (!options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix)) { return(str); } return(str + "M"); }
internal static string FormatLiteral(short value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { // Special Case: for sbyte and short, specifically, negatives are shown // with extra precision. return("0x" + (value >= 0 ? value.ToString("x4") : ((int)value).ToString("x8"))); } else { return(value.ToString(GetFormatCulture(cultureInfo))); } }
internal static string FormatLiteral(char c, ObjectDisplayOptions options) { const char quote = '\''; var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints)) { builder.Append( options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString() ); builder.Append(" "); } var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var escapeNonPrintable = options.IncludesOption( ObjectDisplayOptions.EscapeNonPrintableCharacters ); if (useQuotes) { builder.Append(quote); } string replaceWith; if (escapeNonPrintable && TryReplaceChar(c, out replaceWith)) { builder.Append(replaceWith); } else if (useQuotes && c == quote) { builder.Append('\\'); builder.Append(quote); } else { builder.Append(c); } if (useQuotes) { builder.Append(quote); } return(pooledBuilder.ToStringAndFree()); }
internal static string FormatLiteral(sbyte value, ObjectDisplayOptions options) { ValidateOptions(options); if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { // Special Case: for sbyte and short, specifically, negatives are shown // with extra precision. return("0x" + (value >= 0 ? value.ToString("x2") : ((int)value).ToString("x8"))); } else { return(value.ToString(CultureInfo.InvariantCulture)); } }
/// <summary> /// Returns a C# character literal with the given value. /// </summary> /// <param name="c">The value that the resulting character literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A character literal with the given value.</returns> internal static string FormatLiteral(char c, ObjectDisplayOptions options) { var includeCodePoints = options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints); var result = FormatString(c.ToString(), quote: options.IncludesOption(ObjectDisplayOptions.UseQuotes) ? '\'' : '\0', escapeNonPrintable: !includeCodePoints); if (includeCodePoints) { var codepoint = options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString(); return(codepoint + " " + result); } return(result); }
/// <summary> /// Returns a Lua string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Optionally escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { const char shortStringQuote = '"'; if (value is null) { throw new ArgumentNullException(nameof(value)); } var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters); var utf8Escape = options.IncludesOption(ObjectDisplayOptions.EscapeWithUtf8); var isVerbatim = useQuotes && !escapeNonPrintable && ContainsNewLine(value); string endDelimiter = ""; if (useQuotes) { if (isVerbatim) { if (!TryFastGetVerbatimEquals(value.AsSpan(), out var startDelimiter, out endDelimiter !)) { (startDelimiter, endDelimiter) = SlowGetVerbatimEquals(value); } builder.Append(startDelimiter); } else { endDelimiter = shortStringQuote.ToString(); } } for (var idx = 0; idx < value.Length; idx++) { var ch = value[idx]; if (escapeNonPrintable && TryReplaceChar(ch, out var replaceWith, utf8Escape)) { builder.Append(replaceWith); }
internal static ObjectDisplayOptions GetObjectDisplayOptions( bool useQuotes = false, bool escapeNonPrintable = false, bool includeCodePoints = false) { ObjectDisplayOptions objectDisplayOptions = ObjectDisplayOptions.None; if (useQuotes) { objectDisplayOptions |= ObjectDisplayOptions.UseQuotes; } if (escapeNonPrintable) { objectDisplayOptions |= ObjectDisplayOptions.EscapeNonPrintableCharacters; } if (includeCodePoints) { objectDisplayOptions |= ObjectDisplayOptions.IncludeCodePoints; } return(objectDisplayOptions); }
internal string FormatPrimitive(DkmClrValue value, ObjectDisplayOptions options) { Debug.Assert(value != null); object obj; if (value.Type.GetLmrType().IsDateTime()) { DkmClrValue dateDataValue = value.GetFieldValue(DateTimeUtilities.DateTimeDateDataFieldName); Debug.Assert(dateDataValue.HostObjectValue != null); obj = DateTimeUtilities.ToDateTime((ulong)dateDataValue.HostObjectValue); } else { Debug.Assert(value.HostObjectValue != null); obj = value.HostObjectValue; } return(FormatPrimitiveObject(obj, options)); }
internal static string FormatLiteral(decimal value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { var result = value.ToString(GetFormatCulture(cultureInfo)); return options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix) ? result + "M" : result; }
/// <summary> /// Gets the string representation of a character literal without including the numeric code point. /// </summary> internal string GetValueStringForCharacter(DkmClrValue value, DkmInspectionContext inspectionContext, ObjectDisplayOptions options) { Debug.Assert(value.Type.GetLmrType().IsCharacter()); if (UsesHexadecimalNumbers(inspectionContext)) { options |= ObjectDisplayOptions.UseHexadecimalNumbers; } var charTemp = FormatLiteral((char)value.HostObjectValue, options); Debug.Assert(charTemp != null); return charTemp; }
internal abstract string FormatString(string str, ObjectDisplayOptions options);
internal override string FormatString(string str, ObjectDisplayOptions options) { return ObjectDisplay.FormatString(str, useQuotes: options.IncludesOption(ObjectDisplayOptions.UseQuotes)); }
internal abstract string FormatLiteral(int value, ObjectDisplayOptions options);
internal abstract string FormatPrimitiveObject(object value, ObjectDisplayOptions options);
internal static string FormatLiteral(ulong value, ObjectDisplayOptions options) { var pooledBuilder = PooledStringBuilder.GetInstance(); var sb = pooledBuilder.Builder; if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { sb.Append("0x"); sb.Append(value.ToString("x16")); } else { sb.Append(value.ToString(CultureInfo.InvariantCulture)); } if (options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix)) { sb.Append("UL"); } return pooledBuilder.ToStringAndFree(); }
internal static string FormatLiteral(uint value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { var pooledBuilder = PooledStringBuilder.GetInstance(); var sb = pooledBuilder.Builder; if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { sb.Append("0x"); sb.Append(value.ToString("x8")); } else { sb.Append(value.ToString(GetFormatCulture(cultureInfo))); } if (options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix)) { sb.Append('U'); } return pooledBuilder.ToStringAndFree(); }
/// <summary> /// Returns a C# character literal with the given value. /// </summary> /// <param name="c">The value that the resulting character literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A character literal with the given value.</returns> internal static string FormatLiteral(char c, ObjectDisplayOptions options) { const char quote = '\''; var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints)) { builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString()); builder.Append(" "); } var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters); if (useQuotes) { builder.Append(quote); } string replaceWith; if (escapeNonPrintable && TryReplaceChar(c, out replaceWith)) { builder.Append(replaceWith); } else if (useQuotes && c == quote) { builder.Append('\\'); builder.Append(quote); } else { builder.Append(c); } if (useQuotes) { builder.Append(quote); } return pooledBuilder.ToStringAndFree(); }
internal static string FormatLiteral(short value, ObjectDisplayOptions options) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { // Special Case: for sbyte and short, specifically, negatives are shown // with extra precision. return "0x" + (value >= 0 ? value.ToString("x4") : ((int)value).ToString("x8")); } else { return value.ToString(CultureInfo.InvariantCulture); } }
internal override string FormatLiteral(int value, ObjectDisplayOptions options) { return ObjectDisplay.FormatLiteral(value, options & ~ObjectDisplayOptions.UseQuotes); }
internal override string FormatPrimitiveObject(object value, ObjectDisplayOptions options) { return ObjectDisplay.FormatPrimitive(value, options); }
internal override string FormatLiteral(char c, ObjectDisplayOptions options) { return ObjectDisplay.FormatLiteral(c, options); }
internal override string GetNamesForFlagsEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt) { var usedFields = ArrayBuilder<EnumField>.GetInstance(); FillUsedEnumFields(usedFields, fields, underlyingValue); if (usedFields.Count == 0) { return null; } var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; for (int i = usedFields.Count - 1; i >= 0; i--) // Backwards to list smallest first. { AppendEnumTypeAndName(builder, typeToDisplayOpt, usedFields[i].Name); if (i > 0) { builder.Append(" | "); } } usedFields.Free(); return pooled.ToStringAndFree(); }
/// <summary> /// Determines if a flag is set on the <see cref="ObjectDisplayOptions"/> enum. /// </summary> /// <param name="options">The value to check.</param> /// <param name="flag">An enum field that specifies the flag.</param> /// <returns>Whether the <paramref name="flag"/> is set on the <paramref name="options"/>.</returns> internal static bool IncludesOption(this ObjectDisplayOptions options, ObjectDisplayOptions flag) { return (options & flag) == flag; }
internal override string GetNameForEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt) { foreach (var field in fields) { // First match wins (deterministic since sorted). if (underlyingValue == field.Value) { var pooled = PooledStringBuilder.GetInstance(); var builder = pooled.Builder; AppendEnumTypeAndName(builder, typeToDisplayOpt, field.Name); return pooled.ToStringAndFree(); } } return null; }
#pragma warning disable RS0010 /// <remarks> /// The corresponding native code is in EEUserStringBuilder::ErrTryAppendConstantEnum. /// The corresponding roslyn code is in /// <see cref="M:Microsoft.CodeAnalysis.SymbolDisplay.AbstractSymbolDisplayVisitor`1.AddEnumConstantValue(Microsoft.CodeAnalysis.INamedTypeSymbol, System.Object, System.Boolean)"/>. /// NOTE: no curlies for enum values. /// </remarks> #pragma warning restore RS0010 private string GetEnumDisplayString(Type lmrType, DkmClrValue value, ObjectDisplayOptions options, bool includeTypeName, DkmInspectionContext inspectionContext) { Debug.Assert(lmrType.IsEnum); Debug.Assert(value != null); object underlyingValue = value.HostObjectValue; Debug.Assert(underlyingValue != null); string displayString; ArrayBuilder<EnumField> fields = ArrayBuilder<EnumField>.GetInstance(); FillEnumFields(fields, lmrType); // We will normalize/extend all enum values to ulong to ensure that we are always comparing the full underlying value. ulong valueForComparison = ConvertEnumUnderlyingTypeToUInt64(underlyingValue, Type.GetTypeCode(lmrType)); var typeToDisplayOpt = includeTypeName ? lmrType : null; if (valueForComparison != 0 && IsFlagsEnum(lmrType)) { displayString = GetNamesForFlagsEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } else { displayString = GetNameForEnumValue(fields, underlyingValue, valueForComparison, options, typeToDisplayOpt); } fields.Free(); return displayString ?? FormatPrimitive(value, options, inspectionContext); }
internal override string FormatLiteral(int value, ObjectDisplayOptions options) { return ObjectDisplay.FormatLiteral(value, options & ~(ObjectDisplayOptions.UseQuotes | ObjectDisplayOptions.EscapeNonPrintableCharacters)); }
internal string GetValueString(DkmClrValue value, DkmInspectionContext inspectionContext, ObjectDisplayOptions options, GetValueFlags flags) { if (value.IsError()) { return (string)value.HostObjectValue; } if (UsesHexadecimalNumbers(inspectionContext)) { options |= ObjectDisplayOptions.UseHexadecimalNumbers; } var lmrType = value.Type.GetLmrType(); if (IsPredefinedType(lmrType) && !lmrType.IsObject()) { if (lmrType.IsString()) { var stringValue = (string)value.HostObjectValue; if (stringValue == null) { return _nullString; } return IncludeObjectId( value, FormatString(stringValue, options), flags); } else if (lmrType.IsCharacter()) { return IncludeObjectId( value, FormatLiteral((char)value.HostObjectValue, options | ObjectDisplayOptions.IncludeCodePoints), flags); } else { return IncludeObjectId( value, FormatPrimitive(value, options & ~ObjectDisplayOptions.UseQuotes, inspectionContext), flags); } } else if (value.IsNull && !lmrType.IsPointer) { return _nullString; } else if (lmrType.IsEnum) { return IncludeObjectId( value, GetEnumDisplayString(lmrType, value, options, (flags & GetValueFlags.IncludeTypeName) != 0, inspectionContext), flags); } else if (lmrType.IsArray) { return IncludeObjectId( value, GetArrayDisplayString(lmrType, value.ArrayDimensions, value.ArrayLowerBounds, options), flags); } else if (lmrType.IsPointer) { // NOTE: the HostObjectValue will have a size corresponding to the process bitness // and FormatPrimitive will adjust accordingly. var tmp = FormatPrimitive(value, ObjectDisplayOptions.UseHexadecimalNumbers, inspectionContext); // Always in hex. Debug.Assert(tmp != null); return tmp; } else if (lmrType.IsNullable()) { var nullableValue = value.GetNullableValue(inspectionContext); // It should be impossible to nest nullables, so this recursion should introduce only a single extra stack frame. return nullableValue == null ? _nullString : GetValueString(nullableValue, inspectionContext, ObjectDisplayOptions.None, GetValueFlags.IncludeTypeName); } // "value.EvaluateToString()" will check "Call string-conversion function on objects in variables windows" // (Tools > Options setting) and call "value.ToString()" if appropriate. return IncludeObjectId( value, string.Format(_defaultFormat, value.EvaluateToString(inspectionContext) ?? inspectionContext.GetTypeName(value.Type, CustomTypeInfo: null, FormatSpecifiers: NoFormatSpecifiers)), flags); }
internal override string FormatString(string str, ObjectDisplayOptions options) { return ObjectDisplay.FormatLiteral(str, options); }
internal string FormatPrimitive(DkmClrValue value, ObjectDisplayOptions options, DkmInspectionContext inspectionContext) { Debug.Assert(value != null); object obj; if (value.Type.GetLmrType().IsDateTime()) { DkmClrValue dateDataValue = value.GetFieldValue(DateTimeUtilities.DateTimeDateDataFieldName, inspectionContext); Debug.Assert(dateDataValue.HostObjectValue != null); obj = DateTimeUtilities.ToDateTime((ulong)dateDataValue.HostObjectValue); } else { Debug.Assert(value.HostObjectValue != null); obj = value.HostObjectValue; } return FormatPrimitiveObject(obj, options); }
/// <summary> /// Returns a C# string literal with the given value. /// </summary> /// <param name="value">The value that the resulting string literal should have.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string literal with the given value.</returns> /// <remarks> /// Optionally escapes non-printable characters. /// </remarks> public static string FormatLiteral(string value, ObjectDisplayOptions options) { if (value == null) { throw new ArgumentNullException(nameof(value)); } const char quote = '"'; var pooledBuilder = PooledStringBuilder.GetInstance(); var builder = pooledBuilder.Builder; var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes); var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters); var isVerbatim = useQuotes && !escapeNonPrintable && ContainsNewLine(value); if (useQuotes) { if (isVerbatim) { builder.Append('@'); } builder.Append(quote); } foreach (var c in value) { string replaceWith; if (escapeNonPrintable && TryReplaceChar(c, out replaceWith)) { builder.Append(replaceWith); } else if (useQuotes && c == quote) { if (isVerbatim) { builder.Append(quote); builder.Append(quote); } else { builder.Append('\\'); builder.Append(quote); } } else { builder.Append(c); } } if (useQuotes) { builder.Append(quote); } return pooledBuilder.ToStringAndFree(); }
internal abstract string GetArrayDisplayString(Type lmrType, ReadOnlyCollection<int> sizes, ReadOnlyCollection<int> lowerBounds, ObjectDisplayOptions options);
/// <summary> /// Returns a string representation of an object of primitive type. /// </summary> /// <param name="obj">A value to display as a string.</param> /// <param name="options">Options used to customize formatting of an object value.</param> /// <returns>A string representation of an object of primitive type (or null if the type is not supported).</returns> /// <remarks> /// Handles <see cref="bool"/>, <see cref="string"/>, <see cref="char"/>, <see cref="sbyte"/> /// <see cref="byte"/>, <see cref="short"/>, <see cref="ushort"/>, <see cref="int"/>, <see cref="uint"/>, /// <see cref="long"/>, <see cref="ulong"/>, <see cref="double"/>, <see cref="float"/>, <see cref="decimal"/>, /// and <c>null</c>. /// </remarks> public static string FormatPrimitive(object obj, ObjectDisplayOptions options) { if (obj == null) { return NullLiteral; } Type type = obj.GetType(); if (type.GetTypeInfo().IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(int)) { return FormatLiteral((int)obj, options); } if (type == typeof(string)) { return FormatLiteral((string)obj, options); } if (type == typeof(bool)) { return FormatLiteral((bool)obj); } if (type == typeof(char)) { return FormatLiteral((char)obj, options); } if (type == typeof(byte)) { return FormatLiteral((byte)obj, options); } if (type == typeof(short)) { return FormatLiteral((short)obj, options); } if (type == typeof(long)) { return FormatLiteral((long)obj, options); } if (type == typeof(double)) { return FormatLiteral((double)obj, options); } if (type == typeof(ulong)) { return FormatLiteral((ulong)obj, options); } if (type == typeof(uint)) { return FormatLiteral((uint)obj, options); } if (type == typeof(ushort)) { return FormatLiteral((ushort)obj, options); } if (type == typeof(sbyte)) { return FormatLiteral((sbyte)obj, options); } if (type == typeof(float)) { return FormatLiteral((float)obj, options); } if (type == typeof(decimal)) { return FormatLiteral((decimal)obj, options); } return null; }
internal abstract string GetNameForEnumValue(ArrayBuilder<EnumField> fields, object value, ulong underlyingValue, ObjectDisplayOptions options, Type typeToDisplayOpt);
internal static string FormatLiteral(int value, ObjectDisplayOptions options) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { return "0x" + value.ToString("x8"); } else { return value.ToString(CultureInfo.InvariantCulture); } }
internal abstract string FormatLiteral(char c, ObjectDisplayOptions options);
internal static string FormatLiteral(decimal value, ObjectDisplayOptions options) { var result = value.ToString(CultureInfo.InvariantCulture); return options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix) ? result + "M" : result; }
internal static string FormatLiteral(int value, ObjectDisplayOptions options, CultureInfo cultureInfo = null) { if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers)) { return "0x" + value.ToString("x8"); } else { return value.ToString(GetFormatCulture(cultureInfo)); } }