Ejemplo n.º 1
0
        public ExternTypeSymbol(INamedTypeSymbol sourceSymbol, AbstractPhaseContext context)
            : base(sourceSymbol, context)
        {
            TryGetSystemType(sourceSymbol, out Type systemType);
            SystemType = systemType;

            Type udonType = UdonSharpUtils.UserTypeToUdonType(SystemType);

            UdonType = (ExternTypeSymbol)(udonType == SystemType ? this : context.GetUdonTypeSymbol(sourceSymbol));

            ExternSignature = CompilerUdonInterface.GetUdonTypeName(this);
        }
        private string BuildExternSignature(TypeSymbol containingType, string methodName)
        {
            Type methodSourceType = containingType.UdonType.SystemType;

            methodSourceType = UdonSharpUtils.RemapBaseType(methodSourceType);

            string functionNamespace = CompilerUdonInterface.SanitizeTypeName(methodSourceType.FullName ?? methodSourceType.Namespace + methodSourceType.Name).Replace("VRCUdonUdonBehaviour", "VRCUdonCommonInterfacesIUdonEventReceiver");

            methodName = $"__{methodName}";
            var parameters = Parameters;

            string paramStr = "";

            if (parameters.Length > 0)
            {
                paramStr = "_"; // Arg separator

                foreach (ParameterSymbol parameter in parameters)
                {
                    paramStr += $"_{CompilerUdonInterface.GetUdonTypeName(parameter.Type)}";
                }
            }
            else if (IsConstructor)
            {
                paramStr = "__";
            }

            string returnStr;

            if (!IsConstructor)
            {
                returnStr = ReturnType != null ? $"__{CompilerUdonInterface.GetUdonTypeName(ReturnType)}" : "__SystemVoid";
            }
            else
            {
                returnStr = $"__{CompilerUdonInterface.GetUdonTypeName(containingType)}";
            }

            string finalFunctionSig = $"{functionNamespace}.{methodName}{paramStr}{returnStr}";

            return(finalFunctionSig);
        }
Ejemplo n.º 3
0
        private string GetSignature(AbstractPhaseContext context)
        {
            System.Type methodSourceType = ContainingType.UdonType.SystemType;

            methodSourceType = UdonSharpUtils.RemapBaseType(methodSourceType);

            if (methodSourceType == typeof(string) &&
                (Parameters[0].Type.UdonType.SystemType == typeof(object) ||
                 Parameters[1].Type.UdonType.SystemType == typeof(object)))
            {
                return("SystemString.__Concat__SystemObject_SystemObject__SystemString");
            }

            string functionNamespace = CompilerUdonInterface.SanitizeTypeName(methodSourceType.FullName ??
                                                                              methodSourceType.Namespace + methodSourceType.Name);

            string methodName = $"__{GetOperatorUdonName().Trim('_').TrimStart('.')}";
            var    parameters = RoslynSymbol.Parameters;

            string paramStr = "_";                                                                                  // Arg separator

            if (parameters.Length > 1 || methodName.Contains("UnaryMinus") || methodName.Contains("UnaryNegation")) // Binary operators
            {
                foreach (IParameterSymbol parameter in parameters)
                {
                    paramStr +=
                        $"_{CompilerUdonInterface.GetUdonTypeName(context.GetTypeSymbol(parameter.Type))}";
                }
            }
            else // Unary operators, we just use the regular binary operator internally and handle it in the bound operator
            {
                paramStr += $"_{CompilerUdonInterface.GetUdonTypeName(context.GetTypeSymbol(parameters[0].Type))}";
                paramStr += $"_{CompilerUdonInterface.GetUdonTypeName(context.GetTypeSymbol(parameters[0].Type))}";
            }

            string returnStr =
                $"__{CompilerUdonInterface.GetUdonTypeName(ReturnType)}";

            return($"{functionNamespace}.{methodName}{paramStr}{returnStr}");
        }
Ejemplo n.º 4
0
        private static PropertySymbol BuildProperty(AbstractPhaseContext context, BoundExpression sourceExpression)
        {
            TypeSymbol arrayType   = sourceExpression.ValueType;
            TypeSymbol elementType = arrayType.ElementType;

            Type systemType = arrayType.ElementType.UdonType.SystemType;

            if (systemType == typeof(UnityEngine.Object) ||
                systemType.IsSubclassOf(typeof(UnityEngine.Object)))
            {
                arrayType = context.GetTypeSymbol(SpecialType.System_Object).MakeArrayType(context);
            }

            string arrayTypeName        = CompilerUdonInterface.GetMethodTypeName(arrayType.UdonType);
            string arrayElementTypeName = CompilerUdonInterface.GetUdonTypeName(arrayType.UdonType.ElementType);

            TypeSymbol   intType   = context.GetTypeSymbol(SpecialType.System_Int32);
            MethodSymbol setMethod = new ExternSynthesizedMethodSymbol(context, $"{arrayTypeName}.__Set__SystemInt32_{arrayElementTypeName}__SystemVoid",
                                                                       new[] { intType, elementType }, null, false);
            MethodSymbol getMethod = new ExternSynthesizedMethodSymbol(context, $"{arrayTypeName}.__Get__SystemInt32__{arrayElementTypeName}",
                                                                       new[] { intType }, elementType, false);

            return(new SynthesizedPropertySymbol(context, getMethod, setMethod));
        }
Ejemplo n.º 5
0
        protected override TreeViewItem BuildRoot()
        {
            BuildExposedTypeList();

            itemMetadatas.Clear();
            hiearchyItems.Clear();

            TreeViewItem root = new TreeViewItem(0, -1);

            itemMetadatas.Add(root, new TypeItemMetadata());
            int currentID = 1;

            // Build the namespace sections first
            foreach (Type type in _exposedTypes)
            {
                string typeNamespace = type.Namespace;
                if (string.IsNullOrEmpty(typeNamespace))
                {
                    if (type.GetElementType() != null && type.GetElementType().Namespace != null)
                    {
                        typeNamespace = type.GetElementType().Namespace;
                    }
                }
                TreeViewItem namespaceItem = GetNamespaceParent(typeNamespace, root, ref currentID);
            }

            int currentTypeCount = 0;

            foreach (Type type in _exposedTypes.OrderBy(e => e.Name))
            {
                if (currentTypeCount % 30 == 0)
                {
                    EditorUtility.DisplayProgressBar("Adding types...", $"Adding type {type}", currentTypeCount / (float)_exposedTypes.Count);
                }

                currentTypeCount++;

                // if (ShouldHideTypeTopLevel(type, true))
                //     continue;

                string typeNamespace = type.Namespace;
                if (string.IsNullOrEmpty(typeNamespace))
                {
                    if (type.GetElementType() != null && type.GetElementType().Namespace != null)
                    {
                        typeNamespace = type.GetElementType().Namespace;
                    }
                }

                TreeViewItem namespaceParent = GetNamespaceParent(typeNamespace, root, ref currentID);

                string typeTypeName = "";

                if (type.IsEnum)
                {
                    typeTypeName = " <enum>";
                }
                else if (type.IsValueType)
                {
                    typeTypeName = " <struct>";
                }
                else if (type.IsArray)
                {
                    typeTypeName = " <array>";
                }
                else
                {
                    typeTypeName = " <class>";
                }

                TreeViewItem typeParent = new TreeViewItem(currentID++, namespaceParent.depth + 1, type.Name + typeTypeName);
                namespaceParent.AddChild(typeParent);
                itemMetadatas.Add(typeParent, new TypeItemMetadata()
                {
                    isType = true
                });

                //if (!type.IsEnum)
                //{
                //    // Variable definition
                //    TreeViewItem variableDef = new TreeViewItem(currentID++, typeParent.depth + 1, "<variable> " + type.Name);
                //    typeParent.AddChild(variableDef);
                //    itemMetadatas.Add(variableDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Variable) });
                //}

                // Type definition
                //TreeViewItem typeDef = new TreeViewItem(currentID++, typeParent.depth + 1, "<type> " + type.Name);
                //typeParent.AddChild(typeDef);
                //itemMetadatas.Add(typeDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Type) });

                // Internal type
                TreeViewItem internalTypeDef = new TreeViewItem(currentID++, typeParent.depth + 1, "<Type> " + type.Name);
                typeParent.AddChild(internalTypeDef);
                itemMetadatas.Add(internalTypeDef, new TypeItemMetadata()
                {
                    exposed = UdonEditorManager.Instance.GetTypeFromTypeString(CompilerUdonInterface.GetUdonTypeName(type)) != null
                });

                // Const definition
                //if (!type.IsArray && !type.IsEnum)
                //{
                //    TreeViewItem constDef = new TreeViewItem(currentID++, typeParent.depth + 1, "<const> " + type.Name);
                //    typeParent.AddChild(constDef);
                //    itemMetadatas.Add(constDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Const) });
                //}

                BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;
                if (!showBaseTypeMembers)
                {
                    bindingFlags |= BindingFlags.DeclaredOnly;
                }

                foreach (ConstructorInfo constructor in type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly))
                {
                    AddChildNode(typeParent, constructor, ref currentID);
                }

                foreach (FieldInfo field in type.GetFields(bindingFlags))
                {
                    AddChildNode(typeParent, field, ref currentID);
                }

                foreach (PropertyInfo property in type.GetProperties(bindingFlags))
                {
                    AddChildNode(typeParent, property, ref currentID);
                }

                if (!type.IsEnum)
                {
                    foreach (MethodInfo method in type.GetMethods(bindingFlags).Where(e => (!type.IsArray || e.Name != "Address")))
                    {
                        if (method.IsSpecialName && !method.Name.StartsWith("op_"))
                        {
                            continue;
                        }

                        AddChildNode(typeParent, method, ref currentID);
                    }
                }
            }

            EditorUtility.ClearProgressBar();

            BuildDrawInfo(root);

            //foreach (string exposedExtern in exposedUdonExterns)
            //{
            //    Debug.Log(exposedExtern);
            //}

            return(root);
        }
Ejemplo n.º 6
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");
        }