private void FindFunctionTypes(Function function, bool makeNewStuffUp)
        {
            var code = ainFile.DecompiledCodeCache.GetDecompiledCode(function);

            foreach (var e in code.GetChildExpressions())
            {
                if (e.ExpressionType == Instruction.CALLFUNC2 || e.ExpressionType == Instruction.FT_ASSIGNS)
                {
                    int       funcTypeIndex    = -1;
                    IVariable funcTypeVariable = null;
                    if (e.ExpressionType == Instruction.CALLFUNC2)
                    {
                        funcTypeIndex    = e.Arg2.Value;
                        funcTypeVariable = e.Arg1.Variable.Canonicalize();
                    }
                    else if (e.ExpressionType == Instruction.FT_ASSIGNS)
                    {
                        funcTypeIndex    = e.Arg3.Value;
                        funcTypeVariable = e.Arg1.Variable.Canonicalize();
                    }
                    if (funcTypeVariable == null)
                    {
                        var arg1 = e.Arg1;
                        if (arg1 != null)
                        {
                            arg1 = arg1.Arg1;
                        }
                        if (arg1 != null)
                        {
                            funcTypeVariable = arg1.Variable;
                        }
                        if (funcTypeVariable != null)
                        {
                            funcTypeVariable = funcTypeVariable.Canonicalize();
                        }
                    }
                    if (funcTypeVariable != null && funcTypeVariable.StructType == -1)
                    {
                        matches.Clear();
                        finished.Clear();

                        var traceResults = TraceVariable(funcTypeVariable, VariableTraceMode.DirectCopiesRecursive);

                        foreach (var res in traceResults)
                        {
                            if (res.DataType.IsFuncType())
                            {
                                res.StructType = funcTypeIndex;
                            }
                        }
                        funcTypeVariable.StructType = funcTypeIndex;
                    }
                }
                else if (e.ExpressionType == Instruction.DG_CALLBEGIN)
                {
                    int       delegateIndex    = -1;
                    IVariable delegateVariable = null;
                    if (e.ExpressionType == Instruction.DG_CALLBEGIN)
                    {
                        delegateIndex    = e.Value;
                        delegateVariable = e.Arg2.Variable.Canonicalize();
                    }
                    if (delegateVariable == null)
                    {
                        var arg1 = e.Arg2;
                        if (arg1 != null)
                        {
                            arg1 = arg1.Arg1;
                        }
                        if (arg1 != null)
                        {
                            delegateVariable = arg1.Variable;
                        }
                        if (delegateVariable != null)
                        {
                            delegateVariable = delegateVariable.Canonicalize();
                        }
                    }
                    if (delegateVariable != null && delegateVariable.StructType == -1)
                    {
                        matches.Clear();
                        finished.Clear();
                        var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive);

                        foreach (var res in traceResults)
                        {
                            if (res.DataType.IsDelegate())
                            {
                                res.StructType = delegateIndex;
                            }
                        }
                        delegateVariable.StructType = delegateIndex;
                    }
                }
                else if (e.ExpressionType == Instruction.DG_STR_TO_METHOD)
                {
                    var otherExpression = e.GetOtherSideOfBinaryExpression();
                    int delegateIndex   = -1;
                    if (e.Arg2.ExpressionType == Instruction.PUSH)
                    {
                        delegateIndex = e.Arg2.Value;
                    }
                    IVariable delegateVariable = null;
                    if (otherExpression == null)
                    {
                        delegateVariable = e.GetFunctionCallParameter();
                        if (e.Parent != null && e.Parent.ExpressionType == Instruction.DG_ADD)
                        {
                            delegateVariable = e.Parent.Arg1.Variable.Canonicalize();
                        }
                        else
                        {
                        }
                    }
                    else
                    {
                        delegateVariable = otherExpression.Variable;
                        if (delegateVariable != null)
                        {
                            delegateVariable = delegateVariable.Canonicalize();
                        }
                        else
                        {
                        }
                    }
                    if (delegateVariable != null && delegateVariable.StructType == -1 && delegateIndex != -1)
                    {
                        matches.Clear();
                        finished.Clear();
                        var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive);

                        foreach (var res in traceResults)
                        {
                            if (res.DataType.IsDelegate())
                            {
                                res.StructType = delegateIndex;
                            }
                        }
                        delegateVariable.StructType = delegateIndex;
                    }
                }
                else if (e.ExpressionType == Instruction.DG_NEW_FROM_METHOD)
                {
                    var       otherExpression  = e.GetOtherSideOfBinaryExpression();
                    IVariable delegateVariable = null;
                    if (otherExpression == null)
                    {
                        delegateVariable = e.GetFunctionCallParameter();
                        if (e.Parent != null && e.Parent.ExpressionType == Instruction.DG_ADD)
                        {
                            delegateVariable = e.Parent.Arg1.Variable.Canonicalize();
                        }
                        else if (delegateVariable == null)
                        {
                        }
                    }
                    else
                    {
                        delegateVariable = otherExpression.Variable;
                    }
                    if (delegateVariable != null)
                    {
                        Function assignedFunction = null;
                        if (e.Arg2.ExpressionType == Instruction.PUSH)
                        {
                            assignedFunction = ainFile.GetFunction(e.Arg2.Value);
                        }
                        if (assignedFunction != null)
                        {
                            var          matchingTypes = ainFile.MatchingDelegates(assignedFunction);
                            FunctionType firstMatch = null, secondMatch = null;
                            foreach (var m in matchingTypes)
                            {
                                if (firstMatch == null)
                                {
                                    firstMatch = m;
                                }
                                else
                                {
                                    secondMatch = m;
                                    break;
                                }
                            }
                            if (firstMatch != null && (secondMatch == null || makeNewStuffUp))
                            {
                                int delegateIndex = firstMatch.Index;

                                if (delegateVariable.StructType == -1)
                                {
                                    matches.Clear();
                                    finished.Clear();
                                    var traceResults = TraceVariable(delegateVariable, VariableTraceMode.DirectCopiesRecursive);

                                    foreach (var res in traceResults)
                                    {
                                        if (res.DataType.IsDelegate())
                                        {
                                            res.StructType = delegateIndex;
                                        }
                                    }
                                    delegateVariable.StructType = delegateIndex;
                                }
                            }
                        }
                    }
                }
            }
        }