| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Linq; |
| | | 4 | | |
| | | 5 | | namespace NexusLabs.Needlr.Generators.Models; |
| | | 6 | | |
| | | 7 | | /// <summary> |
| | | 8 | | /// Information about a discovered options type (from [Options]). |
| | | 9 | | /// </summary> |
| | | 10 | | internal readonly struct DiscoveredOptions |
| | | 11 | | { |
| | | 12 | | public DiscoveredOptions( |
| | | 13 | | string typeName, |
| | | 14 | | string sectionName, |
| | | 15 | | string? name, |
| | | 16 | | bool validateOnStart, |
| | | 17 | | string assemblyName, |
| | | 18 | | string? sourceFilePath = null, |
| | | 19 | | OptionsValidatorInfo? validatorMethod = null, |
| | | 20 | | string? validateMethodOverride = null, |
| | | 21 | | string? validatorTypeName = null, |
| | | 22 | | PositionalRecordInfo? positionalRecordInfo = null, |
| | | 23 | | IReadOnlyList<OptionsPropertyInfo>? properties = null) |
| | | 24 | | { |
| | 173 | 25 | | TypeName = typeName; |
| | 173 | 26 | | SectionName = sectionName; |
| | 173 | 27 | | Name = name; |
| | 173 | 28 | | ValidateOnStart = validateOnStart; |
| | 173 | 29 | | AssemblyName = assemblyName; |
| | 173 | 30 | | SourceFilePath = sourceFilePath; |
| | 173 | 31 | | ValidatorMethod = validatorMethod; |
| | 173 | 32 | | ValidateMethodOverride = validateMethodOverride; |
| | 173 | 33 | | ValidatorTypeName = validatorTypeName; |
| | 173 | 34 | | PositionalRecordInfo = positionalRecordInfo; |
| | 173 | 35 | | Properties = properties ?? Array.Empty<OptionsPropertyInfo>(); |
| | 173 | 36 | | } |
| | | 37 | | |
| | | 38 | | /// <summary>Fully qualified type name of the options class.</summary> |
| | 1006 | 39 | | public string TypeName { get; } |
| | | 40 | | |
| | | 41 | | /// <summary>Configuration section name (e.g., "Database").</summary> |
| | 456 | 42 | | public string SectionName { get; } |
| | | 43 | | |
| | | 44 | | /// <summary>Named options name (e.g., "Primary"), or null for default options.</summary> |
| | 403 | 45 | | public string? Name { get; } |
| | | 46 | | |
| | | 47 | | /// <summary>Whether to validate options on startup.</summary> |
| | 457 | 48 | | public bool ValidateOnStart { get; } |
| | | 49 | | |
| | 165 | 50 | | public string AssemblyName { get; } |
| | 191 | 51 | | public string? SourceFilePath { get; } |
| | | 52 | | |
| | | 53 | | /// <summary>Information about the validation method (discovered or specified).</summary> |
| | 509 | 54 | | public OptionsValidatorInfo? ValidatorMethod { get; } |
| | | 55 | | |
| | | 56 | | /// <summary>Custom validation method name override from [Options(ValidateMethod = "...")], or null to use conventio |
| | 22 | 57 | | public string? ValidateMethodOverride { get; } |
| | | 58 | | |
| | | 59 | | /// <summary>External validator type name from [Options(Validator = typeof(...))], or null to use options class.</su |
| | 148 | 60 | | public string? ValidatorTypeName { get; } |
| | | 61 | | |
| | | 62 | | /// <summary>Information about positional record primary constructor, if applicable.</summary> |
| | 452 | 63 | | public PositionalRecordInfo? PositionalRecordInfo { get; } |
| | | 64 | | |
| | | 65 | | /// <summary>Bindable properties for AOT code generation.</summary> |
| | 653 | 66 | | public IReadOnlyList<OptionsPropertyInfo> Properties { get; } |
| | | 67 | | |
| | | 68 | | /// <summary>True if this is a named options registration (not default).</summary> |
| | 192 | 69 | | public bool IsNamed => Name != null; |
| | | 70 | | |
| | | 71 | | /// <summary>True if this options type has a custom validator method.</summary> |
| | 429 | 72 | | public bool HasValidatorMethod => ValidatorMethod != null; |
| | | 73 | | |
| | | 74 | | /// <summary>True if an external validator type is specified.</summary> |
| | 138 | 75 | | public bool HasExternalValidator => ValidatorTypeName != null; |
| | | 76 | | |
| | | 77 | | /// <summary>True if this is a positional record that needs a generated parameterless constructor.</summary> |
| | 165 | 78 | | public bool NeedsGeneratedConstructor => PositionalRecordInfo?.IsPartial == true; |
| | | 79 | | |
| | | 80 | | /// <summary>True if this is a non-partial positional record (will emit diagnostic).</summary> |
| | 165 | 81 | | public bool IsNonPartialPositionalRecord => PositionalRecordInfo != null && !PositionalRecordInfo.Value.IsPartial; |
| | | 82 | | |
| | | 83 | | /// <summary>True if this type has any init-only properties (requires factory pattern in AOT).</summary> |
| | 209 | 84 | | public bool HasInitOnlyProperties => Properties.Any(p => p.HasInitOnlySetter); |
| | | 85 | | |
| | | 86 | | /// <summary>True if this is a positional record (uses constructor binding in AOT).</summary> |
| | 87 | 87 | | public bool IsPositionalRecord => PositionalRecordInfo != null; |
| | | 88 | | |
| | | 89 | | /// <summary>True if this type requires factory pattern (Options.Create) instead of Configure delegate in AOT.</summ |
| | 0 | 90 | | public bool RequiresFactoryPattern => IsPositionalRecord || HasInitOnlyProperties; |
| | | 91 | | |
| | | 92 | | /// <summary>True if any property has DataAnnotation validation attributes.</summary> |
| | 1089 | 93 | | public bool HasDataAnnotations => Properties.Any(p => p.HasDataAnnotations); |
| | | 94 | | } |