11using System ;
22using System . Collections ;
3- using System . Collections . Generic ;
43using System . Diagnostics ;
54using System . IO ;
65using System . Linq ;
@@ -16,11 +15,9 @@ namespace Coffee.CSharpCompilerSettings
1615 [ InitializeOnLoad ]
1716 internal static class Core
1817 {
19- private static readonly Dictionary < string , bool > s_EnableAsmdefs = new Dictionary < string , bool > ( ) ;
20- private static readonly Dictionary < string , string > s_AssemblyNames = new Dictionary < string , string > ( ) ;
21- private static readonly bool IsGlobal ;
18+ public static bool IsGlobal { get ; private set ; }
2219
23- private static void DirtyScriptsIfNeeded ( )
20+ public static void DirtyScriptsIfNeeded ( )
2421 {
2522 var assemblyName = GetAssemblyName ( FindAsmdef ( ) ) ;
2623 if ( ! IsGlobal && string . IsNullOrEmpty ( assemblyName ) ) return ;
@@ -36,14 +33,8 @@ public static string GetAssemblyName(string asmdefPath)
3633 {
3734 if ( string . IsNullOrEmpty ( asmdefPath ) ) return null ;
3835
39- string assemblyName ;
40- if ( s_AssemblyNames . TryGetValue ( asmdefPath , out assemblyName ) ) return assemblyName ;
41-
4236 var m = Regex . Match ( File . ReadAllText ( asmdefPath ) , "\" name\" :\\ s*\" ([^\" ]*)\" " ) ;
43- assemblyName = m . Success ? m . Groups [ 1 ] . Value : "" ;
44- s_AssemblyNames [ asmdefPath ] = assemblyName ;
45-
46- return assemblyName ;
37+ return m . Success ? m . Groups [ 1 ] . Value : "" ;
4738 }
4839
4940 public static string GetPortableDllPath ( string asmdefPath )
@@ -54,7 +45,7 @@ public static string GetPortableDllPath(string asmdefPath)
5445 . FirstOrDefault ( x => Regex . IsMatch ( x , "CSharpCompilerSettings_[0-9a-zA-Z]{32}.dll" ) ) ;
5546 }
5647
57- private static bool IsInSameDirectory ( string path )
48+ public static bool IsInSameDirectory ( string path )
5849 {
5950 if ( string . IsNullOrEmpty ( path ) ) return false ;
6051
@@ -63,7 +54,7 @@ private static bool IsInSameDirectory(string path)
6354 return dir == coreAssemblyLocationDir ;
6455 }
6556
66- private static string FindAsmdef ( string path = null )
57+ public static string FindAsmdef ( string path = null )
6758 {
6859 if ( string . IsNullOrEmpty ( path ) )
6960 {
@@ -80,66 +71,31 @@ private static string FindAsmdef(string path = null)
8071 return asmdefPath . Replace ( '\\ ' , '/' ) . Replace ( Environment . CurrentDirectory . Replace ( '\\ ' , '/' ) + "/" , "" ) ;
8172 }
8273
83- private static CscSettingsAsset GetSettings ( )
74+ public static CscSettingsAsset GetSettings ( )
8475 {
8576 return IsGlobal
8677 ? CscSettingsAsset . instance
8778 : CscSettingsAsset . GetAtPath ( FindAsmdef ( ) ) ?? ScriptableObject . CreateInstance < CscSettingsAsset > ( ) ;
8879 }
8980
90- private static void ChangeCompilerProcess ( object compiler , object scriptAssembly , CscSettingsAsset setting )
81+ public static string ModifyResponseFile ( CscSettingsAsset setting , string assemblyName , string asmdefPath , string text )
9182 {
92- var tProgram = Type . GetType ( "UnityEditor.Utils.Program, UnityEditor" ) ;
93- var tScriptCompilerBase = Type . GetType ( "UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor" ) ;
94- var fiProcess = tScriptCompilerBase . GetField ( "process" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
95- var psi = compiler . Get ( "process" , fiProcess ) . Call ( "GetProcessStartInfo" ) as ProcessStartInfo ;
96- var oldCommand = ( psi . FileName + " " + psi . Arguments ) . Replace ( '\\ ' , '/' ) ;
97- var command = oldCommand . Replace ( EditorApplication . applicationContentsPath . Replace ( '\\ ' , '/' ) , "@APP_CONTENTS@" ) ;
98- var isDefaultCsc = Regex . IsMatch ( command , "@APP_CONTENTS@/[^ ]*(mcs|csc)" ) ;
99- var assemblyName = Path . GetFileNameWithoutExtension ( scriptAssembly . Get ( "Filename" ) as string ) ;
100- var asmdefDir = scriptAssembly . Get ( "OriginPath" ) as string ;
101- var asmdefPath = string . IsNullOrEmpty ( asmdefDir ) ? "" : FindAsmdef ( asmdefDir ) ;
102-
103- // csc is not Unity default. It is already modified.
104- if ( ! isDefaultCsc )
105- {
106- Logger . LogWarning ( " <color=#bbbb44><Skipped> current csc is not Unity default. It is already modified.</color>" ) ;
107- return ;
108- }
109-
110- // Kill current process.
111- compiler . Call ( "Dispose" ) ;
112-
113- // Response file.
114- var responseFile = Regex . Replace ( psi . Arguments , "^.*@(.+)$" , "$1" ) ;
115- var text = File . ReadAllText ( responseFile ) ;
83+ var asmdefDir = string . IsNullOrEmpty ( asmdefPath ) ? null : Path . GetDirectoryName ( asmdefPath ) ;
11684 text = Regex . Replace ( text , "[\r \n ]+" , "\n " ) ;
11785 text = Regex . Replace ( text , "^-" , "/" ) ;
11886 text = Regex . Replace ( text , "\n /debug\n " , "\n /debug:portable\n " ) ;
87+ text = Regex . Replace ( text , "\n /nullable.*" , "" ) ;
11988 text += "\n /preferreduilang:en-US" ;
12089
12190 // Compiler
12291 if ( ! setting . UseDefaultCompiler )
12392 {
124- var compilerInfo = CompilerInfo . GetInstalledInfo ( setting . CompilerPackage . PackageId ) ;
125-
126- // csc is not installed. Restart current process.
127- if ( ! compilerInfo . IsValid )
128- {
129- Logger . LogWarning ( " <color=#bbbb44><Skipped> C# compiler '{0}' is not installed. Restart compiler process: {1}</color>" , compilerInfo . Path , oldCommand ) ;
130-
131- var currentProgram = tProgram . New ( psi ) ;
132- currentProgram . Call ( "Start" ) ;
133- compiler . Set ( "process" , currentProgram , fiProcess ) ;
134- return ;
135- }
136-
137- // Change exe file path.
138- compilerInfo . Setup ( psi , responseFile ) ;
93+ // Change language version.
13994 text = Regex . Replace ( text , "\n /langversion:[^\n ]+\n " , "\n /langversion:" + setting . LanguageVersion + "\n " ) ;
14095
14196 // Nullable.
142- text += "\n /nullable:" + setting . Nullable . ToString ( ) . ToLower ( ) ;
97+ if ( setting . IsSupportNullable )
98+ text += "\n /nullable:" + setting . Nullable . ToString ( ) . ToLower ( ) ;
14399 }
144100
145101 // Modify scripting define symbols.
@@ -177,18 +133,71 @@ private static void ChangeCompilerProcess(object compiler, object scriptAssembly
177133 text += string . Format ( "\n /ruleset:\" {0}\" " , ruleset ) ;
178134
179135 // Editor Config.
180- var configs = new [ ]
181- {
182- ".editorconfig" ,
183- Utils . PathCombine ( asmdefDir ?? "Assets" , ".editorconfig" )
184- }
185- . Where ( File . Exists ) ;
186- foreach ( var config in configs )
187- text += string . Format ( "\n /analyzerconfig:\" {0}\" " , config ) ;
136+ // var configs = new[]
137+ // {
138+ // ".editorconfig",
139+ // Utils.PathCombine(asmdefDir ?? "Assets", ".editorconfig")
140+ // }
141+ // .Where(File.Exists);
142+ // foreach (var config in configs)
143+ // text += string.Format("\n/analyzerconfig:\"{0}\"", config);
188144 }
189145
190146 // Replace NewLine and save.
191147 text = Regex . Replace ( text , "\n " , Environment . NewLine ) ;
148+
149+ return text ;
150+ }
151+
152+ private static void ChangeCompilerProcess ( object compiler , object scriptAssembly , CscSettingsAsset setting )
153+ {
154+ var tProgram = Type . GetType ( "UnityEditor.Utils.Program, UnityEditor" ) ;
155+ var tScriptCompilerBase = Type . GetType ( "UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor" ) ;
156+ var fiProcess = tScriptCompilerBase . GetField ( "process" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
157+ var psi = compiler . Get ( "process" , fiProcess ) . Call ( "GetProcessStartInfo" ) as ProcessStartInfo ;
158+ var oldCommand = ( psi . FileName + " " + psi . Arguments ) . Replace ( '\\ ' , '/' ) ;
159+ var command = oldCommand . Replace ( EditorApplication . applicationContentsPath . Replace ( '\\ ' , '/' ) , "@APP_CONTENTS@" ) ;
160+ var isDefaultCsc = Regex . IsMatch ( command , "@APP_CONTENTS@/[^ ]*(mcs|csc)" ) ;
161+ var assemblyName = Path . GetFileNameWithoutExtension ( scriptAssembly . Get ( "Filename" ) as string ) ;
162+ var asmdefDir = scriptAssembly . Get ( "OriginPath" ) as string ;
163+ var asmdefPath = string . IsNullOrEmpty ( asmdefDir ) ? "" : FindAsmdef ( asmdefDir ) ;
164+
165+ // csc is not Unity default. It is already modified.
166+ if ( ! isDefaultCsc )
167+ {
168+ Logger . LogWarning ( " <color=#bbbb44><Skipped> current csc is not Unity default. It is already modified.</color>" ) ;
169+ return ;
170+ }
171+
172+ // Kill current process.
173+ compiler . Call ( "Dispose" ) ;
174+
175+ // Response file.
176+ var responseFile = Regex . Replace ( psi . Arguments , "^.*@(.+)$" , "$1" ) ;
177+
178+ // Compiler
179+ if ( ! setting . UseDefaultCompiler )
180+ {
181+ var compilerInfo = CompilerInfo . GetInstalledInfo ( setting . CompilerPackage . PackageId ) ;
182+
183+ // csc is not installed. Restart current process.
184+ if ( ! compilerInfo . IsValid )
185+ {
186+ Logger . LogWarning ( " <color=#bbbb44><Skipped> C# compiler '{0}' is not installed. Restart compiler process: {1}</color>" , compilerInfo . Path , oldCommand ) ;
187+
188+ var currentProgram = tProgram . New ( psi ) ;
189+ currentProgram . Call ( "Start" ) ;
190+ compiler . Set ( "process" , currentProgram , fiProcess ) ;
191+ return ;
192+ }
193+
194+ // Change exe file path.
195+ compilerInfo . Setup ( psi , responseFile ) ;
196+ }
197+
198+ // Modify response file.
199+ var text = File . ReadAllText ( responseFile ) ;
200+ text = ModifyResponseFile ( setting , assemblyName , asmdefPath , text ) ;
192201 File . WriteAllText ( responseFile , text ) ;
193202
194203 // Logging
@@ -202,7 +211,7 @@ private static void ChangeCompilerProcess(object compiler, object scriptAssembly
202211 compiler . Set ( "process" , program , fiProcess ) ;
203212 }
204213
205- private static void OnAssemblyCompilationStarted ( string name )
214+ public static void OnAssemblyCompilationStarted ( string name )
206215 {
207216 try
208217 {
@@ -254,7 +263,7 @@ private static void OnAssemblyCompilationStarted(string name)
254263 }
255264 }
256265
257- static Core ( )
266+ public static void Initialize ( )
258267 {
259268 IsGlobal = new [ ]
260269 {
@@ -301,6 +310,7 @@ static Core()
301310
302311 // Register callback.
303312 Logger . LogDebug ( "<color=#22aa22><b>InitializeOnLoad:</b></color> start watching assembly compilation." ) ;
313+ CompilationPipeline . assemblyCompilationStarted -= OnAssemblyCompilationStarted ;
304314 CompilationPipeline . assemblyCompilationStarted += OnAssemblyCompilationStarted ;
305315
306316 // Install custom csc before compilation.
@@ -319,5 +329,10 @@ static Core()
319329 if ( 2021 <= major || ( major == 2020 && 2 <= minor ) )
320330 DirtyScriptsIfNeeded ( ) ;
321331 }
332+
333+ static Core ( )
334+ {
335+ Initialize ( ) ;
336+ }
322337 }
323338}
0 commit comments