GenerateEnumMemberCombinationsAttribute.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // ReSharper disable RedundantUsingDirective
  2. using System;
  3. using JetBrains.Annotations;
  4. using Terminal.Gui.Analyzers.Internal.Compatibility;
  5. namespace Terminal.Gui.Analyzers.Internal.Attributes;
  6. /// <summary>
  7. /// Designates an enum member for inclusion in generation of bitwise combinations with other members decorated with
  8. /// this attribute which have the same <see cref="GroupTag"/> value.<br/>
  9. /// </summary>
  10. /// <remarks>
  11. /// <para>
  12. /// This attribute is only considered for enum types with the <see cref="GenerateEnumExtensionMethodsAttribute"/>.
  13. /// </para>
  14. /// </remarks>
  15. [AttributeUsage (AttributeTargets.Enum)]
  16. [UsedImplicitly]
  17. public sealed class GenerateEnumMemberCombinationsAttribute : System.Attribute
  18. {
  19. private const byte MaximumPopCountLimit = 14;
  20. private uint _mask;
  21. private uint _maskPopCount;
  22. private byte _popCountLimit = 8;
  23. /// <inheritdoc cref="CombinationGroupingAttribute.GroupTag" />
  24. public string GroupTag { get; set; }
  25. /// <summary>
  26. /// The mask for the group defined in <see cref="GroupTag"/>
  27. /// </summary>
  28. public uint Mask
  29. {
  30. get => _mask;
  31. set
  32. {
  33. #if NET8_0_OR_GREATER
  34. _maskPopCount = uint.PopCount (value);
  35. #else
  36. _maskPopCount = value.GetPopCount ();
  37. #endif
  38. PopCountLimitExceeded = _maskPopCount > PopCountLimit;
  39. MaximumPopCountLimitExceeded = _maskPopCount > MaximumPopCountLimit;
  40. if (PopCountLimitExceeded || MaximumPopCountLimitExceeded)
  41. {
  42. return;
  43. }
  44. _mask = value;
  45. }
  46. }
  47. /// <summary>
  48. /// The maximum number of bits allowed to be set to 1 in <see cref="Mask"/>.
  49. /// </summary>
  50. /// <remarks>
  51. /// <para>
  52. /// Default: 8 (256 possible combinations)
  53. /// </para>
  54. /// <para>
  55. /// Increasing this value is not recommended!<br/>
  56. /// Decreasing this value is pointless unless you want to limit maximum possible generated combinations even
  57. /// further.
  58. /// </para>
  59. /// <para>
  60. /// If the result of <see cref="NumericExtensions.GetPopCount(uint)"/>(<see cref="Mask"/>) exceeds 2 ^
  61. /// <see cref="PopCountLimit"/>, no
  62. /// combinations will be generated for the members which otherwise would have been included by <see cref="Mask"/>.
  63. /// Values exceeding the actual population count of <see cref="Mask"/> have no effect.
  64. /// </para>
  65. /// <para>
  66. /// This option is set to a sane default of 8, but also has a hard-coded limit of 14 (16384 combinations), as a
  67. /// protection against generation of extremely large files.
  68. /// </para>
  69. /// <para>
  70. /// CAUTION: The maximum number of possible combinations possible is equal to 1 &lt;&lt;
  71. /// <see cref="NumericExtensions.GetPopCount(uint)"/>(<see cref="Mask"/>).
  72. /// See <see cref="MaximumPopCountLimit"/> for hard-coded limit,
  73. /// </para>
  74. /// </remarks>
  75. public byte PopCountLimit
  76. {
  77. get => _popCountLimit;
  78. set
  79. {
  80. #if NET8_0_OR_GREATER
  81. _maskPopCount = uint.PopCount (_mask);
  82. #else
  83. _maskPopCount = _mask.GetPopCount ();
  84. #endif
  85. PopCountLimitExceeded = _maskPopCount > value;
  86. MaximumPopCountLimitExceeded = _maskPopCount > MaximumPopCountLimit;
  87. if (PopCountLimitExceeded || MaximumPopCountLimitExceeded)
  88. {
  89. return;
  90. }
  91. _mask = value;
  92. _popCountLimit = value;
  93. }
  94. }
  95. [UsedImplicitly]
  96. internal bool MaximumPopCountLimitExceeded { get; private set; }
  97. [UsedImplicitly]
  98. internal bool PopCountLimitExceeded { get; private set; }
  99. }