void LogException(CompileTaskResult result, System.Exception e, SyntaxNode node, out string logMessage)
        {
            logMessage = "";

            if (node != null)
            {
                FileLinePositionSpan lineSpan = node.GetLocation().GetLineSpan();

                CompileError error = new CompileError();
                error.script   = programAsset.sourceCsScript;
                error.errorStr = $"{e.GetType()}: {e.Message}";
                error.lineIdx  = lineSpan.StartLinePosition.Line;
                error.charIdx  = lineSpan.StartLinePosition.Character;

                result.compileErrors.Add(error);
            }
            else
            {
                logMessage = e.ToString();
                Debug.LogException(e);
            }
#if UDONSHARP_DEBUG
            Debug.LogException(e);
            Debug.LogError(e.StackTrace);
#endif
        }
        public CompileTaskResult Compile(List <ClassDefinition> classDefinitions, Microsoft.CodeAnalysis.SyntaxTree syntaxTree, string sourceCode, bool isEditorBuild)
        {
            programAsset.compileErrors.Clear();

            CompileTaskResult result = new CompileTaskResult();

            result.programAsset = programAsset;

            moduleSymbols.OpenSymbolTable();

            UdonSharpFieldVisitor fieldVisitor = new UdonSharpFieldVisitor(fieldsWithInitializers);

            fieldVisitor.Visit(syntaxTree.GetRoot());

            MethodVisitor methodVisitor = new MethodVisitor(resolver, moduleSymbols, moduleLabels);

            int errorCount = 0;

            try
            {
                methodVisitor.Visit(syntaxTree.GetRoot());
            }
            catch (System.Exception e)
            {
                LogException(result, e, methodVisitor.visitorContext.currentNode, out string logMessage);

                programAsset.compileErrors.Add(logMessage);

                errorCount++;
            }

            if (ErrorCount > 0)
            {
                return(result);
            }

            ClassDebugInfo debugInfo = null;

            if (settings == null || settings.buildDebugInfo)
            {
                debugInfo = new ClassDebugInfo(sourceCode, settings == null || settings.includeInlineCode);
            }

            ASTVisitor visitor = new ASTVisitor(resolver, moduleSymbols, moduleLabels, methodVisitor.definedMethods, classDefinitions, debugInfo);

            try
            {
                visitor.Visit(syntaxTree.GetRoot());
                visitor.VerifyIntegrity();
            }
            catch (System.Exception e)
            {
                LogException(result, e, visitor.visitorContext.currentNode, out string logMessage);

                programAsset.compileErrors.Add(logMessage);

                errorCount++;
            }

            if (errorCount > 0)
            {
                return(result);
            }

            moduleSymbols.CloseSymbolTable();

            if (errorCount == 0)
            {
                compiledClassDefinition = classDefinitions.Find(e => e.userClassType == visitor.visitorContext.behaviourUserType);

                string dataBlock = BuildHeapDataBlock();
                string codeBlock = visitor.GetCompiledUasm();

                result.compiledAssembly = dataBlock + codeBlock;
                result.symbolCount      = (uint)(moduleSymbols.GetAllUniqueChildSymbols().Count + visitor.GetExternStrCount());

                programAsset.behaviourIDHeapVarName = visitor.GetIDHeapVarName();

                programAsset.fieldDefinitions = visitor.visitorContext.localFieldDefinitions;
#if UDON_BETA_SDK
                programAsset.behaviourSyncMode = visitor.visitorContext.behaviourSyncMode;
#endif

                if (debugInfo != null)
                {
                    debugInfo.FinalizeDebugInfo();
                }

                UdonSharpEditorCache.Instance.SetDebugInfo(programAsset, isEditorBuild ? UdonSharpEditorCache.DebugInfoType.Editor : UdonSharpEditorCache.DebugInfoType.Client, debugInfo);
                //programAsset.debugInfo = debugInfo;
            }

            return(result);
        }
Пример #3
0
        public void Compile()
        {
            Profiler.BeginSample("UdonSharp Compile");

            System.Diagnostics.Stopwatch compileTimer = new System.Diagnostics.Stopwatch();
            compileTimer.Start();

            int totalErrorCount = 0;

            try
            {
                List <ClassDefinition> classDefinitions = BuildClassDefinitions();
                if (classDefinitions == null)
                {
                    totalErrorCount++;
                }

                if (totalErrorCount == 0)
                {
#if UDONSHARP_DEBUG // Single threaded compile
                    List <CompileTaskResult> compileTasks = new List <CompileTaskResult>();

                    foreach (CompilationModule module in modules)
                    {
                        compileTasks.Add(module.Compile(classDefinitions));
                    }
#else
                    List <Task <CompileTaskResult> > compileTasks = new List <Task <CompileTaskResult> >();

                    foreach (CompilationModule module in modules)
                    {
                        compileTasks.Add(Task.Factory.StartNew(() => module.Compile(classDefinitions)));
                    }
#endif

                    int totalTaskCount = compileTasks.Count;

                    while (compileTasks.Count > 0)
                    {
#if UDONSHARP_DEBUG
                        CompileTaskResult compileResult = compileTasks.Last();
                        compileTasks.RemoveAt(compileTasks.Count - 1);
#else
                        Task <CompileTaskResult> compileResultTask = Task.WhenAny(compileTasks).Result;
                        compileTasks.Remove(compileResultTask);

                        CompileTaskResult compileResult = compileResultTask.Result;
#endif

                        if (compileResult.compileErrors.Count == 0)
                        {
                            compileResult.programAsset.SetUdonAssembly(compileResult.compiledAssembly);
                            compileResult.programAsset.AssembleCsProgram(compileResult.symbolCount);
                        }
                        else
                        {
                            foreach (CompileError error in compileResult.compileErrors)
                            {
                                string errorMessage = UdonSharpUtils.LogBuildError(error.errorStr,
                                                                                   AssetDatabase.GetAssetPath(error.script).Replace("/", "\\"),
                                                                                   error.lineIdx,
                                                                                   error.charIdx);

                                compileResult.programAsset.compileErrors.Add(errorMessage);
                            }

                            totalErrorCount += compileResult.compileErrors.Count;
                        }

                        int processedTaskCount = totalTaskCount - compileTasks.Count;

                        EditorUtility.DisplayProgressBar("UdonSharp Compile",
                                                         $"Compiling scripts ({processedTaskCount}/{totalTaskCount})...",
                                                         Mathf.Clamp01((processedTaskCount / ((float)totalTaskCount + 1f))));
                    }

                    if (totalErrorCount == 0)
                    {
                        EditorUtility.DisplayProgressBar("UdonSharp Compile", "Assigning constants...", 1f);
                        int initializerErrorCount = AssignHeapConstants();
                        totalErrorCount += initializerErrorCount;

                        if (initializerErrorCount == 0)
                        {
                            foreach (CompilationModule module in modules)
                            {
                                module.programAsset.ApplyProgram();
                            }
                        }
                    }
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }

            compileTimer.Stop();

            EditorUtility.ClearProgressBar();

            if (totalErrorCount == 0)
            {
                if (modules.Length > 5)
                {
                    Debug.Log($"[UdonSharp] Compile of {modules.Length} scripts finished in {compileTimer.Elapsed.ToString("mm\\:ss\\.fff")}");
                }
                else
                {
                    Debug.Log($"[UdonSharp] Compile of script{(modules.Length > 1 ? "s" : "")} {string.Join(", ", modules.Select(e => Path.GetFileName(AssetDatabase.GetAssetPath(e.programAsset.sourceCsScript))))} finished in {compileTimer.Elapsed.ToString("mm\\:ss\\.fff")}");
                }
            }

            Profiler.EndSample();
        }
        public CompileTaskResult Compile(List <ClassDefinition> classDefinitions)
        {
            programAsset.compileErrors.Clear();

            SyntaxTree tree = CSharpSyntaxTree.ParseText(sourceCode);

            CompileTaskResult result = new CompileTaskResult();

            result.programAsset = programAsset;

            int errorCount = 0;

            foreach (Diagnostic diagnostic in tree.GetDiagnostics())
            {
                if (diagnostic.Severity == DiagnosticSeverity.Error)
                {
                    errorCount++;

                    LinePosition linePosition = diagnostic.Location.GetLineSpan().StartLinePosition;

                    CompileError error = new CompileError();
                    error.script   = programAsset.sourceCsScript;
                    error.errorStr = $"error {diagnostic.Descriptor.Id}: {diagnostic.GetMessage()}";
                    error.lineIdx  = linePosition.Line;
                    error.charIdx  = linePosition.Character;

                    result.compileErrors.Add(error);
                }
            }

            if (errorCount > 0)
            {
                return(result);
            }

            moduleSymbols.OpenSymbolTable();

            UdonSharpFieldVisitor fieldVisitor = new UdonSharpFieldVisitor(fieldsWithInitializers);

            fieldVisitor.Visit(tree.GetRoot());

            MethodVisitor methodVisitor = new MethodVisitor(resolver, moduleSymbols, moduleLabels);

            methodVisitor.Visit(tree.GetRoot());

            ClassDebugInfo debugInfo = null;

            if (settings == null || settings.buildDebugInfo)
            {
                debugInfo = new ClassDebugInfo(sourceCode, settings == null || settings.includeInlineCode);
            }

            ASTVisitor visitor = new ASTVisitor(resolver, moduleSymbols, moduleLabels, methodVisitor.definedMethods, classDefinitions, debugInfo);

            try
            {
                visitor.Visit(tree.GetRoot());
                visitor.VerifyIntegrity();
            }
            catch (System.Exception e)
            {
                SyntaxNode currentNode = visitor.visitorContext.currentNode;

                string logMessage = "";

                if (currentNode != null)
                {
                    FileLinePositionSpan lineSpan = currentNode.GetLocation().GetLineSpan();

                    CompileError error = new CompileError();
                    error.script   = programAsset.sourceCsScript;
                    error.errorStr = $"{e.GetType()}: {e.Message}";
                    error.lineIdx  = lineSpan.StartLinePosition.Line;
                    error.charIdx  = lineSpan.StartLinePosition.Character;

                    result.compileErrors.Add(error);
                }
                else
                {
                    logMessage = e.ToString();
                    Debug.LogException(e);
                }
#if UDONSHARP_DEBUG
                Debug.LogException(e);
                Debug.LogError(e.StackTrace);
#endif

                programAsset.compileErrors.Add(logMessage);

                errorCount++;
            }

            if (errorCount > 0)
            {
                return(result);
            }

            moduleSymbols.CloseSymbolTable();

            if (errorCount == 0)
            {
                compiledClassDefinition = classDefinitions.Find(e => e.userClassType == visitor.visitorContext.behaviourUserType);

                string dataBlock = BuildHeapDataBlock();
                string codeBlock = visitor.GetCompiledUasm();

                result.compiledAssembly = dataBlock + codeBlock;
                result.symbolCount      = (uint)(moduleSymbols.GetAllUniqueChildSymbols().Count + visitor.GetExternStrCount());

                programAsset.behaviourIDHeapVarName = visitor.GetIDHeapVarName();

                programAsset.fieldDefinitions = visitor.visitorContext.localFieldDefinitions;

                if (debugInfo != null)
                {
                    debugInfo.FinalizeDebugInfo();
                }

                programAsset.debugInfo = debugInfo;
            }

            return(result);
        }