Example #1
0
        /// <summary>
        /// Searches the class hierarchy to find the original owner of the given function (by function name)
        /// </summary>
        private UClass GetOriginalFunctionOwner(UFunction function, out UFunction originalFunction,
                                                out bool isInterfaceImplementation)
        {
            KeyValuePair <UFunction, bool> funcInfo;

            if (lazyOriginalFunctionCache.TryGetValue(function, out funcInfo))
            {
                originalFunction          = funcInfo.Key;
                isInterfaceImplementation = funcInfo.Value;
                return(originalFunction.GetOwnerClass());
            }
            UClass result = GetOriginalFunctionOwnerInternal(function, out originalFunction, out isInterfaceImplementation);

            lazyOriginalFunctionCache.Add(function, new KeyValuePair <UFunction, bool>(originalFunction, isInterfaceImplementation));
            return(result);
        }
Example #2
0
        private void AppendFunctionOffsets(CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder, UFunction function,
                                           bool isGetter, bool isSetter, List <string> namespaces)
        {
            bool   isInterface = false;
            UClass owner       = function.GetOwnerClass();

            if (owner != null && owner.ClassFlags.HasFlag(EClassFlags.Interface))
            {
                isInterface = true;
            }

            string functionName = GetFunctionName(function);

            if (isGetter)
            {
                functionName += "_getter";
            }
            else if (isSetter)
            {
                functionName += "_setter";
            }
            Dictionary <UProperty, string> paramNames = GetParamNames(function);

            if (Settings.GenerateIsValidSafeguards)
            {
                builder.AppendLine("static bool " + functionName + Settings.VarNames.IsValid + ";");
            }
            if ((function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent) && function.GetSuperFunction() == null) || isInterface)
            {
                builder.AppendLine("IntPtr " + functionName + Settings.VarNames.InstanceFunctionAddress + ";");
            }
            builder.AppendLine("static IntPtr " + functionName + Settings.VarNames.FunctionAddress + ";");
            builder.AppendLine("static int " + functionName + Settings.VarNames.ParamsSize + ";");

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffset(builder, functionName + "_" + paramName, parameter, true, namespaces);
            }

            offsetsBuilder.AppendLine(functionName + Settings.VarNames.FunctionAddress + " = " + Names.NativeReflectionCached_GetFunction +
                                      "(" + Settings.VarNames.ClassAddress + ", \"" + function.GetName() + "\");");
            offsetsBuilder.AppendLine(functionName + Settings.VarNames.ParamsSize + " = " + Names.NativeReflection_GetFunctionParamsSize +
                                      "(" + functionName + Settings.VarNames.FunctionAddress + ");");

            foreach (KeyValuePair <UProperty, string> param in paramNames)
            {
                UProperty parameter = param.Key;
                string    paramName = param.Value;

                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                AppendPropertyOffsetNativeTypeLoader(offsetsBuilder, functionName + "_" + paramName, parameter, functionName);
            }
            if (Settings.GenerateIsValidSafeguards)
            {
                // XXXX_IsValid = param1_IsValid && param2_IsValid && param3_IsValid;
                string paramsValid = string.Join(" && ", paramNames.Values.Select(x => functionName + "_" + x + Settings.VarNames.IsValid));
                if (!string.IsNullOrEmpty(paramsValid))
                {
                    paramsValid = " && " + paramsValid;
                }
                offsetsBuilder.AppendLine(functionName + Settings.VarNames.IsValid + " = " +
                                          functionName + Settings.VarNames.FunctionAddress + " != IntPtr.Zero" + paramsValid + ";");
                offsetsBuilder.AppendLine(Names.NativeReflection_LogFunctionIsValid + "(\"" + function.GetPathName() + "\", " +
                                          functionName + Settings.VarNames.IsValid + ");");
            }
        }
Example #3
0
        /// <summary>
        /// Searches the class hierarchy to find the original owner of the given function (by function name)
        /// </summary>
        private UClass GetOriginalFunctionOwnerInternal(UFunction function, out UFunction originalFunction,
                                                        out bool isInterfaceImplementation)
        {
            // Interfaces really mess up this function. Two interfaces could potentially provide the same function
            // in the class hierarchy. Or a class up the chain could provide a function but also an interface with
            // the same function name could exist. None of this maps to C# well in terms of ensuring this is all handled
            // properly AND with name conflict resolution (which is what GetOriginalFunctionOwner is partially used for).
            // - We ALWAYS want use the first interface found with the same function name in order to produce valid C#.
            //   (even if this then technically isn't necessarily the original function / owner).
            // - We should log when we find this type of situation where there are functions are redefined in a
            //   class / interface combo (regular class:class conflict should be fine).
            // - TODO: Handle interface hierarchy

            FName functionName = function.GetFName();

            isInterfaceImplementation = false;

            originalFunction = function;
            UClass owner = function.GetOwnerClass();

            if (owner != null)
            {
                // First check the interfaces of THIS class.
                foreach (FImplementedInterface implementedInterface in owner.Interfaces)
                {
                    UClass interfaceClass = implementedInterface.InterfaceClass;
                    if (interfaceClass != null)
                    {
                        UFunction interfaceFunction = interfaceClass.FindFunctionByName(functionName, false);
                        if (interfaceFunction != null)
                        {
                            originalFunction = interfaceFunction;
                            ValidateNoInterfaceFunctionConflict(owner, originalFunction, interfaceClass, true);

                            // We found the original function directly within one of the implemented interfaces.
                            // This means the input function is an implementation for one of the interfaces.
                            isInterfaceImplementation = true;
                            return(interfaceClass);
                        }
                    }
                }

                UClass parentClass = owner.GetSuperClass();
                while (parentClass != null)
                {
                    // Check the interfaces of the parent class.
                    foreach (FImplementedInterface implementedInterface in parentClass.Interfaces)
                    {
                        UClass interfaceClass = implementedInterface.InterfaceClass;
                        if (interfaceClass != null)
                        {
                            UFunction interfaceFunction = interfaceClass.FindFunctionByName(functionName, false);
                            if (interfaceFunction != null)
                            {
                                originalFunction = interfaceFunction;
                                ValidateNoInterfaceFunctionConflict(parentClass, originalFunction, interfaceClass, false);
                                return(interfaceClass);
                            }
                        }
                    }

                    UFunction parentFunction = parentClass.FindFunctionByName(functionName, false);
                    if (parentFunction == null)
                    {
                        break;
                    }
                    originalFunction = parentFunction;
                    owner            = parentClass;
                    parentClass      = parentClass.GetSuperClass();
                }
            }
            return(owner);
        }