internal DkmEvaluationAsyncResult FormatAsyncResult( string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmClrCustomTypeInfo declaredTypeInfo = null, DkmInspectionContext inspectionContext = null ) { DkmEvaluationAsyncResult asyncResult = default(DkmEvaluationAsyncResult); var workList = new DkmWorkList(); value.GetResult( workList, DeclaredType: declaredType ?? value.Type, CustomTypeInfo: declaredTypeInfo, InspectionContext: inspectionContext ?? DefaultInspectionContext, FormatSpecifiers: Formatter.NoFormatSpecifiers, ResultName: name, ResultFullName: fullName, CompletionRoutine: r => asyncResult = r ); workList.Execute(); return(asyncResult); }
private void GetResultAndContinue( EvalResult result, WorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, bool useDebuggerDisplay, CompletionRoutine <DkmEvaluationResult> completionRoutine) { var value = result.Value; // Value may have been replaced (specifically, for Nullable<T>). DebuggerDisplayInfo displayInfo; if (value.TryGetDebuggerDisplayInfo(out displayInfo)) { var targetType = displayInfo.TargetType; var attribute = displayInfo.Attribute; CompletionRoutine <Exception> onException = e => completionRoutine(CreateEvaluationResultFromException(e, result, inspectionContext)); var innerWorkList = workList.InnerWorkList; EvaluateDebuggerDisplayStringAndContinue(value, innerWorkList, inspectionContext, targetType, attribute.Name, displayName => EvaluateDebuggerDisplayStringAndContinue(value, innerWorkList, inspectionContext, targetType, attribute.Value, displayValue => EvaluateDebuggerDisplayStringAndContinue(value, innerWorkList, inspectionContext, targetType, attribute.TypeName, displayType => workList.ContinueWith(() => completionRoutine(GetResult(inspectionContext, result, declaredType, declaredTypeInfo, displayName.Result, displayValue.Result, displayType.Result, useDebuggerDisplay))), onException), onException), onException); } else { completionRoutine(GetResult(inspectionContext, result, declaredType, declaredTypeInfo, displayName: null, displayValue: null, displayType: null, useDebuggerDisplay: false)); } }
internal DkmEvaluationResult FormatResult( string name, string fullName, DkmClrValue value, DkmClrType declaredType = null, DkmClrCustomTypeInfo declaredTypeInfo = null, DkmInspectionContext inspectionContext = null ) { var asyncResult = FormatAsyncResult( name, fullName, value, declaredType, declaredTypeInfo, inspectionContext ); var exception = asyncResult.Exception; if (exception != null) { ExceptionDispatchInfo.Capture(exception).Throw(); } return(asyncResult.Result); }
public void DynamicAttribute_OtherGuid() { var typeInfo = DkmClrCustomTypeInfo.Create(Guid.NewGuid(), new ReadOnlyCollection <byte>(new byte[] { 1 })); Assert.Equal("object", typeof(object).GetTypeName(typeInfo)); Assert.Equal("object[]", typeof(object[]).GetTypeName(typeInfo)); }
private void GetResultAndContinue( EvalResultDataItem dataItem, WorkList workList, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmInspectionContext inspectionContext, EvalResultDataItem parent, CompletionRoutine <DkmEvaluationResult> completionRoutine) { var value = dataItem.Value; // Value may have been replaced (specifically, for Nullable<T>). DebuggerDisplayInfo displayInfo; if (value.TryGetDebuggerDisplayInfo(out displayInfo)) { var targetType = displayInfo.TargetType; var attribute = displayInfo.Attribute; CompletionRoutine <Exception> onException = e => completionRoutine(CreateEvaluationResultFromException(e, dataItem, inspectionContext)); EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.Name, displayName => EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.Value, displayValue => EvaluateDebuggerDisplayStringAndContinue(value, workList, inspectionContext, targetType, attribute.TypeName, displayType => { completionRoutine(GetResult(inspectionContext, dataItem, declaredType, declaredTypeInfo, displayName.Result, displayValue.Result, displayType.Result, parent)); }, onException), onException), onException); } else { completionRoutine(GetResult(inspectionContext, dataItem, declaredType, declaredTypeInfo, displayName: null, displayValue: null, displayType: null, parent: parent)); } }
public static string GetTypeName( this System.Type type, DkmClrCustomTypeInfo typeInfo = null, bool escapeKeywordIdentifiers = false, DkmInspectionContext inspectionContext = null ) { var formatter = new CSharpFormatter(); var clrType = new DkmClrType((TypeImpl)type); if (inspectionContext == null) { var inspectionSession = new DkmInspectionSession( ImmutableArray.Create <IDkmClrFormatter>(formatter), ImmutableArray.Create <IDkmClrResultProvider>(new CSharpResultProvider()) ); inspectionContext = new DkmInspectionContext( inspectionSession, DkmEvaluationFlags.None, radix: 10, runtimeInstance: null ); } return(escapeKeywordIdentifiers ? ((IDkmClrFullNameProvider)formatter).GetClrTypeName( inspectionContext, clrType, typeInfo ) : inspectionContext.GetTypeName(clrType, typeInfo, Formatter.NoFormatSpecifiers)); }
public static string GetTypeName(this System.Type type, DkmClrCustomTypeInfo typeInfo, bool escapeKeywordIdentifiers = false) { bool sawInvalidIdentifier; var result = CSharpFormatter.Instance.GetTypeName(new TypeAndCustomInfo((TypeImpl)type, typeInfo), escapeKeywordIdentifiers, out sawInvalidIdentifier); Assert.False(sawInvalidIdentifier); return(result); }
string IDkmClrFormatter2.GetEditableValueString( DkmClrValue value, DkmInspectionContext inspectionContext, DkmClrCustomTypeInfo customTypeInfo ) { return(GetEditableValue(value, inspectionContext, customTypeInfo)); }
internal static DkmClrCustomTypeInfo Create( ReadOnlyCollection <byte> dynamicFlags, ReadOnlyCollection <string> tupleElementNames) { var payload = Encode(dynamicFlags, tupleElementNames); return((payload == null) ? null : DkmClrCustomTypeInfo.Create(PayloadTypeId, payload)); }
string IDkmClrFullNameProvider.GetClrTypeName( DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo ) { throw new NotImplementedException(); }
string IDkmClrFormatter.GetTypeName( DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo, ReadOnlyCollection <string> formatSpecifiers ) { return(inspectionContext.GetTypeName(clrType, customTypeInfo, formatSpecifiers)); }
string IDkmClrFullNameProvider.GetClrObjectCreationExpression( DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, string[] arguments ) { throw new NotImplementedException(); }
string IDkmClrFormatter2.GetValueString( DkmClrValue value, DkmClrCustomTypeInfo customTypeInfo, DkmInspectionContext inspectionContext, ReadOnlyCollection <string> formatSpecifiers ) { return(value.GetValueString(inspectionContext, formatSpecifiers)); }
internal static EvalResult CreateResultsOnlyRow( DkmInspectionContext inspectionContext, string name, string fullName, ReadOnlyCollection <string> formatSpecifiers, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmClrValue value, ResultProvider resultProvider ) { string errorMessage; if (value.IsError()) { errorMessage = (string)value.HostObjectValue; } else if (value.HasExceptionThrown()) { errorMessage = value.GetExceptionMessage(inspectionContext, name); } else { var enumerableType = GetEnumerableType(value); if (enumerableType != null) { var expansion = CreateExpansion( inspectionContext, value, enumerableType, resultProvider ); if (expansion != null) { return(expansion.CreateResultsViewRow( inspectionContext, name, fullName, formatSpecifiers, new TypeAndCustomInfo(declaredType, declaredTypeInfo), value, includeResultsFormatSpecifier: true, fullNameProvider: resultProvider.FullNameProvider )); } errorMessage = Resources.ResultsViewNoSystemCore; } else { errorMessage = Resources.ResultsViewNotEnumerable; } } Debug.Assert(errorMessage != null); return(new EvalResult(name, errorMessage, inspectionContext)); }
string IDkmClrFullNameProvider.GetClrCastExpression( DkmInspectionContext inspectionContext, string argument, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, DkmClrCastExpressionOptions castExpressionOptions ) { throw new NotImplementedException(); }
string IDkmClrFullNameProvider.GetClrMemberName( DkmInspectionContext inspectionContext, string parentFullName, DkmClrType declaringType, DkmClrCustomTypeInfo declaringTypeInfo, string memberName, bool memberAccessRequiresExplicitCast, bool memberIsStatic) { return(((IDkmClrFullNameProvider)_fallback).GetClrMemberName(inspectionContext, parentFullName, declaringType, declaringTypeInfo, memberName, memberAccessRequiresExplicitCast, memberIsStatic)); }
public string GetTypeName( DkmClrType ClrType, DkmClrCustomTypeInfo CustomTypeInfo, ReadOnlyCollection <string> FormatSpecifiers ) { return(InspectionSession.InvokeFormatter( this, MethodId.GetTypeName, f => f.GetTypeName(this, ClrType, CustomTypeInfo, FormatSpecifiers) )); }
internal static EvalResult CreateResultsOnlyRowIfSynthesizedEnumerable( DkmInspectionContext inspectionContext, string name, string fullName, ReadOnlyCollection <string> formatSpecifiers, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, DkmClrValue value, ResultProvider resultProvider ) { if ((value.ValueFlags & DkmClrValueFlags.Synthetic) == 0) { return(null); } // Must be declared as IEnumerable or IEnumerable<T>, not a derived type. var enumerableType = GetEnumerableType( value, declaredType, requireExactInterface: true ); if (enumerableType == null) { return(null); } var expansion = CreateExpansion( inspectionContext, value, enumerableType, resultProvider ); if (expansion == null) { return(null); } return(expansion.CreateResultsViewRow( inspectionContext, name, fullName, formatSpecifiers, new TypeAndCustomInfo(declaredType, declaredTypeInfo), value, includeResultsFormatSpecifier: false, fullNameProvider: resultProvider.FullNameProvider )); }
private DkmEvaluationResult GetResult( DkmInspectionContext inspectionContext, EvalResult result, DkmClrType declaredType, DkmClrCustomTypeInfo declaredTypeInfo, string displayName, string displayValue, string displayType, bool useDebuggerDisplay) { var name = result.Name; Debug.Assert(name != null); var typeDeclaringMemberAndInfo = result.TypeDeclaringMemberAndInfo; // Note: Don't respect the debugger display name on the root element: // 1) In the Watch window, that's where the user's text goes. // 2) In the Locals window, that's where the local name goes. // Note: Dev12 respects the debugger display name in the Locals window, // but not in the Watch window, but we can't distinguish and this // behavior seems reasonable. if (displayName != null && useDebuggerDisplay) { name = displayName; } else if (typeDeclaringMemberAndInfo.Type != null) { name = GetQualifiedMemberName(inspectionContext, typeDeclaringMemberAndInfo, name, FullNameProvider); } var value = result.Value; string display; if (value.HasExceptionThrown()) { display = result.DisplayValue ?? value.GetExceptionMessage(inspectionContext, result.FullNameWithoutFormatSpecifiers ?? result.Name); } else if (displayValue != null) { display = value.IncludeObjectId(displayValue); } else { display = value.GetValueString(inspectionContext, Formatter.NoFormatSpecifiers); } var typeName = displayType ?? GetTypeName(inspectionContext, value, declaredType, declaredTypeInfo, result.Kind); return(CreateEvaluationResult(inspectionContext, value, name, typeName, display, result)); }
public void CustomTypeInfoConstructor_OtherGuid() { var customTypeInfo = DkmClrCustomTypeInfo.Create(Guid.NewGuid(), new ReadOnlyCollection <byte>(new byte[] { 0x01 })); ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( customTypeInfo.PayloadTypeId, customTypeInfo.Payload, out dynamicFlags, out tupleElementNames); Assert.Null(dynamicFlags); Assert.Null(tupleElementNames); }
public DynamicFlagsCustomTypeInfo(DkmClrCustomTypeInfo typeInfo) { if (typeInfo == null || typeInfo.PayloadTypeId != PayloadTypeId) { _bits = null; } else { var builder = ArrayBuilder <byte> .GetInstance(); builder.AddRange(typeInfo.Payload); _bits = new BitArray(builder.ToArrayAndFree()); } }
string IDkmClrFullNameProvider.GetClrMemberName( DkmInspectionContext inspectionContext, string parentFullName, DkmClrType declaringType, DkmClrCustomTypeInfo declaringTypeInfo, string memberName, bool memberAccessRequiresExplicitCast, bool memberIsStatic ) { string qualifier; if (memberIsStatic) { bool sawInvalidIdentifier; qualifier = GetTypeName( new TypeAndCustomInfo(declaringType, declaringTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier ); if (sawInvalidIdentifier) { return(null); // FullName wouldn't be parseable. } } else if (memberAccessRequiresExplicitCast) { bool sawInvalidIdentifier; var typeName = GetTypeName( new TypeAndCustomInfo(declaringType, declaringTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier ); if (sawInvalidIdentifier) { return(null); // FullName wouldn't be parseable. } qualifier = GetCastExpression( parentFullName, typeName, DkmClrCastExpressionOptions.ParenthesizeEntireExpression ); } else { qualifier = parentFullName; } return($"{qualifier}.{memberName}"); }
string IDkmClrFormatter.GetTypeName( DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo typeInfo, ReadOnlyCollection <string> formatSpecifiers ) { bool unused; return(GetTypeName( new TypeAndCustomInfo(type, typeInfo), escapeKeywordIdentifiers: false, sawInvalidIdentifier: out unused )); }
string IDkmClrFullNameProvider.GetClrTypeName( DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo ) { Debug.Assert(inspectionContext != null); bool sawInvalidIdentifier; var name = GetTypeName( new TypeAndCustomInfo(clrType, customTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier ); return(sawInvalidIdentifier ? null : name); }
/// <summary> /// Return a copy of the custom type info without tuple element names. /// </summary> internal static DkmClrCustomTypeInfo WithNoTupleElementNames(this DkmClrCustomTypeInfo typeInfo) { if ((typeInfo == null) || (typeInfo.Payload == null) || typeInfo.PayloadTypeId != PayloadTypeId) { return(typeInfo); } var payload = typeInfo.Payload; int length = payload[0] + 1; if (length == payload.Count) { return(typeInfo); } return(DkmClrCustomTypeInfo.Create(PayloadTypeId, new ReadOnlyCollection <byte>(CopyBytes(payload, 0, length)))); }
string IDkmClrFullNameProvider.GetClrObjectCreationExpression( DkmInspectionContext inspectionContext, DkmClrType type, DkmClrCustomTypeInfo customTypeInfo, string[] arguments ) { bool sawInvalidIdentifier; var name = GetTypeName( new TypeAndCustomInfo(type, customTypeInfo), escapeKeywordIdentifiers: true, sawInvalidIdentifier: out sawInvalidIdentifier ); if (sawInvalidIdentifier) { return(null); } return(GetObjectCreationExpression(name, arguments)); }
/// <summary> /// This method is called by the debug engine to populate the text representing the type of /// a result. /// </summary> /// <param name="inspectionContext">Context of the evaluation. This contains options/flags /// to be used during compilation. It also contains the InspectionSession. The inspection /// session is the object that provides lifetime management for our objects. When the user /// steps or continues the process, the debug engine will dispose of the inspection session</param> /// <param name="clrType">This is the raw type we want to format</param> /// <param name="customTypeInfo">If Expression Compiler passed any additional information /// about the type that doesn't exist in metadata, this parameter contais that information.</param> /// <param name="formatSpecifiers">A list of custom format specifiers that the debugger did /// not understand. If you want special format specifiers for your language, handle them /// here. The formatter should ignore any format specifiers it does not understand.</param> /// <returns>The text of the type name to display</returns> string IDkmClrFormatter.GetTypeName( DkmInspectionContext inspectionContext, DkmClrType clrType, DkmClrCustomTypeInfo customTypeInfo, ReadOnlyCollection <string> formatSpecifiers) { // Get the LMR type for the DkmClrType. LMR Types (Microsoft.VisualStudio.Debugger.Metadata.Type) // are similar to System.Type, but represent types that live in the process being debugged. Type lmrType = clrType.GetLmrType(); XSharpType xType = Utility.GetXSharpTypeForLmrType(lmrType); if (xType == XSharpType.Invalid) { // We don't know about this type. Delegate to the C# Formatter to format the // type name. return(inspectionContext.GetTypeName(clrType, customTypeInfo, formatSpecifiers)); } return(xType.ToString()); }
/// <summary> /// Return a copy of the custom type info with the leading dynamic flag removed. /// There are no changes to tuple element names since this is used for walking /// into an array element type only which does not affect tuple element names. /// </summary> internal static DkmClrCustomTypeInfo?SkipOne(DkmClrCustomTypeInfo customInfo) { if (customInfo == null) { return(customInfo); } Decode( customInfo.PayloadTypeId, customInfo.Payload, out var dynamicFlags, out var tupleElementNames); if (dynamicFlags == null) { return(customInfo); } return(Create(DynamicFlagsCustomTypeInfo.SkipOne(dynamicFlags), tupleElementNames)); }
private static void ValidateCustomTypeInfo(params byte[] payload) { Assert.NotNull(payload); var dkmClrCustomTypeInfo = DkmClrCustomTypeInfo.Create(DynamicFlagsCustomTypeInfo.PayloadTypeId, new ReadOnlyCollection <byte>(payload)); var dynamicFlagsCustomTypeInfo = DynamicFlagsCustomTypeInfo.Create(dkmClrCustomTypeInfo); ValidateBytes(dynamicFlagsCustomTypeInfo, payload); var dkmClrCustomTypeInfo2 = dynamicFlagsCustomTypeInfo.GetCustomTypeInfo(); if (dynamicFlagsCustomTypeInfo.Any()) { Assert.Equal(dkmClrCustomTypeInfo.PayloadTypeId, dkmClrCustomTypeInfo2.PayloadTypeId); Assert.Equal(dkmClrCustomTypeInfo.Payload, dkmClrCustomTypeInfo2.Payload); } else { Assert.Null(dkmClrCustomTypeInfo2); } }
/// <summary> /// Return a copy of the custom type info with the leading dynamic flag removed. /// There are no changes to tuple element names since this is used for walking /// into an array element type only which does not affect tuple element names. /// </summary> internal static DkmClrCustomTypeInfo SkipOne(DkmClrCustomTypeInfo customInfo) { if (customInfo == null) { return(customInfo); } ReadOnlyCollection <byte> dynamicFlags; ReadOnlyCollection <string> tupleElementNames; CustomTypeInfo.Decode( customInfo.PayloadTypeId, customInfo.Payload, out dynamicFlags, out tupleElementNames); if (dynamicFlags == null) { return(customInfo); } return(Create(DynamicFlagsCustomTypeInfo.SkipOne(dynamicFlags), tupleElementNames)); }