GetComponentSchemaProvider.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using UnityEditor;
  6. using UnityEngine;
  7. using Object = UnityEngine.Object;
  8. namespace LLM.Editor.Analysis
  9. {
  10. public class GetComponentSchemaProvider : IContextProvider
  11. {
  12. public class MemberSchema
  13. {
  14. public string name;
  15. public string memberType; // "Property" or "Field"
  16. public string valueType;
  17. }
  18. public object GetContext(Object target, string qualifier)
  19. {
  20. if (string.IsNullOrEmpty(qualifier))
  21. {
  22. return "Error: A component type name (qualifier) is required.";
  23. }
  24. try
  25. {
  26. var type = AppDomain.CurrentDomain.GetAssemblies()
  27. .SelectMany(assembly => assembly.GetTypes())
  28. .FirstOrDefault(t => t.FullName == qualifier && typeof(Component).IsAssignableFrom(t));
  29. if (type == null)
  30. {
  31. return $"Error: Could not find a Component type named '{qualifier}'.";
  32. }
  33. var members = new List<MemberSchema>();
  34. // 1. Get all public properties with a public setter, excluding obsolete/hidden ones.
  35. var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
  36. .Where(p => p.CanWrite && p.GetSetMethod(true) != null && p.GetSetMethod(true).IsPublic)
  37. .Where(p => !p.IsDefined(typeof(ObsoleteAttribute), true))
  38. .Where(p => !p.IsDefined(typeof(HideInInspector), true));
  39. members.AddRange(properties.Select(p => new MemberSchema
  40. {
  41. name = p.Name,
  42. memberType = "Property",
  43. valueType = p.PropertyType.FullName
  44. }));
  45. // 2. Get all fields (public and private) to check for serialization attributes.
  46. var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  47. var serializableFields = fields.Where(f =>
  48. {
  49. if (f.IsDefined(typeof(ObsoleteAttribute), true)) return false;
  50. if (f.IsDefined(typeof(HideInInspector), true)) return false;
  51. // A field is serialized if it's public OR has the [SerializeField] attribute.
  52. return f.IsPublic || f.IsDefined(typeof(SerializeField), true);
  53. });
  54. members.AddRange(serializableFields.Select(f => new MemberSchema
  55. {
  56. name = f.Name,
  57. memberType = "Field",
  58. valueType = f.FieldType.FullName
  59. }));
  60. // Return a distinct list, as a property can have a backing field with the same name.
  61. return members.GroupBy(m => m.name)
  62. .Select(g => g.First())
  63. .OrderBy(m => m.name)
  64. .ToList();
  65. }
  66. catch (Exception e)
  67. {
  68. return $"Error reflecting on type '{qualifier}': {e.Message}";
  69. }
  70. }
  71. }
  72. }