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