Merge branch 'v2_develop' into v2_PackageReference_Ranges

This commit is contained in:
Tig
2024-07-11 07:02:46 -06:00
committed by GitHub
78 changed files with 730 additions and 3573 deletions

View File

@@ -43,7 +43,6 @@ jobs:
- name: Build Release
run: |
dotnet-gitversion /updateprojectfiles
dotnet build ./Analyzers/Terminal.Gui.Analyzers.Internal --no-incremental --nologo --force --configuration Release
dotnet build --no-incremental --nologo --force --configuration Release
- name: Pack

View File

@@ -1,10 +0,0 @@
{
"solution": {
"path": "Terminal.sln",
"projects": [
"Analyzers\\Terminal.Gui.Analyzers.Internal.Debugging\\Terminal.Gui.Analyzers.Internal.Debugging.csproj",
"Analyzers\\Terminal.Gui.Analyzers.Internal.Tests\\Terminal.Gui.Analyzers.Internal.Tests.csproj",
"Analyzers\\Terminal.Gui.Analyzers.Internal\\Terminal.Gui.Analyzers.Internal.csproj",
]
}
}

View File

@@ -1,23 +0,0 @@
<Project>
<PropertyGroup>
<Nullable>enable</Nullable>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<WarningLevel>8</WarningLevel>
<CharacterSet>UTF-8</CharacterSet>
<Deterministic>true</Deterministic>
<UTF8OutPut>true</UTF8OutPut>
<DefineConstants>$(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS</DefineConstants>
<NoLogo>True</NoLogo>
<DefineTrace>True</DefineTrace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="JetBrains.ExternalAnnotations" Version="10.2.149" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Buffers" />
<Using Include="System.Collections.Specialized" />
<Using Include="System.Numerics" />
<Using Include="System.Runtime.CompilerServices" />
</ItemGroup>
</Project>

View File

@@ -1,23 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Debugging;
static class Program
{
static void Main (string [] args)
{
}
}
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "It's not that deep")]
public enum TestEnum
{
Zero = 0,
One,
Two = 2,
Three,
Six = 6
}

View File

@@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.10.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Terminal.Gui.Analyzers.Internal\Terminal.Gui.Analyzers.Internal.csproj">
<PrivateAssets>all</PrivateAssets>
<OutputItemType>Analyzer</OutputItemType>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Update="JetBrains.Annotations" Version="2024.2.0" />
</ItemGroup>
</Project>

View File

@@ -1,42 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
internal sealed class SignedEnumMemberValues
{
internal const int Bit31 = ~0b_01111111_11111111_11111111_11111111;
internal const int Bit30 = 0b_01000000_00000000_00000000_00000000;
internal const int Bit29 = 0b_00100000_00000000_00000000_00000000;
internal const int Bit28 = 0b_00010000_00000000_00000000_00000000;
internal const int Bit27 = 0b_00001000_00000000_00000000_00000000;
internal const int Bit26 = 0b_00000100_00000000_00000000_00000000;
internal const int Bit25 = 0b_00000010_00000000_00000000_00000000;
internal const int Bit24 = 0b_00000001_00000000_00000000_00000000;
internal const int Bit23 = 0b_00000000_10000000_00000000_00000000;
internal const int Bit22 = 0b_00000000_01000000_00000000_00000000;
internal const int Bit21 = 0b_00000000_00100000_00000000_00000000;
internal const int Bit20 = 0b_00000000_00010000_00000000_00000000;
internal const int Bit19 = 0b_00000000_00001000_00000000_00000000;
internal const int Bit18 = 0b_00000000_00000100_00000000_00000000;
internal const int Bit17 = 0b_00000000_00000010_00000000_00000000;
internal const int Bit16 = 0b_00000000_00000001_00000000_00000000;
internal const int Bit15 = 0b_00000000_00000000_10000000_00000000;
internal const int Bit14 = 0b_00000000_00000000_01000000_00000000;
internal const int Bit13 = 0b_00000000_00000000_00100000_00000000;
internal const int Bit12 = 0b_00000000_00000000_00010000_00000000;
internal const int Bit11 = 0b_00000000_00000000_00001000_00000000;
internal const int Bit10 = 0b_00000000_00000000_00000100_00000000;
internal const int Bit09 = 0b_00000000_00000000_00000010_00000000;
internal const int Bit08 = 0b_00000000_00000000_00000001_00000000;
internal const int Bit07 = 0b_00000000_00000000_00000000_10000000;
internal const int Bit06 = 0b_00000000_00000000_00000000_01000000;
internal const int Bit05 = 0b_00000000_00000000_00000000_00100000;
internal const int Bit04 = 0b_00000000_00000000_00000000_00010000;
internal const int Bit03 = 0b_00000000_00000000_00000000_00001000;
internal const int Bit02 = 0b_00000000_00000000_00000000_00000100;
internal const int Bit01 = 0b_00000000_00000000_00000000_00000010;
internal const int Bit00 = 0b_00000000_00000000_00000000_00000001;
internal const int All_0 = 0;
internal const int All_1 = ~All_0;
internal const int Alternating_01 = 0b_01010101_01010101_01010101_01010101;
internal const int Alternating_10 = ~Alternating_01;
internal const int EvenBytesHigh = 0b_00000000_11111111_00000000_11111111;
internal const int OddBytesHigh = ~EvenBytesHigh;
}

View File

@@ -1,51 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BasicEnum"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = 0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = 0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = 0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,51 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BasicEnum_ExplicitInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum_ExplicitInt
{
Bit31 = BasicEnum_ExplicitInt.Bit31,
Bit30 = BasicEnum_ExplicitInt.Bit30,
Bit29 = BasicEnum_ExplicitInt.Bit29,
Bit28 = BasicEnum_ExplicitInt.Bit28,
Bit27 = BasicEnum_ExplicitInt.Bit27,
Bit26 = BasicEnum_ExplicitInt.Bit26,
Bit25 = BasicEnum_ExplicitInt.Bit25,
Bit24 = BasicEnum_ExplicitInt.Bit24,
Bit23 = BasicEnum_ExplicitInt.Bit23,
Bit22 = BasicEnum_ExplicitInt.Bit22,
Bit21 = BasicEnum_ExplicitInt.Bit21,
Bit20 = BasicEnum_ExplicitInt.Bit20,
Bit19 = BasicEnum_ExplicitInt.Bit19,
Bit18 = BasicEnum_ExplicitInt.Bit18,
Bit17 = BasicEnum_ExplicitInt.Bit17,
Bit16 = BasicEnum_ExplicitInt.Bit16,
Bit15 = BasicEnum_ExplicitInt.Bit15,
Bit14 = BasicEnum_ExplicitInt.Bit14,
Bit13 = BasicEnum_ExplicitInt.Bit13,
Bit12 = BasicEnum_ExplicitInt.Bit12,
Bit11 = BasicEnum_ExplicitInt.Bit11,
Bit10 = BasicEnum_ExplicitInt.Bit10,
Bit09 = BasicEnum_ExplicitInt.Bit09,
Bit08 = BasicEnum_ExplicitInt.Bit08,
Bit07 = BasicEnum_ExplicitInt.Bit07,
Bit06 = BasicEnum_ExplicitInt.Bit06,
Bit05 = BasicEnum_ExplicitInt.Bit05,
Bit04 = BasicEnum_ExplicitInt.Bit04,
Bit03 = BasicEnum_ExplicitInt.Bit03,
Bit02 = BasicEnum_ExplicitInt.Bit02,
Bit01 = BasicEnum_ExplicitInt.Bit01,
Bit00 = BasicEnum_ExplicitInt.Bit00,
All_0 = BasicEnum_ExplicitInt.All_0,
All_1 = BasicEnum_ExplicitInt.All_1,
Alternating_01 = BasicEnum_ExplicitInt.Alternating_01,
Alternating_10 = BasicEnum_ExplicitInt.Alternating_10,
EvenBytesHigh = BasicEnum_ExplicitInt.EvenBytesHigh,
OddBytesHigh = BasicEnum_ExplicitInt.OddBytesHigh
}

View File

@@ -1,52 +0,0 @@
// ReSharper disable EnumUnderlyingTypeIsInt
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BetterEnum_ExplicitInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute.FastIsDefined"/> = <see langword="false" />.
/// </summary>
[GenerateEnumExtensionMethods (FastIsDefined = false)]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum_ExplicitInt_NoFastIsDefined : int
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = 0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = 0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = 0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,51 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BasicEnum_ExplicitUInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum_ExplicitUInt : uint
{
Bit31 = 0b_10000000_00000000_00000000_00000000u,
Bit30 = 0b_01000000_00000000_00000000_00000000u,
Bit29 = 0b_00100000_00000000_00000000_00000000u,
Bit28 = 0b_00010000_00000000_00000000_00000000u,
Bit27 = 0b_00001000_00000000_00000000_00000000u,
Bit26 = 0b_00000100_00000000_00000000_00000000u,
Bit25 = 0b_00000010_00000000_00000000_00000000u,
Bit24 = 0b_00000001_00000000_00000000_00000000u,
Bit23 = 0b_00000000_10000000_00000000_00000000u,
Bit22 = 0b_00000000_01000000_00000000_00000000u,
Bit21 = 0b_00000000_00100000_00000000_00000000u,
Bit20 = 0b_00000000_00010000_00000000_00000000u,
Bit19 = 0b_00000000_00001000_00000000_00000000u,
Bit18 = 0b_00000000_00000100_00000000_00000000u,
Bit17 = 0b_00000000_00000010_00000000_00000000u,
Bit16 = 0b_00000000_00000001_00000000_00000000u,
Bit15 = 0b_00000000_00000000_10000000_00000000u,
Bit14 = 0b_00000000_00000000_01000000_00000000u,
Bit13 = 0b_00000000_00000000_00100000_00000000u,
Bit12 = 0b_00000000_00000000_00010000_00000000u,
Bit11 = 0b_00000000_00000000_00001000_00000000u,
Bit10 = 0b_00000000_00000000_00000100_00000000u,
Bit09 = 0b_00000000_00000000_00000010_00000000u,
Bit08 = 0b_00000000_00000000_00000001_00000000u,
Bit07 = 0b_00000000_00000000_00000000_10000000u,
Bit06 = 0b_00000000_00000000_00000000_01000000u,
Bit05 = 0b_00000000_00000000_00000000_00100000u,
Bit04 = 0b_00000000_00000000_00000000_00010000u,
Bit03 = 0b_00000000_00000000_00000000_00001000u,
Bit02 = 0b_00000000_00000000_00000000_00000100u,
Bit01 = 0b_00000000_00000000_00000000_00000010u,
Bit00 = 0b_00000000_00000000_00000000_00000001u,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,51 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BetterEnum_ExplicitUInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute.FastIsDefined"/> = <see langword="false" />.
/// </summary>
[GenerateEnumExtensionMethods (FastIsDefined = false)]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum_ExplicitUInt_NoFastIsDefined : uint
{
Bit31 = 0b_10000000_00000000_00000000_00000000u,
Bit30 = 0b_01000000_00000000_00000000_00000000u,
Bit29 = 0b_00100000_00000000_00000000_00000000u,
Bit28 = 0b_00010000_00000000_00000000_00000000u,
Bit27 = 0b_00001000_00000000_00000000_00000000u,
Bit26 = 0b_00000100_00000000_00000000_00000000u,
Bit25 = 0b_00000010_00000000_00000000_00000000u,
Bit24 = 0b_00000001_00000000_00000000_00000000u,
Bit23 = 0b_00000000_10000000_00000000_00000000u,
Bit22 = 0b_00000000_01000000_00000000_00000000u,
Bit21 = 0b_00000000_00100000_00000000_00000000u,
Bit20 = 0b_00000000_00010000_00000000_00000000u,
Bit19 = 0b_00000000_00001000_00000000_00000000u,
Bit18 = 0b_00000000_00000100_00000000_00000000u,
Bit17 = 0b_00000000_00000010_00000000_00000000u,
Bit16 = 0b_00000000_00000001_00000000_00000000u,
Bit15 = 0b_00000000_00000000_10000000_00000000u,
Bit14 = 0b_00000000_00000000_01000000_00000000u,
Bit13 = 0b_00000000_00000000_00100000_00000000u,
Bit12 = 0b_00000000_00000000_00010000_00000000u,
Bit11 = 0b_00000000_00000000_00001000_00000000u,
Bit10 = 0b_00000000_00000000_00000100_00000000u,
Bit09 = 0b_00000000_00000000_00000010_00000000u,
Bit08 = 0b_00000000_00000000_00000001_00000000u,
Bit07 = 0b_00000000_00000000_00000000_10000000u,
Bit06 = 0b_00000000_00000000_00000000_01000000u,
Bit05 = 0b_00000000_00000000_00000000_00100000u,
Bit04 = 0b_00000000_00000000_00000000_00010000u,
Bit03 = 0b_00000000_00000000_00000000_00001000u,
Bit02 = 0b_00000000_00000000_00000000_00000100u,
Bit01 = 0b_00000000_00000000_00000000_00000010u,
Bit00 = 0b_00000000_00000000_00000000_00000001u,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,51 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="BetterEnum"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute.FastIsDefined"/> = <see langword="false" />.
/// </summary>
[GenerateEnumExtensionMethods (FastIsDefined = false)]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterEnum_NoFastIsDefined
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = 0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = 0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = 0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,52 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="FlagsEnum"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterFlagsEnum
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = -0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = -0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = -0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,53 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// <summary>
/// Same as <see cref="FlagsEnum_ExplicitInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterFlagsEnum_ExplicitInt : int
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = -0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = -0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = -0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,52 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Same as <see cref="FlagsEnum_ExplicitUInt"/>, but with <see cref="GenerateEnumExtensionMethodsAttribute"/> applied.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods]
[SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BetterFlagsEnum_ExplicitUInt : uint
{
Bit31 = 0b_10000000_00000000_00000000_00000000u,
Bit30 = 0b_01000000_00000000_00000000_00000000u,
Bit29 = 0b_00100000_00000000_00000000_00000000u,
Bit28 = 0b_00010000_00000000_00000000_00000000u,
Bit27 = 0b_00001000_00000000_00000000_00000000u,
Bit26 = 0b_00000100_00000000_00000000_00000000u,
Bit25 = 0b_00000010_00000000_00000000_00000000u,
Bit24 = 0b_00000001_00000000_00000000_00000000u,
Bit23 = 0b_00000000_10000000_00000000_00000000u,
Bit22 = 0b_00000000_01000000_00000000_00000000u,
Bit21 = 0b_00000000_00100000_00000000_00000000u,
Bit20 = 0b_00000000_00010000_00000000_00000000u,
Bit19 = 0b_00000000_00001000_00000000_00000000u,
Bit18 = 0b_00000000_00000100_00000000_00000000u,
Bit17 = 0b_00000000_00000010_00000000_00000000u,
Bit16 = 0b_00000000_00000001_00000000_00000000u,
Bit15 = 0b_00000000_00000000_10000000_00000000u,
Bit14 = 0b_00000000_00000000_01000000_00000000u,
Bit13 = 0b_00000000_00000000_00100000_00000000u,
Bit12 = 0b_00000000_00000000_00010000_00000000u,
Bit11 = 0b_00000000_00000000_00001000_00000000u,
Bit10 = 0b_00000000_00000000_00000100_00000000u,
Bit09 = 0b_00000000_00000000_00000010_00000000u,
Bit08 = 0b_00000000_00000000_00000001_00000000u,
Bit07 = 0b_00000000_00000000_00000000_10000000u,
Bit06 = 0b_00000000_00000000_00000000_01000000u,
Bit05 = 0b_00000000_00000000_00000000_00100000u,
Bit04 = 0b_00000000_00000000_00000000_00010000u,
Bit03 = 0b_00000000_00000000_00000000_00001000u,
Bit02 = 0b_00000000_00000000_00000000_00000100u,
Bit01 = 0b_00000000_00000000_00000000_00000010u,
Bit00 = 0b_00000000_00000000_00000000_00000001u,
All_0 = 0,
All_1 = ~All_0,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = ~Alternating_01,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
OddBytesHigh = ~EvenBytesHigh,
}

View File

@@ -1,48 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Basic enum without explicitly-defined backing type and no attributes on the enum or any of its members.
/// </summary>
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BasicEnum
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = 0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = 0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = 0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = -1,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = unchecked((int)0b_10101010_10101010_10101010_10101010),
OddBytesHigh = unchecked((int)0b_11111111_00000000_11111111_00000000),
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111,
}

View File

@@ -1,50 +0,0 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Basic enum with explicitly-defined backing type of int and no attributes on the enum or any of its members.
/// </summary>
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BasicEnum_ExplicitInt : int
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = 0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = 0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = 0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = -1,
Alternating_01 = 0b_01010101_01010101_01010101_01010101,
Alternating_10 = unchecked((int)0b_10101010_10101010_10101010_10101010),
OddBytesHigh = unchecked((int)0b_11111111_00000000_11111111_00000000),
EvenBytesHigh = unchecked((int)0b_00000000_11111111_00000000_11111111),
}

View File

@@ -1,48 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Basic enum with explicitly-defined backing type of uint and no attributes on the enum or any of its members.
/// </summary>
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum BasicEnum_ExplicitUInt : uint
{
Bit31 = 0b_10000000_00000000_00000000_00000000u,
Bit30 = 0b_01000000_00000000_00000000_00000000u,
Bit29 = 0b_00100000_00000000_00000000_00000000u,
Bit28 = 0b_00010000_00000000_00000000_00000000u,
Bit27 = 0b_00001000_00000000_00000000_00000000u,
Bit26 = 0b_00000100_00000000_00000000_00000000u,
Bit25 = 0b_00000010_00000000_00000000_00000000u,
Bit24 = 0b_00000001_00000000_00000000_00000000u,
Bit23 = 0b_00000000_10000000_00000000_00000000u,
Bit22 = 0b_00000000_01000000_00000000_00000000u,
Bit21 = 0b_00000000_00100000_00000000_00000000u,
Bit20 = 0b_00000000_00010000_00000000_00000000u,
Bit19 = 0b_00000000_00001000_00000000_00000000u,
Bit18 = 0b_00000000_00000100_00000000_00000000u,
Bit17 = 0b_00000000_00000010_00000000_00000000u,
Bit16 = 0b_00000000_00000001_00000000_00000000u,
Bit15 = 0b_00000000_00000000_10000000_00000000u,
Bit14 = 0b_00000000_00000000_01000000_00000000u,
Bit13 = 0b_00000000_00000000_00100000_00000000u,
Bit12 = 0b_00000000_00000000_00010000_00000000u,
Bit11 = 0b_00000000_00000000_00001000_00000000u,
Bit10 = 0b_00000000_00000000_00000100_00000000u,
Bit09 = 0b_00000000_00000000_00000010_00000000u,
Bit08 = 0b_00000000_00000000_00000001_00000000u,
Bit07 = 0b_00000000_00000000_00000000_10000000u,
Bit06 = 0b_00000000_00000000_00000000_01000000u,
Bit05 = 0b_00000000_00000000_00000000_00100000u,
Bit04 = 0b_00000000_00000000_00000000_00010000u,
Bit03 = 0b_00000000_00000000_00000000_00001000u,
Bit02 = 0b_00000000_00000000_00000000_00000100u,
Bit01 = 0b_00000000_00000000_00000000_00000010u,
Bit00 = 0b_00000000_00000000_00000000_00000001u,
All_0 = 0b_00000000_00000000_00000000_00000000u,
All_1 = 0b_11111111_11111111_11111111_11111111u,
Alternating_01 = 0b_01010101_01010101_01010101_01010101u,
Alternating_10 = 0b_10101010_10101010_10101010_10101010u,
OddBytesHigh = 0b_11111111_00000000_11111111_00000000u,
EvenBytesHigh = 0b_00000000_11111111_00000000_11111111u,
}

View File

@@ -1,45 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Flags enum without explicitly-defined backing type and only a <see cref="FlagsAttribute"/> on the enum declaration No other attributes on the enum or its members..
/// </summary>
[Flags]
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum FlagsEnum
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = -0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = -0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = -0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = -1
}

View File

@@ -1,45 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Flags enum with explicitly-defined backing type of int and only a <see cref="FlagsAttribute"/> on the enum declaration No other attributes on the enum or its members..
/// </summary>
[Flags]
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum FlagsEnum_ExplicitInt : int
{
Bit31 = -0b_10000000_00000000_00000000_00000000,
Bit30 = 0b_01000000_00000000_00000000_00000000,
Bit29 = 0b_00100000_00000000_00000000_00000000,
Bit28 = 0b_00010000_00000000_00000000_00000000,
Bit27 = 0b_00001000_00000000_00000000_00000000,
Bit26 = 0b_00000100_00000000_00000000_00000000,
Bit25 = 0b_00000010_00000000_00000000_00000000,
Bit24 = 0b_00000001_00000000_00000000_00000000,
Bit23 = -0b_00000000_10000000_00000000_00000000,
Bit22 = 0b_00000000_01000000_00000000_00000000,
Bit21 = 0b_00000000_00100000_00000000_00000000,
Bit20 = 0b_00000000_00010000_00000000_00000000,
Bit19 = 0b_00000000_00001000_00000000_00000000,
Bit18 = 0b_00000000_00000100_00000000_00000000,
Bit17 = 0b_00000000_00000010_00000000_00000000,
Bit16 = 0b_00000000_00000001_00000000_00000000,
Bit15 = -0b_00000000_00000000_10000000_00000000,
Bit14 = 0b_00000000_00000000_01000000_00000000,
Bit13 = 0b_00000000_00000000_00100000_00000000,
Bit12 = 0b_00000000_00000000_00010000_00000000,
Bit11 = 0b_00000000_00000000_00001000_00000000,
Bit10 = 0b_00000000_00000000_00000100_00000000,
Bit09 = 0b_00000000_00000000_00000010_00000000,
Bit08 = 0b_00000000_00000000_00000001_00000000,
Bit07 = -0b_00000000_00000000_00000000_10000000,
Bit06 = 0b_00000000_00000000_00000000_01000000,
Bit05 = 0b_00000000_00000000_00000000_00100000,
Bit04 = 0b_00000000_00000000_00000000_00010000,
Bit03 = 0b_00000000_00000000_00000000_00001000,
Bit02 = 0b_00000000_00000000_00000000_00000100,
Bit01 = 0b_00000000_00000000_00000000_00000010,
Bit00 = 0b_00000000_00000000_00000000_00000001,
All_0 = 0,
All_1 = -1
}

View File

@@ -1,45 +0,0 @@
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
/// <summary>
/// Flags enum with explicitly-defined backing type of uint and only a <see cref="FlagsAttribute"/> on the enum declaration No other attributes on the enum or its members..
/// </summary>
[Flags]
[SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Naming is intentional.")]
[SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Justification = "Order is intentional.")]
public enum FlagsEnum_ExplicitUInt : uint
{
Bit31 = 0b_10000000_00000000_00000000_00000000u,
Bit30 = 0b_01000000_00000000_00000000_00000000u,
Bit29 = 0b_00100000_00000000_00000000_00000000u,
Bit28 = 0b_00010000_00000000_00000000_00000000u,
Bit27 = 0b_00001000_00000000_00000000_00000000u,
Bit26 = 0b_00000100_00000000_00000000_00000000u,
Bit25 = 0b_00000010_00000000_00000000_00000000u,
Bit24 = 0b_00000001_00000000_00000000_00000000u,
Bit23 = 0b_00000000_10000000_00000000_00000000u,
Bit22 = 0b_00000000_01000000_00000000_00000000u,
Bit21 = 0b_00000000_00100000_00000000_00000000u,
Bit20 = 0b_00000000_00010000_00000000_00000000u,
Bit19 = 0b_00000000_00001000_00000000_00000000u,
Bit18 = 0b_00000000_00000100_00000000_00000000u,
Bit17 = 0b_00000000_00000010_00000000_00000000u,
Bit16 = 0b_00000000_00000001_00000000_00000000u,
Bit15 = 0b_00000000_00000000_10000000_00000000u,
Bit14 = 0b_00000000_00000000_01000000_00000000u,
Bit13 = 0b_00000000_00000000_00100000_00000000u,
Bit12 = 0b_00000000_00000000_00010000_00000000u,
Bit11 = 0b_00000000_00000000_00001000_00000000u,
Bit10 = 0b_00000000_00000000_00000100_00000000u,
Bit09 = 0b_00000000_00000000_00000010_00000000u,
Bit08 = 0b_00000000_00000000_00000001_00000000u,
Bit07 = 0b_00000000_00000000_00000000_10000000u,
Bit06 = 0b_00000000_00000000_00000000_01000000u,
Bit05 = 0b_00000000_00000000_00000000_00100000u,
Bit04 = 0b_00000000_00000000_00000000_00010000u,
Bit03 = 0b_00000000_00000000_00000000_00001000u,
Bit02 = 0b_00000000_00000000_00000000_00000100u,
Bit01 = 0b_00000000_00000000_00000000_00000010u,
Bit00 = 0b_00000000_00000000_00000000_00000001u,
All_0 = 0b_00000000_00000000_00000000_00000000u,
All_1 = 0b_11111111_11111111_11111111_11111111u
}

View File

@@ -1,306 +0,0 @@
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Reflection;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using Terminal.Gui.Analyzers.Internal.Attributes;
using Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
// ReSharper disable InconsistentNaming
namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions;
[TestFixture]
[Category ("Source Generators")]
[TestOf (typeof (EnumExtensionMethodsIncrementalGenerator))]
[Parallelizable (ParallelScope.Children)]
[SuppressMessage ("ReSharper", "ExceptionNotDocumented")]
public class EnumExtensionMethodsIncrementalGeneratorTests
{
private static bool _isInitialized;
/// <summary>All enum types declared in the test assembly.</summary>
private static readonly ObservableCollection<Type> _allEnumTypes = [];
/// <summary>
/// All enum types without a <see cref="GenerateEnumExtensionMethodsAttribute"/>, <see cref="_allEnumTypes"/>
/// </summary>
private static readonly HashSet<Type> _boringEnumTypes = [];
/// <summary>All extension classes generated for enums with our attribute.</summary>
private static readonly ObservableCollection<Type> _enumExtensionClasses = [];
private static readonly ConcurrentDictionary<Type, EnumData> _extendedEnumTypeMappings = [];
private static IEnumerable<Type> ExtendedEnumTypes => _extendedEnumTypeMappings.Keys;
private static readonly ReaderWriterLockSlim _initializationLock = new ();
private static IEnumerable<AssemblyExtendedEnumTypeAttribute> GetAssemblyExtendedEnumTypeAttributes () =>
Assembly.GetExecutingAssembly ()
.GetCustomAttributes<AssemblyExtendedEnumTypeAttribute> ();
private static IEnumerable<TestCaseData> Get_AssemblyExtendedEnumTypeAttribute_EnumHasGeneratorAttribute_Cases ()
{
return GetAssemblyExtendedEnumTypeAttributes ()
.Select (
static attr => new TestCaseData (attr)
{
TestName = $"{nameof (AssemblyExtendedEnumTypeAttribute_EnumHasGeneratorAttribute)}({attr.EnumType.Name},{attr.ExtensionClass.Name})",
HasExpectedResult = true,
ExpectedResult = true
});
}
[Test]
[Category ("Attributes")]
[TestCaseSource (nameof (Get_AssemblyExtendedEnumTypeAttribute_EnumHasGeneratorAttribute_Cases))]
public bool AssemblyExtendedEnumTypeAttribute_EnumHasGeneratorAttribute (AssemblyExtendedEnumTypeAttribute attr)
{
Assume.That (attr, Is.Not.Null);
Assume.That (attr.EnumType, Is.Not.Null);
Assume.That (attr.EnumType.IsEnum);
return attr.EnumType.IsDefined (typeof (GenerateEnumExtensionMethodsAttribute));
}
[Test]
[Category("Attributes")]
public void AssemblyExtendedEnumTypeAttribute_ExtensionClassHasExpectedReverseMappingAttribute ([ValueSource(nameof(GetAssemblyExtendedEnumTypeAttributes))]AssemblyExtendedEnumTypeAttribute attr)
{
Assume.That (attr, Is.Not.Null);
Assume.That (attr.ExtensionClass, Is.Not.Null);
Assume.That (attr.ExtensionClass.IsClass);
Assume.That (attr.ExtensionClass.IsSealed);
Assert.That (attr.ExtensionClass.IsDefined (typeof (ExtensionsForEnumTypeAttribute<>)));
}
[Test]
[Category("Attributes")]
public void ExtendedEnum_AssemblyHasMatchingAttribute ([ValueSource(nameof(GetExtendedEnum_EnumData))]EnumData enumData)
{
Assume.That (enumData, Is.Not.Null);
Assume.That (enumData.EnumType, Is.Not.Null);
Assume.That (enumData.EnumType.IsEnum);
Assert.That (enumData.EnumType, Has.Attribute<GenerateEnumExtensionMethodsAttribute> ());
}
[Test]
public void BoringEnum_DoesNotHaveExtensions ([ValueSource (nameof (_boringEnumTypes))] Type enumType)
{
Assume.That (enumType.IsEnum);
Assert.That (enumType, Has.No.Attribute<GenerateEnumExtensionMethodsAttribute> ());
}
[Test]
public void ExtendedEnum_FastIsDefinedFalse_DoesNotHaveFastIsDefined ([ValueSource (nameof (GetExtendedEnumTypes_FastIsDefinedFalse))] EnumData enumData)
{
Assume.That (enumData.EnumType.IsEnum);
Assume.That (enumData.EnumType, Has.Attribute<GenerateEnumExtensionMethodsAttribute> ());
Assume.That (enumData.GeneratorAttribute, Is.Not.Null);
Assume.That (enumData.GeneratorAttribute, Is.EqualTo (enumData.EnumType.GetCustomAttribute<GenerateEnumExtensionMethodsAttribute> ()));
Assume.That (enumData.GeneratorAttribute, Has.Property ("FastIsDefined").False);
Assume.That (enumData.ExtensionClass, Is.Not.Null);
Assert.That (enumData.ExtensionClass!.GetMethod ("FastIsDefined"), Is.Null);
}
[Test]
public void ExtendedEnum_StaticExtensionClassExists ([ValueSource (nameof (ExtendedEnumTypes))] Type enumType)
{
Assume.That (enumType.IsEnum);
Assume.That (enumType, Has.Attribute<GenerateEnumExtensionMethodsAttribute> ());
Assume.That (enumType, Has.Attribute<GenerateEnumExtensionMethodsAttribute> ());
}
[Test]
public void ExtendedEnum_FastIsDefinedTrue_HasFastIsDefined ([ValueSource (nameof (GetExtendedEnumTypes_FastIsDefinedTrue))] EnumData enumData)
{
Assume.That (enumData.EnumType, Is.Not.Null);
Assume.That (enumData.EnumType.IsEnum);
Assume.That (enumData.EnumType, Has.Attribute<GenerateEnumExtensionMethodsAttribute> ());
Assume.That (enumData.ExtensionClass, Is.Not.Null);
TypeWrapper extensionClassTypeInfo = new(enumData.ExtensionClass!);
Assume.That (extensionClassTypeInfo.IsStaticClass);
Assume.That (enumData.GeneratorAttribute, Is.Not.Null);
Assume.That (enumData.GeneratorAttribute, Is.EqualTo (enumData.EnumType.GetCustomAttribute<GenerateEnumExtensionMethodsAttribute> ()));
Assume.That (enumData.GeneratorAttribute, Has.Property ("FastIsDefined").True);
MethodInfo? fastIsDefinedMethod = enumData.ExtensionClass!.GetMethod ("FastIsDefined");
Assert.That (fastIsDefinedMethod, Is.Not.Null);
Assert.That (fastIsDefinedMethod, Has.Attribute<ExtensionAttribute> ());
extensionClassTypeInfo.GetMethodsWithAttribute<ExtensionAttribute> (false);
}
private static IEnumerable<EnumData> GetExtendedEnum_EnumData ()
{
_initializationLock.EnterUpgradeableReadLock ();
try
{
if (!_isInitialized)
{
Initialize ();
}
return _extendedEnumTypeMappings.Values;
}
finally
{
_initializationLock.ExitUpgradeableReadLock ();
}
}
private static IEnumerable<EnumData> GetExtendedEnumTypes_FastIsDefinedFalse ()
{
_initializationLock.EnterUpgradeableReadLock ();
try
{
if (!_isInitialized)
{
Initialize ();
}
return _extendedEnumTypeMappings.Values.Where (static t => t.GeneratorAttribute?.FastIsDefined is false);
}
finally
{
_initializationLock.ExitUpgradeableReadLock ();
}
}
private static IEnumerable<EnumData> GetExtendedEnumTypes_FastIsDefinedTrue ()
{
_initializationLock.EnterUpgradeableReadLock ();
try
{
if (!_isInitialized)
{
Initialize ();
}
return _extendedEnumTypeMappings.Values.Where (static t => t.GeneratorAttribute?.FastIsDefined is true);
}
finally
{
_initializationLock.ExitUpgradeableReadLock ();
}
}
private static void Initialize ()
{
if (!_initializationLock.IsUpgradeableReadLockHeld || !_initializationLock.TryEnterWriteLock (5000))
{
return;
}
try
{
if (_isInitialized)
{
return;
}
_allEnumTypes.CollectionChanged += AllEnumTypes_CollectionChanged;
_enumExtensionClasses.CollectionChanged += EnumExtensionClasses_OnCollectionChanged;
Type [] allAssemblyTypes = Assembly
.GetExecutingAssembly ()
.GetTypes ();
foreach (Type type in allAssemblyTypes.Where (IsDefinedEnum))
{
_allEnumTypes.Add (type);
}
foreach (Type type in allAssemblyTypes.Where (HasExtensionForEnumTypeAttribute))
{
_enumExtensionClasses.Add (type);
}
_isInitialized = true;
}
finally
{
_initializationLock.ExitWriteLock ();
}
return;
static bool IsDefinedEnum (Type t) { return t is { IsEnum: true, IsGenericType: false, IsConstructedGenericType: false, IsTypeDefinition: true }; }
static void AllEnumTypes_CollectionChanged (object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action is not NotifyCollectionChangedAction.Add and not NotifyCollectionChangedAction.Replace || e.NewItems is null)
{
return;
}
foreach (Type enumType in e.NewItems.OfType<Type> ())
{
if (enumType.GetCustomAttribute<GenerateEnumExtensionMethodsAttribute> () is not { } generatorAttribute)
{
_boringEnumTypes.Add (enumType);
continue;
}
_extendedEnumTypeMappings.AddOrUpdate (
enumType,
CreateNewEnumData,
UpdateGeneratorAttributeProperty,
generatorAttribute);
}
}
static EnumData CreateNewEnumData (Type tEnum, GenerateEnumExtensionMethodsAttribute attr) { return new (tEnum, attr); }
static EnumData UpdateGeneratorAttributeProperty (Type tEnum, EnumData data, GenerateEnumExtensionMethodsAttribute attr)
{
data.GeneratorAttribute ??= attr;
return data;
}
static void EnumExtensionClasses_OnCollectionChanged (object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Add)
{
return;
}
foreach (Type extensionClassType in e.NewItems!.OfType<Type> ())
{
if (extensionClassType.GetCustomAttribute (typeof (ExtensionsForEnumTypeAttribute<>), false) is not IExtensionsForEnumTypeAttributes
{
EnumType.IsEnum: true
} extensionForAttribute)
{
continue;
}
_extendedEnumTypeMappings [extensionForAttribute.EnumType].ExtensionClass ??= extensionClassType;
}
}
}
private static bool HasExtensionForEnumTypeAttribute (Type t) => t.IsClass && t.IsDefined (typeof (ExtensionsForEnumTypeAttribute<>));
public sealed record EnumData (
Type EnumType,
GenerateEnumExtensionMethodsAttribute? GeneratorAttribute = null,
Type? ExtensionClass = null,
IExtensionsForEnumTypeAttributes? ExtensionForEnumTypeAttribute = null)
{
public Type? ExtensionClass { get; set; } = ExtensionClass;
public IExtensionsForEnumTypeAttributes? ExtensionForEnumTypeAttribute { get; set; } = ExtensionForEnumTypeAttribute;
public GenerateEnumExtensionMethodsAttribute? GeneratorAttribute { get; set; } = GeneratorAttribute;
}
}

View File

@@ -1,3 +0,0 @@
[assembly: SuppressMessage ("Naming", "CA1707:Identifiers should not contain underscores", Scope = "module", Justification = "Naming is intentional.")]
[assembly: SuppressMessage ("Roslynator", "RCS1154:Sort enum members", Scope = "module", Justification = "Order is intentional.")]
[assembly: SuppressMessage ("Naming", "CA1711:Identifiers should not have incorrect suffix", Scope = "module", Justification = "Naming is intentional.")]

View File

@@ -1,111 +0,0 @@
using System.CodeDom.Compiler;
using System.Text;
namespace Terminal.Gui.Analyzers.Internal.Tests;
[TestFixture]
[Category ("Extension Methods")]
[TestOf (typeof (IndentedTextWriterExtensions))]
[Parallelizable (ParallelScope.Children)]
public class IndentedTextWriterExtensionsTests
{
[Test]
public void Pop_Decrements ()
{
StringBuilder sb = new (0);
using var sw = new StringWriter (sb);
using var writer = new IndentedTextWriter (sw);
writer.Indent = 5;
Assume.That (writer.Indent, Is.EqualTo (5));
writer.Pop ();
Assert.That (writer.Indent, Is.EqualTo (4));
}
[Test]
public void Pop_WithClosing_WritesAndPops ([Values ("}", ")", "]")] string scopeClosing)
{
StringBuilder sb = new (256);
using var sw = new StringWriter (sb);
using var writer = new IndentedTextWriter (sw, " ");
writer.Indent = 5;
writer.Flush ();
Assume.That (writer.Indent, Is.EqualTo (5));
Assume.That (sb.Length, Is.Zero);
// Need to write something first, or IndentedTextWriter won't emit the indentation for the first call.
// So we'll write an empty line.
writer.WriteLine ();
for (ushort indentCount = 5; indentCount > 0;)
{
writer.Pop (scopeClosing);
Assert.That (writer.Indent, Is.EqualTo (--indentCount));
}
writer.Flush ();
var result = sb.ToString ();
Assert.That (
result,
Is.EqualTo (
$"""
{scopeClosing}
{scopeClosing}
{scopeClosing}
{scopeClosing}
{scopeClosing}
"""));
}
[Test]
public void Push_Increments ()
{
StringBuilder sb = new (32);
using var sw = new StringWriter (sb);
using var writer = new IndentedTextWriter (sw, " ");
for (int indentCount = 0; indentCount < 5; indentCount++)
{
writer.Push ();
Assert.That (writer.Indent, Is.EqualTo (indentCount + 1));
}
}
[Test]
public void Push_WithOpening_WritesAndPushes ([Values ('{', '(', '[')] char scopeOpening)
{
StringBuilder sb = new (256);
using var sw = new StringWriter (sb);
using var writer = new IndentedTextWriter (sw, " ");
for (ushort indentCount = 0; indentCount < 5;)
{
writer.Push ("Opening UninterestingEnum", scopeOpening);
Assert.That (writer.Indent, Is.EqualTo (++indentCount));
}
writer.Flush ();
var result = sb.ToString ();
Assert.That (
result,
Is.EqualTo (
$"""
Opening UninterestingEnum
{scopeOpening}
Opening UninterestingEnum
{scopeOpening}
Opening UninterestingEnum
{scopeOpening}
Opening UninterestingEnum
{scopeOpening}
Opening UninterestingEnum
{scopeOpening}
"""));
}
}

View File

@@ -1,52 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>12</LangVersion>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebugType>portable</DebugType>
<DefineConstants>$(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS</DefineConstants>
<ImplicitUsings>enable</ImplicitUsings>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Terminal.Gui.Analyzers.Internal\Terminal.Gui.Analyzers.Internal.csproj">
<PrivateAssets>all</PrivateAssets>
<OutputItemType>Analyzer</OutputItemType>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework" />
<Using Include="Terminal.Gui" />
<Using Include="Terminal.Gui.Analyzers" />
<Using Include="Terminal.Gui.Analyzers.Internal" />
<Using Include="System.Diagnostics.CodeAnalysis" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="JetBrains.Annotations" Version="2024.2.0" />
</ItemGroup>
</Project>

View File

@@ -1,3 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generators_005Cenumextensions_005Cenumdefinitions_005Cwithgenerator/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generators_005Cenumextensions_005Cenumdefinitions_005Cwithoutgenerator/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -1,20 +0,0 @@
using Microsoft.CodeAnalysis;
namespace Terminal.Gui.Analyzers.Internal;
internal static class AccessibilityExtensions
{
internal static string ToCSharpString (this Accessibility value)
{
return value switch
{
Accessibility.Public => "public",
Accessibility.Internal => "internal",
Accessibility.Private => "private",
Accessibility.Protected => "protected",
Accessibility.ProtectedAndInternal => "private protected",
Accessibility.ProtectedOrInternal => "protected internal",
_ => string.Empty
};
}
}

View File

@@ -1,8 +0,0 @@
## Release 1.0
### New Rules
Rule ID | Category | Severity | Notes
--------|----------|----------|--------------------
TG0001 | Usage | Error | TG0001_GlobalNamespaceNotSupported
TG0002 | Usage | Error | TG0002_UnderlyingTypeNotSupported

View File

@@ -1,4 +0,0 @@
### New Rules
Rule ID | Category | Severity | Notes
--------|----------|----------|--------------------

View File

@@ -1,117 +0,0 @@
#define JETBRAINS_ANNOTATIONS
using System.Collections.Immutable;
using System.Linq;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Terminal.Gui.Analyzers.Internal.Attributes;
using Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
namespace Terminal.Gui.Analyzers.Internal.Analyzers;
/// <summary>
/// Design-time analyzer that checks for proper use of <see cref="GenerateEnumExtensionMethodsAttribute"/>.
/// </summary>
[DiagnosticAnalyzer (LanguageNames.CSharp)]
[UsedImplicitly]
internal sealed class GenerateEnumExtensionMethodsAttributeAnalyzer : DiagnosticAnalyzer
{
// ReSharper disable once InconsistentNaming
private static readonly DiagnosticDescriptor TG0001_GlobalNamespaceNotSupported = new (
// ReSharper restore InconsistentNaming
"TG0001",
$"{nameof (GenerateEnumExtensionMethodsAttribute)} not supported on global enums",
"{0} is in the global namespace, which is not supported by the source generator ({1}) used by {2}. Move the enum to a namespace or remove the attribute.",
"Usage",
DiagnosticSeverity.Error,
true,
null,
null,
WellKnownDiagnosticTags.NotConfigurable,
WellKnownDiagnosticTags.Compiler);
// ReSharper disable once InconsistentNaming
private static readonly DiagnosticDescriptor TG0002_UnderlyingTypeNotSupported = new (
"TG0002",
$"{nameof (GenerateEnumExtensionMethodsAttribute)} not supported for this enum type",
"{0} has an underlying type of {1}, which is not supported by the source generator ({2}) used by {3}. Only enums backed by int or uint are supported.",
"Usage",
DiagnosticSeverity.Error,
true,
null,
null,
WellKnownDiagnosticTags.NotConfigurable,
WellKnownDiagnosticTags.Compiler);
/// <inheritdoc/>
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
[
TG0001_GlobalNamespaceNotSupported,
TG0002_UnderlyingTypeNotSupported
];
/// <inheritdoc/>
public override void Initialize (AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis (GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution ();
context.RegisterSyntaxNodeAction (CheckAttributeLocations, SyntaxKind.EnumDeclaration);
return;
static void CheckAttributeLocations (SyntaxNodeAnalysisContext analysisContext)
{
ISymbol? symbol = analysisContext.SemanticModel.GetDeclaredSymbol (analysisContext.Node) as INamedTypeSymbol;
if (symbol is not INamedTypeSymbol { EnumUnderlyingType: { } } enumSymbol)
{
// Somehow not even an enum declaration.
// Skip it.
return;
}
// Check attributes for those we care about and react accordingly.
foreach (AttributeData attributeData in enumSymbol.GetAttributes ())
{
if (attributeData.AttributeClass?.Name != nameof (GenerateEnumExtensionMethodsAttribute))
{
// Just skip - not an interesting attribute.
continue;
}
// Check enum underlying type for supported types (int and uint, currently)
// Report TG0002 if unsupported underlying type.
if (enumSymbol.EnumUnderlyingType is not { SpecialType: SpecialType.System_Int32 or SpecialType.System_UInt32 })
{
analysisContext.ReportDiagnostic (
Diagnostic.Create (
TG0002_UnderlyingTypeNotSupported,
enumSymbol.Locations.FirstOrDefault (),
enumSymbol.Name,
enumSymbol.EnumUnderlyingType.Name,
nameof (EnumExtensionMethodsIncrementalGenerator),
nameof (GenerateEnumExtensionMethodsAttribute)
)
);
}
// Check enum namespace (only non-global supported, currently)
// Report TG0001 if in the global namespace.
if (enumSymbol.ContainingSymbol is not INamespaceSymbol { IsGlobalNamespace: false })
{
analysisContext.ReportDiagnostic (
Diagnostic.Create (
TG0001_GlobalNamespaceNotSupported,
enumSymbol.Locations.FirstOrDefault (),
enumSymbol.Name,
nameof (EnumExtensionMethodsIncrementalGenerator),
nameof (GenerateEnumExtensionMethodsAttribute)
)
);
}
}
}
}
}

View File

@@ -1,3 +0,0 @@
N:System.Runtime.CompilerServices
N:System.Diagnostics.CodeAnalysis
N:System.Numerics

View File

@@ -1,27 +0,0 @@
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable once RedundantNullableDirective
#nullable enable
namespace Terminal.Gui.Analyzers.Internal.Attributes;
/// <summary>Assembly attribute declaring a known pairing of an <see langword="enum" /> type to an extension class.</summary>
/// <remarks>This attribute should only be written by internal source generators for Terminal.Gui. No other usage of any kind is supported.</remarks>
[System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class AssemblyExtendedEnumTypeAttribute : System.Attribute
{
/// <summary>Creates a new instance of <see cref="AssemblyExtendedEnumTypeAttribute" /> from the provided parameters.</summary>
/// <param name="enumType">The <see cref="System.Type" /> of an <see langword="enum" /> decorated with a <see cref="GenerateEnumExtensionMethodsAttribute" />.</param>
/// <param name="extensionClass">The <see cref="System.Type" /> of the <see langword="class" /> decorated with an <see cref="ExtensionsForEnumTypeAttribute{TEnum}" /> referring to the same type as <paramref name="enumType" />.</param>
public AssemblyExtendedEnumTypeAttribute (System.Type enumType, System.Type extensionClass)
{
EnumType = enumType;
ExtensionClass = extensionClass;
}
///<summary>An <see langword="enum" /> type that has been extended by Terminal.Gui source generators.</summary>
public System.Type EnumType { get; init; }
///<summary>A class containing extension methods for <see cref="EnumType"/>.</summary>
public System.Type ExtensionClass { get; init; }
/// <inheritdoc />
public override string ToString () => $"{EnumType.Name},{ExtensionClass.Name}";
}

View File

@@ -1,37 +0,0 @@
// ReSharper disable RedundantNameQualifier
// ReSharper disable RedundantNullableDirective
// ReSharper disable UnusedType.Global
#pragma warning disable IDE0001, IDE0240
#nullable enable
namespace Terminal.Gui.Analyzers.Internal.Attributes;
/// <summary>
/// Attribute written by the source generator for <see langword="enum" /> extension classes, for easier analysis and reflection.
/// </summary>
/// <remarks>
/// Properties are just convenient shortcuts to properties of <typeparamref name="TEnum"/>.
/// </remarks>
[System.AttributeUsage (System.AttributeTargets.Class | System.AttributeTargets.Interface)]
internal sealed class ExtensionsForEnumTypeAttribute<TEnum>: System.Attribute, IExtensionsForEnumTypeAttributes where TEnum : struct, System.Enum
{
/// <summary>
/// The namespace-qualified name of <typeparamref name="TEnum"/>.
/// </summary>
public string EnumFullName => EnumType.FullName!;
/// <summary>
/// The unqualified name of <typeparamref name="TEnum"/>.
/// </summary>
public string EnumName => EnumType.Name;
/// <summary>
/// The namespace containing <typeparamref name="TEnum"/>.
/// </summary>
public string EnumNamespace => EnumType.Namespace!;
/// <summary>
/// The <see cref="System.Type"/> given by <see langword="typeof"/>(<typeparamref name="TEnum"/>).
/// </summary>
public System.Type EnumType => typeof (TEnum);
}

View File

@@ -1,110 +0,0 @@
// ReSharper disable RedundantNullableDirective
// ReSharper disable RedundantUsingDirective
// ReSharper disable ClassNeverInstantiated.Global
#nullable enable
using System;
using Attribute = System.Attribute;
using AttributeUsageAttribute = System.AttributeUsageAttribute;
using AttributeTargets = System.AttributeTargets;
namespace Terminal.Gui.Analyzers.Internal.Attributes;
/// <summary>
/// Used to enable source generation of a common set of extension methods for enum types.
/// </summary>
[AttributeUsage (AttributeTargets.Enum)]
internal sealed class GenerateEnumExtensionMethodsAttribute : Attribute
{
/// <summary>
/// The name of the generated static class.
/// </summary>
/// <remarks>
/// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".<br/>
/// No other validation is performed, so illegal values will simply result in compiler errors.
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public string? ClassName { get; set; }
/// <summary>
/// The namespace in which to place the generated static class containing the extension methods.
/// </summary>
/// <remarks>
/// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.<br/>
/// No other validation is performed, so illegal values will simply result in compiler errors.
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public string? ClassNamespace { get; set; }
/// <summary>
/// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
/// <see cref="Enum.HasFlag"/> method.
/// </summary>
/// <remarks>
/// <para>
/// Default: false
/// </para>
/// <para>
/// If the enum is not decorated with <see cref="FlagsAttribute"/>, this option has no effect.
/// </para>
/// <para>
/// If multiple members have the same value, the first member with that value will be used and subsequent members
/// with the same value will be skipped.
/// </para>
/// <para>
/// Overloads taking the enum type itself as well as the underlying type of the enum will be generated, enabling
/// avoidance of implicit or explicit cast overhead.
/// </para>
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public bool FastHasFlags { get; set; }
/// <summary>
/// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
/// <see cref="Enum.IsDefined"/> method,
/// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
/// </summary>
/// <remarks>
/// <para>
/// Default: true
/// </para>
/// <para>
/// If multiple members have the same value, the first member with that value will be used and subsequent members
/// with the same value will be skipped.
/// </para>
/// <para>
/// As with <see cref="Enum.IsDefined"/> the source generator only considers explicitly-named members.<br/>
/// Generation of values which represent valid bitwise combinations of members of enums decorated with
/// <see cref="FlagsAttribute"/> is not affected by this property.
/// </para>
/// </remarks>
public bool FastIsDefined { get; init; } = true;
/// <summary>
/// Gets a <see langword="bool"/> value indicating if this <see cref="GenerateEnumExtensionMethodsAttribute"/> instance
/// contains default values only. See <see href="#remarks">remarks</see> of this method or documentation on properties of this type for details.
/// </summary>
/// <returns>
/// A <see langword="bool"/> value indicating if all property values are default for this
/// <see cref="GenerateEnumExtensionMethodsAttribute"/> instance.
/// </returns>
/// <remarks>
/// Default values that will result in a <see langword="true"/> return value are:<br/>
/// <see cref="FastIsDefined"/> &amp;&amp; !<see cref="FastHasFlags"/> &amp;&amp; <see cref="ClassName"/>
/// <see langword="is"/> <see langword="null"/> &amp;&amp; <see cref="ClassNamespace"/> <see langword="is"/>
/// <see langword="null"/>
/// </remarks>
public override bool IsDefaultAttribute ()
{
return FastIsDefined
&& !FastHasFlags
&& ClassName is null
&& ClassNamespace is null;
}
}

View File

@@ -1,14 +0,0 @@
// ReSharper disable All
using System;
namespace Terminal.Gui.Analyzers.Internal.Attributes;
/// <summary>
/// Interface to simplify general enumeration of constructed generic types for
/// <see cref="ExtensionsForEnumTypeAttribute{TEnum}"/>
/// </summary>
internal interface IExtensionsForEnumTypeAttributes
{
Type EnumType { get; }
}

View File

@@ -1,11 +0,0 @@
// ReSharper disable once CheckNamespace
namespace System.Numerics;
/// <summary>
/// Included for compatibility with .net7+, but has no members.
/// Thus it cannot be explicitly used in generator code.
/// Use it for static analysis only.
/// </summary>
/// <typeparam name="T">The left operand type.</typeparam>
/// <typeparam name="T1">The right operand type.</typeparam>
/// <typeparam name="T2">The return type.</typeparam>
internal interface IEqualityOperators<T, T1, T2>;

View File

@@ -1,6 +0,0 @@
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field, Inherited = false)]
public sealed class IntrinsicAttribute : Attribute
{
}

View File

@@ -1,43 +0,0 @@
// ReSharper disable once CheckNamespace
namespace Terminal.Gui.Analyzers.Internal.Compatibility;
/// <summary>
/// Extension methods for <see langword="int"/> and <see langword="uint"/> types.
/// </summary>
/// <remarks>
/// This is mostly just for backward compatibility with netstandard2.0.
/// </remarks>
public static class NumericExtensions
{
/// <summary>
/// Gets the population count (number of bits set to 1) of this 32-bit value.
/// </summary>
/// <param name="value">The value to get the population count of.</param>
/// <remarks>
/// The algorithm is the well-known SWAR (SIMD Within A Register) method for population count.<br/>
/// Included for hardware- and runtime- agnostic support for the equivalent of the x86 popcnt instruction, since
/// System.Numerics.Intrinsics isn't available in netstandard2.0.<br/>
/// It performs the operation simultaneously on 4 bytes at a time, rather than the naive method of testing all 32 bits
/// individually.<br/>
/// Most compilers can recognize this and turn it into a single platform-specific instruction, when available.
/// </remarks>
/// <returns>
/// An unsigned 32-bit integer value containing the population count of <paramref name="value"/>.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint GetPopCount (this uint value)
{
unchecked
{
value -= (value >> 1) & 0x55555555;
value = (value & 0x33333333) + ((value >> 2) & 0x33333333);
value = (value + (value >> 4)) & 0x0F0F0F0F;
return (value * 0x01010101) >> 24;
}
}
/// <inheritdoc cref="GetPopCount(uint)"/>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint GetPopCount (this int value) { return GetPopCount (Unsafe.As<int, uint> (ref value)); }
}

View File

@@ -1,204 +0,0 @@
// ReSharper disable MemberCanBePrivate.Global
using System;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui.Analyzers.Internal.Constants;
/// <summary>String constants for frequently-used boilerplate.</summary>
/// <remarks>These are for performance, instead of using Roslyn to build it all during execution of analyzers.</remarks>
internal static class Strings
{
internal const string AnalyzersAttributesNamespace = $"{InternalAnalyzersNamespace}.Attributes";
internal const string AssemblyExtendedEnumTypeAttributeFullName = $"{AnalyzersAttributesNamespace}.{nameof (AssemblyExtendedEnumTypeAttribute)}";
internal const string DefaultTypeNameSuffix = "Extensions";
internal const string FallbackClassNamespace = $"{TerminalGuiRootNamespace}";
internal const string InternalAnalyzersNamespace = $"{AnalyzersRootNamespace}.Internal";
internal const string TerminalGuiRootNamespace = "Terminal.Gui";
private const string AnalyzersRootNamespace = $"{TerminalGuiRootNamespace}.Analyzers";
private const string NetStandard20CompatibilityNamespace = $"{InternalAnalyzersNamespace}.Compatibility";
/// <summary>
/// Names of dotnet namespaces and types. Included as compile-time constants to avoid unnecessary work for the Roslyn
/// source generators.
/// </summary>
/// <remarks>Implemented as nested static types because XmlDoc doesn't work on namespaces.</remarks>
internal static class DotnetNames
{
/// <summary>Fully-qualified attribute type names. Specific applications (uses) are in <see cref="Applications"/>.</summary>
internal static class Attributes
{
/// <inheritdoc cref="CompilerGeneratedAttribute"/>
internal const string CompilerGenerated = $"{Namespaces.System_Runtime_CompilerServices}.{nameof (CompilerGeneratedAttribute)}";
/// <inheritdoc cref="DebuggerNonUserCodeAttribute"/>
internal const string DebuggerNonUserCode = $"{Namespaces.System_Diagnostics}.{nameof (DebuggerNonUserCodeAttribute)}";
/// <inheritdoc cref="ExcludeFromCodeCoverageAttribute"/>
internal const string ExcludeFromCodeCoverage = $"{Namespaces.System_Diagnostics_CodeAnalysis}.{nameof (ExcludeFromCodeCoverageAttribute)}";
internal const string Flags = $"{Namespaces.SystemNs}.{nameof (FlagsAttribute)}";
internal const string GeneratedCode = $"{Namespaces.System_CodeDom_Compiler}.{nameof (GeneratedCodeAttribute)}";
/// <inheritdoc cref="MethodImplOptions.AggressiveInlining"/>
/// <remarks>Use of this attribute should be carefully evaluated.</remarks>
internal const string MethodImpl = $"{Namespaces.System_Runtime_CompilerServices}.{nameof (MethodImplAttribute)}";
/// <summary>Attributes formatted for use in code, including square brackets.</summary>
internal static class Applications
{
// ReSharper disable MemberHidesStaticFromOuterClass
internal const string Flags = $"[{Attributes.Flags}]";
/// <inheritdoc cref="System.CodeDom.Compiler.GeneratedCodeAttribute"/>
internal const string GeneratedCode = $"""[{Attributes.GeneratedCode}("{InternalAnalyzersNamespace}","1.0")]""";
/// <inheritdoc cref="MethodImplOptions.AggressiveInlining"/>
/// <remarks>Use of this attribute should be carefully evaluated.</remarks>
internal const string AggressiveInlining = $"[{MethodImpl}({Types.MethodImplOptions}.{nameof (MethodImplOptions.AggressiveInlining)})]";
/// <inheritdoc cref="DebuggerNonUserCodeAttribute"/>
internal const string DebuggerNonUserCode = $"[{Attributes.DebuggerNonUserCode}]";
/// <inheritdoc cref="CompilerGeneratedAttribute"/>
internal const string CompilerGenerated = $"[{Attributes.CompilerGenerated}]";
/// <inheritdoc cref="ExcludeFromCodeCoverageAttribute"/>
internal const string ExcludeFromCodeCoverage = $"[{Attributes.ExcludeFromCodeCoverage}]";
// ReSharper restore MemberHidesStaticFromOuterClass
}
}
/// <summary>Names of dotnet namespaces.</summary>
internal static class Namespaces
{
internal const string SystemNs = nameof (System);
// ReSharper disable InconsistentNaming
internal const string System_CodeDom = $"{SystemNs}.{nameof (System.CodeDom)}";
internal const string System_CodeDom_Compiler = $"{System_CodeDom}.{nameof (System.CodeDom.Compiler)}";
internal const string System_ComponentModel = $"{SystemNs}.{nameof (System.ComponentModel)}";
internal const string System_Diagnostics = $"{SystemNs}.{nameof (System.Diagnostics)}";
internal const string System_Diagnostics_CodeAnalysis = $"{System_Diagnostics}.{nameof (System.Diagnostics.CodeAnalysis)}";
internal const string System_Numerics = $"{SystemNs}.{nameof (System.Numerics)}";
internal const string System_Runtime = $"{SystemNs}.{nameof (System.Runtime)}";
internal const string System_Runtime_CompilerServices = $"{System_Runtime}.{nameof (System.Runtime.CompilerServices)}";
// ReSharper restore InconsistentNaming
}
internal static class Types
{
internal const string Attribute = $"{Namespaces.SystemNs}.{nameof (System.Attribute)}";
internal const string AttributeTargets = $"{Namespaces.SystemNs}.{nameof (System.AttributeTargets)}";
internal const string AttributeUsageAttribute = $"{Namespaces.SystemNs}.{nameof (System.AttributeUsageAttribute)}";
internal const string MethodImplOptions =
$"{Namespaces.System_Runtime_CompilerServices}.{nameof (System.Runtime.CompilerServices.MethodImplOptions)}";
}
}
internal static class Templates
{
internal const string AutoGeneratedCommentBlock = $"""
//------------------------------------------------------------------------------
// <auto-generated>
// This file and the code it contains was generated by a source generator in
// the {InternalAnalyzersNamespace} library.
//
// Modifications to this file are not supported and will be lost when
// source generation is triggered, either implicitly or explicitly.
// </auto-generated>
//------------------------------------------------------------------------------
""";
/// <summary>
/// A set of explicit type aliases to work around Terminal.Gui having name collisions with types like
/// <see cref="System.Attribute"/>.
/// </summary>
internal const string DotnetExplicitTypeAliasUsingDirectives = $"""
using Attribute = {DotnetNames.Types.Attribute};
using AttributeUsageAttribute = {DotnetNames.Types.AttributeUsageAttribute};
using GeneratedCode = {DotnetNames.Attributes.GeneratedCode};
""";
/// <summary>Using directives for common namespaces in generated code.</summary>
internal const string DotnetNamespaceUsingDirectives = $"""
using {DotnetNames.Namespaces.SystemNs};
using {DotnetNames.Namespaces.System_CodeDom};
using {DotnetNames.Namespaces.System_CodeDom_Compiler};
using {DotnetNames.Namespaces.System_ComponentModel};
using {DotnetNames.Namespaces.System_Numerics};
using {DotnetNames.Namespaces.System_Runtime};
using {DotnetNames.Namespaces.System_Runtime_CompilerServices};
""";
/// <summary>
/// A set of empty namespaces that MAY be referenced in generated code, especially in using statements,
/// which are always included to avoid additional complexity due to conditional compilation.
/// </summary>
internal const string DummyNamespaceDeclarations = $$"""
// These are dummy declarations to avoid complexity with conditional compilation.
#pragma warning disable IDE0079 // Remove unnecessary suppression
#pragma warning disable RCS1259 // Remove empty syntax
namespace {{TerminalGuiRootNamespace}} { }
namespace {{AnalyzersRootNamespace}} { }
namespace {{InternalAnalyzersNamespace}} { }
namespace {{NetStandard20CompatibilityNamespace}} { }
namespace {{AnalyzersAttributesNamespace}} { }
#pragma warning restore RCS1259 // Remove empty syntax
#pragma warning restore IDE0079 // Remove unnecessary suppression
""";
internal const string StandardHeader = $"""
{AutoGeneratedCommentBlock}
// ReSharper disable RedundantUsingDirective
// ReSharper disable once RedundantNullableDirective
{NullableContextDirective}
{StandardUsingDirectivesText}
""";
/// <summary>
/// Standard set of using directives for generated extension method class files.
/// Not all are always needed, but all are included so we don't have to worry about it.
/// </summary>
internal const string StandardUsingDirectivesText = $"""
{DotnetNamespaceUsingDirectives}
{DotnetExplicitTypeAliasUsingDirectives}
using {TerminalGuiRootNamespace};
using {AnalyzersRootNamespace};
using {InternalAnalyzersNamespace};
using {AnalyzersAttributesNamespace};
using {NetStandard20CompatibilityNamespace};
""";
internal const string AttributesForGeneratedInterfaces = $"""
{DotnetNames.Attributes.Applications.GeneratedCode}
{DotnetNames.Attributes.Applications.CompilerGenerated}
""";
internal const string AttributesForGeneratedTypes = $"""
{DotnetNames.Attributes.Applications.GeneratedCode}
{DotnetNames.Attributes.Applications.CompilerGenerated}
{DotnetNames.Attributes.Applications.DebuggerNonUserCode}
{DotnetNames.Attributes.Applications.ExcludeFromCodeCoverage}
""";
/// <summary>
/// Preprocessor directive to enable nullability context for generated code.<br/>
/// This should always be emitted, as it applies only to generated code.<br/>
/// As such, generated code MUST be properly annotated.
/// </summary>
internal const string NullableContextDirective = "#nullable enable";
}
}

View File

@@ -1,235 +0,0 @@
using System;
using System.CodeDom.Compiler;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using Microsoft.CodeAnalysis.Text;
using Terminal.Gui.Analyzers.Internal.Constants;
namespace Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
/// <summary>
/// The class responsible for turning an <see cref="EnumExtensionMethodsGenerationInfo"/>
/// into actual C# code.
/// </summary>
/// <remarks>Try to use this type as infrequently as possible.</remarks>
/// <param name="metadata">
/// A reference to an <see cref="IGeneratedTypeMetadata{TSelf}"/> which will be used
/// to generate the extension class code. The object will not be validated,
/// so it is critical that it be correct and remain unchanged while in use
/// by an instance of this class. Behavior if those rules are not followed
/// is undefined.
/// </param>
[SuppressMessage ("CodeQuality", "IDE0079", Justification = "Suppressions here are intentional and the warnings they disable are just noise.")]
internal sealed class CodeWriter (in EnumExtensionMethodsGenerationInfo metadata) : IStandardCSharpCodeGenerator<EnumExtensionMethodsGenerationInfo>
{
// Using the null suppression operator here because this will always be
// initialized to non-null before a reference to it is returned.
private SourceText _sourceText = null!;
/// <inheritdoc/>
public EnumExtensionMethodsGenerationInfo Metadata
{
[MethodImpl (MethodImplOptions.AggressiveInlining)]
[return: NotNull]
get;
[param: DisallowNull]
set;
} = metadata;
/// <inheritdoc/>
public ref readonly SourceText GenerateSourceText (Encoding? encoding = null)
{
encoding ??= Encoding.UTF8;
_sourceText = SourceText.From (GetFullSourceText (), encoding);
return ref _sourceText;
}
/// <summary>
/// Gets the using directive for the namespace containing the enum,
/// if different from the extension class namespace, or an empty string, if they are the same.
/// </summary>
private string EnumNamespaceUsingDirective => Metadata.TargetTypeNamespace != Metadata.GeneratedTypeNamespace
// ReSharper disable once HeapView.ObjectAllocation
? $"using {Metadata.TargetTypeNamespace};"
: string.Empty;
private string EnumTypeKeyword => Metadata.EnumBackingTypeCode switch
{
TypeCode.Int32 => "int",
TypeCode.UInt32 => "uint",
_ => string.Empty
};
/// <summary>Gets the class declaration line.</summary>
private string ExtensionClassDeclarationLine => $"public static partial class {Metadata.GeneratedTypeName}";
// ReSharper disable once HeapView.ObjectAllocation
/// <summary>Gets the XmlDoc for the extension class declaration.</summary>
private string ExtensionClassDeclarationXmlDoc =>
$"/// <summary>Extension methods for the <see cref=\"{Metadata.TargetTypeFullName}\"/> <see langword=\"enum\" /> type.</summary>";
// ReSharper disable once HeapView.ObjectAllocation
/// <summary>Gets the extension class file-scoped namespace directive.</summary>
private string ExtensionClassNamespaceDirective => $"namespace {Metadata.GeneratedTypeNamespace};";
/// <summary>
/// An attribute to decorate the extension class with for easy mapping back to the target enum type, for reflection and
/// analysis.
/// </summary>
private string ExtensionsForTypeAttributeLine => $"[ExtensionsForEnumType<{Metadata.TargetTypeFullName}>]";
/// <summary>
/// Creates the code for the FastHasFlags method.
/// </summary>
/// <remarks>
/// Since the generator already only writes code for enums backed by <see langword="int"/> and <see langword="uint"/>,
/// this method is safe, as we'll always be using a DWORD.
/// </remarks>
/// <param name="w">An instance of an <see cref="IndentedTextWriter"/> to write to.</param>
private void GetFastHasFlagsMethods (IndentedTextWriter w)
{
// The version taking the same enum type as the check value.
w.WriteLine (
$"/// <summary>Determines if the specified flags are set in the current value of this <see cref=\"{Metadata.TargetTypeFullName}\" />.</summary>");
w.WriteLine ("/// <remarks>NO VALIDATION IS PERFORMED!</remarks>");
w.WriteLine (
$"/// <returns>True, if all flags present in <paramref name=\"checkFlags\" /> are also present in the current value of the <see cref=\"{Metadata.TargetTypeFullName}\" />.<br />Otherwise false.</returns>");
w.WriteLine (Strings.DotnetNames.Attributes.Applications.AggressiveInlining);
w.Push (
$"{Metadata.Accessibility.ToCSharpString ()} static bool FastHasFlags (this {Metadata.TargetTypeFullName} e, {Metadata.TargetTypeFullName} checkFlags)");
w.WriteLine ($"ref uint enumCurrentValueRef = ref Unsafe.As<{Metadata.TargetTypeFullName},uint> (ref e);");
w.WriteLine ($"ref uint checkFlagsValueRef = ref Unsafe.As<{Metadata.TargetTypeFullName},uint> (ref checkFlags);");
w.WriteLine ("return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;");
w.Pop ();
// The version taking the underlying type of the enum as the check value.
w.WriteLine (
$"/// <summary>Determines if the specified mask bits are set in the current value of this <see cref=\"{Metadata.TargetTypeFullName}\" />.</summary>");
w.WriteLine (
$"/// <param name=\"e\">The <see cref=\"{Metadata.TargetTypeFullName}\" /> value to check against the <paramref name=\"mask\" /> value.</param>");
w.WriteLine ("/// <param name=\"mask\">A mask to apply to the current value.</param>");
w.WriteLine (
$"/// <returns>True, if all bits set to 1 in the mask are also set to 1 in the current value of the <see cref=\"{Metadata.TargetTypeFullName}\" />.<br />Otherwise false.</returns>");
w.WriteLine ("/// <remarks>NO VALIDATION IS PERFORMED!</remarks>");
w.WriteLine (Strings.DotnetNames.Attributes.Applications.AggressiveInlining);
w.Push (
$"{Metadata.Accessibility.ToCSharpString ()} static bool FastHasFlags (this {Metadata.TargetTypeFullName} e, {EnumTypeKeyword} mask)");
w.WriteLine ($"ref {EnumTypeKeyword} enumCurrentValueRef = ref Unsafe.As<{Metadata.TargetTypeFullName},{EnumTypeKeyword}> (ref e);");
w.WriteLine ("return (enumCurrentValueRef & mask) == mask;");
w.Pop ();
}
/// <summary>
/// Creates the code for the FastIsDefined method.
/// </summary>
[SuppressMessage ("ReSharper", "SwitchStatementHandlesSomeKnownEnumValuesWithDefault", Justification = "Only need to handle int and uint.")]
[SuppressMessage ("ReSharper", "SwitchStatementMissingSomeEnumCasesNoDefault", Justification = "Only need to handle int and uint.")]
private void GetFastIsDefinedMethod (IndentedTextWriter w)
{
w.WriteLine (
$"/// <summary>Determines if the specified <see langword=\"{EnumTypeKeyword}\" /> value is explicitly defined as a named value of the <see cref=\"{Metadata.TargetTypeFullName}\" /> <see langword=\"enum\" /> type.</summary>");
w.WriteLine (
"/// <remarks>Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are not explicitly named will return false.</remarks>");
w.Push (
$"{Metadata.Accessibility.ToCSharpString ()} static bool FastIsDefined (this {Metadata.TargetTypeFullName} e, {EnumTypeKeyword} value)");
w.Push ("return value switch");
switch (Metadata.EnumBackingTypeCode)
{
case TypeCode.Int32:
foreach (int definedValue in Metadata._intMembers)
{
w.WriteLine ($"{definedValue:D} => true,");
}
break;
case TypeCode.UInt32:
foreach (uint definedValue in Metadata._uIntMembers)
{
w.WriteLine ($"{definedValue:D} => true,");
}
break;
}
w.WriteLine ("_ => false");
w.Pop ("};");
w.Pop ();
}
private string GetFullSourceText ()
{
StringBuilder sb = new (
$"""
{Strings.Templates.StandardHeader}
[assembly: {Strings.AssemblyExtendedEnumTypeAttributeFullName} (typeof({Metadata.TargetTypeFullName}), typeof({Metadata.GeneratedTypeFullName}))]
{EnumNamespaceUsingDirective}
{ExtensionClassNamespaceDirective}
{ExtensionClassDeclarationXmlDoc}
{Strings.Templates.AttributesForGeneratedTypes}
{ExtensionsForTypeAttributeLine}
{ExtensionClassDeclarationLine}
""",
4096);
using IndentedTextWriter w = new (new StringWriter (sb));
w.Push ();
GetNamedValuesToInt32Method (w);
GetNamedValuesToUInt32Method (w);
if (Metadata.GenerateFastIsDefined)
{
GetFastIsDefinedMethod (w);
}
if (Metadata.GenerateFastHasFlags)
{
GetFastHasFlagsMethods (w);
}
w.Pop ();
w.Flush ();
return sb.ToString ();
}
[MethodImpl (MethodImplOptions.AggressiveInlining)]
private void GetNamedValuesToInt32Method (IndentedTextWriter w)
{
w.WriteLine (
$"/// <summary>Directly converts this <see cref=\"{Metadata.TargetTypeFullName}\" /> value to an <see langword=\"int\" /> value with the same binary representation.</summary>");
w.WriteLine ("/// <remarks>NO VALIDATION IS PERFORMED!</remarks>");
w.WriteLine (Strings.DotnetNames.Attributes.Applications.AggressiveInlining);
w.Push ($"{Metadata.Accessibility.ToCSharpString ()} static int AsInt32 (this {Metadata.TargetTypeFullName} e)");
w.WriteLine ($"return Unsafe.As<{Metadata.TargetTypeFullName},int> (ref e);");
w.Pop ();
}
[MethodImpl (MethodImplOptions.AggressiveInlining)]
private void GetNamedValuesToUInt32Method (IndentedTextWriter w)
{
w.WriteLine (
$"/// <summary>Directly converts this <see cref=\"{Metadata.TargetTypeFullName}\" /> value to a <see langword=\"uint\" /> value with the same binary representation.</summary>");
w.WriteLine ("/// <remarks>NO VALIDATION IS PERFORMED!</remarks>");
w.WriteLine (Strings.DotnetNames.Attributes.Applications.AggressiveInlining);
w.Push ($"{Metadata.Accessibility.ToCSharpString ()} static uint AsUInt32 (this {Metadata.TargetTypeFullName} e)");
w.WriteLine ($"return Unsafe.As<{Metadata.TargetTypeFullName},uint> (ref e);");
w.Pop ();
}
}

View File

@@ -1,443 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Terminal.Gui.Analyzers.Internal.Attributes;
using Terminal.Gui.Analyzers.Internal.Constants;
namespace Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
/// <summary>
/// Type containing the information necessary to generate code according to the declared attribute values,
/// as well as the actual code to create the corresponding source code text, to be used in the
/// source generator pipeline.
/// </summary>
/// <remarks>
/// Minimal validation is performed by this type.<br/>
/// Errors in analyzed source code will result in generation failure or broken output.<br/>
/// This type is not intended for use outside of Terminal.Gui library development.
/// </remarks>
internal sealed record EnumExtensionMethodsGenerationInfo : IGeneratedTypeMetadata<EnumExtensionMethodsGenerationInfo>,
IEqualityOperators<EnumExtensionMethodsGenerationInfo, EnumExtensionMethodsGenerationInfo, bool>
{
private const int ExplicitFastHasFlagsMask = 0b_0100;
private const int ExplicitFastIsDefinedMask = 0b_1000;
private const int ExplicitNameMask = 0b_0010;
private const int ExplicitNamespaceMask = 0b_0001;
private const string GeneratorAttributeFullyQualifiedName = $"{GeneratorAttributeNamespace}.{GeneratorAttributeName}";
private const string GeneratorAttributeName = nameof (GenerateEnumExtensionMethodsAttribute);
private const string GeneratorAttributeNamespace = Strings.AnalyzersAttributesNamespace;
/// <summary>
/// Type containing the information necessary to generate code according to the declared attribute values,
/// as well as the actual code to create the corresponding source code text, to be used in the
/// source generator pipeline.
/// </summary>
/// <param name="enumNamespace">The fully-qualified namespace of the enum type, without assembly name.</param>
/// <param name="enumTypeName">
/// The name of the enum type, as would be given by <see langword="nameof"/> on the enum's type
/// declaration.
/// </param>
/// <param name="typeNamespace">
/// The fully-qualified namespace in which to place the generated code, without assembly name. If omitted or explicitly
/// null, uses the value provided in <paramref name="enumNamespace"/>.
/// </param>
/// <param name="typeName">
/// The name of the generated class. If omitted or explicitly null, appends "Extensions" to the value of
/// <paramref name="enumTypeName"/>.
/// </param>
/// <param name="enumBackingTypeCode">The backing type of the enum. Defaults to <see cref="int"/>.</param>
/// <param name="generateFastHasFlags">
/// Whether to generate a fast HasFlag alternative. (Default: true) Ignored if the enum does not also have
/// <see cref="FlagsAttribute"/>.
/// </param>
/// <param name="generateFastIsDefined">Whether to generate a fast IsDefined alternative. (Default: true)</param>
/// <remarks>
/// Minimal validation is performed by this type.<br/>
/// Errors in analyzed source code will result in generation failure or broken output.<br/>
/// This type is not intended for use outside of Terminal.Gui library development.
/// </remarks>
public EnumExtensionMethodsGenerationInfo (
string enumNamespace,
string enumTypeName,
string? typeNamespace = null,
string? typeName = null,
TypeCode enumBackingTypeCode = TypeCode.Int32,
bool generateFastHasFlags = true,
bool generateFastIsDefined = true
) : this (enumNamespace, enumTypeName, enumBackingTypeCode)
{
GeneratedTypeNamespace = typeNamespace ?? enumNamespace;
GeneratedTypeName = typeName ?? string.Concat (enumTypeName, Strings.DefaultTypeNameSuffix);
GenerateFastHasFlags = generateFastHasFlags;
GenerateFastIsDefined = generateFastIsDefined;
}
public EnumExtensionMethodsGenerationInfo (string enumNamespace, string enumTypeName, TypeCode enumBackingType)
{
// Interning these since they're rather unlikely to change.
string enumInternedNamespace = string.Intern (enumNamespace);
string enumInternedName = string.Intern (enumTypeName);
TargetTypeNamespace = enumInternedNamespace;
TargetTypeName = enumInternedName;
EnumBackingTypeCode = enumBackingType;
}
[AccessedThroughProperty (nameof (EnumBackingTypeCode))]
private readonly TypeCode _enumBackingTypeCode;
[AccessedThroughProperty (nameof (GeneratedTypeName))]
private string? _generatedTypeName;
[AccessedThroughProperty (nameof (GeneratedTypeNamespace))]
private string? _generatedTypeNamespace;
private BitVector32 _discoveredProperties = new (0);
/// <summary>The name of the extension class.</summary>
public string? GeneratedTypeName
{
get => _generatedTypeName ?? string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
set => _generatedTypeName = value ?? string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
}
/// <summary>The namespace for the extension class.</summary>
/// <remarks>
/// Value is not validated by the set accessor.<br/>
/// Get accessor will never return null and is thus marked [NotNull] for static analysis, even though the property is
/// declared as a nullable <see langword="string?"/>.<br/>If the backing field for this property is null, the get
/// accessor will return <see cref="TargetTypeNamespace"/> instead.
/// </remarks>
public string? GeneratedTypeNamespace
{
get => _generatedTypeNamespace ?? TargetTypeNamespace;
set => _generatedTypeNamespace = value ?? TargetTypeNamespace;
}
/// <inheritdoc/>
public string TargetTypeFullName => string.Concat (TargetTypeNamespace, ".", TargetTypeName);
/// <inheritdoc/>
public Accessibility Accessibility
{
get;
[UsedImplicitly]
internal set;
} = Accessibility.Public;
/// <inheritdoc/>
public TypeKind TypeKind => TypeKind.Class;
/// <inheritdoc/>
public bool IsRecord => false;
/// <inheritdoc/>
public bool IsClass => true;
/// <inheritdoc/>
public bool IsStruct => false;
/// <inheritdoc/>
public bool IsByRefLike => false;
/// <inheritdoc/>
public bool IsSealed => false;
/// <inheritdoc/>
public bool IsAbstract => false;
/// <inheritdoc/>
public bool IsEnum => false;
/// <inheritdoc/>
public bool IsStatic => true;
/// <inheritdoc/>
public bool IncludeInterface => false;
public string GeneratedTypeFullName => $"{GeneratedTypeNamespace}.{GeneratedTypeName}";
/// <summary>Whether to generate the extension class as partial (Default: true)</summary>
public bool IsPartial => true;
/// <summary>The fully-qualified namespace of the source enum type.</summary>
public string TargetTypeNamespace
{
get;
[UsedImplicitly]
set;
}
/// <summary>The UNQUALIFIED name of the source enum type.</summary>
public string TargetTypeName
{
get;
[UsedImplicitly]
set;
}
/// <summary>
/// The backing type for the enum.
/// </summary>
/// <remarks>For simplicity and formality, only System.Int32 and System.UInt32 are supported at this time.</remarks>
public TypeCode EnumBackingTypeCode
{
get => _enumBackingTypeCode;
init
{
if (value is not TypeCode.Int32 and not TypeCode.UInt32)
{
throw new NotSupportedException ("Only System.Int32 and System.UInt32 are supported at this time.");
}
_enumBackingTypeCode = value;
}
}
/// <summary>
/// Whether a fast alternative to the built-in Enum.HasFlag method will be generated (Default: false)
/// </summary>
public bool GenerateFastHasFlags { [UsedImplicitly] get; set; }
/// <summary>Whether a switch-based IsDefined replacement will be generated (Default: true)</summary>
public bool GenerateFastIsDefined { [UsedImplicitly]get; set; } = true;
internal ImmutableHashSet<int>? _intMembers;
internal ImmutableHashSet<uint>? _uIntMembers;
/// <summary>
/// Fully-qualified name of the extension class
/// </summary>
internal string FullyQualifiedClassName => $"{GeneratedTypeNamespace}.{GeneratedTypeName}";
/// <summary>
/// Whether a Flags was found on the enum type.
/// </summary>
internal bool HasFlagsAttribute {[UsedImplicitly] get; set; }
private static readonly SymbolDisplayFormat FullyQualifiedSymbolDisplayFormatWithoutGlobal =
SymbolDisplayFormat.FullyQualifiedFormat
.WithGlobalNamespaceStyle (
SymbolDisplayGlobalNamespaceStyle.Omitted);
internal bool TryConfigure (INamedTypeSymbol enumSymbol, CancellationToken cancellationToken)
{
using var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken);
cts.Token.ThrowIfCancellationRequested ();
ImmutableArray<AttributeData> attributes = enumSymbol.GetAttributes ();
// This is theoretically impossible, but guarding just in case and canceling if it does happen.
if (attributes.Length == 0)
{
cts.Cancel (true);
return false;
}
// Check all attributes provided for anything interesting.
// Attributes can be in any order, so just check them all and adjust at the end if necessary.
// Note that we do not perform as strict validation on actual usage of the attribute, at this stage,
// because the analyzer should have already thrown errors for invalid uses like global namespace
// or unsupported enum underlying types.
foreach (AttributeData attr in attributes)
{
cts.Token.ThrowIfCancellationRequested ();
string? attributeFullyQualifiedName = attr.AttributeClass?.ToDisplayString (FullyQualifiedSymbolDisplayFormatWithoutGlobal);
// Skip if null or not possibly an attribute we care about
if (attributeFullyQualifiedName is null or not { Length: >= 5 })
{
continue;
}
switch (attributeFullyQualifiedName)
{
// For Flags enums
case Strings.DotnetNames.Attributes.Flags:
{
HasFlagsAttribute = true;
}
continue;
// For the attribute that started this whole thing
case GeneratorAttributeFullyQualifiedName:
{
// If we can't successfully complete this method,
// something is wrong enough that we may as well just stop now.
if (!TryConfigure (attr, cts.Token))
{
if (cts.Token.CanBeCanceled)
{
cts.Cancel ();
}
return false;
}
}
continue;
}
}
// Now get the members, if we know we'll need them.
if (GenerateFastIsDefined || GenerateFastHasFlags)
{
if (EnumBackingTypeCode == TypeCode.Int32)
{
PopulateIntMembersHashSet (enumSymbol);
}
else if (EnumBackingTypeCode == TypeCode.UInt32)
{
PopulateUIntMembersHashSet (enumSymbol);
}
}
return true;
}
private void PopulateIntMembersHashSet (INamedTypeSymbol enumSymbol)
{
ImmutableArray<ISymbol> enumMembers = enumSymbol.GetMembers ();
IEnumerable<IFieldSymbol> fieldSymbols = enumMembers.OfType<IFieldSymbol> ();
_intMembers = fieldSymbols.Select (static m => m.HasConstantValue ? (int)m.ConstantValue : 0).ToImmutableHashSet ();
}
private void PopulateUIntMembersHashSet (INamedTypeSymbol enumSymbol)
{
_uIntMembers = enumSymbol.GetMembers ().OfType<IFieldSymbol> ().Select (static m => (uint)m.ConstantValue).ToImmutableHashSet ();
}
private bool HasExplicitFastHasFlags
{
[UsedImplicitly]get => _discoveredProperties [ExplicitFastHasFlagsMask];
set => _discoveredProperties [ExplicitFastHasFlagsMask] = value;
}
private bool HasExplicitFastIsDefined
{
[UsedImplicitly]get => _discoveredProperties [ExplicitFastIsDefinedMask];
set => _discoveredProperties [ExplicitFastIsDefinedMask] = value;
}
private bool HasExplicitTypeName
{
get => _discoveredProperties [ExplicitNameMask];
set => _discoveredProperties [ExplicitNameMask] = value;
}
private bool HasExplicitTypeNamespace
{
get => _discoveredProperties [ExplicitNamespaceMask];
set => _discoveredProperties [ExplicitNamespaceMask] = value;
}
[MemberNotNullWhen (true, nameof (_generatedTypeName), nameof (_generatedTypeNamespace))]
private bool TryConfigure (AttributeData attr, CancellationToken cancellationToken)
{
using var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken);
cts.Token.ThrowIfCancellationRequested ();
if (attr is not { NamedArguments.Length: > 0 })
{
// Just a naked attribute, so configure with appropriate defaults.
GeneratedTypeNamespace = TargetTypeNamespace;
GeneratedTypeName = string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
return true;
}
cts.Token.ThrowIfCancellationRequested ();
foreach (KeyValuePair<string, TypedConstant> kvp in attr.NamedArguments)
{
string? propName = kvp.Key;
TypedConstant propValue = kvp.Value;
cts.Token.ThrowIfCancellationRequested ();
// For every property name and value pair, set associated metadata
// property, if understood.
switch (propName, propValue)
{
// Null or empty string doesn't make sense, so skip if it happens.
case (null, _):
case ("", _):
continue;
// ClassName is specified, not explicitly null, and at least 1 character long.
case (AttributeProperties.TypeNamePropertyName, { IsNull: false, Value: string { Length: > 1 } classNameProvidedValue }):
if (string.IsNullOrWhiteSpace (classNameProvidedValue))
{
return false;
}
GeneratedTypeName = classNameProvidedValue;
HasExplicitTypeName = true;
continue;
// Class namespace is specified, not explicitly null, and at least 1 character long.
case (AttributeProperties.TypeNamespacePropertyName, { IsNull: false, Value: string { Length: > 1 } classNamespaceProvidedValue }):
if (string.IsNullOrWhiteSpace (classNamespaceProvidedValue))
{
return false;
}
GeneratedTypeNamespace = classNamespaceProvidedValue;
HasExplicitTypeNamespace = true;
continue;
// FastHasFlags is specified
case (AttributeProperties.FastHasFlagsPropertyName, { IsNull: false } fastHasFlagsConstant):
GenerateFastHasFlags = fastHasFlagsConstant.Value is true;
HasExplicitFastHasFlags = true;
continue;
// FastIsDefined is specified
case (AttributeProperties.FastIsDefinedPropertyName, { IsNull: false } fastIsDefinedConstant):
GenerateFastIsDefined = fastIsDefinedConstant.Value is true;
HasExplicitFastIsDefined = true;
continue;
}
}
// The rest is simple enough it's not really worth worrying about cancellation, so don't bother from here on...
// Configure anything that wasn't specified that doesn't have an implicitly safe default
if (!HasExplicitTypeName || _generatedTypeName is null)
{
_generatedTypeName = string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
}
if (!HasExplicitTypeNamespace || _generatedTypeNamespace is null)
{
_generatedTypeNamespace = TargetTypeNamespace;
}
if (!HasFlagsAttribute)
{
GenerateFastHasFlags = false;
}
return true;
}
private static class AttributeProperties
{
internal const string FastHasFlagsPropertyName = nameof (GenerateEnumExtensionMethodsAttribute.FastHasFlags);
internal const string FastIsDefinedPropertyName = nameof (GenerateEnumExtensionMethodsAttribute.FastIsDefined);
internal const string TypeNamePropertyName = nameof (GenerateEnumExtensionMethodsAttribute.ClassName);
internal const string TypeNamespacePropertyName = nameof (GenerateEnumExtensionMethodsAttribute.ClassNamespace);
}
}

View File

@@ -1,452 +0,0 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Terminal.Gui.Analyzers.Internal.Attributes;
using Terminal.Gui.Analyzers.Internal.Constants;
namespace Terminal.Gui.Analyzers.Internal.Generators.EnumExtensions;
/// <summary>
/// Incremental code generator for enums decorated with <see cref="GenerateEnumExtensionMethodsAttribute"/>.
/// </summary>
[SuppressMessage ("CodeQuality", "IDE0079", Justification = "Suppressions here are intentional and the warnings they disable are just noise.")]
[Generator (LanguageNames.CSharp)]
public sealed class EnumExtensionMethodsIncrementalGenerator : IIncrementalGenerator
{
private const string ExtensionsForEnumTypeAttributeFullyQualifiedName = $"{Strings.AnalyzersAttributesNamespace}.{ExtensionsForEnumTypeAttributeName}";
private const string ExtensionsForEnumTypeAttributeName = "ExtensionsForEnumTypeAttribute";
private const string GeneratorAttributeFullyQualifiedName = $"{Strings.AnalyzersAttributesNamespace}.{GeneratorAttributeName}";
private const string GeneratorAttributeName = nameof (GenerateEnumExtensionMethodsAttribute);
/// <summary>Fully-qualified symbol name format without the "global::" prefix.</summary>
private static readonly SymbolDisplayFormat _fullyQualifiedSymbolDisplayFormatWithoutGlobal =
SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle (SymbolDisplayGlobalNamespaceStyle.Omitted);
/// <inheritdoc/>
/// <remarks>
/// <para>
/// Basically, this method is called once by the compiler, and is responsible for wiring up
/// everything important about how source generation works.
/// </para>
/// <para>
/// See in-line comments for specifics of what's going on.
/// </para>
/// <para>
/// Note that <paramref name="context"/> is everything in the compilation,
/// except for code generated by this generator or generators which have not yet executed.<br/>
/// The methods registered to perform generation get called on-demand by the host (the IDE,
/// compiler, etc), sometimes as often as every single keystroke.
/// </para>
/// </remarks>
public void Initialize (IncrementalGeneratorInitializationContext context)
{
// Write out namespaces that may be used later. Harmless to declare them now and will avoid
// additional processing and potential omissions later on.
context.RegisterPostInitializationOutput (GenerateDummyNamespaces);
// This executes the delegate given to it immediately after Roslyn gets all set up.
//
// As written, this will result in the GenerateEnumExtensionMethodsAttribute code
// being added to the environment, so that it can be used without having to actually
// be declared explicitly in the target project.
// This is important, as it guarantees the type will exist and also guarantees it is
// defined exactly as the generator expects it to be defined.
context.RegisterPostInitializationOutput (GenerateAttributeSources);
// Next up, we define our pipeline.
// To do so, we create one or more IncrementalValuesProvider<T> objects, each of which
// defines on stage of analysis or generation as needed.
//
// Critically, these must be as fast and efficient as reasonably possible because,
// once the pipeline is registered, this stuff can get called A LOT.
//
// Note that declaring these doesn't really do much of anything unless they are given to the
// RegisterSourceOutput method at the end of this method.
//
// The delegates are not actually evaluated right here. That is triggered by changes being
// made to the source code.
// This provider grabs attributes that pass our filter and then creates lightweight
// metadata objects to be used in the final code generation step.
// It also preemptively removes any nulls from the collection before handing things off
// to the code generation logic.
IncrementalValuesProvider<EnumExtensionMethodsGenerationInfo?> enumGenerationInfos =
context
.SyntaxProvider
// This method is a highly-optimized (and highly-recommended) filter on the incoming
// code elements that only bothers to present code that is annotated with the specified
// attribute, by its fully-qualified name, as a string, which is the first parameter.
//
// Two delegates are passed to it, in the second and third parameters.
//
// The second parameter is a filter predicate taking each SyntaxNode that passes the
// name filter above, and then refines that result.
//
// It is critical that the filter predicate be as simple and fast as possible, as it
// will be called a ton, triggered by keystrokes or anything else that modifies code
// in or even related to (in either direction) the pre-filtered code.
// It should collect metadata only and not actually generate any code.
// It must return a boolean indicating whether the supplied SyntaxNode should be
// given to the transform delegate at all.
//
// The third parameter is the "transform" delegate.
// That one only runs when code is changed that passed both the attribute name filter
// and the filter predicate in the second parameter.
// It will be called for everything that passes both of those, so it can still happen
// a lot, but should at least be pretty close.
// In our case, it should be 100% accurate, since we're using OUR attribute, which can
// only be applied to enum types in the first place.
//
// That delegate is responsible for creating some sort of lightweight data structure
// which can later be used to generate the actual source code for output.
//
// THIS DELEGATE DOES NOT GENERATE CODE!
// However, it does need to return instances of the metadata class in use that are either
// null or complete enough to generate meaningful code from, later on.
//
// We then filter out any that were null with the .Where call at the end, so that we don't
// know or care about them when it's time to generate code.
//
// While the syntax of that .Where call is the same as LINQ, that is actually a
// highly-optimized implementation specifically for this use.
.ForAttributeWithMetadataName (
GeneratorAttributeFullyQualifiedName,
IsPotentiallyInterestingDeclaration,
GatherMetadataForCodeGeneration
)
.WithTrackingName ("CollectEnumMetadata")
.Where (static eInfo => eInfo is { });
// Finally, we wire up any IncrementalValuesProvider<T> instances above to the appropriate
// delegate that takes the SourceProductionContext that is current at run-time and an instance of
// our metadata type and takes appropriate action.
// Typically that means generating code from that metadata and adding it to the compilation via
// the received context object.
//
// As with everything else , the delegate will be invoked once for each item that passed
// all of the filters above, so we get to write that method from the perspective of a single
// enum type declaration.
context.RegisterSourceOutput (enumGenerationInfos, GenerateSourceFromGenerationInfo);
}
private static EnumExtensionMethodsGenerationInfo? GatherMetadataForCodeGeneration (
GeneratorAttributeSyntaxContext context,
CancellationToken cancellationToken
)
{
var cts = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken);
cancellationToken.ThrowIfCancellationRequested ();
// If it's not an enum symbol, we don't care.
// EnumUnderlyingType is null for non-enums, so this validates it's an enum declaration.
if (context.TargetSymbol is not INamedTypeSymbol { EnumUnderlyingType: { } } namedSymbol)
{
return null;
}
INamespaceSymbol? enumNamespaceSymbol = namedSymbol.ContainingNamespace;
if (enumNamespaceSymbol is null or { IsGlobalNamespace: true })
{
// Explicitly choosing not to support enums in the global namespace.
// The corresponding analyzer will report this.
return null;
}
string enumName = namedSymbol.Name;
string enumNamespace = enumNamespaceSymbol.ToDisplayString (_fullyQualifiedSymbolDisplayFormatWithoutGlobal);
TypeCode enumTypeCode = namedSymbol.EnumUnderlyingType.Name switch
{
"UInt32" => TypeCode.UInt32,
"Int32" => TypeCode.Int32,
_ => TypeCode.Empty
};
EnumExtensionMethodsGenerationInfo info = new (
enumNamespace,
enumName,
enumTypeCode
);
if (!info.TryConfigure (namedSymbol, cts.Token))
{
cts.Cancel ();
cts.Token.ThrowIfCancellationRequested ();
}
return info;
}
private static void GenerateAttributeSources (IncrementalGeneratorPostInitializationContext postInitializationContext)
{
postInitializationContext
.AddSource (
$"{nameof (IExtensionsForEnumTypeAttributes)}.g.cs",
SourceText.From (
$$"""
// ReSharper disable All
{{Strings.Templates.AutoGeneratedCommentBlock}}
using System;
namespace {{Strings.AnalyzersAttributesNamespace}};
/// <summary>
/// Interface to simplify general enumeration of constructed generic types for
/// <see cref="ExtensionsForEnumTypeAttribute{TEnum}"/>
/// </summary>
{{Strings.Templates.AttributesForGeneratedInterfaces}}
public interface IExtensionsForEnumTypeAttributes
{
System.Type EnumType { get; }
}
""",
Encoding.UTF8));
postInitializationContext
.AddSource (
$"{nameof (AssemblyExtendedEnumTypeAttribute)}.g.cs",
SourceText.From (
$$"""
// ReSharper disable All
#nullable enable
{{Strings.Templates.AutoGeneratedCommentBlock}}
namespace {{Strings.AnalyzersAttributesNamespace}};
/// <summary>Assembly attribute declaring a known pairing of an <see langword="enum" /> type to an extension class.</summary>
/// <remarks>This attribute should only be written by internal source generators for Terminal.Gui. No other usage of any kind is supported.</remarks>
{{Strings.Templates.AttributesForGeneratedTypes}}
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class {{nameof(AssemblyExtendedEnumTypeAttribute)}} : System.Attribute
{
/// <summary>Creates a new instance of <see cref="AssemblyExtendedEnumTypeAttribute" /> from the provided parameters.</summary>
/// <param name="enumType">The <see cref="System.Type" /> of an <see langword="enum" /> decorated with a <see cref="GenerateEnumExtensionMethodsAttribute" />.</param>
/// <param name="extensionClass">The <see cref="System.Type" /> of the <see langword="class" /> decorated with an <see cref="ExtensionsForEnumTypeAttribute{TEnum}" /> referring to the same type as <paramref name="enumType" />.</param>
public AssemblyExtendedEnumTypeAttribute (System.Type enumType, System.Type extensionClass)
{
EnumType = enumType;
ExtensionClass = extensionClass;
}
/// <summary>An <see langword="enum" /> type that has been extended by Terminal.Gui source generators.</summary>
public System.Type EnumType { get; init; }
/// <summary>A class containing extension methods for <see cref="EnumType"/>.</summary>
public System.Type ExtensionClass { get; init; }
/// <inheritdoc />
public override string ToString () => $"{EnumType.Name},{ExtensionClass.Name}";
}
""",
Encoding.UTF8));
postInitializationContext
.AddSource (
$"{GeneratorAttributeFullyQualifiedName}.g.cs",
SourceText.From (
$$"""
{{Strings.Templates.StandardHeader}}
namespace {{Strings.AnalyzersAttributesNamespace}};
/// <summary>
/// Used to enable source generation of a common set of extension methods for enum types.
/// </summary>
{{Strings.Templates.AttributesForGeneratedTypes}}
[{{Strings.DotnetNames.Types.AttributeUsageAttribute}} ({{Strings.DotnetNames.Types.AttributeTargets}}.Enum)]
public sealed class {{GeneratorAttributeName}} : {{Strings.DotnetNames.Types.Attribute}}
{
/// <summary>
/// The name of the generated static class.
/// </summary>
/// <remarks>
/// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".<br/>
/// No other validation is performed, so illegal values will simply result in compiler errors.
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public string? ClassName { get; set; }
/// <summary>
/// The namespace in which to place the generated static class containing the extension methods.
/// </summary>
/// <remarks>
/// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.<br/>
/// No other validation is performed, so illegal values will simply result in compiler errors.
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public string? ClassNamespace { get; set; }
/// <summary>
/// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
/// <see cref="Enum.HasFlag"/> method.
/// </summary>
/// <remarks>
/// <para>
/// Default: false
/// </para>
/// <para>
/// If the enum is not decorated with <see cref="Flags"/>, this option has no effect.
/// </para>
/// <para>
/// If multiple members have the same value, the first member with that value will be used and subsequent members
/// with the same value will be skipped.
/// </para>
/// <para>
/// Overloads taking the enum type itself as well as the underlying type of the enum will be generated, enabling
/// avoidance of implicit or explicit cast overhead.
/// </para>
/// <para>
/// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
/// </para>
/// </remarks>
public bool FastHasFlags { get; set; }
/// <summary>
/// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
/// <see cref="Enum.IsDefined"/> method,
/// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
/// </summary>
/// <remarks>
/// <para>
/// Default: true
/// </para>
/// <para>
/// If multiple members have the same value, the first member with that value will be used and subsequent members
/// with the same value will be skipped.
/// </para>
/// <para>
/// As with <see cref="Enum.IsDefined"/> the source generator only considers explicitly-named members.<br/>
/// Generation of values which represent valid bitwise combinations of members of enums decorated with
/// <see cref="Flags"/> is not affected by this property.
/// </para>
/// </remarks>
public bool FastIsDefined { get; init; } = true;
/// <summary>
/// Gets a <see langword="bool"/> value indicating if this <see cref="GenerateEnumExtensionMethodsAttribute"/> instance
/// contains default values only. See <see href="#remarks">remarks</see> of this method or documentation on properties of this type for details.
/// </summary>
/// <returns>
/// A <see langword="bool"/> value indicating if all property values are default for this
/// <see cref="GenerateEnumExtensionMethodsAttribute"/> instance.
/// </returns>
/// <remarks>
/// Default values that will result in a <see langword="true"/> return value are:<br/>
/// <see cref="FastIsDefined"/> &amp;&amp; !<see cref="FastHasFlags"/> &amp;&amp; <see cref="ClassName"/>
/// <see langword="is"/> <see langword="null"/> &amp;&amp; <see cref="ClassNamespace"/> <see langword="is"/>
/// <see langword="null"/>
/// </remarks>
public override bool IsDefaultAttribute ()
{
return FastIsDefined
&& !FastHasFlags
&& ClassName is null
&& ClassNamespace is null;
}
}
""",
Encoding.UTF8));
postInitializationContext
.AddSource (
$"{ExtensionsForEnumTypeAttributeFullyQualifiedName}.g.cs",
SourceText.From (
$$"""
// ReSharper disable RedundantNameQualifier
// ReSharper disable RedundantNullableDirective
// ReSharper disable UnusedType.Global
{{Strings.Templates.AutoGeneratedCommentBlock}}
#nullable enable
namespace {{Strings.AnalyzersAttributesNamespace}};
/// <summary>
/// Attribute written by the source generator for enum extension classes, for easier analysis and reflection.
/// </summary>
/// <remarks>
/// Properties are just convenient shortcuts to properties of <typeparamref name="TEnum"/>.
/// </remarks>
{{Strings.Templates.AttributesForGeneratedTypes}}
[System.AttributeUsageAttribute (System.AttributeTargets.Class | System.AttributeTargets.Interface)]
public sealed class {{ExtensionsForEnumTypeAttributeName}}<TEnum>: System.Attribute, IExtensionsForEnumTypeAttributes where TEnum : struct, Enum
{
/// <summary>
/// The namespace-qualified name of <typeparamref name="TEnum"/>.
/// </summary>
public string EnumFullName => EnumType.FullName!;
/// <summary>
/// The unqualified name of <typeparamref name="TEnum"/>.
/// </summary>
public string EnumName => EnumType.Name;
/// <summary>
/// The namespace containing <typeparamref name="TEnum"/>.
/// </summary>
public string EnumNamespace => EnumType.Namespace!;
/// <summary>
/// The <see cref="Type"/> given by <see langword="typeof"/>(<typeparamref name="TEnum"/>).
/// </summary>
public Type EnumType => typeof (TEnum);
}
""",
Encoding.UTF8));
}
[SuppressMessage ("Roslynator", "RCS1267", Justification = "Intentionally used so that Spans are used.")]
private static void GenerateDummyNamespaces (IncrementalGeneratorPostInitializationContext postInitializeContext)
{
postInitializeContext.AddSource (
string.Concat (Strings.InternalAnalyzersNamespace, "Namespaces.g.cs"),
SourceText.From (Strings.Templates.DummyNamespaceDeclarations, Encoding.UTF8));
}
private static void GenerateSourceFromGenerationInfo (SourceProductionContext context, EnumExtensionMethodsGenerationInfo? enumInfo)
{
// Just in case we still made it this far with a null...
if (enumInfo is not { })
{
return;
}
CodeWriter writer = new (enumInfo);
context.AddSource ($"{enumInfo.FullyQualifiedClassName}.g.cs", writer.GenerateSourceText ());
}
/// <summary>
/// Returns true if <paramref name="syntaxNode"/> is an EnumDeclarationSyntax
/// whose parent is a NamespaceDeclarationSyntax, FileScopedNamespaceDeclarationSyntax, or a
/// (Class|Struct)DeclarationSyntax.<br/>
/// Additional filtering is performed in later stages.
/// </summary>
private static bool IsPotentiallyInterestingDeclaration (SyntaxNode syntaxNode, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested ();
return syntaxNode is
{
RawKind: 8858, //(int)SyntaxKind.EnumDeclaration,
Parent.RawKind: 8845 //(int)SyntaxKind.FileScopedNamespaceDeclaration
or 8842 //(int)SyntaxKind.NamespaceDeclaration
or 8855 //(int)SyntaxKind.ClassDeclaration
or 8856 //(int)SyntaxKind.StructDeclaration
or 9068 //(int)SyntaxKind.RecordStructDeclaration
or 9063 //(int)SyntaxKind.RecordDeclaration
};
}
}

View File

@@ -1,3 +0,0 @@
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage ("Naming", "CA1708:Names should differ by more than case", Scope = "module", Justification = "That's coming from an external generator.")]

View File

@@ -1,38 +0,0 @@
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
namespace Terminal.Gui.Analyzers.Internal;
/// <summary>
/// Interface for all generators to use for their metadata classes.
/// </summary>
/// <typeparam name="TSelf">The type implementing this interface.</typeparam>
internal interface IGeneratedTypeMetadata<out TSelf> where TSelf : IGeneratedTypeMetadata<TSelf>
{
[UsedImplicitly]
string GeneratedTypeNamespace { get; }
[UsedImplicitly]
string? GeneratedTypeName { get; }
[UsedImplicitly]
string GeneratedTypeFullName { get; }
[UsedImplicitly]
string TargetTypeNamespace { get; }
[UsedImplicitly]
string TargetTypeName { get; }
string TargetTypeFullName { get; }
[UsedImplicitly]
Accessibility Accessibility { get; }
TypeKind TypeKind { get; }
bool IsRecord { get; }
bool IsClass { get; }
bool IsStruct { get; }
[UsedImplicitly]
bool IsPartial { get; }
bool IsByRefLike { get; }
bool IsSealed { get; }
bool IsAbstract { get; }
bool IsEnum { get; }
bool IsStatic { get; }
[UsedImplicitly]
bool IncludeInterface { get; }
}

View File

@@ -1,28 +0,0 @@
using System.Text;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis.Text;
namespace Terminal.Gui.Analyzers.Internal;
internal interface IStandardCSharpCodeGenerator<T> where T : IGeneratedTypeMetadata<T>
{
/// <summary>
/// Generates and returns the full source text corresponding to <see cref="Metadata"/>,
/// in the requested <paramref name="encoding"/> or <see cref="Encoding.UTF8"/> if not provided.
/// </summary>
/// <param name="encoding">
/// The <see cref="Encoding"/> of the generated source text or <see cref="Encoding.UTF8"/> if not
/// provided.
/// </param>
/// <returns></returns>
[UsedImplicitly]
[SkipLocalsInit]
ref readonly SourceText GenerateSourceText (Encoding? encoding = null);
/// <summary>
/// A type implementing <see cref="IGeneratedTypeMetadata{T}"/> which
/// will be used for source generation.
/// </summary>
[UsedImplicitly]
T Metadata { get; set; }
}

View File

@@ -1,71 +0,0 @@
using System.CodeDom.Compiler;
namespace Terminal.Gui.Analyzers.Internal;
/// <summary>
/// Just a simple set of extension methods to increment and decrement the indentation
/// level of an <see cref="IndentedTextWriter"/> via push and pop terms, and to avoid having
/// explicit values all over the place.
/// </summary>
public static class IndentedTextWriterExtensions
{
/// <summary>
/// Decrements <see cref="IndentedTextWriter.Indent"/> by 1, but only if it is greater than 0.
/// </summary>
/// <returns>
/// The resulting indentation level of the <see cref="IndentedTextWriter"/>.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int Pop (this IndentedTextWriter w, string endScopeDelimiter = "}")
{
if (w.Indent > 0)
{
w.Indent--;
w.WriteLine (endScopeDelimiter);
}
return w.Indent;
}
/// <summary>
/// Decrements <see cref="IndentedTextWriter.Indent"/> by 1 and then writes a closing curly brace.
/// </summary>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static void PopCurly (this IndentedTextWriter w, bool withSemicolon = false)
{
w.Indent--;
if (withSemicolon)
{
w.WriteLine ("};");
}
else
{
w.WriteLine ('}');
}
}
/// <summary>
/// Increments <see cref="IndentedTextWriter.Indent"/> by 1, with optional parameters to customize the scope push.
/// </summary>
/// <param name="w">An instance of an <see cref="IndentedTextWriter"/>.</param>
/// <param name="declaration">
/// The first line to be written before indenting and before the optional <paramref name="scopeDelimiter"/> line or
/// null if not needed.
/// </param>
/// <param name="scopeDelimiter">
/// An opening delimiter to write. Written before the indentation and after <paramref name="declaration"/> (if provided). Default is an opening curly brace.
/// </param>
/// <remarks>Calling with no parameters will write an opening curly brace and a line break at the current indentation and then increment.</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static void Push (this IndentedTextWriter w, string? declaration = null, char scopeDelimiter = '{')
{
if (declaration is { Length: > 0 })
{
w.WriteLine (declaration);
}
w.WriteLine (scopeDelimiter);
w.Indent++;
}
}

View File

@@ -1,8 +0,0 @@
{
"profiles": {
"InternalAnalyzers Debug": {
"commandName": "DebugRoslynComponent",
"targetProject": "..\\Terminal.Gui.Analyzers.Internal.Debugging\\Terminal.Gui.Analyzers.Internal.Debugging.csproj"
}
}
}

View File

@@ -1,67 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!--
Do not remove netstandard2.0 from the TargetFramework.
Visual Studio requires that Analyzers/Generators target netstandard2.0 to work properly.
Also do not change this to TargetFrameworks without fully understanding the behavior change that implies.
-->
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<OutputType>Library</OutputType>
<LangVersion>12</LangVersion>
<RootNamespace>Terminal.Gui.Analyzers.Internal</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<IsRoslynComponent>true</IsRoslynComponent>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<ApiCompatExcludeAttributesFile Include="ApiCompatExcludedAttributes.txt" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Compatibility/*.cs" />
</ItemGroup>
<PropertyGroup>
<!-- Disabling some useless warnings caused by the netstandard2.0 target -->
<NoWarn>$(NoWarn);nullable;CA1067</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="Compatibility/IEqualityOperators.cs" />
<Compile Include="Compatibility/NumericExtensions.cs" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="AnalyzerReleases.Unshipped.md" />
<AdditionalFiles Include="AnalyzerReleases.Shipped.md" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Meziantou.Polyfill" Version="1.0.39" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" Version="4.12.4" PrivateAssets="all" />
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.12.4" PrivateAssets="all" />
<PackageReference Include="Roslynator.CSharp" Version="4.12.4" PrivateAssets="all" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" PrivateAssets="all" />
<PackageReference Include="System.Runtime.Extensions" Version="4.3.1" PrivateAssets="all" />
<PackageReference Include="System.Runtime.Numerics" Version="4.3.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="JetBrains.Annotations" Version="2024.2.0" />
</ItemGroup>
</Project>

View File

@@ -1,4 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp120</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/UsageCheckingInspectionLevel/@EntryValue">InternalsOnly</s:String>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=compatibility/@EntryIndexedValue">False</s:Boolean></wpf:ResourceDictionary>

View File

@@ -2,8 +2,6 @@
"solution": {
"path": "Terminal.sln",
"projects": [
"Analyzers\\Terminal.Gui.Analyzers.Internal.Tests\\Terminal.Gui.Analyzers.Internal.Tests.csproj",
"Analyzers\\Terminal.Gui.Analyzers.Internal\\Terminal.Gui.Analyzers.Internal.csproj",
"Terminal.Gui\\Terminal.Gui.csproj",
"UICatalog\\UICatalog.csproj",
"UnitTests\\UnitTests.csproj"

View File

@@ -2,7 +2,6 @@
"solution": {
"path": "Terminal.sln",
"projects": [
"Analyzers\\Terminal.Gui.Analyzers.Internal\\Terminal.Gui.Analyzers.Internal.csproj",
"Terminal.Gui\\Terminal.Gui.csproj",
"UICatalog\\UICatalog.csproj",
"UnitTests\\UnitTests.csproj"

View File

@@ -1,117 +0,0 @@
#
# Module manifest for module 'Terminal.Gui.Powershell.Analyzers'
#
# Generated by: Brandon Thetford (GitHub @dodexahedron)
#
# Generated on: 4/24/2024
#
@{
# Script module or binary module file associated with this manifest.
RootModule = ''
# Version number of this module.
ModuleVersion = '1.0.0'
# Supported PSEditions
CompatiblePSEditions = @('Core')
# ID used to uniquely identify this module
GUID = '3e85001d-6539-4cf1-b71c-ec9e983f7fc8'
# Author of this module
Author = 'Brandon Thetford (GitHub @dodexahedron)'
# Company or vendor of this module
CompanyName = 'The Terminal.Gui Project'
# Copyright statement for this module
Copyright = '(c) Brandon Thetford (GitHub @dodexahedron). Provided to the Terminal.Gui project and you under the terms of the MIT License.'
# Description of the functionality provided by this module
Description = 'Operations involving Terminal.Gui analyzer projects, fur use during development of Terminal.Gui'
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.4.0'
# Name of the PowerShell host required by this module
PowerShellHostName = 'ConsoleHost'
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @('Microsoft.PowerShell.Management','Microsoft.PowerShell.Utility','./Terminal.Gui.PowerShell.Core.psd1')
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules.
NestedModules = @('./Terminal.Gui.PowerShell.Analyzers.psm1')
# Functions to export from this module.
FunctionsToExport = @('Build-Analyzers')
# Cmdlets to export from this module.
CmdletsToExport = @()
# Variables to export from this module
VariablesToExport = @()
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = @()
# A URL to the license for this module.
LicenseUri = 'https://github.com/gui-cs/Terminal.Gui/Scripts/COPYRIGHT'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/gui-cs/Terminal.Gui'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}

View File

@@ -1,96 +0,0 @@
<#
.SYNOPSIS
Builds all analyzer projects in Debug and Release configurations.
.DESCRIPTION
Uses dotnet build to build all analyzer projects, with optional behavior changes via switch parameters.
.PARAMETER AutoClose
Automatically close running Visual Studio processes which have the Terminal.sln solution loaded, before taking any other actions.
.PARAMETER AutoLaunch
Automatically start a new Visual Studio process and load the solution after completion.
.PARAMETER Force
Carry out operations unconditionally and do not prompt for confirmation.
.PARAMETER NoClean
Do not delete the bin and obj folders before building the analyzers. Usually best not to use this, but can speed up the builds slightly.
.PARAMETER Quiet
Write less text output to the terminal.
.INPUTS
None
.OUTPUTS
None
#>
Function Build-Analyzers {
[CmdletBinding()]
param(
[Parameter(Mandatory=$false, HelpMessage="Automatically close running Visual Studio processes which have the Terminal.sln solution loaded, before taking any other actions.")]
[switch]$AutoClose,
[Parameter(Mandatory=$false, HelpMessage="Automatically start a new Visual Studio process and load the solution after completion.")]
[switch]$AutoLaunch,
[Parameter(Mandatory=$false, HelpMessage="Carry out operations unconditionally and do not prompt for confirmation.")]
[switch]$Force,
[Parameter(Mandatory=$false, HelpMessage="Do not delete the bin and obj folders before building the analyzers.")]
[switch]$NoClean,
[Parameter(Mandatory=$false, HelpMessage="Write less text output to the terminal.")]
[switch]$Quiet
)
if($AutoClose) {
if(!$Quiet) {
Write-Host Closing Visual Studio processes
}
Close-Solution
}
if($Force){
$response = 'Y'
}
elseif(!$Force && $NoClean){
$response = ($r = Read-Host "Pre-build Terminal.Gui.InternalAnalyzers without removing old build artifacts? [Y/n]") ? $r : 'Y'
}
else{
$response = ($r = Read-Host "Delete bin and obj folders for Terminal.Gui and Terminal.Gui.InternalAnalyzers and pre-build Terminal.Gui.InternalAnalyzers? [Y/n]") ? $r : 'Y'
}
if (($response -ne 'Y')) {
Write-Host Took no action
return
}
Push-Location $InternalAnalyzersProjectDirectory
if(!$NoClean) {
if(!$Quiet) {
Write-Host Deleting bin and obj folders for Terminal.Gui
}
Remove-Item -Recurse -Force $TerminalGuiProjectDirectory/bin -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $TerminalGuiProjectDirectory/obj -ErrorAction SilentlyContinue
if(!$Quiet) {
Write-Host Deleting bin and obj folders for Terminal.Gui.InternalAnalyzers
}
Remove-Item -Recurse -Force $InternalAnalyzersProjectDirectory/bin -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $InternalAnalyzersProjectDirectory/obj -ErrorAction SilentlyContinue
}
if(!$Quiet) {
Write-Host Building analyzers in Debug configuration
}
dotnet build $InternalAnalyzersProjectFilePath --no-incremental --nologo --force --configuration Debug
if(!$Quiet) {
Write-Host Building analyzers in Release configuration
}
dotnet build $InternalAnalyzersProjectFilePath --no-incremental --nologo --force --configuration Release
Pop-Location
if(!$AutoLaunch) {
Write-Host -ForegroundColor Green Finished. Restart Visual Studio for changes to take effect.
} else {
if(!$Quiet) {
Write-Host -ForegroundColor Green Finished. Re-loading Terminal.sln.
}
Open-Solution
}
return
}

View File

@@ -69,9 +69,6 @@ Function Set-PowerShellEnvironment {
New-Variable -Name SolutionFilePath -Value (Join-Path -Resolve $RepositoryRootDirectory "Terminal.sln") -Option ReadOnly -Scope Global -Visibility Public
New-Variable -Name TerminalGuiProjectDirectory -Value (Join-Path -Resolve $RepositoryRootDirectory "Terminal.Gui") -Option ReadOnly -Scope Global -Visibility Public
New-Variable -Name TerminalGuiProjectFilePath -Value (Join-Path -Resolve $TerminalGuiProjectDirectory "Terminal.Gui.csproj") -Option ReadOnly -Scope Global -Visibility Public
New-Variable -Name AnalyzersDirectory -Value (Join-Path -Resolve $RepositoryRootDirectory "Analyzers") -Option ReadOnly -Scope Global -Visibility Public
New-Variable -Name InternalAnalyzersProjectDirectory -Value (Join-Path -Resolve $AnalyzersDirectory "Terminal.Gui.Analyzers.Internal") -Option ReadOnly -Scope Global -Visibility Public
New-Variable -Name InternalAnalyzersProjectFilePath -Value (Join-Path -Resolve $InternalAnalyzersProjectDirectory "Terminal.Gui.Analyzers.Internal.csproj") -Option ReadOnly -Scope Global -Visibility Public
# Save existing PSModulePath for optional reset later.
# If it is already saved, do not overwrite, but continue anyway.
@@ -137,9 +134,6 @@ Function Reset-PowerShellEnvironment {
Remove-Variable -Name TerminalGuiProjectDirectory -Scope Global -Force -ErrorAction SilentlyContinue
Remove-Variable -Name TerminalGuiProjectFilePath -Scope Global -Force -ErrorAction SilentlyContinue
Remove-Variable -Name ScriptsDirectory -Scope Global -Force -ErrorAction SilentlyContinue
Remove-Variable -Name AnalyzersDirectory -Scope Global -Force -ErrorAction SilentlyContinue
Remove-Variable -Name InternalAnalyzersProjectDirectory -Scope Global -Force -ErrorAction SilentlyContinue
Remove-Variable -Name InternalAnalyzersProjectFilePath -Scope Global -Force -ErrorAction SilentlyContinue
}
# This ensures the environment is reset when unloading the module.

View File

@@ -81,7 +81,7 @@ RequiredModules = @(
# Modules to import as nested modules of this module.
# This module is just a shortcut that loads all of our modules.
NestedModules = @('./Terminal.Gui.PowerShell.Core.psd1', './Terminal.Gui.PowerShell.Analyzers.psd1', './Terminal.Gui.PowerShell.Git.psd1', './Terminal.Gui.PowerShell.Build.psd1')
NestedModules = @('./Terminal.Gui.PowerShell.Core.psd1', './Terminal.Gui.PowerShell.Git.psd1', './Terminal.Gui.PowerShell.Build.psd1')
# Functions to export from this module.
# Not filtered, so exports all functions exported by all nested modules.

View File

@@ -1,12 +1,10 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
/// <summary>
/// Determines the position of items when arranged in a container.
/// </summary>
[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum Alignment
{
/// <summary>

View File

@@ -1,4 +1,4 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
@@ -6,7 +6,6 @@ namespace Terminal.Gui;
/// Determines alignment modes for <see cref="Alignment"/>.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum AlignmentModes
{
/// <summary>

View File

@@ -0,0 +1,51 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.AddOrSubtract"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class AddOrSubtractExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.AddOrSubtract"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this AddOrSubtract e) => Unsafe.As<AddOrSubtract, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.AddOrSubtract"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this AddOrSubtract e) => Unsafe.As<AddOrSubtract, uint> (ref e);
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.AddOrSubtract"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this AddOrSubtract _, int value)
{
return value switch
{
0 => true,
1 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,53 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.Alignment"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class AlignmentExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Alignment"/> value to an <see langword="int"/> value with the same
/// binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this Alignment e) => Unsafe.As<Alignment, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Alignment"/> value to a <see langword="uint"/> value with the same
/// binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this Alignment e) => Unsafe.As<Alignment, uint> (ref e);
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.Alignment"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this Alignment _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
3 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,90 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.AlignmentModes"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class AlignmentModesExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.AlignmentModes"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this AlignmentModes e) => Unsafe.As<AlignmentModes, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.AlignmentModes"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this AlignmentModes e) => Unsafe.As<AlignmentModes, uint> (ref e);
/// <summary>
/// Determines if the specified flags are set in the current value of this
/// <see cref="Terminal.Gui.AlignmentModes"/>.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
/// <returns>
/// True, if all flags present in <paramref name="checkFlags"/> are also present in the current value of the
/// <see cref="Terminal.Gui.AlignmentModes"/>.<br/>Otherwise false.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this AlignmentModes e, AlignmentModes checkFlags)
{
ref uint enumCurrentValueRef = ref Unsafe.As<AlignmentModes, uint> (ref e);
ref uint checkFlagsValueRef = ref Unsafe.As<AlignmentModes, uint> (ref checkFlags);
return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
}
/// <summary>
/// Determines if the specified mask bits are set in the current value of this
/// <see cref="Terminal.Gui.AlignmentModes"/>.
/// </summary>
/// <param name="e">The <see cref="Terminal.Gui.AlignmentModes"/> value to check against the <paramref name="mask"/> value.</param>
/// <param name="mask">A mask to apply to the current value.</param>
/// <returns>
/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
/// <see cref="Terminal.Gui.AlignmentModes"/>.<br/>Otherwise false.
/// </returns>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this AlignmentModes e, int mask)
{
ref int enumCurrentValueRef = ref Unsafe.As<AlignmentModes, int> (ref e);
return (enumCurrentValueRef & mask) == mask;
}
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.AlignmentModes"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this AlignmentModes _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
4 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,89 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.BorderSettings"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class BorderSettingsExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.BorderSettings"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this BorderSettings e) => Unsafe.As<BorderSettings, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.BorderSettings"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this BorderSettings e) => Unsafe.As<BorderSettings, uint> (ref e);
/// <summary>
/// Determines if the specified flags are set in the current value of this
/// <see cref="Terminal.Gui.BorderSettings"/>.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
/// <returns>
/// True, if all flags present in <paramref name="checkFlags"/> are also present in the current value of the
/// <see cref="Terminal.Gui.BorderSettings"/>.<br/>Otherwise false.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this BorderSettings e, BorderSettings checkFlags)
{
ref uint enumCurrentValueRef = ref Unsafe.As<BorderSettings, uint> (ref e);
ref uint checkFlagsValueRef = ref Unsafe.As<BorderSettings, uint> (ref checkFlags);
return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
}
/// <summary>
/// Determines if the specified mask bits are set in the current value of this
/// <see cref="Terminal.Gui.BorderSettings"/>.
/// </summary>
/// <param name="e">The <see cref="Terminal.Gui.BorderSettings"/> value to check against the <paramref name="mask"/> value.</param>
/// <param name="mask">A mask to apply to the current value.</param>
/// <returns>
/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
/// <see cref="Terminal.Gui.BorderSettings"/>.<br/>Otherwise false.
/// </returns>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this BorderSettings e, int mask)
{
ref int enumCurrentValueRef = ref Unsafe.As<BorderSettings, int> (ref e);
return (enumCurrentValueRef & mask) == mask;
}
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.BorderSettings"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this BorderSettings _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,89 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.DimAutoStyle"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class DimAutoStyleExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.DimAutoStyle"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this DimAutoStyle e) => Unsafe.As<DimAutoStyle, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.DimAutoStyle"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this DimAutoStyle e) => Unsafe.As<DimAutoStyle, uint> (ref e);
/// <summary>
/// Determines if the specified flags are set in the current value of this <see cref="Terminal.Gui.DimAutoStyle"/>
/// .
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
/// <returns>
/// True, if all flags present in <paramref name="checkFlags"/> are also present in the current value of the
/// <see cref="Terminal.Gui.DimAutoStyle"/>.<br/>Otherwise false.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this DimAutoStyle e, DimAutoStyle checkFlags)
{
ref uint enumCurrentValueRef = ref Unsafe.As<DimAutoStyle, uint> (ref e);
ref uint checkFlagsValueRef = ref Unsafe.As<DimAutoStyle, uint> (ref checkFlags);
return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
}
/// <summary>
/// Determines if the specified mask bits are set in the current value of this
/// <see cref="Terminal.Gui.DimAutoStyle"/>.
/// </summary>
/// <param name="e">The <see cref="Terminal.Gui.DimAutoStyle"/> value to check against the <paramref name="mask"/> value.</param>
/// <param name="mask">A mask to apply to the current value.</param>
/// <returns>
/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
/// <see cref="Terminal.Gui.DimAutoStyle"/>.<br/>Otherwise false.
/// </returns>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this DimAutoStyle e, int mask)
{
ref int enumCurrentValueRef = ref Unsafe.As<DimAutoStyle, int> (ref e);
return (enumCurrentValueRef & mask) == mask;
}
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.DimAutoStyle"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this DimAutoStyle _, int value)
{
return value switch
{
1 => true,
2 => true,
3 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,51 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.DimPercentMode"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class DimPercentModeExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.DimPercentMode"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this DimPercentMode e) => Unsafe.As<DimPercentMode, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.DimPercentMode"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this DimPercentMode e) => Unsafe.As<DimPercentMode, uint> (ref e);
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.DimPercentMode"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this DimPercentMode _, int value)
{
return value switch
{
0 => true,
1 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,51 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.Dimension"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
public static class DimensionExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Dimension"/> value to an <see langword="int"/> value with the same
/// binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this Dimension e) => Unsafe.As<Dimension, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Dimension"/> value to a <see langword="uint"/> value with the same
/// binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this Dimension e) => Unsafe.As<Dimension, uint> (ref e);
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.Dimension"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this Dimension _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,93 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.KeyBindingScope"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class KeyBindingScopeExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.KeyBindingScope"/> value to an <see langword="int"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this KeyBindingScope e) => Unsafe.As<KeyBindingScope, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.KeyBindingScope"/> value to a <see langword="uint"/> value with the
/// same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this KeyBindingScope e) => Unsafe.As<KeyBindingScope, uint> (ref e);
/// <summary>
/// Determines if the specified flags are set in the current value of this
/// <see cref="Terminal.Gui.KeyBindingScope"/>.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
/// <returns>
/// True, if all flags present in <paramref name="checkFlags"/> are also present in the current value of the
/// <see cref="Terminal.Gui.KeyBindingScope"/>.<br/>Otherwise false.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this KeyBindingScope e, KeyBindingScope checkFlags)
{
ref uint enumCurrentValueRef = ref Unsafe.As<KeyBindingScope, uint> (ref e);
ref uint checkFlagsValueRef = ref Unsafe.As<KeyBindingScope, uint> (ref checkFlags);
return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
}
/// <summary>
/// Determines if the specified mask bits are set in the current value of this
/// <see cref="Terminal.Gui.KeyBindingScope"/>.
/// </summary>
/// <param name="e">
/// The <see cref="Terminal.Gui.KeyBindingScope"/> value to check against the <paramref name="mask"/>
/// value.
/// </param>
/// <param name="mask">A mask to apply to the current value.</param>
/// <returns>
/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
/// <see cref="Terminal.Gui.KeyBindingScope"/>.<br/>Otherwise false.
/// </returns>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this KeyBindingScope e, int mask)
{
ref int enumCurrentValueRef = ref Unsafe.As<KeyBindingScope, int> (ref e);
return (enumCurrentValueRef & mask) == mask;
}
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.KeyBindingScope"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this KeyBindingScope _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
4 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,53 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.Side"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class SideExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Side"/> value to an <see langword="int"/> value with the same binary
/// representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this Side e) => Unsafe.As<Side, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.Side"/> value to a <see langword="uint"/> value with the same binary
/// representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this Side e) => Unsafe.As<Side, uint> (ref e);
/// <summary>
/// Determines if the specified <see langword="int"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.Side"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this Side _, int value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
3 => true,
_ => false
};
}
}

View File

@@ -0,0 +1,93 @@
#nullable enable
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Terminal.Gui.EnumExtensions;
/// <summary>Extension methods for the <see cref="Terminal.Gui.ViewDiagnosticFlags"/> <see langword="enum"/> type.</summary>
[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
[CompilerGenerated]
[DebuggerNonUserCode]
[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
[PublicAPI]
public static class ViewDiagnosticFlagsExtensions
{
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.ViewDiagnosticFlags"/> value to an <see langword="int"/> value with
/// the same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static int AsInt32 (this ViewDiagnosticFlags e) => Unsafe.As<ViewDiagnosticFlags, int> (ref e);
/// <summary>
/// Directly converts this <see cref="Terminal.Gui.ViewDiagnosticFlags"/> value to a <see langword="uint"/> value with
/// the same binary representation.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static uint AsUInt32 (this ViewDiagnosticFlags e) => Unsafe.As<ViewDiagnosticFlags, uint> (ref e);
/// <summary>
/// Determines if the specified flags are set in the current value of this
/// <see cref="Terminal.Gui.ViewDiagnosticFlags"/>.
/// </summary>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
/// <returns>
/// True, if all flags present in <paramref name="checkFlags"/> are also present in the current value of the
/// <see cref="Terminal.Gui.ViewDiagnosticFlags"/>.<br/>Otherwise false.
/// </returns>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this ViewDiagnosticFlags e, ViewDiagnosticFlags checkFlags)
{
ref uint enumCurrentValueRef = ref Unsafe.As<ViewDiagnosticFlags, uint> (ref e);
ref uint checkFlagsValueRef = ref Unsafe.As<ViewDiagnosticFlags, uint> (ref checkFlags);
return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
}
/// <summary>
/// Determines if the specified mask bits are set in the current value of this
/// <see cref="Terminal.Gui.ViewDiagnosticFlags"/>.
/// </summary>
/// <param name="e">
/// The <see cref="Terminal.Gui.ViewDiagnosticFlags"/> value to check against the <paramref name="mask"/>
/// value.
/// </param>
/// <param name="mask">A mask to apply to the current value.</param>
/// <returns>
/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
/// <see cref="Terminal.Gui.ViewDiagnosticFlags"/>.<br/>Otherwise false.
/// </returns>
/// <remarks>NO VALIDATION IS PERFORMED!</remarks>
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public static bool FastHasFlags (this ViewDiagnosticFlags e, uint mask)
{
ref uint enumCurrentValueRef = ref Unsafe.As<ViewDiagnosticFlags, uint> (ref e);
return (enumCurrentValueRef & mask) == mask;
}
/// <summary>
/// Determines if the specified <see langword="uint"/> value is explicitly defined as a named value of the
/// <see cref="Terminal.Gui.ViewDiagnosticFlags"/> <see langword="enum"/> type.
/// </summary>
/// <remarks>
/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
/// not explicitly named will return false.
/// </remarks>
public static bool FastIsDefined (this ViewDiagnosticFlags _, uint value)
{
return value switch
{
0 => true,
1 => true,
2 => true,
4 => true,
_ => false
};
}
}

View File

@@ -1,4 +1,4 @@
using Terminal.Gui.Analyzers.Internal.Attributes;

namespace Terminal.Gui;
@@ -10,7 +10,7 @@ namespace Terminal.Gui;
/// <para>Key bindings are scoped to the most-focused view (<see cref="Focused"/>) by default.</para>
/// </remarks>
[Flags]
[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum KeyBindingScope
{
/// <summary>The key binding is disabled.</summary>

View File

@@ -19,7 +19,7 @@
<!-- .NET Build Settings -->
<!-- =================================================================== -->
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<RootNamespace>$(AssemblyName)</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -73,6 +73,7 @@
<Using Include="JetBrains.Annotations.PureAttribute" Alias="PureAttribute" />
<Using Include="System.Drawing" />
<Using Include="System.Text" />
<Using Include="Terminal.Gui.EnumExtensions" />
</ItemGroup>
<!-- =================================================================== -->
<!-- Assembliy names for which internal items are visible -->

View File

@@ -1,4 +1,4 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
@@ -6,7 +6,7 @@ namespace Terminal.Gui;
/// Determines the settings for <see cref="Border"/>.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum BorderSettings
{
/// <summary>

View File

@@ -1,11 +1,8 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
namespace Terminal.Gui;
/// <summary>
/// Describes whether an operation should add or subtract values.
/// </summary>
[GenerateEnumExtensionMethods]
public enum AddOrSubtract
{
/// <summary>

View File

@@ -1,4 +1,4 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
@@ -6,7 +6,7 @@ namespace Terminal.Gui;
/// Specifies how <see cref="Dim.Auto"/> will compute the dimension.
/// </summary>
[Flags]
[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum DimAutoStyle
{
/// <summary>

View File

@@ -1,12 +1,10 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
/// <summary>
/// Indicates the mode for a <see cref="DimPercent"/> object.
/// </summary>
[GenerateEnumExtensionMethods]
public enum DimPercentMode
{
/// <summary>

View File

@@ -1,12 +1,10 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
/// <summary>
/// Indicates the dimension for <see cref="Dim"/> operations.
/// </summary>
[GenerateEnumExtensionMethods]
public enum Dimension
{
/// <summary>

View File

@@ -1,4 +1,4 @@
using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
@@ -6,7 +6,6 @@ namespace Terminal.Gui;
/// Indicates the side for <see cref="Pos"/> operations.
/// </summary>
///
[GenerateEnumExtensionMethods]
public enum Side
{
/// <summary>

View File

@@ -1,11 +1,10 @@

using Terminal.Gui.Analyzers.Internal.Attributes;
namespace Terminal.Gui;
/// <summary>Enables diagnostic functions for <see cref="View"/>.</summary>
[Flags]
[GenerateEnumExtensionMethods(FastHasFlags = true)]
public enum ViewDiagnosticFlags : uint
{
/// <summary>All diagnostics off</summary>

View File

@@ -14,14 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example", "Example\Example.
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E143FB1F-0B88-48CB-9086-72CDCECFCD22}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Analyzers", "Analyzers", "{CCADA0BC-61CF-4B4B-96BA-A3B0C0A7F54D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui.Analyzers.Internal", "Analyzers\Terminal.Gui.Analyzers.Internal\Terminal.Gui.Analyzers.Internal.csproj", "{5DE91722-8765-4E2B-97E4-2A18010B5CED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui.Analyzers.Internal.Tests", "Analyzers\Terminal.Gui.Analyzers.Internal.Tests\Terminal.Gui.Analyzers.Internal.Tests.csproj", "{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui.Analyzers.Internal.Debugging", "Analyzers\Terminal.Gui.Analyzers.Internal.Debugging\Terminal.Gui.Analyzers.Internal.Debugging.csproj", "{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkitExample", "CommunityToolkitExample\CommunityToolkitExample.csproj", "{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Settings", "Settings", "{B8F48EE8-34A6-43B7-B00E-CD91CDD93962}"
@@ -61,14 +53,6 @@ Global
{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}.Release|Any CPU.Build.0 = Release|Any CPU
{5DE91722-8765-4E2B-97E4-2A18010B5CED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DE91722-8765-4E2B-97E4-2A18010B5CED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DE91722-8765-4E2B-97E4-2A18010B5CED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DE91722-8765-4E2B-97E4-2A18010B5CED}.Release|Any CPU.Build.0 = Release|Any CPU
{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD}.Release|Any CPU.Build.0 = Release|Any CPU
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88979F89-9A42-448F-AE3E-3060145F6375}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -85,10 +69,6 @@ Global
{B0A602CD-E176-449D-8663-64238D54F857}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0A602CD-E176-449D-8663-64238D54F857}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0A602CD-E176-449D-8663-64238D54F857}.Release|Any CPU.Build.0 = Release|Any CPU
{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2}.Release|Any CPU.Build.0 = Release|Any CPU
{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -98,9 +78,6 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5DE91722-8765-4E2B-97E4-2A18010B5CED} = {CCADA0BC-61CF-4B4B-96BA-A3B0C0A7F54D}
{715DB4BA-F989-4DF6-B46F-5ED26A32B2DD} = {CCADA0BC-61CF-4B4B-96BA-A3B0C0A7F54D}
{C2AD09BD-D579-45A7-ACA3-E4EF3BC027D2} = {CCADA0BC-61CF-4B4B-96BA-A3B0C0A7F54D}
{B8F48EE8-34A6-43B7-B00E-CD91CDD93962} = {E143FB1F-0B88-48CB-9086-72CDCECFCD22}
{13BB2C46-B324-4B9C-92EB-CE6184D4736E} = {E143FB1F-0B88-48CB-9086-72CDCECFCD22}
{C7A51224-5E0F-4986-AB37-A6BF89966C12} = {E143FB1F-0B88-48CB-9086-72CDCECFCD22}

View File

@@ -45,5 +45,6 @@
<Using Include="System.Drawing.PointF" Alias="PointF" />
<Using Include="System.Drawing.Size" Alias="Size" />
<Using Include="System.Drawing.SizeF" Alias="SizeF" />
<Using Include="Terminal.Gui.EnumExtensions" />
</ItemGroup>
</Project>