Ejemplo n.º 1
0
        private static bool TryCreateGetComponentInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                            MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions,
                                                            out BoundInvocationExpression createdInvocation)
        {
            if (symbol.RoslynSymbol != null &&
                symbol.RoslynSymbol.IsGenericMethod &&
                symbol.TypeArguments.Length == 1 &&
                _getComponentNames.Contains(symbol.Name) &&
                (symbol.ContainingType.UdonType.SystemType == typeof(Component) || symbol.ContainingType.UdonType.SystemType == typeof(GameObject)))
            {
                TypeSymbol gameObjectType = context.GetTypeSymbol(typeof(GameObject));
                TypeSymbol typeArgument   = symbol.TypeArguments[0];

                // udon-workaround: Work around the udon bug where it checks the strongbox type instead of variable type and blows up when the strong box is `object`
                if (instanceExpression.ValueType == gameObjectType)
                {
                    PropertySymbol accessProperty = gameObjectType.GetMember <PropertySymbol>("transform", context);
                    instanceExpression = BoundAccessExpression.BindAccess(context, node, accessProperty, instanceExpression);
                }
                else
                {
                    PropertySymbol accessProperty = context.GetTypeSymbol(typeof(Component)).GetMember <PropertySymbol>("transform", context);
                    instanceExpression = BoundAccessExpression.BindAccess(context, node, accessProperty, instanceExpression);
                }

                TypeSymbol udonSharpBehaviourType = context.GetTypeSymbol(typeof(UdonSharpBehaviour));

                // Exact UdonSharpBehaviour type match
                if (typeArgument == udonSharpBehaviourType)
                {
                    MethodSymbol getComponentMethodShim = context.GetTypeSymbol(typeof(GetComponentShim))
                                                          .GetMembers <MethodSymbol>(symbol.Name + "USB", context)
                                                          .First(e => e.Parameters.Length == parameterExpressions.Length + 1);

                    createdInvocation = new BoundStaticUserMethodInvocation(node, getComponentMethodShim,
                                                                            new [] { instanceExpression }.Concat(parameterExpressions).ToArray());

                    context.MarkSymbolReferenced(getComponentMethodShim);

                    return(true);
                }

                // Subclass of UdonSharpBehaviour
                if (typeArgument.IsUdonSharpBehaviour)
                {
                    // Handle inherited types
                    if (context.CompileContext.HasInheritedUdonSharpBehaviours(typeArgument))
                    {
                        MethodSymbol getComponentInheritedMethodShim = context.GetTypeSymbol(typeof(GetComponentShim))
                                                                       .GetMembers <MethodSymbol>(symbol.Name + "I", context)
                                                                       .First(e => e.Parameters.Length == parameterExpressions.Length + 1);

                        getComponentInheritedMethodShim = getComponentInheritedMethodShim.ConstructGenericMethod(context, new [] { typeArgument });

                        createdInvocation = new BoundStaticUserMethodInvocation(node, getComponentInheritedMethodShim,
                                                                                new [] { instanceExpression }.Concat(parameterExpressions).ToArray());

                        context.MarkSymbolReferenced(getComponentInheritedMethodShim);

                        return(true);
                    }

                    MethodSymbol getComponentMethodShim = context.GetTypeSymbol(typeof(GetComponentShim))
                                                          .GetMembers <MethodSymbol>(symbol.Name, context)
                                                          .First(e => e.Parameters.Length == parameterExpressions.Length + 1);

                    getComponentMethodShim = getComponentMethodShim.ConstructGenericMethod(context, new [] { typeArgument });

                    createdInvocation = new BoundStaticUserMethodInvocation(node, getComponentMethodShim,
                                                                            new [] { instanceExpression }.Concat(parameterExpressions).ToArray());

                    context.MarkSymbolReferenced(getComponentMethodShim);

                    return(true);
                }

                if (_brokenGetComponentTypes.Contains(typeArgument.UdonType.SystemType))
                {
                    MethodSymbol getComponentInheritedMethodShim = context.GetTypeSymbol(typeof(GetComponentShim))
                                                                   .GetMembers <MethodSymbol>(symbol.Name + "VRC", context)
                                                                   .First(e => e.Parameters.Length == parameterExpressions.Length + 1);

                    getComponentInheritedMethodShim = getComponentInheritedMethodShim.ConstructGenericMethod(context, new [] { typeArgument });

                    createdInvocation = new BoundStaticUserMethodInvocation(node, getComponentInheritedMethodShim,
                                                                            new [] { instanceExpression }.Concat(parameterExpressions).ToArray());

                    context.MarkSymbolReferenced(getComponentInheritedMethodShim);

                    return(true);
                }

                createdInvocation = new BoundGetUnityEngineComponentInvocation(context, node, symbol,
                                                                               instanceExpression,
                                                                               parameterExpressions);

                return(true);
            }

            createdInvocation = null;
            return(false);
        }