#if UNITY_EDITOR using System.IO; using UnityEditor; using UnityEngine; /// /// 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 /// 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); } /// /// 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 /// 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 "" không có dấu cách ở đầu int lastProjectTag = content.LastIndexOf(""); if (lastProjectTag < 0) { Debug.LogWarning($"[UnityEditorOnlyAnalyzer] Could not find 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 = $@" "; string modifiedContent = content.Substring(0, lastProjectTag) + analyzerInclude; Debug.Log($"[UnityEditorOnlyAnalyzer] ✅ Added analyzer to {fileName}"); return modifiedContent; } /// /// Public method để menu item có thể gọi thủ công /// 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(); } /// /// 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 /// 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 "" không có dấu cách int lastProjectTag = content.LastIndexOf(""); if (lastProjectTag >= 0) { string analyzerInclude = $@" "; 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."); } } } /// /// Menu item để trigger thủ công việc thêm analyzer /// 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