Skip to content

Commit 34d1a28

Browse files
committed
feat: support nuget package drawer
1 parent e6770d5 commit 34d1a28

File tree

3 files changed

+283
-6
lines changed

3 files changed

+283
-6
lines changed

Editor/NugetPackageDrawer.cs

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using UnityEditor;
6+
using UnityEngine;
7+
8+
namespace Coffee.CSharpCompilerSettings
9+
{
10+
[CustomPropertyDrawer(typeof(NugetPackage))]
11+
internal class NugetPackageDrawer : PropertyDrawer
12+
{
13+
public static readonly float Height = 2 * (EditorGUIUtility.singleLineHeight + 2);
14+
15+
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
16+
{
17+
return Height;
18+
}
19+
20+
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
21+
{
22+
EditorGUI.BeginProperty(position, label, property);
23+
var p = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
24+
25+
var indentLevel = EditorGUI.indentLevel;
26+
var labelWidth = EditorGUIUtility.labelWidth;
27+
EditorGUI.indentLevel = 0;
28+
EditorGUIUtility.labelWidth = 50;
29+
{
30+
var spName = property.FindPropertyRelative("m_Name");
31+
var spVersion = property.FindPropertyRelative("m_Version");
32+
33+
DrawPackageNameField(new Rect(p.x, p.y, p.width, 16), spName, spVersion);
34+
DrawPackageVersionField(new Rect(p.x, p.y + 18, p.width, 16), spName, spVersion);
35+
}
36+
EditorGUI.indentLevel = indentLevel;
37+
EditorGUIUtility.labelWidth = labelWidth;
38+
39+
EditorGUI.EndProperty();
40+
}
41+
42+
private void DrawPackageNameField(Rect rect, SerializedProperty spName, SerializedProperty spVersion)
43+
{
44+
// Text field.
45+
var r = new Rect(rect.x, rect.y, rect.width - 18, 16);
46+
EditorGUI.BeginChangeCheck();
47+
EditorGUI.PropertyField(r, spName);
48+
if (EditorGUI.EndChangeCheck())
49+
spVersion.stringValue = "";
50+
51+
// Draw button.
52+
r = new Rect(rect.x + rect.width - 14, rect.y + 4, 14, 12);
53+
if (!GUI.Button(r, EditorGUIUtility.IconContent("icon dropdown"), EditorStyles.label)) return;
54+
55+
GUI.FocusControl("");
56+
57+
// Create menu.
58+
var menu = new GenericMenu();
59+
foreach (var pkgName in NugetPackageCatalog.GetPackageNames())
60+
menu.AddItem(new GUIContent(pkgName), spName.stringValue == pkgName, () =>
61+
{
62+
spName.stringValue = pkgName;
63+
spVersion.stringValue = "";
64+
});
65+
66+
menu.ShowAsContext();
67+
}
68+
69+
private static void DrawPackageVersionField(Rect rect, SerializedProperty spName, SerializedProperty spVersion)
70+
{
71+
// Draw button.
72+
var selectedVersion = string.IsNullOrEmpty(spVersion.stringValue) ? "-" : spVersion.stringValue;
73+
var buttonRect = EditorGUI.PrefixLabel(rect, new GUIContent(spVersion.displayName, spVersion.tooltip));
74+
if (!GUI.Button(buttonRect, selectedVersion, EditorStyles.popup)) return;
75+
76+
// Refresh package versions.
77+
var pkgName = spName.stringValue;
78+
NugetPackageCatalog.RefreshAvailableVersions(pkgName);
79+
80+
// Create menu.
81+
var menu = new GenericMenu();
82+
foreach (var pkgVersion in NugetPackageCatalog.GetPackagePreReleaseVersions(pkgName))
83+
menu.AddItem(new GUIContent("Pre Releases/" + pkgVersion), selectedVersion == pkgVersion, () => spVersion.stringValue = pkgVersion);
84+
if (0 < menu.GetItemCount())
85+
menu.AddSeparator("");
86+
foreach (var pkgVersion in NugetPackageCatalog.GetPackageVersions(pkgName))
87+
menu.AddItem(new GUIContent(pkgVersion), selectedVersion == pkgVersion, () => spVersion.stringValue = pkgVersion);
88+
89+
if (menu.GetItemCount() == 0)
90+
menu.AddDisabledItem(new GUIContent("No available versions"));
91+
menu.ShowAsContext();
92+
}
93+
}
94+
95+
internal class NugetPackageCatalog : ScriptableSingleton<NugetPackageCatalog>
96+
{
97+
#pragma warning disable 649
98+
[Serializable]
99+
private class CatalogRoot
100+
{
101+
public CatalogPage[] items;
102+
103+
[Serializable]
104+
internal class CatalogPage
105+
{
106+
public Package[] items;
107+
108+
[Serializable]
109+
internal class Package
110+
{
111+
public PackageDetails catalogEntry;
112+
113+
[Serializable]
114+
internal class PackageDetails
115+
{
116+
public string id;
117+
public string version;
118+
}
119+
}
120+
}
121+
}
122+
#pragma warning restore 649
123+
124+
125+
public static NugetPackage.CategoryType CurrentCategory = NugetPackage.CategoryType.Compiler;
126+
127+
public List<NugetPackage> m_Packages = new List<NugetPackage>()
128+
{
129+
new NugetPackage("Microsoft.Net.Compilers.Toolset", "3.5.0", NugetPackage.CategoryType.Compiler),
130+
new NugetPackage("Microsoft.Net.Compilers", "3.5.0", NugetPackage.CategoryType.Compiler),
131+
new NugetPackage("OpenSesame.Net.Compilers.Toolset", "3.5.0", NugetPackage.CategoryType.Compiler),
132+
new NugetPackage("OpenSesame.Net.Compilers", "3.5.0", NugetPackage.CategoryType.Compiler),
133+
new NugetPackage("Roslynator.Analyzers", "3.0.0", NugetPackage.CategoryType.Analyzer),
134+
new NugetPackage("Roslynator.CodeAnalysis.Analyzers", "1.0.0", NugetPackage.CategoryType.Analyzer),
135+
new NugetPackage("Roslynator.Formatting.Analyzers", "1.0.0", NugetPackage.CategoryType.Analyzer),
136+
new NugetPackage("ErrorProne.NET.CoreAnalyzers", "0.1.2", NugetPackage.CategoryType.Analyzer),
137+
new NugetPackage("StyleCop.Analyzers", "1.0.0", NugetPackage.CategoryType.Analyzer),
138+
};
139+
140+
public static IEnumerable<string> GetPackageNames()
141+
{
142+
return instance.m_Packages
143+
.Where(x => x.Category == CurrentCategory)
144+
.Select(x => x.Name)
145+
.Distinct();
146+
}
147+
148+
public static IEnumerable<string> GetPackageVersions(string packageName)
149+
{
150+
return instance.m_Packages
151+
.Where(x => x.Name == packageName && x.Category == CurrentCategory)
152+
.Select(x => x.Version)
153+
.Where(x => !SemVersion.Parse(x).IsPrerelease);
154+
}
155+
156+
public static IEnumerable<string> GetPackagePreReleaseVersions(string packageName)
157+
{
158+
return instance.m_Packages
159+
.Where(x => x.Name == packageName && x.Category == CurrentCategory)
160+
.Select(x => x.Version)
161+
.Where(x => SemVersion.Parse(x).IsPrerelease);
162+
}
163+
164+
public static void RefreshAvailableVersions(string packageName)
165+
{
166+
var filename = "Temp/DownloadedPackages/" + packageName + ".json/index";
167+
if (!File.Exists(filename))
168+
{
169+
try
170+
{
171+
EditorUtility.DisplayProgressBar("Package Installer", string.Format("Fetch package versions: {0}", packageName), 0.5f);
172+
var file = Utils.DownloadFile("https://api.nuget.org/v3/registration5-gz-semver2/" + packageName.ToLower() + "/index.json");
173+
Utils.ExtractArchive(file, Path.GetDirectoryName(filename));
174+
}
175+
catch
176+
{
177+
var dir = Path.GetDirectoryName(filename);
178+
if (!Directory.Exists(dir))
179+
Directory.CreateDirectory(dir);
180+
181+
File.WriteAllText(filename, "{}");
182+
Logger.LogException("Package '{0}' is not found.", packageName);
183+
return;
184+
}
185+
finally
186+
{
187+
EditorUtility.ClearProgressBar();
188+
}
189+
}
190+
191+
var json = File.ReadAllText(filename);
192+
var obj = JsonUtility.FromJson<CatalogRoot>(json);
193+
if (obj.items == null || obj.items.Length == 0) return;
194+
195+
instance.m_Packages = instance.m_Packages
196+
.Concat(obj.items
197+
.SelectMany(x => x.items)
198+
.Select(x => new NugetPackage(x.catalogEntry.id, x.catalogEntry.version, CurrentCategory)))
199+
.Distinct()
200+
.OrderBy(x => x.Name)
201+
.ThenByDescending(x => SemVersion.Parse(x.Version))
202+
.ToList();
203+
}
204+
}
205+
}

Plugins/CSharpCompilerSettings/CompilerFilter.cs.meta renamed to Editor/NugetPackageDrawer.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Plugins/CSharpCompilerSettings/CscSettingsAsset.cs

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.IO;
23
using System.Text;
34
using UnityEditor;
@@ -14,6 +15,68 @@ internal enum Nullable
1415
Annotations,
1516
}
1617

18+
internal enum CompilerType
19+
{
20+
BuiltIn,
21+
CustomPackage
22+
}
23+
24+
[Serializable]
25+
public struct NugetPackage
26+
{
27+
public enum CategoryType
28+
{
29+
Compiler,
30+
Analyzer,
31+
}
32+
33+
[SerializeField] private string m_Name;
34+
[SerializeField] private string m_Version;
35+
[SerializeField] private CategoryType m_Category;
36+
37+
public string PackageId
38+
{
39+
get { return m_Name + "." + m_Version; }
40+
}
41+
42+
public string Name
43+
{
44+
get { return m_Name; }
45+
}
46+
47+
public string Version
48+
{
49+
get { return m_Version; }
50+
}
51+
52+
public CategoryType Category
53+
{
54+
get { return m_Category; }
55+
}
56+
57+
public NugetPackage(string name, string version, CategoryType category = CategoryType.Compiler)
58+
{
59+
m_Name = name;
60+
m_Version = version;
61+
m_Category = category;
62+
}
63+
64+
public override string ToString()
65+
{
66+
return PackageId;
67+
}
68+
}
69+
70+
public class SplitAttribute : PropertyAttribute
71+
{
72+
public char separater { get; }
73+
74+
public SplitAttribute(char separater)
75+
{
76+
this.separater = separater;
77+
}
78+
}
79+
1780
internal class CscSettingsAsset : ScriptableObject, ISerializationCallbackReceiver
1881
{
1982
public const string k_SettingsPath = "ProjectSettings/CSharpCompilerSettings.asset";
@@ -27,10 +90,12 @@ internal class CscSettingsAsset : ScriptableObject, ISerializationCallbackReceiv
2790
[SerializeField] private bool m_EnableLogging = false;
2891
[SerializeField] private bool m_EnableNullable = false;
2992
[SerializeField] private Nullable m_Nullable = Nullable.Disable;
93+
[SerializeField] private NugetPackage m_CompilerPackage = new NugetPackage("Microsoft.Net.Compilers", "3.5.0", NugetPackage.CategoryType.Compiler);
3094

3195
[Tooltip(
3296
"When compiling this assembly, add or remove specific symbols separated with semicolons (;) or commas (,).\nSymbols starting with '!' will be removed.\n\ne.g. 'SYMBOL_TO_ADD;!SYMBOL_TO_REMOVE;...'")]
3397
[SerializeField]
98+
[Split(';')]
3499
private string m_ModifySymbols = "";
35100

36101
private static CscSettingsAsset CreateFromProjectSettings()
@@ -42,11 +107,8 @@ private static CscSettingsAsset CreateFromProjectSettings()
42107
}
43108

44109
private static CscSettingsAsset s_Instance;
45-
46110
public static CscSettingsAsset instance => s_Instance ? s_Instance : s_Instance = CreateFromProjectSettings();
47-
48-
public string PackageId => m_PackageName + "." + m_PackageVersion;
49-
111+
public NugetPackage CompilerPackage => m_CompilerPackage;
50112
public bool UseDefaultCompiler => m_CompilerType == CompilerType.BuiltIn;
51113
public bool ShouldToRecompile => m_CompilerType == CompilerType.CustomPackage || !string.IsNullOrEmpty(m_ModifySymbols);
52114
public Nullable Nullable => m_Nullable;
@@ -100,7 +162,7 @@ public static CscSettingsAsset GetAtPath(string path)
100162
{
101163
try
102164
{
103-
return !Core.HasPortableDll(path)
165+
return string.IsNullOrEmpty(Core.GetPortableDllPath(path))
104166
? null
105167
: CreateFromJson(AssetImporter.GetAtPath(path).userData);
106168
}
@@ -120,6 +182,9 @@ public static CscSettingsAsset CreateFromJson(string json = "")
120182
public void OnBeforeSerialize()
121183
{
122184
m_UseDefaultCompiler = m_CompilerType == CompilerType.BuiltIn;
185+
m_EnableNullable = m_Nullable != Nullable.Disable;
186+
m_PackageName = m_CompilerPackage.Name;
187+
m_PackageVersion = m_CompilerPackage.Version;
123188
}
124189

125190
public void OnAfterDeserialize()
@@ -131,13 +196,20 @@ public void OnAfterDeserialize()
131196
? CompilerType.BuiltIn
132197
: CompilerType.CustomPackage;
133198
}
199+
134200
if (m_Version < 130)
135201
{
136202
m_Version = 130;
137203
m_Nullable = m_EnableNullable
138204
? Nullable.Enable
139205
: Nullable.Disable;
140206
}
207+
208+
if (m_Version < 140)
209+
{
210+
m_Version = 140;
211+
m_CompilerPackage = new NugetPackage(m_PackageName, m_PackageVersion, NugetPackage.CategoryType.Compiler);
212+
}
141213
}
142214
}
143215
}

0 commit comments

Comments
 (0)