From 74fd06722027455acd6c2776386a64a3c890627b Mon Sep 17 00:00:00 2001 From: max Date: Wed, 29 Dec 2021 23:46:52 +0100 Subject: [PATCH] Required Attribute Validator --- CHANGELOG.md | 2 + Editor/IValidator.cs | 1 + Editor/ValidatorEditorWindow.cs | 2 +- Editor/Validators/AssetValidator.cs | 4 +- .../Validators/RequiredAttributeValidator.cs | 74 +++++++++++++++++++ .../RequiredAttributeValidator.cs.meta | 11 +++ Editor/Validators/SceneValidator.cs | 10 ++- Runtime/Validators.meta | 8 ++ Runtime/Validators/Attributes.meta | 8 ++ .../Attributes/RequiredAttribute.cs | 19 +++++ .../Attributes/RequiredAttribute.cs.meta | 11 +++ package.json | 2 +- 12 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 Editor/Validators/RequiredAttributeValidator.cs create mode 100644 Editor/Validators/RequiredAttributeValidator.cs.meta create mode 100644 Runtime/Validators.meta create mode 100644 Runtime/Validators/Attributes.meta create mode 100644 Runtime/Validators/Attributes/RequiredAttribute.cs create mode 100644 Runtime/Validators/Attributes/RequiredAttribute.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d6d566..769c591 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Change Log: ## 0.1.1 +- First prototype of Attribute validator. +## 0.1.1 - Search input. - GUI toolbar. - WarningType filter. diff --git a/Editor/IValidator.cs b/Editor/IValidator.cs index f067f61..6bab4f5 100644 --- a/Editor/IValidator.cs +++ b/Editor/IValidator.cs @@ -2,6 +2,7 @@ namespace Validator.Editor { public interface IValidator { + public string MenuName { get; } public Report Validate(); } } \ No newline at end of file diff --git a/Editor/ValidatorEditorWindow.cs b/Editor/ValidatorEditorWindow.cs index f0d78f8..340d7b9 100644 --- a/Editor/ValidatorEditorWindow.cs +++ b/Editor/ValidatorEditorWindow.cs @@ -156,7 +156,7 @@ namespace Validator.Editor validatorOptionsMenu.AddSeparator(""); foreach (ValidatorInfo validatorInfo in validators) { - validatorOptionsMenu.AddItem(new GUIContent($"{validatorInfo.validator.GetType().Name}"), validatorInfo.isEnabled, OnValidatorInfoVisibilityChangedEvent, validatorInfo); + validatorOptionsMenu.AddItem(new GUIContent($"{validatorInfo.validator.MenuName}"), validatorInfo.isEnabled, OnValidatorInfoVisibilityChangedEvent, validatorInfo); } validatorOptionsMenu.ShowAsContext(); } diff --git a/Editor/Validators/AssetValidator.cs b/Editor/Validators/AssetValidator.cs index 3555138..3cee642 100644 --- a/Editor/Validators/AssetValidator.cs +++ b/Editor/Validators/AssetValidator.cs @@ -6,9 +6,11 @@ namespace Validator.Editor { public class AssetValidator : IValidator { + public string MenuName => nameof(AssetValidator); + public Report Validate() { - Report report = new Report("AssetValidator"); + Report report = new Report(nameof(AssetValidator)); List objects = FindAssetsByType(); for (int i = 0; i < objects.Count; i++) diff --git a/Editor/Validators/RequiredAttributeValidator.cs b/Editor/Validators/RequiredAttributeValidator.cs new file mode 100644 index 0000000..3c16e4f --- /dev/null +++ b/Editor/Validators/RequiredAttributeValidator.cs @@ -0,0 +1,74 @@ +using System.Linq; +using System.Reflection; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace Validator.Editor +{ + public class RequiredAttributeAssetValidator : IValidator + { + public string MenuName => "Attributes/RequiredAttributeAssetValidator"; + + public Report Validate() + { + Report report = new Report(nameof(RequiredAttributeAssetValidator)); + + List objects = AssetValidator.FindAssetsByType(); + + for (int i = 0; i < objects.Count; i++) + { + EditorUtility.DisplayProgressBar("RequiredAttributeAssetValidator", "RequiredAttribute...", (float)i / objects.Count); + IEnumerable<(FieldInfo FieldInfo, RequiredAttribute Attribute)> fieldsWithRequiredAttribute = from fi in objects[i].GetType().GetFields() + let attr = fi.GetCustomAttributes(typeof(RequiredAttribute), true) + where attr.Length == 1 + select (FieldInfo: fi, Attribute: attr.First() as RequiredAttribute); + + foreach ((FieldInfo FieldInfo, RequiredAttribute Attribute) field in fieldsWithRequiredAttribute) + { + object o = field.FieldInfo.GetValue(objects[i]); + if (o == null || o.Equals(null)) + { + report.Log(objects[i], field.Attribute.WarningType, field.Attribute.Category, $"{field.FieldInfo.Name} is null", $"Assign {field.FieldInfo.FieldType}"); + } + } + } + EditorUtility.ClearProgressBar(); + + return report; + } + } + + public class RequiredAttributeSceneValidator : IValidator + { + public string MenuName => "Attributes/RequiredAttributeSceneValidator"; + + public Report Validate() + { + Report report = new Report(nameof(RequiredAttributeSceneValidator)); + + List objects = SceneValidator.FindAllObjectsOfType(); + + for (int i = 0; i < objects.Count; i++) + { + EditorUtility.DisplayProgressBar("RequiredAttributeSceneValidator", "RequiredAttribute...", (float)i / objects.Count); + IEnumerable<(FieldInfo FieldInfo, RequiredAttribute Attribute)> fieldsWithRequiredAttribute = from fi in objects[i].GetType().GetFields() + let attr = fi.GetCustomAttributes(typeof(RequiredAttribute), true) + where attr.Length == 1 + select (FieldInfo: fi, Attribute: attr.First() as RequiredAttribute); + + foreach ((FieldInfo FieldInfo, RequiredAttribute Attribute) field in fieldsWithRequiredAttribute) + { + object o = field.FieldInfo.GetValue(objects[i]); + if (o == null || o.Equals(null)) + { + report.Log(objects[i], field.Attribute.WarningType, field.Attribute.Category, $"{field.FieldInfo.Name} is null", $"Assign {field.FieldInfo.FieldType}"); + } + } + } + EditorUtility.ClearProgressBar(); + + return report; + } + } +} \ No newline at end of file diff --git a/Editor/Validators/RequiredAttributeValidator.cs.meta b/Editor/Validators/RequiredAttributeValidator.cs.meta new file mode 100644 index 0000000..91224a3 --- /dev/null +++ b/Editor/Validators/RequiredAttributeValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90d5c1b8964451644b0aa09257ab0bc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Validators/SceneValidator.cs b/Editor/Validators/SceneValidator.cs index 02843b1..6fa6060 100644 --- a/Editor/Validators/SceneValidator.cs +++ b/Editor/Validators/SceneValidator.cs @@ -7,9 +7,11 @@ namespace Validator.Editor { public class SceneValidator : IValidator { - public Report Validate() + public string MenuName => nameof(SceneValidator); + + public Report Validate() { - Report report = new Report("SceneValidator"); + Report report = new Report(nameof(SceneValidator)); List objects = FindAllObjectsOfType(); for (int i = 0; i < objects.Count; i++) @@ -17,7 +19,7 @@ namespace Validator.Editor EditorUtility.DisplayProgressBar("SceneValidator", "Validate...", (float)i / objects.Count); objects[i].Validate(report); - } + } EditorUtility.ClearProgressBar(); return report; @@ -37,7 +39,7 @@ namespace Validator.Editor return gameObjects; } - private static List FindAllObjectsOfType() + public static List FindAllObjectsOfType() { List objects = new List(); diff --git a/Runtime/Validators.meta b/Runtime/Validators.meta new file mode 100644 index 0000000..66f62c8 --- /dev/null +++ b/Runtime/Validators.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8cd25e23ad137e24ea0f469556831712 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Validators/Attributes.meta b/Runtime/Validators/Attributes.meta new file mode 100644 index 0000000..bff1298 --- /dev/null +++ b/Runtime/Validators/Attributes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 25705f09a21a10049aed213ea301db84 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Validators/Attributes/RequiredAttribute.cs b/Runtime/Validators/Attributes/RequiredAttribute.cs new file mode 100644 index 0000000..3bff5e7 --- /dev/null +++ b/Runtime/Validators/Attributes/RequiredAttribute.cs @@ -0,0 +1,19 @@ +using System; + +namespace Validator +{ + [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] + public class RequiredAttribute : Attribute + { + public WarningType WarningType { get; private set; } = WarningType.Error; + public string Category { get; private set; } = ReportCategories.Design; + + public RequiredAttribute() { } + + public RequiredAttribute(WarningType warningType = WarningType.Error, string category = ReportCategories.Design) + { + WarningType = warningType; + Category = category; + } + } +} \ No newline at end of file diff --git a/Runtime/Validators/Attributes/RequiredAttribute.cs.meta b/Runtime/Validators/Attributes/RequiredAttribute.cs.meta new file mode 100644 index 0000000..4b031a2 --- /dev/null +++ b/Runtime/Validators/Attributes/RequiredAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4dbbb107f0e849140b1132ac5dcca90f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json index 1544536..2a733c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.vertexcolor.validator", "displayName": "Validator", - "version": "0.1.1", + "version": "0.1.2", "unity": "2019.3", "description": "Unity project validator framework.", "category": "Tool",