private static bool TryCreateTMPMethodInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                         MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                         out BoundInvocationExpression createdInvocation)
        {
            if (symbol.ContainingType != null &&
                symbol.ContainingType.ToString() == "TMPro.TMP_Text")
            {
                createdInvocation = new BoundExternInvocation(node, context,
                                                              new ExternSynthesizedMethodSymbol(context, symbol.Name, instanceExpression.ValueType, symbol.Parameters.Select(e => e.Type).ToArray(), symbol.ReturnType, symbol.IsStatic),
                                                              instanceExpression,
                                                              parameterExpressions);

                return(true);
            }

            createdInvocation = null;
            return(false);
        }
        private static bool TryCreateBaseEnumMethodInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                              MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                              out BoundInvocationExpression createdInvocation)
        {
            if ((symbol.Name == "ToString" || symbol.Name == "GetHashCode" || symbol.Name == "Equals") &&
                symbol.ContainingType != null &&
                symbol.ContainingType == context.GetTypeSymbol(SpecialType.System_Enum))
            {
                createdInvocation = new BoundExternInvocation(node, context,
                                                              context.GetTypeSymbol(SpecialType.System_Object).GetMember <MethodSymbol>(symbol.Name, context),
                                                              instanceExpression,
                                                              parameterExpressions);

                return(true);
            }

            createdInvocation = null;
            return(false);
        }
        private static bool TryCreateArrayMethodInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                           MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                           out BoundInvocationExpression createdInvocation)
        {
            if ((symbol.Name == "IndexOf" || symbol.Name == "BinarySearch" || symbol.Name == "LastIndexOf" || symbol.Name == "Reverse") &&
                symbol.ContainingType == context.GetTypeSymbol(typeof(Array)))
            {
                MethodSymbol arrayMethod = context.GetTypeSymbol(typeof(Array))
                                           .GetMembers <MethodSymbol>(symbol.Name, context)
                                           .First(e => !e.RoslynSymbol.IsGenericMethod && e.Parameters.Length == symbol.Parameters.Length);

                createdInvocation = new BoundExternInvocation(node, context, arrayMethod, instanceExpression,
                                                              parameterExpressions);
                return(true);
            }

            createdInvocation = null;
            return(false);
        }
        /// <summary>
        /// Udon exposes a generic SetProgramVariable which the overload finding will attempt to use and fail to find,
        ///  so just use the non-generic version in this case
        /// </summary>
        private static bool TryCreateSetProgramVariableInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                                  MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                                  out BoundInvocationExpression createdInvocation)
        {
            if (symbol.Name == "SetProgramVariable" &&
                symbol.ContainingType == context.GetTypeSymbol(typeof(UdonBehaviour)))
            {
                MethodSymbol setProgramVarObjMethod = context.GetTypeSymbol(typeof(UdonBehaviour))
                                                      .GetMembers <MethodSymbol>("SetProgramVariable", context)
                                                      .First(e => !e.RoslynSymbol.IsGenericMethod);

                createdInvocation = new BoundExternInvocation(node, context, setProgramVarObjMethod, instanceExpression,
                                                              parameterExpressions);
                return(true);
            }

            createdInvocation = null;
            return(false);
        }
        private static bool TryCreateInstantiationInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                             MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                             out BoundInvocationExpression createdInvocation)
        {
            switch (symbol.Name)
            {
            case "Instantiate_Extern" when symbol.ContainingType == context.GetTypeSymbol(typeof(InstantiationShim)):
                createdInvocation = new BoundExternInvocation(node, context,
                                                              new ExternSynthesizedMethodSymbol(context,
                                                                                                "VRCInstantiate.__Instantiate__UnityEngineGameObject__UnityEngineGameObject",
                                                                                                parameterExpressions.Select(e => e.ValueType).ToArray(),
                                                                                                context.GetTypeSymbol(typeof(GameObject)), true),
                                                              instanceExpression, parameterExpressions);

                return(true);

            case "VRCInstantiate" when symbol.ContainingType == context.GetTypeSymbol(typeof(UdonSharpBehaviour)):     // Backwards compatibility for UdonSharpBehaviour.VRCInstantiate
            case "Instantiate" when symbol.ContainingType == context.GetTypeSymbol(typeof(UnityEngine.Object)):
            {
                if (symbol.Name != "VRCInstantiate" &&
                    (symbol.TypeArguments.Length != 1 ||
                     symbol.TypeArguments[0] != context.GetTypeSymbol(typeof(GameObject))))
                {
                    throw new NotSupportedException("Udon does not support instantiating non-GameObject types");
                }

                TypeSymbol   instantiateShim   = context.GetTypeSymbol(typeof(InstantiationShim));
                MethodSymbol instantiateMethod = instantiateShim.GetMembers <MethodSymbol>("Instantiate", context)
                                                 .First(e => e.Parameters
                                                        .Select(p => p.Type)
                                                        .SequenceEqual(parameterExpressions
                                                                       .Select(p => p.ValueType)));

                context.MarkSymbolReferenced(instantiateMethod);

                createdInvocation = new BoundStaticUserMethodInvocation(node, instantiateMethod, parameterExpressions);
                return(true);
            }
            }

            createdInvocation = null;
            return(false);
        }
        private static bool TryCreateCompareToInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                         MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                         out BoundInvocationExpression createdInvocation)
        {
            if (symbol.Name == "CompareTo" &&
                symbol.ContainingType != null &&
                symbol.ContainingType == context.GetTypeSymbol(typeof(IComparable)))
            {
                createdInvocation = new BoundExternInvocation(node, context,
                                                              new ExternSynthesizedMethodSymbol(context, "CompareTo", instanceExpression.ValueType,
                                                                                                new [] { instanceExpression.ValueType },
                                                                                                context.GetTypeSymbol(SpecialType.System_Int32), false),
                                                              instanceExpression, parameterExpressions);

                return(true);
            }

            createdInvocation = null;
            return(false);
        }