GenerateEnumExtensionMethodsAttribute.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // ReSharper disable RedundantNullableDirective
  2. // ReSharper disable RedundantUsingDirective
  3. // ReSharper disable ClassNeverInstantiated.Global
  4. #nullable enable
  5. using System;
  6. using Attribute = System.Attribute;
  7. using AttributeUsageAttribute = System.AttributeUsageAttribute;
  8. using AttributeTargets = System.AttributeTargets;
  9. namespace Terminal.Gui.Analyzers.Internal.Attributes;
  10. /// <summary>
  11. /// Used to enable source generation of a common set of extension methods for enum types.
  12. /// </summary>
  13. [AttributeUsage (AttributeTargets.Enum)]
  14. internal sealed class GenerateEnumExtensionMethodsAttribute : Attribute
  15. {
  16. /// <summary>
  17. /// The name of the generated static class.
  18. /// </summary>
  19. /// <remarks>
  20. /// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".<br/>
  21. /// No other validation is performed, so illegal values will simply result in compiler errors.
  22. /// <para>
  23. /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
  24. /// </para>
  25. /// </remarks>
  26. public string? ClassName { get; set; }
  27. /// <summary>
  28. /// The namespace in which to place the generated static class containing the extension methods.
  29. /// </summary>
  30. /// <remarks>
  31. /// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.<br/>
  32. /// No other validation is performed, so illegal values will simply result in compiler errors.
  33. /// <para>
  34. /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
  35. /// </para>
  36. /// </remarks>
  37. public string? ClassNamespace { get; set; }
  38. /// <summary>
  39. /// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
  40. /// <see cref="Enum.HasFlag"/> method.
  41. /// </summary>
  42. /// <remarks>
  43. /// <para>
  44. /// Default: false
  45. /// </para>
  46. /// <para>
  47. /// If the enum is not decorated with <see cref="FlagsAttribute"/>, this option has no effect.
  48. /// </para>
  49. /// <para>
  50. /// If multiple members have the same value, the first member with that value will be used and subsequent members
  51. /// with the same value will be skipped.
  52. /// </para>
  53. /// <para>
  54. /// Overloads taking the enum type itself as well as the underlying type of the enum will be generated, enabling
  55. /// avoidance of implicit or explicit cast overhead.
  56. /// </para>
  57. /// <para>
  58. /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
  59. /// </para>
  60. /// </remarks>
  61. public bool FastHasFlags { get; set; }
  62. /// <summary>
  63. /// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
  64. /// <see cref="Enum.IsDefined"/> method,
  65. /// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
  66. /// </summary>
  67. /// <remarks>
  68. /// <para>
  69. /// Default: true
  70. /// </para>
  71. /// <para>
  72. /// If multiple members have the same value, the first member with that value will be used and subsequent members
  73. /// with the same value will be skipped.
  74. /// </para>
  75. /// <para>
  76. /// As with <see cref="Enum.IsDefined"/> the source generator only considers explicitly-named members.<br/>
  77. /// Generation of values which represent valid bitwise combinations of members of enums decorated with
  78. /// <see cref="FlagsAttribute"/> is not affected by this property.
  79. /// </para>
  80. /// </remarks>
  81. public bool FastIsDefined { get; init; } = true;
  82. /// <summary>
  83. /// Gets a <see langword="bool"/> value indicating if this <see cref="GenerateEnumExtensionMethodsAttribute"/> instance
  84. /// contains default values only. See <see href="#remarks">remarks</see> of this method or documentation on properties of this type for details.
  85. /// </summary>
  86. /// <returns>
  87. /// A <see langword="bool"/> value indicating if all property values are default for this
  88. /// <see cref="GenerateEnumExtensionMethodsAttribute"/> instance.
  89. /// </returns>
  90. /// <remarks>
  91. /// Default values that will result in a <see langword="true"/> return value are:<br/>
  92. /// <see cref="FastIsDefined"/> &amp;&amp; !<see cref="FastHasFlags"/> &amp;&amp; <see cref="ClassName"/>
  93. /// <see langword="is"/> <see langword="null"/> &amp;&amp; <see cref="ClassNamespace"/> <see langword="is"/>
  94. /// <see langword="null"/>
  95. /// </remarks>
  96. public override bool IsDefaultAttribute ()
  97. {
  98. return FastIsDefined
  99. && !FastHasFlags
  100. && ClassName is null
  101. && ClassNamespace is null;
  102. }
  103. }