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 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); }