Skip to content

Commit

Permalink
refactor: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
mob-sakai committed Nov 20, 2020
1 parent f3970cf commit 98515af
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 76 deletions.
8 changes: 8 additions & 0 deletions Editor/CscSettingsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ private static SettingsProvider CreateSettingsProvider()
var sp = analyzerPackages.GetArrayElementAtIndex(index);
EditorGUI.PropertyField(rect, sp, GUIContent.none);
};
s_RoAnalyzerPackages.onChangedCallback = list =>
{
for (var i = 0; i < analyzerPackages.arraySize; i++)
{
var sp = analyzerPackages.GetArrayElementAtIndex(i);
sp.FindPropertyRelative("m_Category").intValue = (int)NugetPackage.CategoryType.Analyzer;
}
};

var includedAssemblies = s_AnalyzerFilter.FindPropertyRelative("m_IncludedAssemblies");
s_RoIncludedAssemblies = new ReorderableList(serializedObject, includedAssemblies);
Expand Down
147 changes: 81 additions & 66 deletions Plugins/CSharpCompilerSettings/Core.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand All @@ -16,11 +15,9 @@ namespace Coffee.CSharpCompilerSettings
[InitializeOnLoad]
internal static class Core
{
private static readonly Dictionary<string, bool> s_EnableAsmdefs = new Dictionary<string, bool>();
private static readonly Dictionary<string, string> s_AssemblyNames = new Dictionary<string, string>();
private static readonly bool IsGlobal;
public static bool IsGlobal { get; private set; }

private static void DirtyScriptsIfNeeded()
public static void DirtyScriptsIfNeeded()
{
var assemblyName = GetAssemblyName(FindAsmdef());
if (!IsGlobal && string.IsNullOrEmpty(assemblyName)) return;
Expand All @@ -36,14 +33,8 @@ public static string GetAssemblyName(string asmdefPath)
{
if (string.IsNullOrEmpty(asmdefPath)) return null;

string assemblyName;
if (s_AssemblyNames.TryGetValue(asmdefPath, out assemblyName)) return assemblyName;

var m = Regex.Match(File.ReadAllText(asmdefPath), "\"name\":\\s*\"([^\"]*)\"");
assemblyName = m.Success ? m.Groups[1].Value : "";
s_AssemblyNames[asmdefPath] = assemblyName;

return assemblyName;
return m.Success ? m.Groups[1].Value : "";
}

public static string GetPortableDllPath(string asmdefPath)
Expand All @@ -54,7 +45,7 @@ public static string GetPortableDllPath(string asmdefPath)
.FirstOrDefault(x => Regex.IsMatch(x, "CSharpCompilerSettings_[0-9a-zA-Z]{32}.dll"));
}

private static bool IsInSameDirectory(string path)
public static bool IsInSameDirectory(string path)
{
if (string.IsNullOrEmpty(path)) return false;

Expand All @@ -63,7 +54,7 @@ private static bool IsInSameDirectory(string path)
return dir == coreAssemblyLocationDir;
}

private static string FindAsmdef(string path = null)
public static string FindAsmdef(string path = null)
{
if (string.IsNullOrEmpty(path))
{
Expand All @@ -80,66 +71,31 @@ private static string FindAsmdef(string path = null)
return asmdefPath.Replace('\\', '/').Replace(Environment.CurrentDirectory.Replace('\\', '/') + "/", "");
}

private static CscSettingsAsset GetSettings()
public static CscSettingsAsset GetSettings()
{
return IsGlobal
? CscSettingsAsset.instance
: CscSettingsAsset.GetAtPath(FindAsmdef()) ?? ScriptableObject.CreateInstance<CscSettingsAsset>();
}

private static void ChangeCompilerProcess(object compiler, object scriptAssembly, CscSettingsAsset setting)
public static string ModifyResponseFile(CscSettingsAsset setting, string assemblyName, string asmdefPath, string text)
{
var tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor");
var tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor");
var fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance);
var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo;
var oldCommand = (psi.FileName + " " + psi.Arguments).Replace('\\', '/');
var command = oldCommand.Replace(EditorApplication.applicationContentsPath.Replace('\\', '/'), "@APP_CONTENTS@");
var isDefaultCsc = Regex.IsMatch(command, "@APP_CONTENTS@/[^ ]*(mcs|csc)");
var assemblyName = Path.GetFileNameWithoutExtension(scriptAssembly.Get("Filename") as string);
var asmdefDir = scriptAssembly.Get("OriginPath") as string;
var asmdefPath = string.IsNullOrEmpty(asmdefDir) ? "" : FindAsmdef(asmdefDir);

// csc is not Unity default. It is already modified.
if (!isDefaultCsc)
{
Logger.LogWarning(" <color=#bbbb44><Skipped> current csc is not Unity default. It is already modified.</color>");
return;
}

// Kill current process.
compiler.Call("Dispose");

// Response file.
var responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1");
var text = File.ReadAllText(responseFile);
var asmdefDir = string.IsNullOrEmpty(asmdefPath) ? null : Path.GetDirectoryName(asmdefPath);
text = Regex.Replace(text, "[\r\n]+", "\n");
text = Regex.Replace(text, "^-", "/");
text = Regex.Replace(text, "\n/debug\n", "\n/debug:portable\n");
text = Regex.Replace(text, "\n/nullable.*", "");
text += "\n/preferreduilang:en-US";

// Compiler
if (!setting.UseDefaultCompiler)
{
var compilerInfo = CompilerInfo.GetInstalledInfo(setting.CompilerPackage.PackageId);

// csc is not installed. Restart current process.
if (!compilerInfo.IsValid)
{
Logger.LogWarning(" <color=#bbbb44><Skipped> C# compiler '{0}' is not installed. Restart compiler process: {1}</color>", compilerInfo.Path, oldCommand);

var currentProgram = tProgram.New(psi);
currentProgram.Call("Start");
compiler.Set("process", currentProgram, fiProcess);
return;
}

// Change exe file path.
compilerInfo.Setup(psi, responseFile);
// Change language version.
text = Regex.Replace(text, "\n/langversion:[^\n]+\n", "\n/langversion:" + setting.LanguageVersion + "\n");

// Nullable.
text += "\n/nullable:" + setting.Nullable.ToString().ToLower();
if (setting.IsSupportNullable)
text += "\n/nullable:" + setting.Nullable.ToString().ToLower();
}

// Modify scripting define symbols.
Expand Down Expand Up @@ -177,18 +133,71 @@ private static void ChangeCompilerProcess(object compiler, object scriptAssembly
text += string.Format("\n/ruleset:\"{0}\"", ruleset);

// Editor Config.
var configs = new[]
{
".editorconfig",
Utils.PathCombine(asmdefDir ?? "Assets", ".editorconfig")
}
.Where(File.Exists);
foreach (var config in configs)
text += string.Format("\n/analyzerconfig:\"{0}\"", config);
// var configs = new[]
// {
// ".editorconfig",
// Utils.PathCombine(asmdefDir ?? "Assets", ".editorconfig")
// }
// .Where(File.Exists);
// foreach (var config in configs)
// text += string.Format("\n/analyzerconfig:\"{0}\"", config);
}

// Replace NewLine and save.
text = Regex.Replace(text, "\n", Environment.NewLine);

return text;
}

private static void ChangeCompilerProcess(object compiler, object scriptAssembly, CscSettingsAsset setting)
{
var tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor");
var tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor");
var fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance);
var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo;
var oldCommand = (psi.FileName + " " + psi.Arguments).Replace('\\', '/');
var command = oldCommand.Replace(EditorApplication.applicationContentsPath.Replace('\\', '/'), "@APP_CONTENTS@");
var isDefaultCsc = Regex.IsMatch(command, "@APP_CONTENTS@/[^ ]*(mcs|csc)");
var assemblyName = Path.GetFileNameWithoutExtension(scriptAssembly.Get("Filename") as string);
var asmdefDir = scriptAssembly.Get("OriginPath") as string;
var asmdefPath = string.IsNullOrEmpty(asmdefDir) ? "" : FindAsmdef(asmdefDir);

// csc is not Unity default. It is already modified.
if (!isDefaultCsc)
{
Logger.LogWarning(" <color=#bbbb44><Skipped> current csc is not Unity default. It is already modified.</color>");
return;
}

// Kill current process.
compiler.Call("Dispose");

// Response file.
var responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1");

// Compiler
if (!setting.UseDefaultCompiler)
{
var compilerInfo = CompilerInfo.GetInstalledInfo(setting.CompilerPackage.PackageId);

// csc is not installed. Restart current process.
if (!compilerInfo.IsValid)
{
Logger.LogWarning(" <color=#bbbb44><Skipped> C# compiler '{0}' is not installed. Restart compiler process: {1}</color>", compilerInfo.Path, oldCommand);

var currentProgram = tProgram.New(psi);
currentProgram.Call("Start");
compiler.Set("process", currentProgram, fiProcess);
return;
}

// Change exe file path.
compilerInfo.Setup(psi, responseFile);
}

// Modify response file.
var text = File.ReadAllText(responseFile);
text = ModifyResponseFile(setting, assemblyName, asmdefPath, text);
File.WriteAllText(responseFile, text);

// Logging
Expand All @@ -202,7 +211,7 @@ private static void ChangeCompilerProcess(object compiler, object scriptAssembly
compiler.Set("process", program, fiProcess);
}

private static void OnAssemblyCompilationStarted(string name)
public static void OnAssemblyCompilationStarted(string name)
{
try
{
Expand Down Expand Up @@ -254,7 +263,7 @@ private static void OnAssemblyCompilationStarted(string name)
}
}

static Core()
public static void Initialize()
{
IsGlobal = new[]
{
Expand Down Expand Up @@ -301,6 +310,7 @@ static Core()

// Register callback.
Logger.LogDebug("<color=#22aa22><b>InitializeOnLoad:</b></color> start watching assembly compilation.");
CompilationPipeline.assemblyCompilationStarted -= OnAssemblyCompilationStarted;
CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted;

// Install custom csc before compilation.
Expand All @@ -319,5 +329,10 @@ static Core()
if (2021 <= major || (major == 2020 && 2 <= minor))
DirtyScriptsIfNeeded();
}

static Core()
{
Initialize();
}
}
}
5 changes: 5 additions & 0 deletions Plugins/CSharpCompilerSettings/CscSettingsAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ public string AdditionalSymbols
}
}

public bool IsSupportNullable
{
get { return LVersion.CSharp8 < m_LanguageVersion; }
}

public static CscSettingsAsset GetAtPath(string path)
{
try
Expand Down
14 changes: 9 additions & 5 deletions Plugins/CSharpCompilerSettings/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,27 @@ public static object New(this Type self, params object[] args)
public static object Call(this object self, string methodName, params object[] args)
{
var types = args.Select(x => x.GetType()).ToArray();
return self.Type().GetMethod(methodName, types)
return self.Type().GetMethods(FLAGS)
.Where(x => x.Name == methodName)
.First(x => x.GetParameters().Select(y => y.ParameterType).SequenceEqual(types))
.Invoke(self.Inst(), args);
}

public static object Call(this object self, Type[] genericTypes, string methodName, params object[] args)
{
return self.Type().GetMethod(methodName, FLAGS)
return self.Type().GetMethods(FLAGS)
.First(x => x.IsGenericMethodDefinition && x.Name == methodName)
.MakeGenericMethod(genericTypes)
.Invoke(self.Inst(), args);
}

public static object Get(this object self, string memberName, MemberInfo mi = null)
{
mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0];
return mi is PropertyInfo
? (mi as PropertyInfo).GetValue(self.Inst(), new object[0])
: (mi as FieldInfo).GetValue(self.Inst());
if (mi is PropertyInfo)
return (mi as PropertyInfo).GetValue(self.Inst(), new object[0]);
else
return (mi as FieldInfo).GetValue(self.Inst());
}

public static void Set(this object self, string memberName, object value, MemberInfo mi = null)
Expand Down
26 changes: 21 additions & 5 deletions Plugins/CSharpCompilerSettings/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using UnityEditor;
using UnityEngine;
Expand All @@ -13,6 +12,8 @@ namespace Coffee.CSharpCompilerSettings
{
internal static class Utils
{
public static bool DisableCompilation { get; set; }

/// <summary>
/// Combine the paths.
/// </summary>
Expand Down Expand Up @@ -45,7 +46,10 @@ public static void RequestCompilation(string assemblyName = null)

if (string.IsNullOrEmpty(assemblyName))
{
editorCompilation.Call("DirtyAllScripts");
if (DisableCompilation)
Logger.LogWarning("Skipped: Disable compilation");
else
editorCompilation.Call("DirtyAllScripts");
return;
}

Expand All @@ -54,7 +58,10 @@ public static void RequestCompilation(string assemblyName = null)
var path = allScripts.FirstOrDefault(x => x.Value == assemblyFilename).Key;
if (string.IsNullOrEmpty(path)) return;

editorCompilation.Call("DirtyScript", path, assemblyFilename);
if (DisableCompilation)
Logger.LogWarning("Skipped: Disable compilation");
else
editorCompilation.Call("DirtyScript", path, assemblyFilename);
}

/// <summary>
Expand All @@ -64,12 +71,21 @@ public static void RequestCompilation(string assemblyName = null)
/// <returns>Installed directory path</returns>
public static string InstallNugetPackage(string packageId)
{
Regex.IsMatch(packageId, @".*\.\d+\.\d+\.*");

var url = "https://globalcdn.nuget.org/packages/" + packageId.ToLower() + ".nupkg";
return InstallPackage(packageId, url);
}

/// <summary>
/// Uninstall NuGet package.
/// </summary>
/// <param name="packageId">Package Id</param>
public static void UninstallNugetPackage(string packageId)
{
var installPath = PathCombine("Library", "InstalledPackages", packageId);
if (Directory.Exists(installPath))
Directory.Delete(installPath, true);
}

/// <summary>
/// Install package from url.
/// </summary>
Expand Down

0 comments on commit 98515af

Please sign in to comment.