コード例 #1
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);
        }
コード例 #2
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));
        }
コード例 #3
0
 public static bool IsUserDefinedEnum(System.Type type)
 {
     return((type.IsEnum && !CompilerUdonInterface.IsExternType(type)) ||
            (type.IsArray && type.GetElementType().IsEnum&& !CompilerUdonInterface.IsExternType(type.GetElementType())));
 }
コード例 #4
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);
        }
コード例 #5
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");
        }
コード例 #6
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);
        }
コード例 #7
0
 public UdonSharpBehaviourMethodSymbol(IMethodSymbol sourceSymbol, AbstractPhaseContext context)
     : base(sourceSymbol, context)
 {
     IsUdonEvent           = CompilerUdonInterface.IsUdonEvent(sourceSymbol.Name);
     ExportedMethodAddress = new ExportAddress(ExportAddress.AddressKind.String, this);
 }
コード例 #8
0
        private static void Compile(CompilationContext compilationContext, IReadOnlyDictionary<string, ProgramAssetInfo> rootProgramLookup, IEnumerable<string> allSourcePaths, string[] scriptingDefines)
        {
            Stopwatch setupTimer = Stopwatch.StartNew();
            
            CompilerUdonInterface.CacheInit();
            CompilerUdonInterface.AssemblyCacheInit();
            
            compilationContext.CurrentPhase = CompilationContext.CompilePhase.Setup;
            ModuleBinding[] syntaxTrees = compilationContext.LoadSyntaxTreesAndCreateModules(allSourcePaths, scriptingDefines);

            foreach (ModuleBinding binding in syntaxTrees)
            {
                foreach (Diagnostic diag in binding.tree.GetDiagnostics())
                {
                    if (diag.Severity != Microsoft.CodeAnalysis.DiagnosticSeverity.Error) continue;
                    
                    compilationContext.AddDiagnostic(DiagnosticSeverity.Error, diag.Location, $"{diag.Severity.ToString().ToLower()} {diag.Id}: {diag.GetMessage()}");
                }
            }

            if (compilationContext.ErrorCount > 0)
                return;

            List<ModuleBinding> rootTrees = new List<ModuleBinding>();
            
            foreach (ModuleBinding treeBinding in syntaxTrees)
            {
                if (rootProgramLookup.ContainsKey(treeBinding.filePath))
                {
                    ProgramAssetInfo info = rootProgramLookup[treeBinding.filePath];
                    treeBinding.programAsset = info.programAsset;
                    treeBinding.programClass = info.scriptClass;
                    // ReSharper disable once Unity.NoNullPropagation
                    treeBinding.programScript = treeBinding?.programAsset?.sourceCsScript;
                    
                    rootTrees.Add(treeBinding);
                }
            }
            
            PrintStageTime("U# Setup", setupTimer);
            
            Stopwatch roslynCompileTimer = Stopwatch.StartNew();

            compilationContext.CurrentPhase = CompilationContext.CompilePhase.RoslynCompile;
            
            // Run compilation for the semantic views
            CSharpCompilation compilation = CSharpCompilation.Create(
                $"UdonSharpRoslynCompileAssembly{_assemblyCounter++}",
                syntaxTrees.Select(e => e.tree),
                CompilationContext.GetMetadataReferences(),
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, concurrentBuild: compilationContext.Options.ConcurrentBuild));

            PrintStageTime("Roslyn Compile", roslynCompileTimer);

            compilationContext.RoslynCompilation = compilation;

            byte[] builtAssembly = null;
            
            Stopwatch roslynEmitTimer = Stopwatch.StartNew();
            
            using (MemoryStream memoryStream = new MemoryStream())
            {
                EmitResult emitResult = compilation.Emit(memoryStream);
                if (emitResult.Success)
                {
                    builtAssembly = memoryStream.ToArray();
                }
                else
                {
                    foreach (Diagnostic diag in emitResult.Diagnostics)
                    {
                        if (diag.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error)
                        {
                            compilationContext.AddDiagnostic(DiagnosticSeverity.Error, diag.Location, $"{diag.Severity.ToString().ToLower()} {diag.Id}: {diag.GetMessage()}");
                        }
                    }
                }
            }
            
            PrintStageTime("Roslyn Emit", roslynEmitTimer);

            if (compilationContext.ErrorCount > 0)
                return;

            foreach (ModuleBinding tree in syntaxTrees)
                tree.semanticModel = compilation.GetSemanticModel(tree.tree);

            ConcurrentBag<(INamedTypeSymbol, ModuleBinding)> rootUdonSharpTypes = new ConcurrentBag<(INamedTypeSymbol, ModuleBinding)>();
            HashSet<INamedTypeSymbol> typesWithAssociatedProgramAssets = new HashSet<INamedTypeSymbol>();
            object programTypesLock = new object();

            Parallel.ForEach(rootTrees, new ParallelOptions { MaxDegreeOfParallelism = MAX_PARALLELISM}, module =>
            {
                SemanticModel model = module.semanticModel;
                SyntaxTree tree = model.SyntaxTree;

                INamedTypeSymbol udonSharpBehaviourDeclaration = null;

                foreach (ClassDeclarationSyntax classDecl in tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
                {
                    if (model.GetDeclaredSymbol(classDecl) is INamedTypeSymbol classType && classType.IsUdonSharpBehaviour())
                    {
                        if (!classType.IsAbstract && classType.Name != Path.GetFileNameWithoutExtension(module.filePath))
                        {
                            compilationContext.AddDiagnostic(DiagnosticSeverity.Error, classType.DeclaringSyntaxReferences.First().GetSyntax(), "UdonSharpBehaviour classes must have the same name as their containing .cs file");
                            return;
                        }

                        if (!ReferenceEquals(module.programScript, null) &&
                            ReferenceEquals(module.programClass, null))
                        {
                            compilationContext.AddDiagnostic(DiagnosticSeverity.Error, classType.DeclaringSyntaxReferences.First().GetSyntax(), "Could not retrieve C# class, make sure the MonoBehaviour class name matches the name of the .cs file and Unity has had a chance to compile the C# script.");
                            return;
                        }
                        
                        if (!ReferenceEquals(module.programAsset, null) && classType.Name == Path.GetFileNameWithoutExtension(module.filePath))
                        {
                            if (classType.IsAbstract)
                            {
                                compilationContext.AddDiagnostic(DiagnosticSeverity.Error, classType.DeclaringSyntaxReferences.First().GetSyntax(), "Abstract U# behaviours cannot have an associated U# program asset");
                                return;
                            }
                            
                            if (classType.IsGenericType)
                            {
                                compilationContext.AddDiagnostic(DiagnosticSeverity.Error, classType.DeclaringSyntaxReferences.First().GetSyntax(), "Generic U# behaviours cannot have an associated U# program asset");
                                return;
                            }
                        }
                        
                        if (classType.IsAbstract || classType.IsGenericType)
                            continue;

                        // If there are multiple UdonSharpBehaviours declared in the same behaviour, they need to be partial classes of the same class
                        // We'll skip adding them as roots in that case
                        if (udonSharpBehaviourDeclaration == null)
                        {
                            udonSharpBehaviourDeclaration = classType;
                            rootUdonSharpTypes.Add((classType, module));
                        }
                    }
                }
コード例 #9
0
        public static BoundInvocationExpression CreateBoundInvocation(AbstractPhaseContext context, SyntaxNode node,
                                                                      MethodSymbol symbol, BoundExpression instanceExpression, BoundExpression[] parameterExpressions)
        {
            if (TryCreateShimInvocation(context, node, symbol, instanceExpression, parameterExpressions, out var boundShimInvocation))
            {
                return(boundShimInvocation);
            }

            if (symbol.IsExtern)
            {
                if (CompilerUdonInterface.IsUdonEvent(symbol.Name) &&
                    symbol.ContainingType == context.GetTypeSymbol(typeof(UdonSharpBehaviour))) // Pass through for making base calls on the U# behaviour type return noop
                {
                    return(new BoundUdonSharpBehaviourInvocationExpression(node, symbol, instanceExpression, parameterExpressions));
                }

                if (symbol.IsOperator)
                {
                    // Enum equality/inequality
                    if (symbol.ContainingType?.IsEnum ?? false)
                    {
                        MethodSymbol objectEqualsMethod = context.GetTypeSymbol(SpecialType.System_Object)
                                                          .GetMember <MethodSymbol>("Equals", context);

                        var boundEqualsInvocation = CreateBoundInvocation(context, node, objectEqualsMethod, parameterExpressions[0],
                                                                          new[] { parameterExpressions[1] });
                        if (symbol.Name == "op_Equality")
                        {
                            return(boundEqualsInvocation);
                        }

                        MethodSymbol boolNotOperator = new ExternSynthesizedOperatorSymbol(
                            BuiltinOperatorType.UnaryNegation, context.GetTypeSymbol(SpecialType.System_Boolean),
                            context);

                        return(new BoundExternInvocation(node, context, boolNotOperator, null, new BoundExpression[] { boundEqualsInvocation }));
                    }

                    if (node is AssignmentExpressionSyntax)
                    {
                        return(new BoundCompoundAssignmentExpression(context, node, (BoundAccessExpression)parameterExpressions[0], symbol, parameterExpressions[1]));
                    }

                    if (symbol is ExternBuiltinOperatorSymbol externBuiltinOperatorSymbol &&
                        externBuiltinOperatorSymbol.OperatorType == BuiltinOperatorType.BitwiseNot)
                    {
                        return(new BoundBitwiseNotExpression(node, parameterExpressions[0]));
                    }

                    if (parameterExpressions.Length == 2 || symbol.Name == "op_UnaryNegation" || symbol.Name == "op_LogicalNot")
                    {
                        return(new BoundBuiltinOperatorInvocationExpression(node, context, symbol, parameterExpressions));
                    }

                    throw new NotSupportedException("Operator expressions must have either 1 or 2 parameters", node.GetLocation());
                }

                return(new BoundExternInvocation(node, context, symbol, instanceExpression, parameterExpressions));
            }

            if (symbol.IsStatic)
            {
                return(new BoundStaticUserMethodInvocation(node, symbol, parameterExpressions));
            }

            if (symbol is UdonSharpBehaviourMethodSymbol udonSharpBehaviourMethodSymbol)
            {
                if (instanceExpression != null && !instanceExpression.IsThis)
                {
                    udonSharpBehaviourMethodSymbol.MarkNeedsReferenceExport();
                }

                return(new BoundUdonSharpBehaviourInvocationExpression(node, symbol, instanceExpression,
                                                                       parameterExpressions));
            }

            throw new System.NotImplementedException();
        }
コード例 #10
0
        protected override bool HandlesTypeSerialization(TypeSerializationMetadata typeMetadata)
        {
            VerifyTypeCheckSanity();

            return(typeMetadata.cSharpType.IsEnum && !CompilerUdonInterface.IsExternType(typeMetadata.cSharpType));
        }