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