public void GetItems(DkmVisualizedExpression visualizedExpression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items) { if (count == 0) { items = new DkmChildVisualizedExpression[0]; return; } var rawContextData = enumContext.GetDataItem <RawEnumContextData>(); var rawContext = rawContextData != null ? rawContextData.RawContext : enumContext; var result = new List <DkmChildVisualizedExpression>(count); if (rawContextData != null && rawContextData.PythonView != null) { if (startIndex == 0) { result.Add(rawContextData.PythonView); --count; } else { --startIndex; } } DkmEvaluationResult[] rawItems; visualizedExpression.GetItemsCallback(rawContext, startIndex, count, out rawItems); for (int i = 0; i < rawItems.Length; ++i) { var rawItem = rawItems[i]; var rawSuccessItem = rawItem as DkmSuccessEvaluationResult; DkmExpressionValueHome home = null; if (rawSuccessItem != null && rawSuccessItem.Address != null) { home = DkmPointerValueHome.Create(rawSuccessItem.Address.Value); } else { home = DkmFakeValueHome.Create(0); } var item = DkmChildVisualizedExpression.Create( visualizedExpression.InspectionContext, visualizedExpression.VisualizerId, visualizedExpression.SourceId, visualizedExpression.StackFrame, home, rawItem, visualizedExpression, (uint)(startIndex + i), rawItem.GetDataItem <RawEvaluationResultHolder>()); result.Add(item); } items = result.ToArray(); }
public override void GetChildItems(DkmEvaluationResultEnumContext enumContext, int start, int count, out DkmChildVisualizedExpression[] items) { var props = GetAllProperties(); int total_num_props = props.Length; int end_idx = Math.Min(start + count, total_num_props); int num_to_return = end_idx - start; items = new DkmChildVisualizedExpression[num_to_return]; for (int idx = start, out_idx = 0; idx < end_idx; ++idx, ++out_idx) { // We want to construct our own visualized expression from the eval. var eval = props[idx] as DkmSuccessEvaluationResult; // @TODO: Perhaps allow for failed evaluations and display anyway with unknown value?? Debug.Assert(eval != null); DkmExpressionValueHome home; if (eval.Address != null) { home = DkmPointerValueHome.Create(eval.Address.Value); } else { home = DkmFakeValueHome.Create(0); } var expr = DkmChildVisualizedExpression.Create( expression_.InspectionContext, // @TODO: This is weird... seems to affect whether we get callback. // Obviously the properties can be of any type, UObject or not. // Perhaps best to put back the guid for PropertyValue, even though we don't really need to use it. Guids.Visualizer.PropertyValue, //Guids.Visualizer.UObject,//Guids.Visualizer.PropertyList, // Seems that in order for these to be passed back to the EE for default expansion, they need to be given // the SourceId from the originally received root expression. PropListExpression.Parent.SourceId, expression_.StackFrame, home, eval, expression_, (uint)idx, null // Don't associate any data with the expression. If the EE calls back to us to expand it, we'll just tell it to use default expansion. ); items[out_idx] = expr; } }
public void EvaluateChildren(DkmChildVisualizedExpression[] output, int startIndex, out int numWritten) { numWritten = 0; if (mode_ == ChildDisplayMode.Inline) { CreateDefaultEnumContext(); int count = ChildCount; DkmEvaluationResult[] results = new DkmEvaluationResult[count]; expression_.GetItemsCallback(defEnumContext_, 0, count, out results); for (int i = 0; i < count; ++i) { DkmSuccessEvaluationResult successResult = results[i] as DkmSuccessEvaluationResult; DkmExpressionValueHome home = null; if (successResult != null && successResult.Address != null) { home = DkmPointerValueHome.Create(successResult.Address.Value); } else { home = DkmFakeValueHome.Create(0); } output[startIndex + i] = DkmChildVisualizedExpression.Create( defEnumContext_.InspectionContext, Guids.CustomVisualizer.ForceDefault, expression_.SourceId, defEnumContext_.StackFrame, home, results[i], expression_, (uint)startIndex, null); EvaluationDataItem originalDataItem = results[i].GetDataItem <EvaluationDataItem>(); } numWritten = count; } else { numWritten = 1; } }
/* public override DkmChildVisualizedExpression GetMostDerived() * { * foreach (var child in MemberExpressions) * { * var eval = child.Value.EvaluationResult as DkmSuccessEvaluationResult; * if (eval != null && eval.Category == DkmEvaluationResultCategory.MostDerivedClass) * { * return child.Value; * } * } * * return null; * } */ private DkmChildVisualizedExpression CreateNewExpression(string expr_str) { DkmSuccessEvaluationResult result_eval = null; try { result_eval = DefaultEE.DefaultEval(expr_str, callback_expr_, true) as DkmSuccessEvaluationResult; } catch (Exception e) { } if (result_eval == null) { return(null); } DkmExpressionValueHome home; if (result_eval.Address != null) { home = DkmPointerValueHome.Create(result_eval.Address.Value); } else { home = DkmFakeValueHome.Create(0); } // @TODO: This is weird. Can I perhaps construct a DkmRootVisualizedExpression instead?? // Not sure about a couple of the parameters needed to do so, Module especially... return(DkmChildVisualizedExpression.Create( result_eval.InspectionContext, expr_.VisualizerId, expr_.SourceId, result_eval.StackFrame, home, result_eval, callback_expr_, //expr_, 0, // ?? null )); }
/// <summary> /// Returns child elements of previous evaluation. /// </summary> public void GetItems(DkmVisualizedExpression visualizedExpression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items) { // Check if we want to use passthrough visualizer PassThroughVisualizer passThroughVisualizer = enumContext.GetDataItem <PassThroughVisualizer>(); if (passThroughVisualizer != null) { passThroughVisualizer.GetItems(visualizedExpression, enumContext, startIndex, count, out items); return; } // Execute our regular visualizer VSCustomVisualizerEvaluator evaluator = visualizedExpression.GetDataItem <VSCustomVisualizerEvaluator>(); IResultVisualizer[] itemsAsResults = evaluator.ResultVisualizer.Children.Skip(startIndex).Take(count).ToArray(); items = new DkmChildVisualizedExpression[itemsAsResults.Length]; for (int i = 0; i < items.Length; i++) { IResultVisualizer item = itemsAsResults[i]; DkmEvaluationResultCategory category; switch (item.DataType) { case CompletionDataType.Class: category = DkmEvaluationResultCategory.Class; break; case CompletionDataType.Property: case CompletionDataType.StaticProperty: category = DkmEvaluationResultCategory.Property; break; case CompletionDataType.Event: category = DkmEvaluationResultCategory.Event; break; case CompletionDataType.Method: category = DkmEvaluationResultCategory.Method; break; case CompletionDataType.Enum: case CompletionDataType.EnumValue: case CompletionDataType.Keyword: case CompletionDataType.Namespace: case CompletionDataType.StaticClass: case CompletionDataType.StaticEvent: case CompletionDataType.StaticMethod: case CompletionDataType.StaticVariable: case CompletionDataType.Unknown: case CompletionDataType.Variable: default: category = DkmEvaluationResultCategory.Data; break; } DkmExpressionValueHome valueHome = visualizedExpression.ValueHome; ulong address = 0; string fullName = string.Empty; string typeName = null; try { if (item.Value is Variable variable) { address = variable.GetPointerAddress(); typeName = variable.GetCodeType().Name; fullName = $"*(({typeName}*)0x{address:X})"; valueHome = DkmPointerValueHome.Create(address); } } catch { } DkmEvaluationResult result; DkmDataItem dataItem = null; if (item.ShouldForceDefaultVisualizer && !string.IsNullOrEmpty(fullName)) { using (DkmLanguageExpression languageExpression = DkmLanguageExpression.Create(visualizedExpression.InspectionContext.Language, DkmEvaluationFlags.TreatAsExpression, fullName, null)) { visualizedExpression.EvaluateExpressionCallback(visualizedExpression.InspectionContext, languageExpression, visualizedExpression.StackFrame, out result); } if (result is DkmSuccessEvaluationResult successResult) { dataItem = new PassThroughVisualizer(successResult); result = DkmSuccessEvaluationResult.Create( successResult.InspectionContext, successResult.StackFrame, item.Name, // Name - Left column successResult.FullName, successResult.Flags, successResult.Value, // Value - Middle column successResult.EditableValue, successResult.Type, // Type - Right column category, successResult.Access, successResult.StorageType, successResult.TypeModifierFlags, successResult.Address, successResult.CustomUIVisualizers, successResult.ExternalModules, successResult.RefreshButtonText, dataItem); } } else { result = DkmSuccessEvaluationResult.Create( visualizedExpression.InspectionContext, visualizedExpression.StackFrame, item.Name, // Name - Left column fullName, // FullName - What is being copied when "Add to watch" DkmEvaluationResultFlags.ReadOnly | (item.IsExpandable ? DkmEvaluationResultFlags.Expandable : DkmEvaluationResultFlags.None), item.ValueString, // Value - Middle column "", item.Type ?? "", // Type - Right column category, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, VSUIVisualizerService.GetUIVisualizers(item), null, null); dataItem = new VSCustomVisualizerEvaluator(result, item); } items[i] = DkmChildVisualizedExpression.Create( visualizedExpression.InspectionContext, visualizedExpression.VisualizerId, visualizedExpression.SourceId, visualizedExpression.StackFrame, valueHome, result, visualizedExpression, (uint)(startIndex + i), dataItem); } }
/* public override DkmChildVisualizedExpression GetMostDerived() * { * foreach (var child in MemberExpressions) * { * var eval = child.Value.EvaluationResult as DkmSuccessEvaluationResult; * if (eval != null && eval.Category == DkmEvaluationResultCategory.MostDerivedClass) * { * return child.Value; * } * } * * return null; * } */ private void EvaluateChildren() { MemberExpressions = new Dictionary <string, DkmChildVisualizedExpression>(); // @TODO: Am assuming that if expr_ is a child expression, it would be more // efficient to use its EvaluationResult property instead of invoking the default // evaluator again. However, doing this results in using child UObject expressions which // have been generated using the custom visualization (since ! specifier is not recursive). // We really don't want this since we just want the default expansion so we can navigate // through the members and bases of the class. // Problem is, don't know how to communicate to the 'UseDefaultEvaluationBehavior' // implementation to use a default expansion in this particular case. Setting the data // item on expr_ before calling GetItemsCallback doesn't work, since the expression that // gets passed through is not actually expr_, but a root visualized expression that was // created by the EE when visualizing the parent, which we don't have access to. // As it is, now that we inline the default expansion alongside the addition of the // 'UE4 Properties' child, this does seem to work. However, not obvious there is any // performance improvement, also not 100% sure it's safe to use the stored evaluation. DkmEvaluationResult uobj_eval = null; if (expr_.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression) { uobj_eval = ((DkmChildVisualizedExpression)expr_).EvaluationResult; } else { uobj_eval = DefaultEE.DefaultEval(callback_expr_, true); } eval_ = (DkmSuccessEvaluationResult)uobj_eval; DkmEvaluationResult[] children; DkmEvaluationResultEnumContext enum_context; try { callback_expr_.GetChildrenCallback(uobj_eval, 0, callback_expr_.InspectionContext, out children, out enum_context); // @NOTE: Assuming count will not be large here!! callback_expr_.GetItemsCallback(enum_context, 0, enum_context.Count, out children); } catch { return; } uint idx = 0; foreach (var child_eval in children) { if (child_eval.TagValue == DkmEvaluationResult.Tag.SuccessResult) { var success_eval = child_eval as DkmSuccessEvaluationResult; Debug.Assert(success_eval != null); DkmExpressionValueHome home; if (success_eval.Address != null) { home = DkmPointerValueHome.Create(success_eval.Address.Value); } else { home = DkmFakeValueHome.Create(0); } DkmChildVisualizedExpression child = DkmChildVisualizedExpression.Create( child_eval.InspectionContext, callback_expr_.VisualizerId, callback_expr_.SourceId, child_eval.StackFrame, home, child_eval, expr_, idx, null ); MemberExpressions[child_eval.Name] = child; } ++idx; } }
public override void GetChildItems(DkmEvaluationResultEnumContext enumContext, int start, int count, out DkmChildVisualizedExpression[] items) { // Cap the requested number to the total remaining from startIndex count = Math.Min(count, enumContext.Count - start); items = new DkmChildVisualizedExpression[count]; uint idx = 0; // Retrieve the default expansion enum context var default_data = enumContext.GetDataItem <DefaultEnumContextDataItem>(); if (start < default_data.Context.Count) { // Requesting default children int default_count = Math.Min(count, default_data.Context.Count - start); DkmEvaluationResult[] default_evals; expression_.GetItemsCallback(default_data.Context, start, default_count, out default_evals); for (int dft_idx = 0; dft_idx < default_count; ++dft_idx, ++idx) { DkmSuccessEvaluationResult success_eval = default_evals[dft_idx] as DkmSuccessEvaluationResult; DkmExpressionValueHome home = null; if (success_eval != null && success_eval.Address != null) { home = DkmPointerValueHome.Create(success_eval.Address.Value); } else { home = DkmFakeValueHome.Create(0); } items[idx] = DkmChildVisualizedExpression.Create( enumContext.InspectionContext, expression_.VisualizerId, // @TODO: Check this is what we want. Will we get callbacks for it, regardless of its type? expression_.SourceId, enumContext.StackFrame, home, default_evals[dft_idx], expression_, (uint)start, null ); } } if (start + count > default_data.Context.Count) { // Requesting custom children // @NOTE: Currently just assuming only 1 custom child (prop list) and hard coding as such. // DkmSuccessEvaluationResult.ExtractFromProperty(IDebugProperty3!!!!!!!) ............................................... // @NOTE: Had thought could just create an expression with a null evaluation // inside it, and by giving it a visualizer guid, the system would call back // to us to evaluate the expression. Seems not to work though, I guess because the // visualizer guid identifies the visualizer but not the containing component, // and since the expression itself doesn't have a type, it can't know that it // should call our component. DkmEvaluationResult eval = DkmSuccessEvaluationResult.Create( enumContext.InspectionContext, enumContext.StackFrame, Resources.UE4PropVis.IDS_DISP_BLUEPRINTPROPERTIES, Resources.UE4PropVis.IDS_DISP_BLUEPRINTPROPERTIES, DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable, "", // @TODO: something like "[<count> properties]" null, "", // Type column DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None, DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None, null, null, null, null ); // This child is just for organization and does not correspond to anything in memory. DkmExpressionValueHome valueHome = DkmFakeValueHome.Create(0); var prop_list_expr = DkmChildVisualizedExpression.Create( enumContext.InspectionContext, Guids.Visualizer.PropertyList, // Associate the expression with ourselves, since we created it Guids.Component.VisualizerComponent, enumContext.StackFrame, valueHome, eval, expression_, idx, null ); // Create a visualizer for the property list, and attach it to the expression. var prop_list_visualizer = new PropertyListVisualizer(prop_list_expr, access_ctx_); prop_list_expr.SetDataItem(DkmDataCreationDisposition.CreateAlways, new ExpressionDataItem(prop_list_visualizer)); items[idx] = prop_list_expr; } }