GetExpressionFullName() публичный статический Метод

public static GetExpressionFullName ( DkmVisualizedExpression expression ) : string
expression DkmVisualizedExpression
Результат string
Пример #1
0
        void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
        {
            Debug.Print("UE4PV: EvaluateVisualizedExpression('{0}'/'{1}', [{2}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue
                        );

            // Sanity check to confirm this is only being invoked for UObject types. @TODO: Remove eventually.
            // Believe this method is only invoked on DkmRootVisualizedExpression instances, not children.
            Debug.Assert(expression.VisualizerId == Guids.Visualizer.UObject);

            UE4Visualizer visualizer = null;
            bool          result     = UE4VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer);

            if (!result)
            {
                OnVisualizerMatchFailed(expression, out resultObject);
                return;
            }

            // Evaluate the visualization result
            DkmEvaluationResult eval = visualizer.EvaluationResult;

            resultObject = eval;

            // Associate the visualizer with the expression
            expression.SetDataItem <ExpressionDataItem>(
                DkmDataCreationDisposition.CreateAlways,
                new ExpressionDataItem(visualizer)
                );
        }
Пример #2
0
 void OnVisualizerMatchFailed(DkmVisualizedExpression expression, out DkmEvaluationResult result)
 {
     result = DkmFailedEvaluationResult.Create(
         expression.InspectionContext,
         expression.StackFrame,
         Utility.GetExpressionName(expression),
         Utility.GetExpressionFullName(expression),
         String.Format("UE4PropVis: No visualizer is registered for VisualizerId {0}", expression.VisualizerId),
         DkmEvaluationResultFlags.Invalid,
         null
         );
 }
Пример #3
0
        void IDkmCustomVisualizer.GetChildren(DkmVisualizedExpression expression, int initialRequestSize, DkmInspectionContext inspectionContext, out DkmChildVisualizedExpression[] initialChildren, out DkmEvaluationResultEnumContext enumContext)
        {
            Debug.Print("UE4PV: GetChildren('{0}'/'{1}', [{2}, {3}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue,
                        expression.VisualizerId
                        );

            var data_item  = expression.GetDataItem <ExpressionDataItem>();
            var visualizer = data_item.Visualizer;

            Debug.Assert(visualizer != null);

            visualizer.PrepareExpansion(out enumContext);
            initialChildren = new DkmChildVisualizedExpression[0];
        }
Пример #4
0
        void IDkmCustomVisualizer.UseDefaultEvaluationBehavior(DkmVisualizedExpression expression, out bool useDefaultEvaluationBehavior, out DkmEvaluationResult defaultEvaluationResult)
        {
            Debug.Print("UE4PV: UseDefaultEvaluationBehavior('{0}'/'{1}', [{2}, {3}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue,
                        expression.VisualizerId
                        );

            if (KUE4VS.ExtContext.Instance.ExtensionOptions.EnablePropVis)
            {
                var data_item = expression.GetDataItem <ExpressionDataItem>();
                if (data_item != null)
                {
                    Debug.Assert(data_item.Visualizer != null);

                    if (data_item.Visualizer.WantsCustomExpansion)
                    {
                        useDefaultEvaluationBehavior = false;
                        defaultEvaluationResult      = null;
                        return;
                    }
                }
            }

            // Don't need any special expansion, just delegate back to the default EE
            useDefaultEvaluationBehavior = true;

            /* @NOTE:
             * Not sure where exactly the problem is, but UObject properties don't expand in VS 2013.
             * When we try, there is an initial call to this method with the property's child expr,
             * so we come here, and do a default eval, which, if the prop is a UObject, will invoke
             * EvaluateVisualizedExpression above with a new root expr. In 2015, that is followed by
             * another call to this method for the root expr, which has an attached visualizer and we
             * do the custom expansion. In 2013, it seems the second call into this method does not
             * occur for some reason.
             */
            defaultEvaluationResult = DefaultEE.DefaultEval(expression, false);

/*
 *      Doing this will crash VS!
 *      DkmSuccessEvaluationResult.Create(null, null, "", "", DkmEvaluationResultFlags.None,
 *                              "", "", "", DkmEvaluationResultCategory.Other, DkmEvaluationResultAccessType.None,
 *                              DkmEvaluationResultStorageType.None, DkmEvaluationResultTypeModifierFlags.None,
 *                              null, null, null, null);
 */     }
Пример #5
0
        void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
        {
            if (KUE4VS.ExtContext.Instance.ExtensionOptions.EnablePropVis == false)
            {
                /*                var LangExpr = DkmLanguageExpression.Create(DefaultEE.CppLanguage, DkmEvaluationFlags.None, Utility.GetExpressionFullName(expression), null);
                 *              expression.EvaluateExpressionCallback(expression.InspectionContext, LangExpr, expression.StackFrame, out resultObject);
                 *              return;
                 */
                resultObject = null;
                return;
            }

            Debug.Print("UE4PV: EvaluateVisualizedExpression('{0}'/'{1}', [{2}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue
                        );

            // Sanity check to confirm this is only being invoked for UObject types. @TODO: Remove eventually.
            // Believe this method is only invoked on DkmRootVisualizedExpression instances, not children.
            Debug.Assert(expression.VisualizerId == Guids.Visualizer.UObject);

            UE4Visualizer visualizer = null;
            bool          result     = UE4VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer);

            if (!result)
            {
                OnVisualizerMatchFailed(expression, out resultObject);
                return;
            }

            // Evaluate the visualization result
            DkmEvaluationResult eval = visualizer.EvaluationResult;

            resultObject = eval;

            // Associate the visualizer with the expression
            expression.SetDataItem <ExpressionDataItem>(
                DkmDataCreationDisposition.CreateAlways,
                new ExpressionDataItem(visualizer)
                );
        }
Пример #6
0
        void IDkmCustomVisualizer.UseDefaultEvaluationBehavior(DkmVisualizedExpression expression, out bool useDefaultEvaluationBehavior, out DkmEvaluationResult defaultEvaluationResult)
        {
            Debug.Print("UE4PV: UseDefaultEvaluationBehavior('{0}'/'{1}', [{2}, {3}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue,
                        expression.VisualizerId
                        );

            var data_item = expression.GetDataItem <ExpressionDataItem>();

            if (data_item != null)
            {
                Debug.Assert(data_item.Visualizer != null);

                if (data_item.Visualizer.WantsCustomExpansion)
                {
                    useDefaultEvaluationBehavior = false;
                    defaultEvaluationResult      = null;
                    return;
                }
            }

            // Don't need any special expansion, just delegate back to the default EE
            useDefaultEvaluationBehavior = true;

            /* @NOTE:
             * Not sure where exactly the problem is, but UObject properties don't expand in VS 2013.
             * When we try, there is an initial call to this method with the property's child expr,
             * so we come here, and do a default eval, which, if the prop is a UObject, will invoke
             * EvaluateVisualizedExpression above with a new root expr. In 2014, that is followed by
             * another call to this method for the root expr, which has an attached visualizer and we
             * do the custom expansion. In 2013, it seems the second call into this method does not
             * occur for some reason.
             */
            defaultEvaluationResult = DefaultEE.DefaultEval(expression, false);
        }
Пример #7
0
        public static DkmEvaluationResult DefaultEval(DkmVisualizedExpression expression, bool raw_format)
        {
            string expr_text = Utility.GetExpressionFullName(expression);

            return(DefaultEval(expr_text, expression, raw_format));
        }
Пример #8
0
        public void EvaluateProperties()
        {
            List <DkmEvaluationResult> evals = new List <DkmEvaluationResult>();

            // Assume we've been constructed with the fabricated property list expression
            DkmChildVisualizedExpression proplist_expr = (DkmChildVisualizedExpression)expression_;

            Debug.Assert(proplist_expr != null);

            // start could be an expression with the type of any UObject-derived class
            DkmVisualizedExpression start_expr = proplist_expr.Parent;

            string base_expression_str = Utility.GetExpressionFullName(start_expr);

            base_expression_str = Utility.StripExpressionFormatting(base_expression_str);

            ExpressionManipulator obj_em = null;

            // @TODO: Deal with non-pointer start expression
            obj_em = ExpressionManipulator.FromExpression(base_expression_str);

            // Determine if our base expression is <UObject-type>* or <UObject-type>
            bool is_pointer = start_expr.GetDataItem <UObjectDataItem>().IsPointer;

            if (!is_pointer)
            {
                obj_em = obj_em.AddressOf();
            }

            var uclass_em = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass);

            if (Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly)
            {
                // See if the actual class of the object instance whose properties we want to enumerate
                // is native or not.
                var is_native_res = UE4Utility.TestUClassFlags(
                    uclass_em.Expression,
                    ClassFlags.Native,
                    start_expr
                    );

                // If the instance class is native, then it can't possibly have any non-native properties,
                // so bail out now.
                // @TODO: Even if the class is not native, we should still be able to avoid doing all the work
                // for enumerating every native property in order to find the non-native ones...
                // @TODO: How best to deal with failed is_native evaluation?
                if (is_native_res.IsValid && is_native_res.Value)
                {
                    return;
                }
            }

            // Get the UStruct part of the UClass, in order to begin iterating properties
            var ustruct_em = uclass_em.PtrCast(Typ.UStruct);
            // Now access PropertyLink member, which is the start of the linked list of properties
            var prop_em = ustruct_em.PtrMember(Memb.FirstProperty);

            uint idx = 0;

            while (true)
            {
                Debug.Print("UE4PV: Invoking raw eval on UProperty* expression");

                var prop_eval = DefaultEE.DefaultEval(prop_em.Expression, start_expr, true) as DkmSuccessEvaluationResult;
                Debug.Assert(prop_eval != null);

                if (prop_eval.Address.Value == 0)
                {
                    // nullptr, end of property list
                    break;
                }

                bool should_skip = false;

                if (!should_skip && Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly)
                {
                    // Check to see if this property is native or blueprint
                    // We can test this by getting the UProperty's Outer, and checking its object flags for RF_Native.
                    var prop_outer_em = prop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjOuter);

                    // @NOTE: RF_Native has gone, and checking for RF_MarkAsNative never seems to return true...
                    //var is_native_res = UE4Utility.TestUObjectFlags(prop_outer_em.Expression, ObjFlags.Native, start_expr);

                    // So, access class flags instead.
                    // Note that we make the assumption here that the property's outer is a UClass, which should be safe since
                    // we're starting out with a uobject, so all properties, including inherited ones, should be outered to a uclass.
                    var prop_outer_uclass_em = prop_outer_em.PtrCast(Typ.UClass);
                    var is_native_res        = UE4Utility.TestUClassFlags(prop_outer_uclass_em.Expression, ClassFlags.Native, start_expr);

                    // According to UE4 UStruct API docs, property linked list is ordered from most-derived
                    // to base. If so, we should be able to bail out here knowing that having hit a native property,
                    // all following properties must be native too.
                    if (is_native_res.IsValid && is_native_res.Value)
                    {
                        return;
                    }
                }

                if (!should_skip)
                {
                    // @TODO: Here we use the starting expression for the container.
                    // May not work if the root expression was not of pointer type!!
                    var prop_val_eval = GeneratePropertyValueEval(
                        obj_em.Expression,
                        prop_em.Expression,
                        idx,
                        start_expr
                        );
                    if (prop_val_eval != null && !Config.IsPropertyHidden(prop_val_eval.Name))
                    {
                        prop_evals_[prop_val_eval.Name] = prop_val_eval;
                        ++idx;
                    }
                }

                // Advance to next link
                prop_em = prop_em.PtrMember(Memb.NextProperty);
            }
        }
Пример #9
0
        protected void EvaluateExpressionResult()
        {
            // We're going to customize the unexpanded display string, as well as the expanded
            // view (if requested later).

            // @TODO: Really don't understand why, but when we invoke the default eval below, and we get
            // reentrant calls for child member UObjects, they are coming back as root expressions
            // with an empty FullName. This subsequently fails to evaluate if we pass it through to
            // default eval again. Perhaps this is somehow related to breaking the potential infinite
            // recursion of visualizing children in order to visualize the parent, but don't follow how it
            // it supposed to be dealt with.
            if (expression_.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression)
            {
                var as_root = expression_ as DkmRootVisualizedExpression;
                if (as_root.FullName.Length == 0)
                {
                    string display_str = "{...}";
                    eval_ = DkmSuccessEvaluationResult.Create(
                        expression_.InspectionContext,
                        expression_.StackFrame,
                        as_root.Name,
                        as_root.Name,
                        DkmEvaluationResultFlags.ReadOnly,
                        display_str,
                        "",
#if !VS2013
                        as_root.Type,
#else
                        "Unknown",
#endif
                        DkmEvaluationResultCategory.Other,
                        DkmEvaluationResultAccessType.None,
                        DkmEvaluationResultStorageType.None,
                        DkmEvaluationResultTypeModifierFlags.None,
                        null,
                        null,
                        null,
                        null
                        );
                    state_ = EvaluationState.MinimalEvaluation;
                    return;
                }
            }
            //

            string custom_display_str             = Resources.UE4PropVis.IDS_DISP_CONDENSED;
            DkmSuccessEvaluationResult proto_eval = null;
            bool   is_pointer;
            bool   is_null;
            string address_str = "";

            // @NOTE: Initially here we were executing the full default evaluation of our expression.
            // Problem is that this will call back into us for all UObject children of the expression,
            // because it needs to generate a visualization for them in order to construct its {member vals...} display string.
            // And then, we just ignore that anyway and display our own...

            // The following attempts to avoid that by casting our expression to void* and then evaluating that.
            // If it fails, we assume we are non-pointer. If it succeeds, we can determine from the result whether we are null or not.

            // @WARNING: This may not be so safe, since we can't determine whether evaluation failed because we tried to cast a non-pointer
            // to void*, or because the passed in expression was not valid in the first place. Believe we should be okay, since we should
            // only be receiving expressions that have already been determined to be suitable for our custom visualizer.

            // Ideally though, we'd be able to get a raw expression evaluation, without any visualization taking place.
            // Seems there must be a way to do this, but looks like it requires using a different API...
            const bool UseVoidCastOptimization = true;

            string default_expr_str = Utility.GetExpressionFullName(expression_);
            if (UseVoidCastOptimization)
            {
                default_expr_str = ExpressionManipulator.FromExpression(default_expr_str).PtrCast(Cpp.Void).Expression;
            }

            DkmEvaluationResult eval = DefaultEE.DefaultEval(default_expr_str, expression_, true);

            if (!UseVoidCastOptimization)
            {
                if (eval.TagValue != DkmEvaluationResult.Tag.SuccessResult)
                {
                    // Genuine failure to evaluate the passed in expression
                    eval_  = eval;
                    state_ = EvaluationState.Failed;
                    return;
                }
                else
                {
                    proto_eval         = (DkmSuccessEvaluationResult)eval;
                    custom_display_str = proto_eval.Value;

                    is_pointer = IsPointer(proto_eval);
                    is_null    = is_pointer && IsPointerNull(proto_eval);
                    // @TODO: need to extract address string
                }
            }
            else
            {
                DkmDataAddress address = null;
                if (eval.TagValue != DkmEvaluationResult.Tag.SuccessResult)
                {
                    // Assume the failure just implies the expression was non-pointer (thereby assuming that it was itself valid!)

                    // @TODO: Could actually fall back onto standard evaluation here, in order to determine for sure
                    // that the original expression is valid. Failure wouldn't be common since most of the time we are
                    // dealing with pointer expressions, so any potential optimization should still be gained.

                    is_pointer = false;
                    is_null    = false;
                }
                else
                {
                    var success = (DkmSuccessEvaluationResult)eval;
                    Debug.Assert(IsPointer(success));
                    is_pointer  = true;
                    is_null     = is_pointer && IsPointerNull(success);
                    address     = success.Address;
                    address_str = success.Value;
                }

                proto_eval = DkmSuccessEvaluationResult.Create(
                    expression_.InspectionContext,
                    expression_.StackFrame,
                    "",
                    "",
                    DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable,
                    "",
                    "",
#if !VS2013
                    Utility.GetExpressionType(expression_),
#else
                    is_pointer ? "UObject *" : "UObject",
#endif
                    DkmEvaluationResultCategory.Other,
                    DkmEvaluationResultAccessType.None,
                    DkmEvaluationResultStorageType.None,
                    DkmEvaluationResultTypeModifierFlags.None,
                    address,
                    null,
                    null,
                    null
                    );
            }

            string obj_expression_str = Utility.GetExpressionFullName(expression_);
            var    obj_em             = ExpressionManipulator.FromExpression(obj_expression_str);

            // Store pointer flags on the expression
            expression_.SetDataItem(
                DkmDataCreationDisposition.CreateAlways,
                new UObjectDataItem(is_pointer, is_null)
                );

            if (!is_pointer)
            {
                // All subsequent manipulations of the expression assume it starts as a pointer to a
                // UObject-derived class, so if our expression is to a dereferenced UObject, just
                // prefix an 'address of' to the expression string.
                obj_em = obj_em.AddressOf();
            }

            // Generate the condensed display string.
            if (is_null)
            {
                if (Config.CustomNullObjectPreview)
                {
                    custom_display_str = "<NULL> UObject";
                }
                else
                {
                    var null_eval = DefaultEE.DefaultEval("(void*)0", expression_, true) as DkmSuccessEvaluationResult;
                    custom_display_str = null_eval.Value + " <NULL>";
                }
            }
            else if (Config.DisplayUObjectPreview)
            {
                // Prefix the address, if this is a pointer expression
                string address_prefix_str = "";
                if (is_pointer)
                {
                    address_prefix_str = address_str + " ";
                }

                // Specialized display for UClass?
                bool uclass_specialized = false;
                if (Config.DisplaySpecializedUClassPreview)
                {
                    var    uclass_em = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass);
                    var    _uclass_fname_expr_str = uclass_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                    string _obj_uclass_name_str   = UE4Utility.GetFNameAsString(_uclass_fname_expr_str, expression_);
                    // @TODO: To simplify and for performance reasons, just hard coding known UClass variants
                    if (_obj_uclass_name_str == "Class" ||
                        _obj_uclass_name_str == "BlueprintGeneratedClass" ||
                        _obj_uclass_name_str == "WidgetBlueprintGeneratedClass")
                    {
                        var    fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                        string obj_name_str   = UE4Utility.GetFNameAsString(fname_expr_str, expression_);

                        var parent_uclass_fname_expr_str = obj_em.PtrCast(Typ.UStruct).PtrMember(Memb.SuperStruct).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                        // This will return null if lookup failed for any reason.
                        // We'll assume this meant no super class exists (ie. we're dealing with UClass itself)
                        string parent_uclass_name_str = UE4Utility.GetFNameAsString(parent_uclass_fname_expr_str, expression_);
                        if (parent_uclass_name_str == null)
                        {
                            parent_uclass_name_str = "None";
                        }

                        custom_display_str = String.Format(
                            "{0}{{ClassName='{1}', Parent='{2}'}}",
                            address_prefix_str,
                            obj_name_str,
                            parent_uclass_name_str
                            );
                        uclass_specialized = true;
                    }
                }

                if (!uclass_specialized)
                {
                    // For standard UObject condensed display string, show the object FName and its UClass.
                    // @TODO: The evaluations required for this may be a performance issue, since they'll be done for all UObject children of any default visualized
                    // aggregate type, even when it is not expanded (the default behaviour is to create a {...} display list of child member visualizations).
                    var    fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                    string obj_name_str   = UE4Utility.GetFNameAsString(fname_expr_str, expression_);

                    var    uclass_fname_expr_str = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                    string obj_uclass_name_str   = UE4Utility.GetFNameAsString(uclass_fname_expr_str, expression_);

                    custom_display_str = String.Format(
                        "{0}{{Name='{1}', Class='{2}'}}",
                        address_prefix_str,
                        obj_name_str,
                        obj_uclass_name_str
                        );
                }
            }

            eval_ = DkmSuccessEvaluationResult.Create(
                proto_eval.InspectionContext,
                proto_eval.StackFrame,
                // Override the eval name with the original expression name, since it will
                // have inherited the ",!" suffix.
                Utility.GetExpressionName(expression_),
                Utility.GetExpressionFullName(expression_),
                proto_eval.Flags,
                custom_display_str,                //success_eval.Value,
                proto_eval.EditableValue,
                proto_eval.Type,
                proto_eval.Category,
                proto_eval.Access,
                proto_eval.StorageType,
                proto_eval.TypeModifierFlags,
                proto_eval.Address,
                proto_eval.CustomUIVisualizers,
                proto_eval.ExternalModules,
                null
                );
            state_ = EvaluationState.Evaluated;
        }