Пример #1
0
 public BoundExternInvocation(SyntaxNode node, AbstractPhaseContext context, MethodSymbol method, BoundExpression instanceExpression, BoundExpression[] parameterExpressions)
     : base(node, method, instanceExpression, parameterExpressions)
 {
     externMethodSymbol = (ExternMethodSymbol)method;
     if (!CompilerUdonInterface.IsExposedToUdon(externMethodSymbol.ExternSignature))
     {
         externMethodSymbol = FindAlternateInvocation(context, method, instanceExpression, parameterExpressions);
         if (externMethodSymbol == null)
         {
             throw new NotExposedException(LocStr.CE_UdonMethodNotExposed, node, $"{method.RoslynSymbol?.ToDisplayString() ?? method.ToString()}, sig: {((ExternMethodSymbol)method).ExternSignature}");
         }
     }
 }
Пример #2
0
        private ExternMethodSymbol FindAlternateInvocation(AbstractPhaseContext context, MethodSymbol originalSymbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions)
        {
            if (originalSymbol.IsStatic || originalSymbol.IsConstructor)
            {
                return(null);
            }

            List <TypeSymbol> candidates = new List <TypeSymbol>();

            FindCandidateInvocationTypes(context, candidates, instanceExpression.ValueType);

            TypeSymbol[] paramTypes = parameterExpressions.Select(ex => ex.ValueType).ToArray();

            foreach (TypeSymbol candidate in candidates)
            {
                ExternMethodSymbol externMethodSymbol = new ExternSynthesizedMethodSymbol(context, originalSymbol.Name, candidate, paramTypes, originalSymbol.ReturnType, false, false);
                if (CompilerUdonInterface.IsExposedToUdon(externMethodSymbol.ExternSignature))
                {
                    return(externMethodSymbol);
                }
            }

            return(null);
        }
Пример #3
0
        private void BuildExposedTypeList()
        {
            if (_exposedTypes != null)
            {
                return;
            }

            // Stopwatch timer = Stopwatch.StartNew();

            try
            {
                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();

                object         typeSetLock    = new object();
                HashSet <Type> exposedTypeSet = new HashSet <Type>();

                int mainThreadID = Thread.CurrentThread.ManagedThreadId;
                _assemblyCounter = 0;
                int totalAssemblies = assemblies.Length;

                Parallel.ForEach(assemblies, new ParallelOptions {
                    MaxDegreeOfParallelism = 3
                }, assembly =>
                {
                    if (assembly.FullName.Contains("UdonSharp") ||
                        assembly.FullName.Contains("CodeAnalysis"))
                    {
                        return;
                    }

                    Interlocked.Increment(ref _assemblyCounter);

                    if (Thread.CurrentThread.ManagedThreadId == mainThreadID) // Can only be called from the main thread, since Parallel.ForEach uses the calling thread for some loops we just only run this in that thread.
                    {
                        EditorUtility.DisplayProgressBar("Processing methods and types...", $"{_assemblyCounter}/{totalAssemblies}", _assemblyCounter / (float)totalAssemblies);
                    }

                    Type[] assemblyTypes = assembly.GetTypes();

                    List <Type> types = new List <Type>();

                    foreach (Type assemblyType in assemblyTypes)
                    {
                        types.Add(assemblyType);
                        types.AddRange(GetNestedTypes(assemblyType));
                    }

                    types = types.Distinct().ToList();

                    HashSet <Type> localExposedTypeSet = new HashSet <Type>();

                    foreach (Type type in types)
                    {
                        if (type.IsByRef)
                        {
                            continue;
                        }

                        string typeName = CompilerUdonInterface.GetUdonTypeName(type);
                        if (UdonEditorManager.Instance.GetTypeFromTypeString(typeName) != null)
                        {
                            localExposedTypeSet.Add(type);

                            if (!type.IsGenericType && !type.IsGenericTypeDefinition)
                            {
                                localExposedTypeSet.Add(type.MakeArrayType());
                            }
                        }

                        MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

                        foreach (MethodInfo method in methods)
                        {
                            if (CompilerUdonInterface.IsExposedToUdon(CompilerUdonInterface.GetUdonMethodName(method)))
                            {
                                localExposedTypeSet.Add(method.DeclaringType);

                                // We also want to highlight types that can be returned or taken as parameters
                                if (method.ReturnType != typeof(void) &&
                                    method.ReturnType.Name != "T" &&
                                    method.ReturnType.Name != "T[]")
                                {
                                    localExposedTypeSet.Add(method.ReturnType);

                                    if (!method.ReturnType.IsArray && !method.ReturnType.IsGenericType &&
                                        !method.ReturnType.IsGenericTypeDefinition)
                                    {
                                        localExposedTypeSet.Add(method.ReturnType.MakeArrayType());
                                    }
                                }

                                foreach (ParameterInfo parameterInfo in method.GetParameters())
                                {
                                    if (!parameterInfo.ParameterType.IsByRef)
                                    {
                                        localExposedTypeSet.Add(parameterInfo.ParameterType);

                                        if (!parameterInfo.ParameterType.IsArray)
                                        {
                                            localExposedTypeSet.Add(parameterInfo.ParameterType.MakeArrayType());
                                        }
                                    }
                                }
                            }
                        }

                        foreach (PropertyInfo property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
                        {
                            MethodInfo propertyGetter = property.GetGetMethod();
                            if (propertyGetter == null)
                            {
                                continue;
                            }

                            if (CompilerUdonInterface.IsExposedToUdon(CompilerUdonInterface.GetUdonMethodName(propertyGetter)))
                            {
                                Type returnType = propertyGetter.ReturnType;

                                localExposedTypeSet.Add(property.DeclaringType);

                                if (returnType != typeof(void) &&
                                    returnType.Name != "T" &&
                                    returnType.Name != "T[]")
                                {
                                    localExposedTypeSet.Add(returnType);

                                    if (!returnType.IsArray && !returnType.IsGenericType &&
                                        !returnType.IsGenericTypeDefinition)
                                    {
                                        localExposedTypeSet.Add(returnType.MakeArrayType());
                                    }
                                }
                            }
                        }

                        foreach (FieldInfo field in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
                        {
                            if (field.DeclaringType?.FullName ==
                                null) // Fix some weird types in Odin that don't have a name for their declaring type
                            {
                                continue;
                            }

                            if (CompilerUdonInterface.IsExposedToUdon(CompilerUdonInterface.GetUdonAccessorName(field, CompilerUdonInterface.FieldAccessorType.Get)))
                            {
                                Type returnType = field.FieldType;

                                localExposedTypeSet.Add(field.DeclaringType);

                                if (returnType != typeof(void) &&
                                    returnType.Name != "T" &&
                                    returnType.Name != "T[]")
                                {
                                    localExposedTypeSet.Add(returnType);

                                    if (!returnType.IsArray && !returnType.IsGenericType &&
                                        !returnType.IsGenericTypeDefinition)
                                    {
                                        localExposedTypeSet.Add(returnType.MakeArrayType());
                                    }
                                }
                            }
                        }
                    }

                    if (localExposedTypeSet.Count == 0)
                    {
                        return;
                    }

                    lock (typeSetLock)
                    {
                        exposedTypeSet.UnionWith(localExposedTypeSet);
                    }
                });

                _exposedTypes = exposedTypeSet.ToList();
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }

            _exposedTypes.RemoveAll(e => e.Name == "T" || e.Name == "T[]");

            // Debug.Log($"Elapsed time {timer.Elapsed.TotalSeconds * 1000.0}ms");
        }
Пример #4
0
        private void AddChildNode(TreeViewItem parentItem, MemberInfo memberInfo, ref int currentID)
        {
            var obsoleteAttribute = memberInfo.GetCustomAttribute <System.ObsoleteAttribute>();

            if (obsoleteAttribute != null)
            {
                return;
            }

            if (memberInfo.MemberType == MemberTypes.Property && (!((PropertyInfo)memberInfo).GetGetMethod()?.IsPublic ?? false))
            {
                return;
            }

            if (memberInfo.DeclaringType.IsEnum)
            {
                return;
            }

            string staticStr = "";
            {
                if ((memberInfo is FieldInfo fieldInfo && fieldInfo.IsStatic) ||
                    (memberInfo is PropertyInfo propertyInfo && (propertyInfo.GetGetMethod()?.IsStatic ?? false)) ||
                    (memberInfo is MethodInfo methodInfo && methodInfo.IsStatic))
                {
                    staticStr = "<Static>";
                }
            }

            TreeViewItem memberItem = new TreeViewItem(currentID++, parentItem.depth + 1, $"<{memberInfo.MemberType}>{staticStr} {memberInfo}");

            TypeItemMetadata itemMetadata = new TypeItemMetadata();

            itemMetadata.member = memberInfo;

            switch (memberInfo.MemberType)
            {
            case MemberTypes.Constructor:
            case MemberTypes.Method:
                itemMetadata.exposed = CompilerUdonInterface.IsExposedToUdon(CompilerUdonInterface.GetUdonMethodName((MethodBase)memberInfo));
                break;

            case MemberTypes.Field:
                string getAccessor = CompilerUdonInterface.GetUdonAccessorName((FieldInfo)memberInfo, CompilerUdonInterface.FieldAccessorType.Get);
                // string setAccessor = resolver.GetUdonFieldAccessorName((FieldInfo)memberInfo, CompilerUdonInterface.FieldAccessorType.Set, false);

                itemMetadata.exposed = CompilerUdonInterface.IsExposedToUdon(getAccessor);
                break;

            case MemberTypes.Property:
                MethodInfo getMethod = ((PropertyInfo)memberInfo).GetGetMethod();

                if (getMethod == null)
                {
                    return;
                }

                string getProperty = CompilerUdonInterface.GetUdonMethodName(getMethod);

                // if (((PropertyInfo)memberInfo).GetSetMethod() != null)
                // {
                //     string setProperty = resolver.GetUdonMethodName(((PropertyInfo)memberInfo).GetSetMethod(), false);
                // }

                itemMetadata.exposed = CompilerUdonInterface.IsExposedToUdon(getProperty);
                break;
            }

            parentItem.AddChild(memberItem);

            itemMetadatas.Add(memberItem, itemMetadata);
        }