158 lines
6.0 KiB
C#
158 lines
6.0 KiB
C#
#if UNITY_EDITOR
|
|
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Tự động thêm UnityEditorOnlyAnalyzer vào các .csproj files khi Unity generate chúng
|
|
/// Analyzer phải ở project root, KHÔNG trong Assets/ để tránh Unity load như runtime assembly
|
|
/// </summary>
|
|
public class AddAnalyzerPostprocessor : AssetPostprocessor
|
|
{
|
|
private static string GetAnalyzerPath()
|
|
{
|
|
string projectRoot = Path.GetDirectoryName(Application.dataPath);
|
|
string analyzerPath = Path.Combine(projectRoot, "UnityEditorOnlyAnalyzer/bin/Release/netstandard2.0/UnityEditorOnlyAnalyzer.dll");
|
|
return Path.GetFullPath(analyzerPath);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity gọi method này cho từng .csproj file được generate
|
|
/// Return content đã được modify - Unity sẽ ghi content này vào file
|
|
/// </summary>
|
|
public static string OnGeneratedCSProject(string path, string content)
|
|
{
|
|
string fileName = Path.GetFileName(path);
|
|
|
|
// Chỉ thêm vào các runtime assemblies, không thêm vào Editor assemblies
|
|
if (fileName != "Assembly-CSharp.csproj" && fileName != "Assembly-CSharp-firstpass.csproj")
|
|
{
|
|
return content;
|
|
}
|
|
|
|
// Kiểm tra xem đã có analyzer chưa
|
|
if (content.Contains("UnityEditorOnlyAnalyzer.dll"))
|
|
{
|
|
return content;
|
|
}
|
|
|
|
string analyzerPath = GetAnalyzerPath();
|
|
|
|
// Kiểm tra analyzer có tồn tại không
|
|
if (!File.Exists(analyzerPath))
|
|
{
|
|
Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Analyzer not found at {analyzerPath}. " +
|
|
"Please build the analyzer first: cd UnityEditorOnlyAnalyzer && dotnet build -c Release");
|
|
return content;
|
|
}
|
|
|
|
// Bug fix 1: Tìm "</Project>" không có dấu cách ở đầu
|
|
int lastProjectTag = content.LastIndexOf("</Project>");
|
|
if (lastProjectTag < 0)
|
|
{
|
|
Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Could not find </Project> tag in {fileName}");
|
|
return content;
|
|
}
|
|
|
|
// Bug fix 2: Không double-escape backslash trong XML - XML tự động escape
|
|
// Chỉ cần đảm bảo path có backslash đúng format Windows
|
|
string analyzerInclude = $@" <ItemGroup>
|
|
<Analyzer Include=""{analyzerPath}"" />
|
|
</ItemGroup>
|
|
</Project>";
|
|
|
|
string modifiedContent = content.Substring(0, lastProjectTag) + analyzerInclude;
|
|
Debug.Log($"[UnityEditorOnlyAnalyzer] ✅ Added analyzer to {fileName}");
|
|
|
|
return modifiedContent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Public method để menu item có thể gọi thủ công
|
|
/// </summary>
|
|
public static void AddAnalyzerToProjects()
|
|
{
|
|
// Trigger Unity regenerate .csproj files để OnGeneratedCSProject được gọi
|
|
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal("", 0);
|
|
AssetDatabase.Refresh();
|
|
|
|
// Cũng gọi fallback method để đảm bảo
|
|
OnGeneratedCSProjectFiles();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Backup method: Unity gọi method này sau khi generate tất cả .csproj files
|
|
/// Chỉ dùng nếu OnGeneratedCSProject không hoạt động
|
|
/// </summary>
|
|
private static void OnGeneratedCSProjectFiles()
|
|
{
|
|
// Fallback: patch files sau khi đã được generate
|
|
string projectRoot = Path.GetDirectoryName(Application.dataPath);
|
|
string analyzerPath = GetAnalyzerPath();
|
|
|
|
if (!File.Exists(analyzerPath))
|
|
{
|
|
Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Analyzer not found at {analyzerPath}. " +
|
|
"Please build the analyzer first: cd UnityEditorOnlyAnalyzer && dotnet build -c Release");
|
|
return;
|
|
}
|
|
|
|
string[] csprojFiles = Directory.GetFiles(projectRoot, "*.csproj", SearchOption.TopDirectoryOnly);
|
|
bool anyModified = false;
|
|
|
|
foreach (string csprojFile in csprojFiles)
|
|
{
|
|
string fileName = Path.GetFileName(csprojFile);
|
|
if (fileName == "Assembly-CSharp.csproj" || fileName == "Assembly-CSharp-firstpass.csproj")
|
|
{
|
|
string content = File.ReadAllText(csprojFile);
|
|
|
|
if (!content.Contains("UnityEditorOnlyAnalyzer.dll"))
|
|
{
|
|
// Bug fix: Tìm "</Project>" không có dấu cách
|
|
int lastProjectTag = content.LastIndexOf("</Project>");
|
|
if (lastProjectTag >= 0)
|
|
{
|
|
string analyzerInclude = $@" <ItemGroup>
|
|
<Analyzer Include=""{analyzerPath}"" />
|
|
</ItemGroup>
|
|
</Project>";
|
|
|
|
content = content.Substring(0, lastProjectTag) + analyzerInclude;
|
|
File.WriteAllText(csprojFile, content);
|
|
anyModified = true;
|
|
Debug.Log($"[UnityEditorOnlyAnalyzer] ✅ Added analyzer to {fileName} (fallback method)");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anyModified)
|
|
{
|
|
Debug.Log("[UnityEditorOnlyAnalyzer] ✅ Analyzer added to .csproj files! Please reload your IDE.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Menu item để trigger thủ công việc thêm analyzer
|
|
/// </summary>
|
|
public class UnityEditorOnlyAnalyzerMenu
|
|
{
|
|
[MenuItem("Tools/Unity Editor Only Analyzer/Add Analyzer to Projects")]
|
|
public static void AddAnalyzerManually()
|
|
{
|
|
AddAnalyzerPostprocessor.AddAnalyzerToProjects();
|
|
}
|
|
|
|
[MenuItem("Tools/Unity Editor Only Analyzer/Regenerate Project Files")]
|
|
public static void RegenerateProjectFiles()
|
|
{
|
|
// Trigger Unity regenerate .csproj files
|
|
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal("", 0);
|
|
AssetDatabase.Refresh();
|
|
Debug.Log("[UnityEditorOnlyAnalyzer] Project files regeneration triggered. Check Console for analyzer messages.");
|
|
}
|
|
}
|
|
#endif
|