コード例 #1
0
        public void Compile()
        {
            Profiler.BeginSample("UdonSharp Compile");

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

            int totalErrorCount = 0;

            try
            {
                EditorUtility.DisplayProgressBar("UdonSharp Compile", "Parsing Syntax Trees...", 0f);

                UdonSharpProgramAsset[] allPrograms = UdonSharpProgramAsset.GetAllUdonSharpPrograms();
                List <(UdonSharpProgramAsset, string)> programAssetsAndPaths = new List <(UdonSharpProgramAsset, string)>();

                foreach (UdonSharpProgramAsset programAsset in allPrograms)
                {
                    if (programAsset == null || programAsset.sourceCsScript == null)
                    {
                        continue;
                    }

                    programAssetsAndPaths.Add((programAsset, AssetDatabase.GetAssetPath(programAsset.sourceCsScript)));
                }

                UdonSharpProgramAsset[] programAssetsToCompile = modules.Select(e => e.programAsset).Where(e => e != null && e.sourceCsScript != null).ToArray();

                try
                {
                    beforeCompile?.Invoke(programAssetsToCompile);
                }
                catch (System.Exception e)
                {
                    Debug.LogError($"Exception thrown by pre compile listener\n{e}");
                }

                object syntaxTreeLock = new object();
                List <(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)> programsAndSyntaxTrees = new List <(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)>();
                Dictionary <UdonSharpProgramAsset, (string, Microsoft.CodeAnalysis.SyntaxTree)> syntaxTreeSourceLookup = new Dictionary <UdonSharpProgramAsset, (string, Microsoft.CodeAnalysis.SyntaxTree)>();

                string[] defines = UdonSharpUtils.GetProjectDefines(isEditorBuild);

                Parallel.ForEach(programAssetsAndPaths, (currentProgram) =>
                {
                    string programSource = UdonSharpUtils.ReadFileTextSync(currentProgram.Item2);

                    Microsoft.CodeAnalysis.SyntaxTree programSyntaxTree = CSharpSyntaxTree.ParseText(programSource, CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.None).WithPreprocessorSymbols(defines));

                    lock (syntaxTreeLock)
                    {
                        programsAndSyntaxTrees.Add((currentProgram.Item1, programSyntaxTree));
                        syntaxTreeSourceLookup.Add(currentProgram.Item1, (programSource, programSyntaxTree));
                    }
                });
コード例 #2
0
        public static void Compile(UdonSharpCompileOptions options = null)
        {
            if (options == null)
                options = new UdonSharpCompileOptions();

            if (UdonSharpUtils.DoesUnityProjectHaveCompileErrors())
            {
                UdonSharpUtils.LogError("All Unity C# compiler errors must be resolved before running an UdonSharp compile.");
                return;
            }
            
            if (CurrentJob != null)
            {
                _compileQueued = true;
                _queuedOptions = options;
                return;
            }
            
            Localization.Loc.InitLocalization();

            UdonSharpProgramAsset[] allPrograms = UdonSharpProgramAsset.GetAllUdonSharpPrograms();

            bool hasError = !ValidateProgramAssetCollisions(allPrograms);
            
            Dictionary<string, ProgramAssetInfo> rootProgramLookup = new Dictionary<string, ProgramAssetInfo>();
            foreach (UdonSharpProgramAsset udonSharpProgram in allPrograms)
            {
                if (udonSharpProgram.sourceCsScript == null)
                {
                    UdonSharpUtils.LogError($"Source C# script on {udonSharpProgram} is null", udonSharpProgram);
                    hasError = true;
                    continue;
                }

                string assetPath = AssetDatabase.GetAssetPath(udonSharpProgram.sourceCsScript);
                
                if (string.IsNullOrEmpty(assetPath))
                {
                    UdonSharpUtils.LogError($"Source C# script on {udonSharpProgram} is null", udonSharpProgram);
                    hasError = true;
                    continue;
                }
                
                rootProgramLookup.Add(assetPath.Replace('\\', '/'), new ProgramAssetInfo() { programAsset = udonSharpProgram ? udonSharpProgram : null, scriptClass = udonSharpProgram != null ? udonSharpProgram.GetClass() : null });
            }

            if (hasError)
            {
                UdonSharpEditorCache.Instance.LastCompileDiagnostics = new []
                    {
                        new UdonSharpEditorCache.CompileDiagnostic()
                        {
                            file = "",
                            message = "Compile validation failed, check console output for details.",
                            severity = DiagnosticSeverity.Error,
                        } 
                    };
                
                return;
            }
            
            // var allSourcePaths = new HashSet<string>(UdonSharpProgramAsset.GetAllUdonSharpPrograms().Where(e => e.isV1Root).Select(e => AssetDatabase.GetAssetPath(e.sourceCsScript).Replace('\\', '/')));
            HashSet<string> allSourcePaths = new HashSet<string>(CompilationContext.GetAllFilteredSourcePaths(options.IsEditorBuild));

            if (!ValidateUdonSharpBehaviours(allPrograms, allSourcePaths))
                return;

            CompilationContext compilationContext = new CompilationContext(options);
            string[] defines = UdonSharpUtils.GetProjectDefines(options.IsEditorBuild);

            EditorApplication.LockReloadAssemblies();

            Task compileTask = new Task(() => Compile(compilationContext, rootProgramLookup, allSourcePaths, defines));
            CurrentJob = new CompileJob() { Context = compilationContext, Task = compileTask, CompileTimer = Stopwatch.StartNew(), CompileOptions = options };
            
            compileTask.Start();
        }
コード例 #3
0
        public void Compile()
        {
            Profiler.BeginSample("UdonSharp Compile");

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

            int totalErrorCount = 0;

            try
            {
                EditorUtility.DisplayProgressBar("UdonSharp Compile", "Initializing...", 0f);

                UdonSharpProgramAsset[] allPrograms = UdonSharpProgramAsset.GetAllUdonSharpPrograms();
                List <(UdonSharpProgramAsset, string)> programAssetsAndPaths = new List <(UdonSharpProgramAsset, string)>();

                foreach (UdonSharpProgramAsset programAsset in allPrograms)
                {
                    if (programAsset == null)
                    {
                        continue;
                    }

                    if (programAsset.sourceCsScript == null)
                    {
                        Debug.LogWarning($"[<color=#FF00FF>UdonSharp</color>] Program asset '{AssetDatabase.GetAssetPath(programAsset)}' is missing a source C# script");
                        continue;
                    }

                    programAssetsAndPaths.Add((programAsset, AssetDatabase.GetAssetPath(programAsset.sourceCsScript)));

                    programAsset.compileErrors.Clear(); // Clear compile errors to keep them from stacking if not resolved
                }

                CheckProgramAssetCollisions(allPrograms);

                UdonSharpProgramAsset[] programAssetsToCompile = modules.Select(e => e.programAsset).Where(e => e != null && e.sourceCsScript != null).ToArray();

                EditorUtility.DisplayProgressBar("UdonSharp Compile", "Executing pre-build events...", 0f);

                try
                {
                    beforeCompile?.Invoke(programAssetsToCompile);
                }
                catch (System.Exception e)
                {
                    Debug.LogError($"Exception thrown by pre compile listener\n{e}");
                }

                EditorUtility.DisplayProgressBar("UdonSharp Compile", "Parsing Syntax Trees...", 0f);

                object syntaxTreeLock = new object();
                List <(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)> programsAndSyntaxTrees = new List <(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)>();
                Dictionary <UdonSharpProgramAsset, (string, Microsoft.CodeAnalysis.SyntaxTree)> syntaxTreeSourceLookup = new Dictionary <UdonSharpProgramAsset, (string, Microsoft.CodeAnalysis.SyntaxTree)>();

                string[] defines = UdonSharpUtils.GetProjectDefines(isEditorBuild);

                Parallel.ForEach(programAssetsAndPaths, (currentProgram) =>
                {
                    string programSource = UdonSharpUtils.ReadFileTextSync(currentProgram.Item2);

#pragma warning disable CS1701 // Warning about System.Collections.Immutable versions potentially not matching
                    Microsoft.CodeAnalysis.SyntaxTree programSyntaxTree = CSharpSyntaxTree.ParseText(programSource, CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.None).WithPreprocessorSymbols(defines));
#pragma warning restore CS1701

                    lock (syntaxTreeLock)
                    {
                        programsAndSyntaxTrees.Add((currentProgram.Item1, programSyntaxTree));
                        syntaxTreeSourceLookup.Add(currentProgram.Item1, (programSource, programSyntaxTree));
                    }
                });
コード例 #4
0
        private static bool UpgradeScripts(UdonSharpProgramAsset[] programAssets)
        {
            if (programAssets.Length == 0)
            {
                return(false);
            }

            if (programAssets.All(e => e.ScriptVersion >= UdonSharpProgramVersion.CurrentVersion))
            {
                return(false);
            }

            CompilationContext compilationContext = new CompilationContext(new UdonSharpCompileOptions());

            ModuleBinding[] bindings = compilationContext.LoadSyntaxTreesAndCreateModules(CompilationContext.GetAllFilteredSourcePaths(false), UdonSharpUtils.GetProjectDefines(false));

            CSharpCompilation compilation = CSharpCompilation.Create(
                $"UdonSharpRoslynUpgradeAssembly{_assemblyCounter++}",
                bindings.Select(e => e.tree),
                CompilationContext.GetMetadataReferences(),
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            bool scriptUpgraded  = false;
            bool versionUpgraded = false;

            foreach (var programAsset in programAssets)
            {
                string        assetPath = AssetDatabase.GetAssetPath(programAsset.sourceCsScript);
                ModuleBinding binding   = bindings.FirstOrDefault(e => e.filePath == assetPath);

                if (binding == null)
                {
                    continue;
                }

                if (programAsset.ScriptVersion < UdonSharpProgramVersion.V1SerializationUpdate)
                {
                    SyntaxTree    bindingTree  = binding.tree;
                    SemanticModel bindingModel = compilation.GetSemanticModel(bindingTree);

                    SerializationUpdateSyntaxRewriter rewriter = new SerializationUpdateSyntaxRewriter(bindingModel);

                    SyntaxNode newRoot = rewriter.Visit(bindingTree.GetRoot());

                    if (rewriter.Modified)
                    {
                        try
                        {
                            File.WriteAllText(binding.filePath, newRoot.ToFullString(), Encoding.UTF8);
                            scriptUpgraded = true;

                            UdonSharpUtils.Log($"Upgraded field serialization attributes on U# script '{binding.filePath}'", programAsset.sourceCsScript);
                        }
                        catch (Exception e)
                        {
                            UdonSharpUtils.LogError($"Could not upgrade U# script, exception: {e}");
                        }
                    }
                    // We expect this to come through a second time after scripts have been updated and change the version on the asset.
                    else
                    {
                        programAsset.ScriptVersion = UdonSharpProgramVersion.V1SerializationUpdate;
                        EditorUtility.SetDirty(programAsset);
                        versionUpgraded = true;
                    }
                }
            }

            if (scriptUpgraded)
            {
                AssetDatabase.Refresh();
                return(true);
            }

            if (versionUpgraded)
            {
                UdonSharpCompilerV1.CompileSync(new UdonSharpCompileOptions());
            }

            return(false);
        }