A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections;
3using UnityEditor;
4
5namespace UnityEngine.TestTools
6{
7 /// <summary>
8 /// `RecompileScripts` is an <see cref="IEditModeTestYieldInstruction"/> that you can yield in Edit Mode tests. It lets you trigger a recompilation of scripts in the Unity Editor.
9 /// </summary>
10 public class RecompileScripts : IEditModeTestYieldInstruction
11 {
12 /// <summary>
13 /// Creates a new instance of the `RecompileScripts` yield instruction.
14 /// <example>
15 /// <code>
16 /// [UnitySetUp]
17 /// public IEnumerator SetUp()
18 /// {
19 /// using (var file = File.CreateText("Assets/temp/myScript.cs"))
20 /// {
21 /// file.Write("public class ATempClass { }");
22 /// }
23 /// AssetDatabase.Refresh();
24 /// yield return new RecompileScripts();
25 /// }
26 /// </code>
27 /// </example>
28 /// </summary>
29 public RecompileScripts() : this(true)
30 {
31 }
32 /// <summary>
33 /// Creates a new instance of the `RecompileScripts` yield instruction.
34 /// </summary>
35 /// <param name="expectScriptCompilation">This parameter indicates if you expect a script compilation to start (defaults to true). If a script compilation does not start and `expectScriptCompilation` is true, then it throws an exception.</param>
36 public RecompileScripts(bool expectScriptCompilation) : this(expectScriptCompilation, true)
37 {
38 }
39
40 /// <summary>
41 /// Creates a new instance of the `RecompileScripts` yield instruction.
42 /// </summary>
43 /// <param name="expectScriptCompilation">This parameter indicates if you expect a script compilation to start (defaults to true). If a script compilation does not start and `expectScriptCompilation` is `true`, then it throws an exception.</param>
44 /// <param name="expectScriptCompilationSuccess">This parameter indicates if you expect a script compilation to succeed. If not succeeded then an exception will be thrown.</param>
45 public RecompileScripts(bool expectScriptCompilation, bool expectScriptCompilationSuccess)
46 {
47 ExpectScriptCompilation = expectScriptCompilation;
48 ExpectScriptCompilationSuccess = expectScriptCompilationSuccess;
49 ExpectDomainReload = true;
50 }
51
52 /// <summary>
53 /// Returns true if the instruction expects a domain reload to occur.
54 /// </summary>
55 public bool ExpectDomainReload { get; private set; }
56 /// <summary>
57 /// Returns true if the instruction expects the Unity Editor to be in **Play Mode**.
58 /// </summary>
59 public bool ExpectedPlaymodeState { get; }
60 /// <summary>
61 /// Indicates whether a script compilation is expected.
62 /// </summary>
63 public bool ExpectScriptCompilation { get; private set; }
64 /// <summary>
65 /// Indicates whether the expected script compilation is expected to succeed.
66 /// </summary>
67 public bool ExpectScriptCompilationSuccess { get; private set; }
68
69 /// <summary>
70 /// The current active instance of the RecompileScripts yield instruction.
71 /// </summary>
72 public static RecompileScripts Current { get; private set; }
73
74 /// <summary>
75 /// Perform the multi step instruction of triggering a recompilation of scripts and waiting for its completion.
76 /// </summary>
77 /// <returns>An IEnumerator with the async steps.</returns>
78 /// <exception cref="Exception">Throws an exception if the editor does not need to recompile scripts or if the script compilation failed when expected to succeed.</exception>
79 public IEnumerator Perform()
80 {
81 Current = this;
82
83 // We need to yield, to give the test runner a chance to prepare for the domain reload
84 // If the script compilation happens very fast, then EditModeRunner.MoveNextAndUpdateYieldObject will not have a chance to set m_CurrentYieldObject
85 // This really should be fixed in EditModeRunner.MoveNextAndUpdateYieldObject
86 yield return null;
87
88 AssetDatabase.Refresh();
89
90 if (ExpectScriptCompilation && !EditorApplication.isCompiling)
91 {
92 Current = null;
93 throw new Exception("Editor does not need to recompile scripts");
94 }
95
96 EditorApplication.UnlockReloadAssemblies();
97
98 while (EditorApplication.isCompiling)
99 {
100 yield return null;
101 }
102
103 Current = null;
104
105 if (ExpectScriptCompilationSuccess && EditorUtility.scriptCompilationFailed)
106 {
107 EditorApplication.LockReloadAssemblies();
108 throw new Exception("Script compilation failed");
109 }
110 }
111 }
112}