diff --git a/.github/workflows/api-docs.yml b/.github/workflows/api-docs.yml
index b2c998fad..7b51e65dc 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/api-docs.yml
@@ -32,7 +32,7 @@ jobs:
- name: Setup Pages
if: github.ref_name == 'main' || github.ref_name == 'develop'
- uses: actions/configure-pages@v4
+ uses: actions/configure-pages@v5
- name: Upload artifact
if: github.ref_name == 'main' || github.ref_name == 'develop'
@@ -49,7 +49,7 @@ jobs:
- name: v2_develop Repository Dispatch ${{ github.ref_name }}
if: github.ref_name == 'v2_develop'
- uses: peter-evans/repository-dispatch@v2
+ uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.V2DOCS_TOKEN }}
repository: gui-cs/Terminal.GuiV2Docs
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index faf867527..64a37dc0a 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -19,7 +19,7 @@ jobs:
fetch-depth: 0 # fetch-depth is needed for GitVersion
- name: Install GitVersion
- uses: gittools/actions/gitversion/setup@v0
+ uses: gittools/actions/gitversion/setup@v1
with:
versionSpec: '5.x'
includePrerelease: true
@@ -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
diff --git a/.gitignore b/.gitignore
index bbfa8e16e..cca1f4801 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,9 +50,9 @@ UnitTests/TestResults
TestResults
# git merge files
-.orig
-.theirs
-.ours
+*.orig
+*.theirs
+*.ours
demo.*
diff --git a/Analyzers.slnf b/Analyzers.slnf
deleted file mode 100644
index 974c5a965..000000000
--- a/Analyzers.slnf
+++ /dev/null
@@ -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",
- ]
- }
-}
\ No newline at end of file
diff --git a/Analyzers/Directory.Build.props b/Analyzers/Directory.Build.props
deleted file mode 100644
index 6a6ec1589..000000000
--- a/Analyzers/Directory.Build.props
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- enable
- latest-recommended
- 8
- UTF-8
- true
- true
- $(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS
- True
- True
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Program.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Program.cs
deleted file mode 100644
index 559424a1b..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Program.cs
+++ /dev/null
@@ -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
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Terminal.Gui.Analyzers.Internal.Debugging.csproj b/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Terminal.Gui.Analyzers.Internal.Debugging.csproj
deleted file mode 100644
index 3cad5995b..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Debugging/Terminal.Gui.Analyzers.Internal.Debugging.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
-
-
-
-
-
-
-
-
-
-
-
-
- all
- Analyzer
- true
-
-
-
-
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/EnumMemberValues.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/EnumMemberValues.cs
deleted file mode 100644
index 0846f8e90..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/EnumMemberValues.cs
+++ /dev/null
@@ -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;
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum.cs
deleted file mode 100644
index 0fb09b8d9..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with applied.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt.cs
deleted file mode 100644
index 535f0448f..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with applied.
-///
-[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
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt_NoFastIsDefined.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt_NoFastIsDefined.cs
deleted file mode 100644
index 3b193b54c..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitInt_NoFastIsDefined.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// ReSharper disable EnumUnderlyingTypeIsInt
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with = .
-///
-[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,
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt.cs
deleted file mode 100644
index ca24165ef..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with applied.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt_NoFastIsDefined.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt_NoFastIsDefined.cs
deleted file mode 100644
index 01edea7a5..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_ExplicitUInt_NoFastIsDefined.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with = .
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_NoFastIsDefined.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_NoFastIsDefined.cs
deleted file mode 100644
index 04f6580ad..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterEnum_NoFastIsDefined.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with = .
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum.cs
deleted file mode 100644
index 2e468941c..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with applied.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitInt.cs
deleted file mode 100644
index 00b1b9487..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitInt.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-///
-/// Same as , but with applied.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitUInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitUInt.cs
deleted file mode 100644
index 9edb067d8..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithGenerator/BetterFlagsEnum_ExplicitUInt.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Same as , but with applied.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum.cs
deleted file mode 100644
index bfb743df6..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Basic enum without explicitly-defined backing type and no attributes on the enum or any of its members.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitInt.cs
deleted file mode 100644
index 8a400ab14..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitInt.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Basic enum with explicitly-defined backing type of int and no attributes on the enum or any of its members.
-///
-[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),
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitUint.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitUint.cs
deleted file mode 100644
index 911e64c9c..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/BasicEnum_ExplicitUint.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Basic enum with explicitly-defined backing type of uint and no attributes on the enum or any of its members.
-///
-[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,
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum.cs
deleted file mode 100644
index b69fcd057..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Flags enum without explicitly-defined backing type and only a on the enum declaration No other attributes on the enum or its members..
-///
-[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
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitInt.cs
deleted file mode 100644
index a01174e71..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitInt.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Flags enum with explicitly-defined backing type of int and only a on the enum declaration No other attributes on the enum or its members..
-///
-[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
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitUInt.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitUInt.cs
deleted file mode 100644
index 39285e26d..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumDefinitions/WithoutGenerator/FlagsEnum_ExplicitUInt.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Terminal.Gui.Analyzers.Internal.Tests.Generators.EnumExtensions.EnumDefinitions;
-
-///
-/// Flags enum with explicitly-defined backing type of uint and only a on the enum declaration No other attributes on the enum or its members..
-///
-[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
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGeneratorTests.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGeneratorTests.cs
deleted file mode 100644
index c134ab9fa..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGeneratorTests.cs
+++ /dev/null
@@ -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;
-
- /// All enum types declared in the test assembly.
- private static readonly ObservableCollection _allEnumTypes = [];
-
- ///
- /// All enum types without a ,
- ///
- private static readonly HashSet _boringEnumTypes = [];
-
- /// All extension classes generated for enums with our attribute.
- private static readonly ObservableCollection _enumExtensionClasses = [];
-
- private static readonly ConcurrentDictionary _extendedEnumTypeMappings = [];
- private static IEnumerable ExtendedEnumTypes => _extendedEnumTypeMappings.Keys;
-
- private static readonly ReaderWriterLockSlim _initializationLock = new ();
-
- private static IEnumerable GetAssemblyExtendedEnumTypeAttributes () =>
- Assembly.GetExecutingAssembly ()
- .GetCustomAttributes ();
-
- private static IEnumerable 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 ());
- }
-
- [Test]
- public void BoringEnum_DoesNotHaveExtensions ([ValueSource (nameof (_boringEnumTypes))] Type enumType)
- {
- Assume.That (enumType.IsEnum);
-
- Assert.That (enumType, Has.No.Attribute ());
- }
-
- [Test]
- public void ExtendedEnum_FastIsDefinedFalse_DoesNotHaveFastIsDefined ([ValueSource (nameof (GetExtendedEnumTypes_FastIsDefinedFalse))] EnumData enumData)
- {
- Assume.That (enumData.EnumType.IsEnum);
- Assume.That (enumData.EnumType, Has.Attribute ());
- Assume.That (enumData.GeneratorAttribute, Is.Not.Null);
- Assume.That (enumData.GeneratorAttribute, Is.EqualTo (enumData.EnumType.GetCustomAttribute ()));
- 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 ());
- Assume.That (enumType, Has.Attribute ());
- }
-
- [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 ());
- 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 ()));
- 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 ());
- extensionClassTypeInfo.GetMethodsWithAttribute (false);
-
-
- }
-
- private static IEnumerable GetExtendedEnum_EnumData ()
- {
- _initializationLock.EnterUpgradeableReadLock ();
-
- try
- {
- if (!_isInitialized)
- {
- Initialize ();
- }
-
- return _extendedEnumTypeMappings.Values;
- }
- finally
- {
- _initializationLock.ExitUpgradeableReadLock ();
- }
- }
-
- private static IEnumerable 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 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 ())
- {
- if (enumType.GetCustomAttribute () 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 ())
- {
- 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;
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/GlobalSuppressions.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/GlobalSuppressions.cs
deleted file mode 100644
index aba37def0..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/GlobalSuppressions.cs
+++ /dev/null
@@ -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.")]
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/IndentedTextWriterExtensionsTests.cs b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/IndentedTextWriterExtensionsTests.cs
deleted file mode 100644
index 250971d58..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/IndentedTextWriterExtensionsTests.cs
+++ /dev/null
@@ -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}
-
- """));
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj
deleted file mode 100644
index e4e88bd61..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
- net8.0
- enable
- 12
- false
- true
- true
- portable
- $(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS
- enable
- true
-
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
- all
- Analyzer
- true
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj.DotSettings b/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj.DotSettings
deleted file mode 100644
index cd5ef68b8..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal.Tests/Terminal.Gui.Analyzers.Internal.Tests.csproj.DotSettings
+++ /dev/null
@@ -1,3 +0,0 @@
-
- True
- True
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/AccessibilityExtensions.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/AccessibilityExtensions.cs
deleted file mode 100644
index fb80ebe87..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/AccessibilityExtensions.cs
+++ /dev/null
@@ -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
- };
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Shipped.md b/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Shipped.md
deleted file mode 100644
index 9316c42e0..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Shipped.md
+++ /dev/null
@@ -1,8 +0,0 @@
-## Release 1.0
-
-### New Rules
-
-Rule ID | Category | Severity | Notes
---------|----------|----------|--------------------
-TG0001 | Usage | Error | TG0001_GlobalNamespaceNotSupported
-TG0002 | Usage | Error | TG0002_UnderlyingTypeNotSupported
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Unshipped.md b/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Unshipped.md
deleted file mode 100644
index cb4c8a8b9..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/AnalyzerReleases.Unshipped.md
+++ /dev/null
@@ -1,4 +0,0 @@
-### New Rules
-
-Rule ID | Category | Severity | Notes
---------|----------|----------|--------------------
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Analyzers/GenerateEnumExtensionMethodsAttributeAnalyzer.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Analyzers/GenerateEnumExtensionMethodsAttributeAnalyzer.cs
deleted file mode 100644
index d49fd37d1..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Analyzers/GenerateEnumExtensionMethodsAttributeAnalyzer.cs
+++ /dev/null
@@ -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;
-
-///
-/// Design-time analyzer that checks for proper use of .
-///
-[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);
-
- ///
- public override ImmutableArray SupportedDiagnostics { get; } =
- [
- TG0001_GlobalNamespaceNotSupported,
- TG0002_UnderlyingTypeNotSupported
- ];
-
- ///
- 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)
- )
- );
- }
- }
- }
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/ApiCompatExcludedAttributes.txt b/Analyzers/Terminal.Gui.Analyzers.Internal/ApiCompatExcludedAttributes.txt
deleted file mode 100644
index 503f1f0bb..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/ApiCompatExcludedAttributes.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-N:System.Runtime.CompilerServices
-N:System.Diagnostics.CodeAnalysis
-N:System.Numerics
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/AssemblyExtendedEnumTypeAttribute.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/AssemblyExtendedEnumTypeAttribute.cs
deleted file mode 100644
index da340e075..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/AssemblyExtendedEnumTypeAttribute.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// ReSharper disable ClassNeverInstantiated.Global
-// ReSharper disable once RedundantNullableDirective
-#nullable enable
-
-namespace Terminal.Gui.Analyzers.Internal.Attributes;
-
-/// Assembly attribute declaring a known pairing of an type to an extension class.
-/// This attribute should only be written by internal source generators for Terminal.Gui. No other usage of any kind is supported.
-[System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple = true)]
-internal sealed class AssemblyExtendedEnumTypeAttribute : System.Attribute
-{
- /// Creates a new instance of from the provided parameters.
- /// The of an decorated with a .
- /// The of the decorated with an referring to the same type as .
- public AssemblyExtendedEnumTypeAttribute (System.Type enumType, System.Type extensionClass)
- {
- EnumType = enumType;
- ExtensionClass = extensionClass;
- }
- ///An type that has been extended by Terminal.Gui source generators.
- public System.Type EnumType { get; init; }
- ///A class containing extension methods for .
- public System.Type ExtensionClass { get; init; }
-
- ///
- public override string ToString () => $"{EnumType.Name},{ExtensionClass.Name}";
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/ExtensionsForEnumTypeAttribute.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/ExtensionsForEnumTypeAttribute.cs
deleted file mode 100644
index be4b6eef4..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/ExtensionsForEnumTypeAttribute.cs
+++ /dev/null
@@ -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;
-
-///
-/// Attribute written by the source generator for extension classes, for easier analysis and reflection.
-///
-///
-/// Properties are just convenient shortcuts to properties of .
-///
-[System.AttributeUsage (System.AttributeTargets.Class | System.AttributeTargets.Interface)]
-internal sealed class ExtensionsForEnumTypeAttribute: System.Attribute, IExtensionsForEnumTypeAttributes where TEnum : struct, System.Enum
-{
- ///
- /// The namespace-qualified name of .
- ///
- public string EnumFullName => EnumType.FullName!;
-
- ///
- /// The unqualified name of .
- ///
- public string EnumName => EnumType.Name;
-
- ///
- /// The namespace containing .
- ///
- public string EnumNamespace => EnumType.Namespace!;
-
- ///
- /// The given by ().
- ///
- public System.Type EnumType => typeof (TEnum);
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/GenerateEnumExtensionMethodsAttribute.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/GenerateEnumExtensionMethodsAttribute.cs
deleted file mode 100644
index 507c45102..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/GenerateEnumExtensionMethodsAttribute.cs
+++ /dev/null
@@ -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;
-
-///
-/// Used to enable source generation of a common set of extension methods for enum types.
-///
-[AttributeUsage (AttributeTargets.Enum)]
-internal sealed class GenerateEnumExtensionMethodsAttribute : Attribute
-{
- ///
- /// The name of the generated static class.
- ///
- ///
- /// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".
- /// No other validation is performed, so illegal values will simply result in compiler errors.
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public string? ClassName { get; set; }
-
- ///
- /// The namespace in which to place the generated static class containing the extension methods.
- ///
- ///
- /// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.
- /// No other validation is performed, so illegal values will simply result in compiler errors.
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public string? ClassNamespace { get; set; }
-
- ///
- /// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
- /// method.
- ///
- ///
- ///
- /// Default: false
- ///
- ///
- /// If the enum is not decorated with , this option has no effect.
- ///
- ///
- /// 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.
- ///
- ///
- /// 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.
- ///
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public bool FastHasFlags { get; set; }
-
- ///
- /// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
- /// method,
- /// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
- ///
- ///
- ///
- /// Default: true
- ///
- ///
- /// 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.
- ///
- ///
- /// As with the source generator only considers explicitly-named members.
- /// Generation of values which represent valid bitwise combinations of members of enums decorated with
- /// is not affected by this property.
- ///
- ///
- public bool FastIsDefined { get; init; } = true;
-
- ///
- /// Gets a value indicating if this instance
- /// contains default values only. See remarks of this method or documentation on properties of this type for details.
- ///
- ///
- /// A value indicating if all property values are default for this
- /// instance.
- ///
- ///
- /// Default values that will result in a return value are:
- /// && ! &&
- /// &&
- ///
- ///
- public override bool IsDefaultAttribute ()
- {
- return FastIsDefined
- && !FastHasFlags
- && ClassName is null
- && ClassNamespace is null;
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/IExtensionsForEnumTypeAttribute.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/IExtensionsForEnumTypeAttribute.cs
deleted file mode 100644
index 4ae8875b7..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Attributes/IExtensionsForEnumTypeAttribute.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// ReSharper disable All
-
-using System;
-
-namespace Terminal.Gui.Analyzers.Internal.Attributes;
-
-///
-/// Interface to simplify general enumeration of constructed generic types for
-///
-///
-internal interface IExtensionsForEnumTypeAttributes
-{
- Type EnumType { get; }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IEqualityOperators.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IEqualityOperators.cs
deleted file mode 100644
index 63493a738..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IEqualityOperators.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// ReSharper disable once CheckNamespace
-namespace System.Numerics;
-///
-/// Included for compatibility with .net7+, but has no members.
-/// Thus it cannot be explicitly used in generator code.
-/// Use it for static analysis only.
-///
-/// The left operand type.
-/// The right operand type.
-/// The return type.
-internal interface IEqualityOperators;
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IntrinsicAttribute.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IntrinsicAttribute.cs
deleted file mode 100644
index 06cd5b3d5..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/IntrinsicAttribute.cs
+++ /dev/null
@@ -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
-{
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/NumericExtensions.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/NumericExtensions.cs
deleted file mode 100644
index 8a6df7be9..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Compatibility/NumericExtensions.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// ReSharper disable once CheckNamespace
-namespace Terminal.Gui.Analyzers.Internal.Compatibility;
-
-///
-/// Extension methods for and types.
-///
-///
-/// This is mostly just for backward compatibility with netstandard2.0.
-///
-public static class NumericExtensions
-{
- ///
- /// Gets the population count (number of bits set to 1) of this 32-bit value.
- ///
- /// The value to get the population count of.
- ///
- /// The algorithm is the well-known SWAR (SIMD Within A Register) method for population count.
- /// 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.
- /// It performs the operation simultaneously on 4 bytes at a time, rather than the naive method of testing all 32 bits
- /// individually.
- /// Most compilers can recognize this and turn it into a single platform-specific instruction, when available.
- ///
- ///
- /// An unsigned 32-bit integer value containing the population count of .
- ///
- [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;
- }
- }
-
- ///
- [MethodImpl (MethodImplOptions.AggressiveInlining)]
- public static uint GetPopCount (this int value) { return GetPopCount (Unsafe.As (ref value)); }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Constants/Strings.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Constants/Strings.cs
deleted file mode 100644
index 3ffb234a6..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Constants/Strings.cs
+++ /dev/null
@@ -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;
-
-/// String constants for frequently-used boilerplate.
-/// These are for performance, instead of using Roslyn to build it all during execution of analyzers.
-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";
-
- ///
- /// Names of dotnet namespaces and types. Included as compile-time constants to avoid unnecessary work for the Roslyn
- /// source generators.
- ///
- /// Implemented as nested static types because XmlDoc doesn't work on namespaces.
- internal static class DotnetNames
- {
- /// Fully-qualified attribute type names. Specific applications (uses) are in .
- internal static class Attributes
- {
- ///
- internal const string CompilerGenerated = $"{Namespaces.System_Runtime_CompilerServices}.{nameof (CompilerGeneratedAttribute)}";
-
- ///
- internal const string DebuggerNonUserCode = $"{Namespaces.System_Diagnostics}.{nameof (DebuggerNonUserCodeAttribute)}";
-
- ///
- 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)}";
-
- ///
- /// Use of this attribute should be carefully evaluated.
- internal const string MethodImpl = $"{Namespaces.System_Runtime_CompilerServices}.{nameof (MethodImplAttribute)}";
-
- /// Attributes formatted for use in code, including square brackets.
- internal static class Applications
- {
- // ReSharper disable MemberHidesStaticFromOuterClass
- internal const string Flags = $"[{Attributes.Flags}]";
-
- ///
- internal const string GeneratedCode = $"""[{Attributes.GeneratedCode}("{InternalAnalyzersNamespace}","1.0")]""";
-
- ///
- /// Use of this attribute should be carefully evaluated.
- internal const string AggressiveInlining = $"[{MethodImpl}({Types.MethodImplOptions}.{nameof (MethodImplOptions.AggressiveInlining)})]";
-
- ///
- internal const string DebuggerNonUserCode = $"[{Attributes.DebuggerNonUserCode}]";
-
- ///
- internal const string CompilerGenerated = $"[{Attributes.CompilerGenerated}]";
-
- ///
- internal const string ExcludeFromCodeCoverage = $"[{Attributes.ExcludeFromCodeCoverage}]";
-
- // ReSharper restore MemberHidesStaticFromOuterClass
- }
- }
-
- /// Names of dotnet namespaces.
- 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 = $"""
- //------------------------------------------------------------------------------
- //
- // 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.
- //
- //------------------------------------------------------------------------------
- """;
-
- ///
- /// A set of explicit type aliases to work around Terminal.Gui having name collisions with types like
- /// .
- ///
- internal const string DotnetExplicitTypeAliasUsingDirectives = $"""
- using Attribute = {DotnetNames.Types.Attribute};
- using AttributeUsageAttribute = {DotnetNames.Types.AttributeUsageAttribute};
- using GeneratedCode = {DotnetNames.Attributes.GeneratedCode};
- """;
-
- /// Using directives for common namespaces in generated code.
- 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};
- """;
-
- ///
- /// 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.
- ///
- 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}
- """;
-
- ///
- /// 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.
- ///
- 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}
- """;
-
- ///
- /// Preprocessor directive to enable nullability context for generated code.
- /// This should always be emitted, as it applies only to generated code.
- /// As such, generated code MUST be properly annotated.
- ///
- internal const string NullableContextDirective = "#nullable enable";
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/CodeWriter.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/CodeWriter.cs
deleted file mode 100644
index f35e20d88..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/CodeWriter.cs
+++ /dev/null
@@ -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;
-
-///
-/// The class responsible for turning an
-/// into actual C# code.
-///
-/// Try to use this type as infrequently as possible.
-///
-/// A reference to an 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.
-///
-[SuppressMessage ("CodeQuality", "IDE0079", Justification = "Suppressions here are intentional and the warnings they disable are just noise.")]
-internal sealed class CodeWriter (in EnumExtensionMethodsGenerationInfo metadata) : IStandardCSharpCodeGenerator
-{
- // 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!;
-
- ///
- public EnumExtensionMethodsGenerationInfo Metadata
- {
- [MethodImpl (MethodImplOptions.AggressiveInlining)]
- [return: NotNull]
- get;
- [param: DisallowNull]
- set;
- } = metadata;
-
- ///
- public ref readonly SourceText GenerateSourceText (Encoding? encoding = null)
- {
- encoding ??= Encoding.UTF8;
- _sourceText = SourceText.From (GetFullSourceText (), encoding);
-
- return ref _sourceText;
- }
-
- ///
- /// 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.
- ///
- 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
- };
-
- /// Gets the class declaration line.
- private string ExtensionClassDeclarationLine => $"public static partial class {Metadata.GeneratedTypeName}";
-
- // ReSharper disable once HeapView.ObjectAllocation
- /// Gets the XmlDoc for the extension class declaration.
- private string ExtensionClassDeclarationXmlDoc =>
- $"/// Extension methods for the type.";
-
- // ReSharper disable once HeapView.ObjectAllocation
- /// Gets the extension class file-scoped namespace directive.
- private string ExtensionClassNamespaceDirective => $"namespace {Metadata.GeneratedTypeNamespace};";
-
- ///
- /// An attribute to decorate the extension class with for easy mapping back to the target enum type, for reflection and
- /// analysis.
- ///
- private string ExtensionsForTypeAttributeLine => $"[ExtensionsForEnumType<{Metadata.TargetTypeFullName}>]";
-
- ///
- /// Creates the code for the FastHasFlags method.
- ///
- ///
- /// Since the generator already only writes code for enums backed by and ,
- /// this method is safe, as we'll always be using a DWORD.
- ///
- /// An instance of an to write to.
- private void GetFastHasFlagsMethods (IndentedTextWriter w)
- {
- // The version taking the same enum type as the check value.
- w.WriteLine (
- $"/// Determines if the specified flags are set in the current value of this .");
- w.WriteLine ("/// NO VALIDATION IS PERFORMED!");
-
- w.WriteLine (
- $"/// True, if all flags present in are also present in the current value of the .
Otherwise false.");
- 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 (
- $"/// Determines if the specified mask bits are set in the current value of this .");
-
- w.WriteLine (
- $"/// The value to check against the value.");
- w.WriteLine ("/// A mask to apply to the current value.");
-
- w.WriteLine (
- $"/// True, if all bits set to 1 in the mask are also set to 1 in the current value of the .
Otherwise false.");
- w.WriteLine ("/// NO VALIDATION IS PERFORMED!");
- 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 ();
- }
-
- ///
- /// Creates the code for the FastIsDefined method.
- ///
- [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 (
- $"/// Determines if the specified value is explicitly defined as a named value of the type.");
-
- w.WriteLine (
- "/// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are not explicitly named will return false.");
-
- 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 (
- $"/// Directly converts this value to an value with the same binary representation.");
- w.WriteLine ("/// NO VALIDATION IS PERFORMED!");
- 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 (
- $"/// Directly converts this value to a value with the same binary representation.");
- w.WriteLine ("/// NO VALIDATION IS PERFORMED!");
- 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 ();
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsGenerationInfo.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsGenerationInfo.cs
deleted file mode 100644
index cab633cbf..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsGenerationInfo.cs
+++ /dev/null
@@ -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;
-
-///
-/// 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.
-///
-///
-/// Minimal validation is performed by this type.
-/// Errors in analyzed source code will result in generation failure or broken output.
-/// This type is not intended for use outside of Terminal.Gui library development.
-///
-internal sealed record EnumExtensionMethodsGenerationInfo : IGeneratedTypeMetadata,
- IEqualityOperators
-{
- 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;
-
- ///
- /// 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.
- ///
- /// The fully-qualified namespace of the enum type, without assembly name.
- ///
- /// The name of the enum type, as would be given by on the enum's type
- /// declaration.
- ///
- ///
- /// The fully-qualified namespace in which to place the generated code, without assembly name. If omitted or explicitly
- /// null, uses the value provided in .
- ///
- ///
- /// The name of the generated class. If omitted or explicitly null, appends "Extensions" to the value of
- /// .
- ///
- /// The backing type of the enum. Defaults to .
- ///
- /// Whether to generate a fast HasFlag alternative. (Default: true) Ignored if the enum does not also have
- /// .
- ///
- /// Whether to generate a fast IsDefined alternative. (Default: true)
- ///
- /// Minimal validation is performed by this type.
- /// Errors in analyzed source code will result in generation failure or broken output.
- /// This type is not intended for use outside of Terminal.Gui library development.
- ///
- 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);
-
- /// The name of the extension class.
- public string? GeneratedTypeName
- {
- get => _generatedTypeName ?? string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
- set => _generatedTypeName = value ?? string.Concat (TargetTypeName, Strings.DefaultTypeNameSuffix);
- }
-
- /// The namespace for the extension class.
- ///
- /// Value is not validated by the set accessor.
- /// Get accessor will never return null and is thus marked [NotNull] for static analysis, even though the property is
- /// declared as a nullable .
If the backing field for this property is null, the get
- /// accessor will return instead.
- ///
- public string? GeneratedTypeNamespace
- {
- get => _generatedTypeNamespace ?? TargetTypeNamespace;
- set => _generatedTypeNamespace = value ?? TargetTypeNamespace;
- }
-
- ///
- public string TargetTypeFullName => string.Concat (TargetTypeNamespace, ".", TargetTypeName);
-
- ///
- public Accessibility Accessibility
- {
- get;
- [UsedImplicitly]
- internal set;
- } = Accessibility.Public;
-
- ///
- public TypeKind TypeKind => TypeKind.Class;
-
- ///
- public bool IsRecord => false;
-
- ///
- public bool IsClass => true;
-
- ///
- public bool IsStruct => false;
-
- ///
- public bool IsByRefLike => false;
-
- ///
- public bool IsSealed => false;
-
- ///
- public bool IsAbstract => false;
-
- ///
- public bool IsEnum => false;
-
- ///
- public bool IsStatic => true;
-
- ///
- public bool IncludeInterface => false;
-
- public string GeneratedTypeFullName => $"{GeneratedTypeNamespace}.{GeneratedTypeName}";
-
- /// Whether to generate the extension class as partial (Default: true)
- public bool IsPartial => true;
-
- /// The fully-qualified namespace of the source enum type.
- public string TargetTypeNamespace
- {
- get;
- [UsedImplicitly]
- set;
- }
-
- /// The UNQUALIFIED name of the source enum type.
- public string TargetTypeName
- {
- get;
- [UsedImplicitly]
- set;
- }
-
- ///
- /// The backing type for the enum.
- ///
- /// For simplicity and formality, only System.Int32 and System.UInt32 are supported at this time.
- 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;
- }
- }
-
- ///
- /// Whether a fast alternative to the built-in Enum.HasFlag method will be generated (Default: false)
- ///
- public bool GenerateFastHasFlags { [UsedImplicitly] get; set; }
-
- /// Whether a switch-based IsDefined replacement will be generated (Default: true)
- public bool GenerateFastIsDefined { [UsedImplicitly]get; set; } = true;
-
- internal ImmutableHashSet? _intMembers;
- internal ImmutableHashSet? _uIntMembers;
-
- ///
- /// Fully-qualified name of the extension class
- ///
- internal string FullyQualifiedClassName => $"{GeneratedTypeNamespace}.{GeneratedTypeName}";
-
- ///
- /// Whether a Flags was found on the enum type.
- ///
- 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 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 enumMembers = enumSymbol.GetMembers ();
- IEnumerable fieldSymbols = enumMembers.OfType ();
- _intMembers = fieldSymbols.Select (static m => m.HasConstantValue ? (int)m.ConstantValue : 0).ToImmutableHashSet ();
- }
- private void PopulateUIntMembersHashSet (INamedTypeSymbol enumSymbol)
- {
- _uIntMembers = enumSymbol.GetMembers ().OfType ().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 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);
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGenerator.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGenerator.cs
deleted file mode 100644
index 7629fd8c2..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Generators/EnumExtensions/EnumExtensionMethodsIncrementalGenerator.cs
+++ /dev/null
@@ -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;
-
-///
-/// Incremental code generator for enums decorated with .
-///
-[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);
-
- /// Fully-qualified symbol name format without the "global::" prefix.
- private static readonly SymbolDisplayFormat _fullyQualifiedSymbolDisplayFormatWithoutGlobal =
- SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle (SymbolDisplayGlobalNamespaceStyle.Omitted);
-
- ///
- ///
- ///
- /// Basically, this method is called once by the compiler, and is responsible for wiring up
- /// everything important about how source generation works.
- ///
- ///
- /// See in-line comments for specifics of what's going on.
- ///
- ///
- /// Note that is everything in the compilation,
- /// except for code generated by this generator or generators which have not yet executed.
- /// The methods registered to perform generation get called on-demand by the host (the IDE,
- /// compiler, etc), sometimes as often as every single keystroke.
- ///
- ///
- 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 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 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 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}};
-
- ///
- /// Interface to simplify general enumeration of constructed generic types for
- ///
- ///
- {{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}};
-
- /// Assembly attribute declaring a known pairing of an type to an extension class.
- /// This attribute should only be written by internal source generators for Terminal.Gui. No other usage of any kind is supported.
- {{Strings.Templates.AttributesForGeneratedTypes}}
- [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple = true)]
- public sealed class {{nameof(AssemblyExtendedEnumTypeAttribute)}} : System.Attribute
- {
- /// Creates a new instance of from the provided parameters.
- /// The of an decorated with a .
- /// The of the decorated with an referring to the same type as .
- public AssemblyExtendedEnumTypeAttribute (System.Type enumType, System.Type extensionClass)
- {
- EnumType = enumType;
- ExtensionClass = extensionClass;
- }
- /// An type that has been extended by Terminal.Gui source generators.
- public System.Type EnumType { get; init; }
- /// A class containing extension methods for .
- public System.Type ExtensionClass { get; init; }
- ///
- public override string ToString () => $"{EnumType.Name},{ExtensionClass.Name}";
- }
-
- """,
- Encoding.UTF8));
-
- postInitializationContext
- .AddSource (
- $"{GeneratorAttributeFullyQualifiedName}.g.cs",
- SourceText.From (
- $$"""
- {{Strings.Templates.StandardHeader}}
-
- namespace {{Strings.AnalyzersAttributesNamespace}};
-
- ///
- /// Used to enable source generation of a common set of extension methods for enum types.
- ///
- {{Strings.Templates.AttributesForGeneratedTypes}}
- [{{Strings.DotnetNames.Types.AttributeUsageAttribute}} ({{Strings.DotnetNames.Types.AttributeTargets}}.Enum)]
- public sealed class {{GeneratorAttributeName}} : {{Strings.DotnetNames.Types.Attribute}}
- {
- ///
- /// The name of the generated static class.
- ///
- ///
- /// If unspecified, null, empty, or only whitespace, defaults to the name of the enum plus "Extensions".
- /// No other validation is performed, so illegal values will simply result in compiler errors.
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public string? ClassName { get; set; }
-
- ///
- /// The namespace in which to place the generated static class containing the extension methods.
- ///
- ///
- /// If unspecified, null, empty, or only whitespace, defaults to the namespace of the enum.
- /// No other validation is performed, so illegal values will simply result in compiler errors.
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public string? ClassNamespace { get; set; }
-
- ///
- /// Whether to generate a fast, zero-allocation, non-boxing, and reflection-free alternative to the built-in
- /// method.
- ///
- ///
- ///
- /// Default: false
- ///
- ///
- /// If the enum is not decorated with , this option has no effect.
- ///
- ///
- /// 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.
- ///
- ///
- /// 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.
- ///
- ///
- /// Explicitly specifying a default value is unnecessary and will result in unnecessary processing.
- ///
- ///
- public bool FastHasFlags { get; set; }
-
- ///
- /// Whether to generate a fast, zero-allocation, and reflection-free alternative to the built-in
- /// method,
- /// using a switch expression as a hard-coded reverse mapping of numeric values to explicitly-named members.
- ///
- ///
- ///
- /// Default: true
- ///
- ///
- /// 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.
- ///
- ///
- /// As with the source generator only considers explicitly-named members.
- /// Generation of values which represent valid bitwise combinations of members of enums decorated with
- /// is not affected by this property.
- ///
- ///
- public bool FastIsDefined { get; init; } = true;
-
- ///
- /// Gets a value indicating if this instance
- /// contains default values only. See remarks of this method or documentation on properties of this type for details.
- ///
- ///
- /// A value indicating if all property values are default for this
- /// instance.
- ///
- ///
- /// Default values that will result in a return value are:
- /// && ! &&
- /// &&
- ///
- ///
- 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}};
-
- ///
- /// Attribute written by the source generator for enum extension classes, for easier analysis and reflection.
- ///
- ///
- /// Properties are just convenient shortcuts to properties of .
- ///
- {{Strings.Templates.AttributesForGeneratedTypes}}
- [System.AttributeUsageAttribute (System.AttributeTargets.Class | System.AttributeTargets.Interface)]
- public sealed class {{ExtensionsForEnumTypeAttributeName}}: System.Attribute, IExtensionsForEnumTypeAttributes where TEnum : struct, Enum
- {
- ///
- /// The namespace-qualified name of .
- ///
- public string EnumFullName => EnumType.FullName!;
-
- ///
- /// The unqualified name of .
- ///
- public string EnumName => EnumType.Name;
-
- ///
- /// The namespace containing .
- ///
- public string EnumNamespace => EnumType.Namespace!;
-
- ///
- /// The given by ().
- ///
- 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 ());
- }
-
- ///
- /// Returns true if is an EnumDeclarationSyntax
- /// whose parent is a NamespaceDeclarationSyntax, FileScopedNamespaceDeclarationSyntax, or a
- /// (Class|Struct)DeclarationSyntax.
- /// Additional filtering is performed in later stages.
- ///
- 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
- };
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/GlobalSuppressions.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/GlobalSuppressions.cs
deleted file mode 100644
index ce2fa970b..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/GlobalSuppressions.cs
+++ /dev/null
@@ -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.")]
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/IGeneratedTypeMetadata.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/IGeneratedTypeMetadata.cs
deleted file mode 100644
index c72a8cc44..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/IGeneratedTypeMetadata.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using JetBrains.Annotations;
-using Microsoft.CodeAnalysis;
-
-namespace Terminal.Gui.Analyzers.Internal;
-
-///
-/// Interface for all generators to use for their metadata classes.
-///
-/// The type implementing this interface.
-internal interface IGeneratedTypeMetadata where TSelf : IGeneratedTypeMetadata
-{
- [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; }
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/IStandardCSharpCodeGenerator.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/IStandardCSharpCodeGenerator.cs
deleted file mode 100644
index a0e3d584d..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/IStandardCSharpCodeGenerator.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Text;
-using JetBrains.Annotations;
-using Microsoft.CodeAnalysis.Text;
-
-namespace Terminal.Gui.Analyzers.Internal;
-
-internal interface IStandardCSharpCodeGenerator where T : IGeneratedTypeMetadata
-{
- ///
- /// Generates and returns the full source text corresponding to ,
- /// in the requested or if not provided.
- ///
- ///
- /// The of the generated source text or if not
- /// provided.
- ///
- ///
- [UsedImplicitly]
- [SkipLocalsInit]
- ref readonly SourceText GenerateSourceText (Encoding? encoding = null);
-
- ///
- /// A type implementing which
- /// will be used for source generation.
- ///
- [UsedImplicitly]
- T Metadata { get; set; }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/IndentedTextWriterExtensions.cs b/Analyzers/Terminal.Gui.Analyzers.Internal/IndentedTextWriterExtensions.cs
deleted file mode 100644
index 90105d582..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/IndentedTextWriterExtensions.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-using System.CodeDom.Compiler;
-
-namespace Terminal.Gui.Analyzers.Internal;
-
-///
-/// Just a simple set of extension methods to increment and decrement the indentation
-/// level of an via push and pop terms, and to avoid having
-/// explicit values all over the place.
-///
-public static class IndentedTextWriterExtensions
-{
- ///
- /// Decrements by 1, but only if it is greater than 0.
- ///
- ///
- /// The resulting indentation level of the .
- ///
- [MethodImpl (MethodImplOptions.AggressiveInlining)]
- public static int Pop (this IndentedTextWriter w, string endScopeDelimiter = "}")
- {
- if (w.Indent > 0)
- {
- w.Indent--;
- w.WriteLine (endScopeDelimiter);
- }
- return w.Indent;
- }
-
- ///
- /// Decrements by 1 and then writes a closing curly brace.
- ///
- [MethodImpl (MethodImplOptions.AggressiveInlining)]
- public static void PopCurly (this IndentedTextWriter w, bool withSemicolon = false)
- {
- w.Indent--;
-
- if (withSemicolon)
- {
- w.WriteLine ("};");
- }
- else
- {
- w.WriteLine ('}');
- }
- }
-
- ///
- /// Increments by 1, with optional parameters to customize the scope push.
- ///
- /// An instance of an .
- ///
- /// The first line to be written before indenting and before the optional line or
- /// null if not needed.
- ///
- ///
- /// An opening delimiter to write. Written before the indentation and after (if provided). Default is an opening curly brace.
- ///
- /// Calling with no parameters will write an opening curly brace and a line break at the current indentation and then increment.
- [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++;
- }
-}
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Properties/launchSettings.json b/Analyzers/Terminal.Gui.Analyzers.Internal/Properties/launchSettings.json
deleted file mode 100644
index 639272733..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Properties/launchSettings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "profiles": {
- "InternalAnalyzers Debug": {
- "commandName": "DebugRoslynComponent",
- "targetProject": "..\\Terminal.Gui.Analyzers.Internal.Debugging\\Terminal.Gui.Analyzers.Internal.Debugging.csproj"
- }
- }
-}
\ No newline at end of file
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj b/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj
deleted file mode 100644
index 80d788ac3..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
- Library
- 12
- Terminal.Gui.Analyzers.Internal
- disable
- true
- true
- True
- true
- true
- true
- True
- true
- true
-
-
-
-
-
-
-
-
-
-
-
-
- $(NoWarn);nullable;CA1067
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj.DotSettings b/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj.DotSettings
deleted file mode 100644
index 6c2c0e27d..000000000
--- a/Analyzers/Terminal.Gui.Analyzers.Internal/Terminal.Gui.Analyzers.Internal.csproj.DotSettings
+++ /dev/null
@@ -1,4 +0,0 @@
-
- CSharp120
- InternalsOnly
- False
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d75e8f486..e92d17f10 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,8 +10,8 @@ We welcome contributions from the community. See [Issues](https://github.com/gui
Terminal.Gui uses the [GitFlow](https://nvie.com/posts/a-successful-git-branching-model/) branching model.
-* The `main` branch is always stable, and always matches the most recently released Nuget package.
-* The `develop` branch is where new development and bug-fixes happen. It is the default branch.
+* The `v1_release_` and `v2_release` branches are always stable, and always matches the most recently released Nuget package.
+* The `v1__develop` and `v2_develop` branches are where new development and bug-fixes happen. `v2_develop` is the default Github branch.
### Forking Terminal.Gui
@@ -33,11 +33,11 @@ You now have your own fork and a local repo that references it as `origin`. Your
### Starting to Make a Change
-Ensure your local `develop` (for v1) or `v2_develop` (for v2) branch is up-to-date with `upstream` (`github.com/gui-cs/Terminal.Gui`):
+Ensure your local `v1_develop` (for v1) or `v2_develop` (for v2) branch is up-to-date with `upstream` (`github.com/gui-cs/Terminal.Gui`):
```powershell
cd ./Terminal.Gui
-git checkout develop
-git pull upstream develop
+git checkout v2_develop
+git pull upstream v2_develop
```
Create a new local branch:
diff --git a/CommunityToolkitExample/CommunityToolkitExample.csproj b/CommunityToolkitExample/CommunityToolkitExample.csproj
index fdb41dfcd..8a25e7c31 100644
--- a/CommunityToolkitExample/CommunityToolkitExample.csproj
+++ b/CommunityToolkitExample/CommunityToolkitExample.csproj
@@ -8,11 +8,8 @@
-
-
-
-
-
+
+
diff --git a/Directory.Build.props b/Directory.Build.props
deleted file mode 100644
index e89be9369..000000000
--- a/Directory.Build.props
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Directory.Build.targets b/Directory.Build.targets
deleted file mode 100644
index 79faf752f..000000000
--- a/Directory.Build.targets
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- $(DefineConstants);DIMAUTO
-
-
\ No newline at end of file
diff --git a/Example/Example.cs b/Example/Example.cs
index 630e6560f..13c7b9138 100644
--- a/Example/Example.cs
+++ b/Example/Example.cs
@@ -6,19 +6,19 @@
using System;
using Terminal.Gui;
-var app = Application.Run ();
-
-Console.WriteLine ($"Username: {app.UserNameText.Text}");
-
-app.Dispose ();
+Application.Run ().Dispose ();
// Before the application exits, reset Terminal.Gui for clean shutdown
Application.Shutdown ();
+// To see this output on the screen it must be done after shutdown,
+// which restores the previous screen.
+Console.WriteLine ($@"Username: {ExampleWindow.UserName}");
+
// Defines a top-level window with border and title
public class ExampleWindow : Window
{
- public TextField UserNameText;
+ public static string UserName;
public ExampleWindow ()
{
@@ -27,7 +27,7 @@ public class ExampleWindow : Window
// Create input components and labels
var usernameLabel = new Label { Text = "Username:" };
- UserNameText = new TextField
+ var userNameText = new TextField
{
// Position text field adjacent to the label
X = Pos.Right (usernameLabel) + 1,
@@ -46,7 +46,7 @@ public class ExampleWindow : Window
Secret = true,
// align with the text box above
- X = Pos.Left (UserNameText),
+ X = Pos.Left (userNameText),
Y = Pos.Top (passwordLabel),
Width = Dim.Fill ()
};
@@ -64,19 +64,20 @@ public class ExampleWindow : Window
// When login button is clicked display a message popup
btnLogin.Accept += (s, e) =>
- {
- if (UserNameText.Text == "admin" && passwordText.Text == "password")
- {
- MessageBox.Query ("Logging In", "Login Successful", "Ok");
- Application.RequestStop ();
- }
- else
- {
- MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
- }
- };
+ {
+ if (userNameText.Text == "admin" && passwordText.Text == "password")
+ {
+ MessageBox.Query ("Logging In", "Login Successful", "Ok");
+ UserName = userNameText.Text;
+ Application.RequestStop ();
+ }
+ else
+ {
+ MessageBox.ErrorQuery ("Logging In", "Incorrect username or password", "Ok");
+ }
+ };
// Add the views to the Window
- Add (usernameLabel, UserNameText, passwordLabel, passwordText, btnLogin);
+ Add (usernameLabel, userNameText, passwordLabel, passwordText, btnLogin);
}
}
diff --git a/FSharpExample/FSharpExample.fsproj b/FSharpExample/FSharpExample.fsproj
index 9effec9fd..82b2802e5 100644
--- a/FSharpExample/FSharpExample.fsproj
+++ b/FSharpExample/FSharpExample.fsproj
@@ -1,7 +1,7 @@
Exe
- net6.0
+ net8.0
1.6.2.0
1.6.2.0
1.6.2+Branch.main.Sha.b6eeb6321685af474ffc17b1390ff1d4894a90c5
@@ -14,6 +14,6 @@
-
+
\ No newline at end of file
diff --git a/FSharpExample/Program.fs b/FSharpExample/Program.fs
index bfeaef2ed..88d801f04 100644
--- a/FSharpExample/Program.fs
+++ b/FSharpExample/Program.fs
@@ -1,454 +1,48 @@
-open System
-open System.Diagnostics
-open System.Globalization
-open System.IO
-open NStack
-open Terminal.Gui
+open Terminal.Gui
-let ustr (x: string) = ustring.Make(x)
-let mutable ml2 = Unchecked.defaultof
+ [RequiresUnreferencedCode ("AOT")]
internal static void Initialize ()
{
_allConfigProperties = new ();
@@ -585,16 +599,20 @@ public static class ConfigurationManager
/// Creates a JSON document with the configuration specified.
///
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
internal static string ToJson ()
{
//Debug.WriteLine ("ConfigurationManager.ToJson()");
- return JsonSerializer.Serialize (Settings!, _serializerOptions);
+ return JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);
}
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
internal static Stream ToStream ()
{
- string json = JsonSerializer.Serialize (Settings!, _serializerOptions);
+ string json = JsonSerializer.Serialize (Settings!, typeof (SettingsScope), _serializerContext);
// turn it into a stream
var stream = new MemoryStream ();
diff --git a/Terminal.Gui/Configuration/DictionaryJsonConverter.cs b/Terminal.Gui/Configuration/DictionaryJsonConverter.cs
index 29963c56b..bed7f874b 100644
--- a/Terminal.Gui/Configuration/DictionaryJsonConverter.cs
+++ b/Terminal.Gui/Configuration/DictionaryJsonConverter.cs
@@ -28,8 +28,8 @@ internal class DictionaryJsonConverter : JsonConverter>
{
string key = reader.GetString ();
reader.Read ();
- var value = JsonSerializer.Deserialize (ref reader, options);
- dictionary.Add (key, value);
+ var value = JsonSerializer.Deserialize (ref reader, typeof (T), _serializerContext);
+ dictionary.Add (key, (T)value);
}
}
else if (reader.TokenType == JsonTokenType.EndArray)
@@ -51,7 +51,7 @@ internal class DictionaryJsonConverter : JsonConverter>
//writer.WriteString (item.Key, item.Key);
writer.WritePropertyName (item.Key);
- JsonSerializer.Serialize (writer, item.Value, options);
+ JsonSerializer.Serialize (writer, item.Value, typeof (T), _serializerContext);
writer.WriteEndObject ();
}
diff --git a/Terminal.Gui/Configuration/KeyCodeJsonConverter.cs b/Terminal.Gui/Configuration/KeyCodeJsonConverter.cs
index c7b705311..9b24c7d0a 100644
--- a/Terminal.Gui/Configuration/KeyCodeJsonConverter.cs
+++ b/Terminal.Gui/Configuration/KeyCodeJsonConverter.cs
@@ -42,7 +42,7 @@ internal class KeyCodeJsonConverter : JsonConverter
}
// The enum uses "D0..D9" for the number keys
- if (Enum.TryParse (reader.GetString ().TrimStart ('D', 'd'), false, out key))
+ if (Enum.TryParse (reader.GetString ()!.TrimStart ('D', 'd'), false, out key))
{
break;
}
diff --git a/Terminal.Gui/Configuration/ScopeJsonConverter.cs b/Terminal.Gui/Configuration/ScopeJsonConverter.cs
index 5419619e2..a23216ea0 100644
--- a/Terminal.Gui/Configuration/ScopeJsonConverter.cs
+++ b/Terminal.Gui/Configuration/ScopeJsonConverter.cs
@@ -1,5 +1,6 @@
#nullable enable
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -11,9 +12,12 @@ namespace Terminal.Gui;
/// data to/from JSON documents.
///
///
-internal class ScopeJsonConverter : JsonConverter where scopeT : Scope
+internal class ScopeJsonConverter<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] scopeT> : JsonConverter where scopeT : Scope
{
+ [RequiresDynamicCode ("Calls System.Type.MakeGenericType(params Type[])")]
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
public override scopeT Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
{
if (reader.TokenType != JsonTokenType.StartObject)
{
@@ -85,7 +89,7 @@ internal class ScopeJsonConverter : JsonConverter where scopeT :
try
{
scope! [propertyName].PropertyValue =
- JsonSerializer.Deserialize (ref reader, propertyType!, options);
+ JsonSerializer.Deserialize (ref reader, propertyType!, _serializerContext);
}
catch (Exception ex)
{
@@ -133,7 +137,7 @@ internal class ScopeJsonConverter : JsonConverter where scopeT :
if (property is { })
{
PropertyInfo prop = scope.GetType ().GetProperty (propertyName!)!;
- prop.SetValue (scope, JsonSerializer.Deserialize (ref reader, prop.PropertyType, options));
+ prop.SetValue (scope, JsonSerializer.Deserialize (ref reader, prop.PropertyType, _serializerContext));
}
else
{
@@ -160,7 +164,8 @@ internal class ScopeJsonConverter : JsonConverter where scopeT :
foreach (PropertyInfo p in properties)
{
writer.WritePropertyName (ConfigProperty.GetJsonPropertyName (p));
- JsonSerializer.Serialize (writer, scope.GetType ().GetProperty (p.Name)?.GetValue (scope), options);
+ object? prop = scope.GetType ().GetProperty (p.Name)?.GetValue (scope);
+ JsonSerializer.Serialize (writer, prop, prop!.GetType (), _serializerContext);
}
foreach (KeyValuePair p in from p in scope
@@ -205,7 +210,8 @@ internal class ScopeJsonConverter : JsonConverter where scopeT :
}
else
{
- JsonSerializer.Serialize (writer, p.Value.PropertyValue, options);
+ object? prop = p.Value.PropertyValue;
+ JsonSerializer.Serialize (writer, prop, prop!.GetType (), _serializerContext);
}
}
@@ -221,6 +227,8 @@ internal class ScopeJsonConverter : JsonConverter where scopeT :
internal class ReadHelper : ReadHelper
{
private readonly ReadDelegate _readDelegate;
+
+ [RequiresUnreferencedCode ("Calls System.Delegate.CreateDelegate(Type, Object, String)")]
public ReadHelper (object converter) { _readDelegate = (ReadDelegate)Delegate.CreateDelegate (typeof (ReadDelegate), converter, "Read"); }
public override object? Read (ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
diff --git a/Terminal.Gui/Configuration/SettingsScope.cs b/Terminal.Gui/Configuration/SettingsScope.cs
index 145ad3cdc..8ce37bbbc 100644
--- a/Terminal.Gui/Configuration/SettingsScope.cs
+++ b/Terminal.Gui/Configuration/SettingsScope.cs
@@ -1,5 +1,6 @@
#nullable enable
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -37,12 +38,14 @@ public class SettingsScope : Scope
/// Updates the with the settings in a JSON string.
/// Json document to update the settings with.
/// The source (filename/resource name) the Json document was read from.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
public SettingsScope? Update (Stream stream, string source)
{
// Update the existing settings with the new settings.
try
{
- Update (JsonSerializer.Deserialize (stream, _serializerOptions)!);
+ Update ((SettingsScope)JsonSerializer.Deserialize (stream, typeof (SettingsScope), _serializerOptions)!);
OnUpdated ();
Debug.WriteLine ($"ConfigurationManager: Read configuration from \"{source}\"");
if (!Sources.Contains (source))
@@ -67,6 +70,8 @@ public class SettingsScope : Scope
/// Updates the with the settings in a JSON file.
///
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
public SettingsScope? Update (string filePath)
{
string realPath = filePath.Replace ("~", Environment.GetFolderPath (Environment.SpecialFolder.UserProfile));
@@ -93,6 +98,8 @@ public class SettingsScope : Scope
/// Updates the with the settings in a JSON string.
/// Json document to update the settings with.
/// The source (filename/resource name) the Json document was read from.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
public SettingsScope? Update (string json, string source)
{
var stream = new MemoryStream ();
@@ -107,6 +114,8 @@ public class SettingsScope : Scope
/// Updates the with the settings from a Json resource.
///
///
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
public SettingsScope? UpdateFromResource (Assembly assembly, string resourceName)
{
if (resourceName is null || string.IsNullOrEmpty (resourceName))
diff --git a/Terminal.Gui/Configuration/SourceGenerationContext.cs b/Terminal.Gui/Configuration/SourceGenerationContext.cs
new file mode 100644
index 000000000..ed93b68ca
--- /dev/null
+++ b/Terminal.Gui/Configuration/SourceGenerationContext.cs
@@ -0,0 +1,23 @@
+using System.Text.Json.Serialization;
+
+namespace Terminal.Gui;
+
+///
+/// Allow AOT and self-contained single file applications with the
+///
+[JsonSerializable (typeof (Attribute))]
+[JsonSerializable (typeof (Color))]
+[JsonSerializable (typeof (ThemeScope))]
+[JsonSerializable (typeof (ColorScheme))]
+[JsonSerializable (typeof (SettingsScope))]
+[JsonSerializable (typeof (AppScope))]
+[JsonSerializable (typeof (Key))]
+[JsonSerializable (typeof (GlyphDefinitions))]
+[JsonSerializable (typeof (ConfigProperty))]
+[JsonSerializable (typeof (ShadowStyle))]
+[JsonSerializable (typeof (string))]
+[JsonSerializable (typeof (bool))]
+[JsonSerializable (typeof (bool?))]
+[JsonSerializable (typeof (Dictionary))]
+internal partial class SourceGenerationContext : JsonSerializerContext
+{ }
diff --git a/Terminal.Gui/Configuration/ThemeManager.cs b/Terminal.Gui/Configuration/ThemeManager.cs
index 9787daa8d..e6efe32e0 100644
--- a/Terminal.Gui/Configuration/ThemeManager.cs
+++ b/Terminal.Gui/Configuration/ThemeManager.cs
@@ -1,6 +1,7 @@
#nullable enable
using System.Collections;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Terminal.Gui;
@@ -64,6 +65,9 @@ public class ThemeManager : IDictionary
public string Theme
{
get => SelectedTheme;
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
set => SelectedTheme = value;
}
@@ -73,9 +77,14 @@ public class ThemeManager : IDictionary
[SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true)]
public static Dictionary? Themes
{
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
get => Settings? ["Themes"]
?.PropertyValue as
Dictionary; // themes ?? new Dictionary ();
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
set =>
//if (themes is null || value is null) {
@@ -93,6 +102,9 @@ public class ThemeManager : IDictionary
internal static string SelectedTheme
{
get => _theme;
+
+ [RequiresUnreferencedCode ("Calls Terminal.Gui.ConfigurationManager.Settings")]
+ [RequiresDynamicCode ("Calls Terminal.Gui.ConfigurationManager.Settings")]
set
{
string oldTheme = _theme;
@@ -109,6 +121,8 @@ public class ThemeManager : IDictionary
/// Event fired he selected theme has changed. application.
public event EventHandler? ThemeChanged;
+ [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+ [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
internal static void GetHardCodedDefaults ()
{
//Debug.WriteLine ("Themes.GetHardCodedDefaults()");
@@ -129,6 +143,8 @@ public class ThemeManager : IDictionary
ThemeChanged?.Invoke (this, new ThemeManagerEventArgs (theme));
}
+ [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+ [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
internal static void Reset ()
{
Debug.WriteLine ("Themes.Reset()");
@@ -140,33 +156,130 @@ public class ThemeManager : IDictionary
#region IDictionary
#pragma warning disable 1591
+ [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")]
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
public ICollection Keys => ((IDictionary)Themes!).Keys;
+
+ [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")]
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
public ICollection Values => ((IDictionary)Themes!).Values;
+
+ [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")]
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
public int Count => ((ICollection>)Themes!).Count;
+
+ [UnconditionalSuppressMessage ("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "")]
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
public bool IsReadOnly => ((ICollection>)Themes!).IsReadOnly;
public ThemeScope this [string key]
{
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
get => ((IDictionary)Themes!) [key];
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
set => ((IDictionary)Themes!) [key] = value;
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
}
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
public void Add (string key, ThemeScope value) { ((IDictionary)Themes!).Add (key, value); }
- public bool ContainsKey (string key) { return ((IDictionary)Themes!).ContainsKey (key); }
- public bool Remove (string key) { return ((IDictionary)Themes!).Remove (key); }
- public bool TryGetValue (string key, out ThemeScope value) { return ((IDictionary)Themes!).TryGetValue (key, out value!); }
- public void Add (KeyValuePair item) { ((ICollection>)Themes!).Add (item); }
- public void Clear () { ((ICollection>)Themes!).Clear (); }
- public bool Contains (KeyValuePair item) { return ((ICollection>)Themes!).Contains (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public bool ContainsKey (string key) { return ((IDictionary)Themes!).ContainsKey (key); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public bool Remove (string key) { return ((IDictionary)Themes!).Remove (key); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public bool TryGetValue (string key, out ThemeScope value) { return ((IDictionary)Themes!).TryGetValue (key, out value!); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public void Add (KeyValuePair item) { ((ICollection>)Themes!).Add (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public void Clear () { ((ICollection>)Themes!).Clear (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+ public bool Contains (KeyValuePair item) { return ((ICollection>)Themes!).Contains (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
public void CopyTo (KeyValuePair [] array, int arrayIndex)
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
{
((ICollection>)Themes!).CopyTo (array, arrayIndex);
}
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
public bool Remove (KeyValuePair item) { return ((ICollection>)Themes!).Remove (item); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("AOT")]
+ [RequiresDynamicCode ("AOT")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
public IEnumerator> GetEnumerator () { return ((IEnumerable>)Themes!).GetEnumerator (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+
+ [RequiresUnreferencedCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+ [RequiresDynamicCode ("Calls Terminal.Gui.ThemeManager.Themes")]
+#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
IEnumerator IEnumerable.GetEnumerator () { return ((IEnumerable)Themes!).GetEnumerator (); }
+#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
+#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
#pragma warning restore 1591
#endregion
diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
index 6aef4230f..7400214ec 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs
@@ -13,6 +13,7 @@
// limitations under the License.
#define GUICS
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace Unix.Terminal;
@@ -69,6 +70,7 @@ internal class UnmanagedLibrary
}
}
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
static UnmanagedLibrary ()
{
PlatformID platform = Environment.OSVersion.Platform;
diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
index 0dd0e9038..86ef13466 100644
--- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
@@ -3,6 +3,7 @@
//
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using static Terminal.Gui.ConsoleDrivers.ConsoleKeyMapping;
using static Terminal.Gui.NetEvents;
@@ -452,6 +453,7 @@ internal class NetEvents : IDisposable
HandleKeyboardEvent (newConsoleKeyInfo);
}
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
private MouseButtonState MapMouseFlags (MouseFlags mouseFlags)
{
MouseButtonState mbs = default;
@@ -1249,6 +1251,7 @@ internal class NetDriver : ConsoleDriver
#region Color Handling
// Cache the list of ConsoleColor values.
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
private static readonly HashSet ConsoleColorValues = new (
Enum.GetValues (typeof (ConsoleColor))
.OfType ()
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index 3c9ba9261..89c82dd58 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -116,7 +116,7 @@ internal class WindowsConsole
var s = _stringBuilder.ToString ();
- result = WriteConsole (_screenBuffer, s, (uint)s.Length, out uint _, null);
+ result = WriteConsole (_screenBuffer, s, (uint)s.Length, out uint _, nint.Zero);
}
if (!result)
@@ -134,7 +134,7 @@ internal class WindowsConsole
public bool WriteANSI (string ansi)
{
- return WriteConsole (_screenBuffer, ansi, (uint)ansi.Length, out uint _, null);
+ return WriteConsole (_screenBuffer, ansi, (uint)ansi.Length, out uint _, nint.Zero);
}
public void ReadFromConsoleOutput (Size size, Coord coords, ref SmallRect window)
@@ -804,7 +804,7 @@ internal class WindowsConsole
string lpbufer,
uint NumberOfCharsToWriten,
out uint lpNumberOfCharsWritten,
- object lpReserved
+ nint lpReserved
);
[DllImport ("kernel32.dll")]
diff --git a/Terminal.Gui/Drawing/Alignment.cs b/Terminal.Gui/Drawing/Alignment.cs
index 40061a8c1..6a160096f 100644
--- a/Terminal.Gui/Drawing/Alignment.cs
+++ b/Terminal.Gui/Drawing/Alignment.cs
@@ -1,12 +1,10 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
///
/// Determines the position of items when arranged in a container.
///
-[GenerateEnumExtensionMethods (FastHasFlags = true)]
-
public enum Alignment
{
///
diff --git a/Terminal.Gui/Drawing/AlignmentModes.cs b/Terminal.Gui/Drawing/AlignmentModes.cs
index 4de4d5c98..b7e0bb87e 100644
--- a/Terminal.Gui/Drawing/AlignmentModes.cs
+++ b/Terminal.Gui/Drawing/AlignmentModes.cs
@@ -1,4 +1,4 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
@@ -6,7 +6,6 @@ namespace Terminal.Gui;
/// Determines alignment modes for .
///
[Flags]
-[GenerateEnumExtensionMethods (FastHasFlags = true)]
public enum AlignmentModes
{
///
diff --git a/Terminal.Gui/Drawing/FillPair.cs b/Terminal.Gui/Drawing/FillPair.cs
new file mode 100644
index 000000000..d0ea12608
--- /dev/null
+++ b/Terminal.Gui/Drawing/FillPair.cs
@@ -0,0 +1,41 @@
+namespace Terminal.Gui;
+
+///
+/// Describes a pair of which cooperate in creating
+/// . One gives foreground color while other gives background.
+///
+public class FillPair
+{
+ ///
+ /// Creates a new instance using the provided fills for foreground and background
+ /// color when assembling .
+ ///
+ ///
+ ///
+ public FillPair (IFill fore, IFill back)
+ {
+ Foreground = fore;
+ Background = back;
+ }
+
+ ///
+ /// The fill which provides point based foreground color.
+ ///
+ public IFill Foreground { get; init; }
+
+ ///
+ /// The fill which provides point based background color.
+ ///
+ public IFill Background { get; init; }
+
+ ///
+ /// Returns the color pair (foreground+background) to use when rendering
+ /// a rune at the given .
+ ///
+ ///
+ ///
+ public Attribute GetAttribute (Point point)
+ {
+ return new (Foreground.GetColor (point), Background.GetColor (point));
+ }
+}
diff --git a/Terminal.Gui/Drawing/Gradient.cs b/Terminal.Gui/Drawing/Gradient.cs
new file mode 100644
index 000000000..3b41e3e49
--- /dev/null
+++ b/Terminal.Gui/Drawing/Gradient.cs
@@ -0,0 +1,255 @@
+// This code is a C# port from python library Terminal Text Effects https://github.com/ChrisBuilds/terminaltexteffects/
+
+namespace Terminal.Gui;
+
+///
+/// Describes the pattern that a results in e.g. ,
+/// etc
+///
+public enum GradientDirection
+{
+ ///
+ /// Color varies along Y axis but is constant on X axis.
+ ///
+ Vertical,
+
+ ///
+ /// Color varies along X axis but is constant on Y axis.
+ ///
+ Horizontal,
+
+ ///
+ /// Color varies by distance from center (i.e. in circular ripples)
+ ///
+ Radial,
+
+ ///
+ /// Color varies by X and Y axis (i.e. a slanted gradient)
+ ///
+ Diagonal
+}
+
+///
+/// Describes a of colors that can be combined
+/// to make a color gradient. Use
+/// to create into gradient fill area maps.
+///
+public class Gradient
+{
+ ///
+ /// The discrete colors that will make up the .
+ ///
+ public List Spectrum { get; }
+
+ private readonly bool _loop;
+ private readonly List _stops;
+ private readonly List _steps;
+
+ ///
+ /// Creates a new instance of the class which hosts a
+ /// of colors including all and interpolated colors
+ /// between each corresponding pair.
+ ///
+ /// The colors to use in the spectrum (N)
+ ///
+ /// The number of colors to generate between each pair (must be N-1 numbers).
+ /// If only one step is passed then it is assumed to be the same distance for all pairs.
+ ///
+ /// True to duplicate the first stop and step so that the gradient repeats itself
+ ///
+ public Gradient (IEnumerable stops, IEnumerable steps, bool loop = false)
+ {
+ _stops = stops.ToList ();
+
+ if (_stops.Count < 1)
+ {
+ throw new ArgumentException ("At least one color stop must be provided.");
+ }
+
+ _steps = steps.ToList ();
+
+ // If multiple colors and only 1 step assume same distance applies to all steps
+ if (_stops.Count > 2 && _steps.Count == 1)
+ {
+ _steps = Enumerable.Repeat (_steps.Single (), _stops.Count () - 1).ToList ();
+ }
+
+ if (_steps.Any (step => step < 1))
+ {
+ throw new ArgumentException ("Steps must be greater than 0.");
+ }
+
+ if (_steps.Count != _stops.Count - 1)
+ {
+ throw new ArgumentException ("Number of steps must be N-1");
+ }
+
+ _loop = loop;
+ Spectrum = GenerateGradient (_steps);
+ }
+
+ ///
+ /// Returns the color to use at the given part of the spectrum
+ ///
+ ///
+ /// Proportion of the way through the spectrum, must be between
+ /// 0 and 1 (inclusive). Returns the last color if is
+ /// .
+ ///
+ ///
+ ///
+ public Color GetColorAtFraction (double fraction)
+ {
+ if (double.IsNaN (fraction))
+ {
+ return Spectrum.Last ();
+ }
+
+ if (fraction is < 0 or > 1)
+ {
+ throw new ArgumentOutOfRangeException (nameof (fraction), @"Fraction must be between 0 and 1.");
+ }
+
+ var index = (int)(fraction * (Spectrum.Count - 1));
+
+ return Spectrum [index];
+ }
+
+ private List GenerateGradient (IEnumerable steps)
+ {
+ List gradient = new ();
+
+ if (_stops.Count == 1)
+ {
+ for (var i = 0; i < steps.Sum (); i++)
+ {
+ gradient.Add (_stops [0]);
+ }
+
+ return gradient;
+ }
+
+ List stopsToUse = _stops.ToList ();
+ List stepsToUse = _steps.ToList ();
+
+ if (_loop)
+ {
+ stopsToUse.Add (_stops [0]);
+ stepsToUse.Add (_steps.First ());
+ }
+
+ var colorPairs = stopsToUse.Zip (stopsToUse.Skip (1), (start, end) => new { start, end });
+ List stepsList = stepsToUse;
+
+ foreach ((var colorPair, int thesteps) in colorPairs.Zip (stepsList, (pair, step) => (pair, step)))
+ {
+ gradient.AddRange (InterpolateColors (colorPair.start, colorPair.end, thesteps));
+ }
+
+ return gradient;
+ }
+
+ private static IEnumerable InterpolateColors (Color start, Color end, int steps)
+ {
+ for (var step = 0; step < steps; step++)
+ {
+ double fraction = (double)step / steps;
+ var r = (int)(start.R + fraction * (end.R - start.R));
+ var g = (int)(start.G + fraction * (end.G - start.G));
+ var b = (int)(start.B + fraction * (end.B - start.B));
+
+ yield return new (r, g, b);
+ }
+
+ yield return end; // Ensure the last color is included
+ }
+
+ ///
+ ///
+ /// Creates a mapping starting at 0,0 and going to and
+ /// (inclusively) using the supplied .
+ ///
+ ///
+ /// Note that this method is inclusive i.e. passing 1/1 results in 4 mapped coordinates.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Dictionary BuildCoordinateColorMapping (int maxRow, int maxColumn, GradientDirection direction)
+ {
+ Dictionary gradientMapping = new ();
+
+ switch (direction)
+ {
+ case GradientDirection.Vertical:
+ for (var row = 0; row <= maxRow; row++)
+ {
+ double fraction = maxRow == 0 ? 1.0 : (double)row / maxRow;
+ Color color = GetColorAtFraction (fraction);
+
+ for (var col = 0; col <= maxColumn; col++)
+ {
+ gradientMapping [new (col, row)] = color;
+ }
+ }
+
+ break;
+
+ case GradientDirection.Horizontal:
+ for (var col = 0; col <= maxColumn; col++)
+ {
+ double fraction = maxColumn == 0 ? 1.0 : (double)col / maxColumn;
+ Color color = GetColorAtFraction (fraction);
+
+ for (var row = 0; row <= maxRow; row++)
+ {
+ gradientMapping [new (col, row)] = color;
+ }
+ }
+
+ break;
+
+ case GradientDirection.Radial:
+ for (var row = 0; row <= maxRow; row++)
+ {
+ for (var col = 0; col <= maxColumn; col++)
+ {
+ double distanceFromCenter = FindNormalizedDistanceFromCenter (maxRow, maxColumn, new (col, row));
+ Color color = GetColorAtFraction (distanceFromCenter);
+ gradientMapping [new (col, row)] = color;
+ }
+ }
+
+ break;
+
+ case GradientDirection.Diagonal:
+ for (var row = 0; row <= maxRow; row++)
+ {
+ for (var col = 0; col <= maxColumn; col++)
+ {
+ double fraction = ((double)row * 2 + col) / (maxRow * 2 + maxColumn);
+ Color color = GetColorAtFraction (fraction);
+ gradientMapping [new (col, row)] = color;
+ }
+ }
+
+ break;
+ }
+
+ return gradientMapping;
+ }
+
+ private static double FindNormalizedDistanceFromCenter (int maxRow, int maxColumn, Point coord)
+ {
+ double centerX = maxColumn / 2.0;
+ double centerY = maxRow / 2.0;
+ double dx = coord.X - centerX;
+ double dy = coord.Y - centerY;
+ double distance = Math.Sqrt (dx * dx + dy * dy);
+ double maxDistance = Math.Sqrt (centerX * centerX + centerY * centerY);
+
+ return distance / maxDistance;
+ }
+}
diff --git a/Terminal.Gui/Drawing/GradientFill.cs b/Terminal.Gui/Drawing/GradientFill.cs
new file mode 100644
index 000000000..6518d2dab
--- /dev/null
+++ b/Terminal.Gui/Drawing/GradientFill.cs
@@ -0,0 +1,42 @@
+namespace Terminal.Gui;
+
+///
+/// Implementation of that uses a color gradient (including
+/// radial, diagonal etc.).
+///
+public class GradientFill : IFill
+{
+ private readonly Dictionary _map;
+
+ ///
+ /// Creates a new instance of the class that can return
+ /// color for any point in the given using the provided
+ /// and .
+ ///
+ ///
+ ///
+ ///
+ public GradientFill (Rectangle area, Gradient gradient, GradientDirection direction)
+ {
+ _map = gradient.BuildCoordinateColorMapping (area.Height - 1, area.Width - 1, direction)
+ .ToDictionary (
+ kvp => new Point (kvp.Key.X + area.X, kvp.Key.Y + area.Y),
+ kvp => kvp.Value);
+ }
+
+ ///
+ /// Returns the color to use for the given or Black if it
+ /// lies outside the prepared gradient area (see constructor).
+ ///
+ ///
+ ///
+ public Color GetColor (Point point)
+ {
+ if (_map.TryGetValue (point, out Color color))
+ {
+ return color;
+ }
+
+ return new (0, 0); // Default to black if point not found
+ }
+}
diff --git a/Terminal.Gui/Drawing/IFill.cs b/Terminal.Gui/Drawing/IFill.cs
new file mode 100644
index 000000000..7d1d19a68
--- /dev/null
+++ b/Terminal.Gui/Drawing/IFill.cs
@@ -0,0 +1,14 @@
+namespace Terminal.Gui;
+
+///
+/// Describes an area fill (e.g. solid color or gradient).
+///
+public interface IFill
+{
+ ///
+ /// Returns the color that should be used at the given point
+ ///
+ ///
+ ///
+ Color GetColor (Point point);
+}
diff --git a/Terminal.Gui/Drawing/LineCanvas.cs b/Terminal.Gui/Drawing/LineCanvas.cs
index b1e0ced13..2bda9e5dd 100644
--- a/Terminal.Gui/Drawing/LineCanvas.cs
+++ b/Terminal.Gui/Drawing/LineCanvas.cs
@@ -4,6 +4,13 @@ namespace Terminal.Gui;
/// Facilitates box drawing and line intersection detection and rendering. Does not support diagonal lines.
public class LineCanvas : IDisposable
{
+ ///
+ /// Optional which when present overrides the
+ /// (colors) of lines in the canvas. This can be used e.g. to apply a global
+ /// across all lines.
+ ///
+ public FillPair? Fill { get; set; }
+
private readonly List _lines = [];
private readonly Dictionary _runeResolvers = new ()
@@ -85,7 +92,7 @@ public class LineCanvas : IDisposable
viewport = Rectangle.Union (viewport, _lines [i].Viewport);
}
- if (viewport is {Width: 0} or {Height: 0})
+ if (viewport is { Width: 0 } or { Height: 0 })
{
viewport = viewport with
{
@@ -135,7 +142,7 @@ public class LineCanvas : IDisposable
)
{
_cachedViewport = Rectangle.Empty;
- _lines.Add (new StraightLine (start, length, orientation, style, attribute));
+ _lines.Add (new (start, length, orientation, style, attribute));
}
/// Adds a new line to the canvas
@@ -183,7 +190,7 @@ public class LineCanvas : IDisposable
if (cell is { })
{
- map.Add (new Point (x, y), cell);
+ map.Add (new (x, y), cell);
}
}
}
@@ -218,7 +225,7 @@ public class LineCanvas : IDisposable
if (rune is { })
{
- map.Add (new Point (x, y), rune.Value);
+ map.Add (new (x, y), rune.Value);
}
}
}
@@ -324,7 +331,10 @@ public class LineCanvas : IDisposable
///
private bool Exactly (HashSet intersects, params IntersectionType [] types) { return intersects.SetEquals (types); }
- private Attribute? GetAttributeForIntersects (IntersectionDefinition? [] intersects) { return intersects [0]!.Line.Attribute; }
+ private Attribute? GetAttributeForIntersects (IntersectionDefinition? [] intersects)
+ {
+ return Fill != null ? Fill.GetAttribute (intersects [0]!.Point) : intersects [0]!.Line.Attribute;
+ }
private Cell? GetCellForIntersects (ConsoleDriver driver, IntersectionDefinition? [] intersects)
{
@@ -428,12 +438,12 @@ public class LineCanvas : IDisposable
useThickDotted ? Glyphs.VLineHvDa4 : Glyphs.VLine;
default:
- throw new Exception (
- "Could not find resolver or switch case for "
- + nameof (runeType)
- + ":"
- + runeType
- );
+ throw new (
+ "Could not find resolver or switch case for "
+ + nameof (runeType)
+ + ":"
+ + runeType
+ );
}
}
@@ -843,4 +853,4 @@ public class LineCanvas : IDisposable
_normal = Glyphs.URCorner;
}
}
-}
\ No newline at end of file
+}
diff --git a/Terminal.Gui/Drawing/SolidFill.cs b/Terminal.Gui/Drawing/SolidFill.cs
new file mode 100644
index 000000000..2619f67ea
--- /dev/null
+++ b/Terminal.Gui/Drawing/SolidFill.cs
@@ -0,0 +1,24 @@
+namespace Terminal.Gui;
+
+///
+/// implementation that uses a solid color for all points
+///
+public class SolidFill : IFill
+{
+ private readonly Color _color;
+
+ ///
+ /// Creates a new instance of the class which will return
+ /// the provided regardless of which point is requested.
+ ///
+ ///
+ public SolidFill (Color color) { _color = color; }
+
+ ///
+ /// Returns the color this instance was constructed with regardless of
+ /// which is being colored.
+ ///
+ ///
+ ///
+ public Color GetColor (Point point) { return _color; }
+}
diff --git a/Terminal.Gui/Drawing/StraightLine.cs b/Terminal.Gui/Drawing/StraightLine.cs
index 9a2785f0f..2f36995df 100644
--- a/Terminal.Gui/Drawing/StraightLine.cs
+++ b/Terminal.Gui/Drawing/StraightLine.cs
@@ -45,6 +45,7 @@ public class StraightLine
/// Gets the rectangle that describes the bounds of the canvas. Location is the coordinates of the line that is
/// furthest left/top and Size is defined by the line that extends the furthest right/bottom.
///
+
// PERF: Probably better to store the rectangle rather than make a new one on every single access to Viewport.
internal Rectangle Viewport
{
@@ -111,26 +112,28 @@ public class StraightLine
return null;
}
+ var p = new Point (x, y);
+
if (StartsAt (x, y))
{
- return new IntersectionDefinition (
- Start,
- GetTypeByLength (
- IntersectionType.StartLeft,
- IntersectionType.PassOverHorizontal,
- IntersectionType.StartRight
- ),
- this
- );
+ return new (
+ p,
+ GetTypeByLength (
+ IntersectionType.StartLeft,
+ IntersectionType.PassOverHorizontal,
+ IntersectionType.StartRight
+ ),
+ this
+ );
}
if (EndsAt (x, y))
{
- return new IntersectionDefinition (
- Start,
- Length < 0 ? IntersectionType.StartRight : IntersectionType.StartLeft,
- this
- );
+ return new (
+ p,
+ Length < 0 ? IntersectionType.StartRight : IntersectionType.StartLeft,
+ this
+ );
}
int xmin = Math.Min (Start.X, Start.X + Length);
@@ -138,11 +141,11 @@ public class StraightLine
if (xmin < x && xmax > x)
{
- return new IntersectionDefinition (
- new Point (x, y),
- IntersectionType.PassOverHorizontal,
- this
- );
+ return new (
+ p,
+ IntersectionType.PassOverHorizontal,
+ this
+ );
}
return null;
@@ -155,26 +158,28 @@ public class StraightLine
return null;
}
+ var p = new Point (x, y);
+
if (StartsAt (x, y))
{
- return new IntersectionDefinition (
- Start,
- GetTypeByLength (
- IntersectionType.StartUp,
- IntersectionType.PassOverVertical,
- IntersectionType.StartDown
- ),
- this
- );
+ return new (
+ p,
+ GetTypeByLength (
+ IntersectionType.StartUp,
+ IntersectionType.PassOverVertical,
+ IntersectionType.StartDown
+ ),
+ this
+ );
}
if (EndsAt (x, y))
{
- return new IntersectionDefinition (
- Start,
- Length < 0 ? IntersectionType.StartDown : IntersectionType.StartUp,
- this
- );
+ return new (
+ p,
+ Length < 0 ? IntersectionType.StartDown : IntersectionType.StartUp,
+ this
+ );
}
int ymin = Math.Min (Start.Y, Start.Y + Length);
@@ -182,11 +187,11 @@ public class StraightLine
if (ymin < y && ymax > y)
{
- return new IntersectionDefinition (
- new Point (x, y),
- IntersectionType.PassOverVertical,
- this
- );
+ return new (
+ p,
+ IntersectionType.PassOverVertical,
+ this
+ );
}
return null;
diff --git a/Terminal.Gui/EnumExtensions/AddOrSubtractExtensions.cs b/Terminal.Gui/EnumExtensions/AddOrSubtractExtensions.cs
new file mode 100644
index 000000000..8fb98d81c
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/AddOrSubtractExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class AddOrSubtractExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this AddOrSubtract e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this AddOrSubtract e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this AddOrSubtract _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/AlignmentExtensions.cs b/Terminal.Gui/EnumExtensions/AlignmentExtensions.cs
new file mode 100644
index 000000000..3666d2de5
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/AlignmentExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class AlignmentExtensions
+{
+ ///
+ /// Directly converts this value to an value with the same
+ /// binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this Alignment e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the same
+ /// binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this Alignment e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this Alignment _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/AlignmentModesExtensions.cs b/Terminal.Gui/EnumExtensions/AlignmentModesExtensions.cs
new file mode 100644
index 000000000..3babe81b6
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/AlignmentModesExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class AlignmentModesExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this AlignmentModes e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this AlignmentModes e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified flags are set in the current value of this
+ /// .
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ ///
+ /// True, if all flags present in are also present in the current value of the
+ /// .
Otherwise false.
+ ///
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this AlignmentModes e, AlignmentModes checkFlags)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+ ref uint checkFlagsValueRef = ref Unsafe.As (ref checkFlags);
+
+ return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
+ }
+
+ ///
+ /// Determines if the specified mask bits are set in the current value of this
+ /// .
+ ///
+ /// The value to check against the value.
+ /// A mask to apply to the current value.
+ ///
+ /// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
+ /// .
Otherwise false.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this AlignmentModes e, int mask)
+ {
+ ref int enumCurrentValueRef = ref Unsafe.As (ref e);
+
+ return (enumCurrentValueRef & mask) == mask;
+ }
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this AlignmentModes _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 4 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/BorderSettingsExtensions.cs b/Terminal.Gui/EnumExtensions/BorderSettingsExtensions.cs
new file mode 100644
index 000000000..074a45976
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/BorderSettingsExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class BorderSettingsExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this BorderSettings e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this BorderSettings e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified flags are set in the current value of this
+ /// .
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ ///
+ /// True, if all flags present in are also present in the current value of the
+ /// .
Otherwise false.
+ ///
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this BorderSettings e, BorderSettings checkFlags)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+ ref uint checkFlagsValueRef = ref Unsafe.As (ref checkFlags);
+
+ return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
+ }
+
+ ///
+ /// Determines if the specified mask bits are set in the current value of this
+ /// .
+ ///
+ /// The value to check against the value.
+ /// A mask to apply to the current value.
+ ///
+ /// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
+ /// .
Otherwise false.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this BorderSettings e, int mask)
+ {
+ ref int enumCurrentValueRef = ref Unsafe.As (ref e);
+
+ return (enumCurrentValueRef & mask) == mask;
+ }
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this BorderSettings _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/DimAutoStyleExtensions.cs b/Terminal.Gui/EnumExtensions/DimAutoStyleExtensions.cs
new file mode 100644
index 000000000..6c0813df8
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/DimAutoStyleExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class DimAutoStyleExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this DimAutoStyle e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this DimAutoStyle e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified flags are set in the current value of this
+ /// .
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ ///
+ /// True, if all flags present in are also present in the current value of the
+ /// .
Otherwise false.
+ ///
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this DimAutoStyle e, DimAutoStyle checkFlags)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+ ref uint checkFlagsValueRef = ref Unsafe.As (ref checkFlags);
+
+ return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
+ }
+
+ ///
+ /// Determines if the specified mask bits are set in the current value of this
+ /// .
+ ///
+ /// The value to check against the value.
+ /// A mask to apply to the current value.
+ ///
+ /// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
+ /// .
Otherwise false.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this DimAutoStyle e, int mask)
+ {
+ ref int enumCurrentValueRef = ref Unsafe.As (ref e);
+
+ return (enumCurrentValueRef & mask) == mask;
+ }
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this DimAutoStyle _, int value)
+ {
+ return value switch
+ {
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/DimPercentModeExtensions.cs b/Terminal.Gui/EnumExtensions/DimPercentModeExtensions.cs
new file mode 100644
index 000000000..2fc943f17
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/DimPercentModeExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class DimPercentModeExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this DimPercentMode e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this DimPercentMode e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this DimPercentMode _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/DimensionExtensions.cs b/Terminal.Gui/EnumExtensions/DimensionExtensions.cs
new file mode 100644
index 000000000..ccbfbf5ed
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/DimensionExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+public static class DimensionExtensions
+{
+ ///
+ /// Directly converts this value to an value with the same
+ /// binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this Dimension e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the same
+ /// binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this Dimension e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this Dimension _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/KeyBindingScopeExtensions.cs b/Terminal.Gui/EnumExtensions/KeyBindingScopeExtensions.cs
new file mode 100644
index 000000000..6f42f4c82
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/KeyBindingScopeExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class KeyBindingScopeExtensions
+{
+ ///
+ /// Directly converts this value to an value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this KeyBindingScope e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the
+ /// same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this KeyBindingScope e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified flags are set in the current value of this
+ /// .
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ ///
+ /// True, if all flags present in are also present in the current value of the
+ /// .
Otherwise false.
+ ///
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this KeyBindingScope e, KeyBindingScope checkFlags)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+ ref uint checkFlagsValueRef = ref Unsafe.As (ref checkFlags);
+
+ return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
+ }
+
+ ///
+ /// Determines if the specified mask bits are set in the current value of this
+ /// .
+ ///
+ ///
+ /// The value to check against the
+ /// value.
+ ///
+ /// A mask to apply to the current value.
+ ///
+ /// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
+ /// .
Otherwise false.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this KeyBindingScope e, int mask)
+ {
+ ref int enumCurrentValueRef = ref Unsafe.As (ref e);
+
+ return (enumCurrentValueRef & mask) == mask;
+ }
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this KeyBindingScope _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 4 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/SideExtensions.cs b/Terminal.Gui/EnumExtensions/SideExtensions.cs
new file mode 100644
index 000000000..b50e12bdc
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/SideExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class SideExtensions
+{
+ ///
+ /// Directly converts this value to an value with the same binary
+ /// representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this Side e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with the same binary
+ /// representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this Side e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this Side _, int value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/EnumExtensions/ViewDiagnosticFlagsExtensions.cs b/Terminal.Gui/EnumExtensions/ViewDiagnosticFlagsExtensions.cs
new file mode 100644
index 000000000..1aa18fe72
--- /dev/null
+++ b/Terminal.Gui/EnumExtensions/ViewDiagnosticFlagsExtensions.cs
@@ -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;
+
+/// Extension methods for the type.
+[GeneratedCode ("Terminal.Gui.Analyzers.Internal", "1.0")]
+[CompilerGenerated]
+[DebuggerNonUserCode]
+[ExcludeFromCodeCoverage (Justification = "Generated code is already tested.")]
+[PublicAPI]
+public static class ViewDiagnosticFlagsExtensions
+{
+ ///
+ /// Directly converts this value to an value with
+ /// the same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static int AsInt32 (this ViewDiagnosticFlags e) => Unsafe.As (ref e);
+
+ ///
+ /// Directly converts this value to a value with
+ /// the same binary representation.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static uint AsUInt32 (this ViewDiagnosticFlags e) => Unsafe.As (ref e);
+
+ ///
+ /// Determines if the specified flags are set in the current value of this
+ /// .
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ ///
+ /// True, if all flags present in are also present in the current value of the
+ /// .
Otherwise false.
+ ///
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this ViewDiagnosticFlags e, ViewDiagnosticFlags checkFlags)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+ ref uint checkFlagsValueRef = ref Unsafe.As (ref checkFlags);
+
+ return (enumCurrentValueRef & checkFlagsValueRef) == checkFlagsValueRef;
+ }
+
+ ///
+ /// Determines if the specified mask bits are set in the current value of this
+ /// .
+ ///
+ ///
+ /// The value to check against the
+ /// value.
+ ///
+ /// A mask to apply to the current value.
+ ///
+ /// True, if all bits set to 1 in the mask are also set to 1 in the current value of the
+ /// .
Otherwise false.
+ ///
+ /// NO VALIDATION IS PERFORMED!
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static bool FastHasFlags (this ViewDiagnosticFlags e, uint mask)
+ {
+ ref uint enumCurrentValueRef = ref Unsafe.As (ref e);
+
+ return (enumCurrentValueRef & mask) == mask;
+ }
+
+ ///
+ /// Determines if the specified value is explicitly defined as a named value of the
+ /// type.
+ ///
+ ///
+ /// Only explicitly named values return true, as with IsDefined. Combined valid flag values of flags enums which are
+ /// not explicitly named will return false.
+ ///
+ public static bool FastIsDefined (this ViewDiagnosticFlags _, uint value)
+ {
+ return value switch
+ {
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 4 => true,
+ _ => false
+ };
+ }
+}
diff --git a/Terminal.Gui/FileServices/FileDialogStyle.cs b/Terminal.Gui/FileServices/FileDialogStyle.cs
index 83adb448c..9cc6557f1 100644
--- a/Terminal.Gui/FileServices/FileDialogStyle.cs
+++ b/Terminal.Gui/FileServices/FileDialogStyle.cs
@@ -1,4 +1,5 @@
-using System.Globalization;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
using System.IO.Abstractions;
using Terminal.Gui.Resources;
using static System.Environment;
@@ -143,6 +144,7 @@ public class FileDialogStyle
///
public string WrongFileTypeFeedback { get; set; } = Strings.fdWrongFileTypeFeedback;
+ [UnconditionalSuppressMessage ("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")]
private Dictionary DefaultTreeRootGetter ()
{
Dictionary roots = new ();
diff --git a/Terminal.Gui/Input/KeyBindingScope.cs b/Terminal.Gui/Input/KeyBindingScope.cs
index 3b6c53ebc..0c75299c7 100644
--- a/Terminal.Gui/Input/KeyBindingScope.cs
+++ b/Terminal.Gui/Input/KeyBindingScope.cs
@@ -1,4 +1,4 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
@@ -10,7 +10,7 @@ namespace Terminal.Gui;
/// Key bindings are scoped to the most-focused view () by default.
///
[Flags]
-[GenerateEnumExtensionMethods (FastHasFlags = true)]
+
public enum KeyBindingScope
{
/// The key binding is disabled.
diff --git a/Terminal.Gui/README.md b/Terminal.Gui/README.md
index fb380d4c0..5c22df0ac 100644
--- a/Terminal.Gui/README.md
+++ b/Terminal.Gui/README.md
@@ -6,9 +6,7 @@ All files required to build the **Terminal.Gui** library (and NuGet package).
- `\` - The root folder contains the source code for the library.
- `Terminal.Gui.sln` - The Visual Studio solution
- - `Application.cs` - A `static` class that provides the base 'application driver'. Given it defines a **Terminal.Gui** application it is both logically and literally (because `static`) a singleton. It has direct dependencies on `MainLoop`, `Events.cs` `NetDriver`, `CursesDriver`, `WindowsDriver`, `Responder`, `View`, and `TopLevel` (and nothing else).
- - `MainLoop.cs` - Defines `IMainLoopDriver` and implements the `MainLoop` class.
- - A few supporting class files
+ - `Application\` - The core `Application` logic, including `Application.cs`, which is is a `static` class that provides the base 'application engine', `RunState`, and `MainLoop`.
- `ConsoleDrivers\`
- `ConsoleDriver.cs` - Definition for the Console Driver API.
@@ -38,7 +36,7 @@ All files required to build the **Terminal.Gui** library (and NuGet package).
- `Dialog` -
- etc...
-- `Types/` - A folder (not namespace) containing implementations of `Point`, `Rect`, and `Size` which are ancient versions of the modern `System.Drawing.Point`, `System.Drawing.Size`, and `System.Drawning.Rectangle`.
+- `FileServcies/` - File services classes.
## Version numbers
diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index 1959d51d3..4feaf3ae5 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -1,4 +1,4 @@
-
+
@@ -19,16 +19,19 @@
- net8.0
+ net8.0
12
$(AssemblyName)
true
true
portable
- $(DefineConstants);JETBRAINS_ANNOTATIONS;CONTRACTS_FULL;CODE_ANALYSIS
+ $(DefineConstants);CONTRACTS_FULL;CODE_ANALYSIS
enable
true
true
+ false
+ true
+ true
true
@@ -49,21 +52,16 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
- all
- Analyzer
- false
-
+
+
+
+
@@ -73,6 +71,7 @@
+
diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs
index 39d98f635..2931cd9ad 100644
--- a/Terminal.Gui/View/Adornment/Border.cs
+++ b/Terminal.Gui/View/Adornment/Border.cs
@@ -78,7 +78,7 @@ public class Border : Adornment
if ((Parent?.Arrangement & ViewArrangement.Movable) != 0)
{
HighlightStyle |= HighlightStyle.Hover;
- }
+ }
#endif
base.BeginInit ();
@@ -149,31 +149,32 @@ public class Border : Adornment
}
}
- Rectangle GetBorderRectangle (Rectangle screenRect)
+ private Rectangle GetBorderRectangle (Rectangle screenRect)
{
return new (
- screenRect.X + Math.Max (0, Thickness.Left - 1),
- screenRect.Y + Math.Max (0, Thickness.Top - 1),
- Math.Max (
- 0,
- screenRect.Width
- - Math.Max (
- 0,
- Math.Max (0, Thickness.Left - 1)
- + Math.Max (0, Thickness.Right - 1)
- )
- ),
- Math.Max (
- 0,
- screenRect.Height
- - Math.Max (
- 0,
- Math.Max (0, Thickness.Top - 1)
- + Math.Max (0, Thickness.Bottom - 1)
- )
- )
- );
+ screenRect.X + Math.Max (0, Thickness.Left - 1),
+ screenRect.Y + Math.Max (0, Thickness.Top - 1),
+ Math.Max (
+ 0,
+ screenRect.Width
+ - Math.Max (
+ 0,
+ Math.Max (0, Thickness.Left - 1)
+ + Math.Max (0, Thickness.Right - 1)
+ )
+ ),
+ Math.Max (
+ 0,
+ screenRect.Height
+ - Math.Max (
+ 0,
+ Math.Max (0, Thickness.Top - 1)
+ + Math.Max (0, Thickness.Bottom - 1)
+ )
+ )
+ );
}
+
///
/// Sets the style of the border by changing the . This is a helper API for setting the
/// to (1,1,1,1) and setting the line style of the views that comprise the border. If
@@ -196,21 +197,22 @@ public class Border : Adornment
set => _lineStyle = value;
}
- private bool _showTitle = true;
+ private BorderSettings _settings = BorderSettings.Title;
///
- /// Gets or sets whether the title should be shown. The default is .
+ /// Gets or sets the settings for the border.
///
- public bool ShowTitle
+ public BorderSettings Settings
{
- get => _showTitle;
+ get => _settings;
set
{
- if (value == _showTitle)
+ if (value == _settings)
{
return;
}
- _showTitle = value;
+
+ _settings = value;
Parent?.SetNeedsDisplay ();
}
@@ -225,6 +227,7 @@ public class Border : Adornment
if (!Parent.Arrangement.HasFlag (ViewArrangement.Movable))
{
e.Cancel = true;
+
return;
}
@@ -235,9 +238,9 @@ public class Border : Adornment
_savedForeColor = ColorScheme.Normal.Foreground;
}
- ColorScheme cs = new ColorScheme (ColorScheme)
+ var cs = new ColorScheme (ColorScheme)
{
- Normal = new Attribute (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background)
+ Normal = new (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background)
};
ColorScheme = cs;
}
@@ -254,12 +257,13 @@ public class Border : Adornment
if (e.NewValue == HighlightStyle.None && _savedForeColor.HasValue)
{
- ColorScheme cs = new ColorScheme (ColorScheme)
+ var cs = new ColorScheme (ColorScheme)
{
- Normal = new Attribute (_savedForeColor.Value, ColorScheme.Normal.Background)
+ Normal = new (_savedForeColor.Value, ColorScheme.Normal.Background)
};
ColorScheme = cs;
}
+
Parent?.SetNeedsDisplay ();
e.Cancel = true;
}
@@ -267,7 +271,7 @@ public class Border : Adornment
private Point? _dragPosition;
private Point _startGrabPoint;
- ///
+ ///
protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
{
if (base.OnMouseEvent (mouseEvent))
@@ -322,16 +326,17 @@ public class Border : Adornment
_dragPosition = mouseEvent.Position;
- Point parentLoc = Parent.SuperView?.ScreenToViewport (new (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y)) ?? mouseEvent.ScreenPosition;
+ Point parentLoc = Parent.SuperView?.ScreenToViewport (new (mouseEvent.ScreenPosition.X, mouseEvent.ScreenPosition.Y))
+ ?? mouseEvent.ScreenPosition;
GetLocationEnsuringFullVisibility (
- Parent,
- parentLoc.X - _startGrabPoint.X,
- parentLoc.Y - _startGrabPoint.Y,
- out int nx,
- out int ny,
- out _
- );
+ Parent,
+ parentLoc.X - _startGrabPoint.X,
+ parentLoc.Y - _startGrabPoint.Y,
+ out int nx,
+ out int ny,
+ out _
+ );
Parent.X = nx;
Parent.Y = ny;
@@ -352,7 +357,6 @@ public class Border : Adornment
return false;
}
-
///
protected override void Dispose (bool disposing)
{
@@ -403,7 +407,7 @@ public class Border : Adornment
// ...thickness extends outward (border/title is always as far in as possible)
// PERF: How about a call to Rectangle.Offset?
- var borderBounds = GetBorderRectangle (screenBounds);
+ Rectangle borderBounds = GetBorderRectangle (screenBounds);
int topTitleLineY = borderBounds.Y;
int titleY = borderBounds.Y;
var titleBarsLength = 0; // the little vertical thingies
@@ -421,7 +425,7 @@ public class Border : Adornment
int sideLineLength = borderBounds.Height;
bool canDrawBorder = borderBounds is { Width: > 0, Height: > 0 };
- if (ShowTitle)
+ if (Settings.FastHasFlags (BorderSettings.Title))
{
if (Thickness.Top == 2)
{
@@ -453,9 +457,10 @@ public class Border : Adornment
}
}
- if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && ShowTitle && !string.IsNullOrEmpty (Parent?.Title))
+ if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title) && !string.IsNullOrEmpty (Parent?.Title))
{
- var focus = Parent.GetNormalColor ();
+ Attribute focus = Parent.GetNormalColor ();
+
if (Parent.SuperView is { } && Parent.SuperView?.Subviews!.Count (s => s.CanFocus) > 1)
{
// Only use focus color if there are multiple focusable views
@@ -492,7 +497,7 @@ public class Border : Adornment
{
// ╔╡Title╞═════╗
// ╔╡╞═════╗
- if (borderBounds.Width < 4 || !ShowTitle || string.IsNullOrEmpty (Parent?.Title))
+ if (borderBounds.Width < 4 || !Settings.FastHasFlags (BorderSettings.Title) || string.IsNullOrEmpty (Parent?.Title))
{
// ╔╡╞╗ should be ╔══╗
lc.AddLine (
@@ -631,7 +636,7 @@ public class Border : Adornment
Driver.SetAttribute (prevAttr);
// TODO: This should be moved to LineCanvas as a new BorderStyle.Ruler
- if (View.Diagnostics.HasFlag (ViewDiagnosticFlags.Ruler))
+ if (Diagnostics.HasFlag (ViewDiagnosticFlags.Ruler))
{
// Top
var hruler = new Ruler { Length = screenBounds.Width, Orientation = Orientation.Horizontal };
@@ -642,7 +647,7 @@ public class Border : Adornment
}
// Redraw title
- if (drawTop && maxTitleWidth > 0 && ShowTitle)
+ if (drawTop && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title))
{
Parent.TitleTextFormatter.Draw (
new (borderBounds.X + 2, titleY, maxTitleWidth, 1),
@@ -670,6 +675,45 @@ public class Border : Adornment
vruler.Draw (new (screenBounds.X + screenBounds.Width - 1, screenBounds.Y + 1), 1);
}
}
+
+ // TODO: This should not be done on each draw?
+ if (Settings.FastHasFlags (BorderSettings.Gradient))
+ {
+ SetupGradientLineCanvas (lc, screenBounds);
+ }
+ else
+ {
+ lc.Fill = null;
+ }
}
}
+
+ private void SetupGradientLineCanvas (LineCanvas lc, Rectangle rect)
+ {
+ GetAppealingGradientColors (out List stops, out List steps);
+
+ var g = new Gradient (stops, steps);
+
+ var fore = new GradientFill (rect, g, GradientDirection.Diagonal);
+ var back = new SolidFill (GetNormalColor ().Background);
+
+ lc.Fill = new (fore, back);
+ }
+
+ private static void GetAppealingGradientColors (out List stops, out List steps)
+ {
+ // Define the colors of the gradient stops with more appealing colors
+ stops = new()
+ {
+ new (0, 128, 255), // Bright Blue
+ new (0, 255, 128), // Bright Green
+ new (255, 255), // Bright Yellow
+ new (255, 128), // Bright Orange
+ new (255, 0, 128) // Bright Pink
+ };
+
+ // Define the number of steps between each color for smoother transitions
+ // If we pass only a single value then it will assume equal steps between all pairs
+ steps = new() { 15 };
+ }
}
diff --git a/Terminal.Gui/View/Adornment/BorderSettings.cs b/Terminal.Gui/View/Adornment/BorderSettings.cs
new file mode 100644
index 000000000..7b4846d34
--- /dev/null
+++ b/Terminal.Gui/View/Adornment/BorderSettings.cs
@@ -0,0 +1,26 @@
+
+
+namespace Terminal.Gui;
+
+///
+/// Determines the settings for .
+///
+[Flags]
+
+public enum BorderSettings
+{
+ ///
+ /// No settings.
+ ///
+ None = 0,
+
+ ///
+ /// Show the title.
+ ///
+ Title = 1,
+
+ ///
+ /// Use to draw the border.
+ ///
+ Gradient = 2,
+}
diff --git a/Terminal.Gui/View/Adornment/Margin.cs b/Terminal.Gui/View/Adornment/Margin.cs
index 2e1ea5760..046965e32 100644
--- a/Terminal.Gui/View/Adornment/Margin.cs
+++ b/Terminal.Gui/View/Adornment/Margin.cs
@@ -223,7 +223,7 @@ public class Margin : Adornment
if (ShadowStyle != ShadowStyle.None && _rightShadow is { } && _bottomShadow is { })
{
_rightShadow.Y = Parent.Border.Thickness.Top > 0
- ? Parent.Border.Thickness.Top - (Parent.Border.Thickness.Top > 2 && Parent.Border.ShowTitle ? 1 : 0)
+ ? Parent.Border.Thickness.Top - (Parent.Border.Thickness.Top > 2 && Parent.Border.Settings.FastHasFlags (BorderSettings.Title) ? 1 : 0)
: 1;
_bottomShadow.X = Parent.Border.Thickness.Left > 0 ? Parent.Border.Thickness.Left : 1;
}
diff --git a/Terminal.Gui/View/Layout/AddOrSubtract.cs b/Terminal.Gui/View/Layout/AddOrSubtract.cs
index e03cfbcfd..83d1dd12c 100644
--- a/Terminal.Gui/View/Layout/AddOrSubtract.cs
+++ b/Terminal.Gui/View/Layout/AddOrSubtract.cs
@@ -1,11 +1,8 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
-
-namespace Terminal.Gui;
+namespace Terminal.Gui;
///
/// Describes whether an operation should add or subtract values.
///
-[GenerateEnumExtensionMethods]
public enum AddOrSubtract
{
///
diff --git a/Terminal.Gui/View/Layout/DimAutoStyle.cs b/Terminal.Gui/View/Layout/DimAutoStyle.cs
index f350e8045..ee712f0fb 100644
--- a/Terminal.Gui/View/Layout/DimAutoStyle.cs
+++ b/Terminal.Gui/View/Layout/DimAutoStyle.cs
@@ -1,4 +1,4 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
@@ -6,7 +6,7 @@ namespace Terminal.Gui;
/// Specifies how will compute the dimension.
///
[Flags]
-[GenerateEnumExtensionMethods (FastHasFlags = true)]
+
public enum DimAutoStyle
{
///
diff --git a/Terminal.Gui/View/Layout/DimPercentMode.cs b/Terminal.Gui/View/Layout/DimPercentMode.cs
index 60a7da056..10077848b 100644
--- a/Terminal.Gui/View/Layout/DimPercentMode.cs
+++ b/Terminal.Gui/View/Layout/DimPercentMode.cs
@@ -1,12 +1,10 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
///
/// Indicates the mode for a object.
///
-[GenerateEnumExtensionMethods]
-
public enum DimPercentMode
{
///
diff --git a/Terminal.Gui/View/Layout/Dimension.cs b/Terminal.Gui/View/Layout/Dimension.cs
index cc56ffd4b..8cfb3f7f0 100644
--- a/Terminal.Gui/View/Layout/Dimension.cs
+++ b/Terminal.Gui/View/Layout/Dimension.cs
@@ -1,12 +1,10 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
///
/// Indicates the dimension for operations.
///
-
-[GenerateEnumExtensionMethods]
public enum Dimension
{
///
diff --git a/Terminal.Gui/View/Layout/Side.cs b/Terminal.Gui/View/Layout/Side.cs
index 6708904da..afdc5640e 100644
--- a/Terminal.Gui/View/Layout/Side.cs
+++ b/Terminal.Gui/View/Layout/Side.cs
@@ -1,4 +1,4 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
@@ -6,7 +6,6 @@ namespace Terminal.Gui;
/// Indicates the side for operations.
///
///
-[GenerateEnumExtensionMethods]
public enum Side
{
///
diff --git a/Terminal.Gui/View/ViewDiagnostics.cs b/Terminal.Gui/View/ViewDiagnostics.cs
index 20899cfd0..c7ac7b851 100644
--- a/Terminal.Gui/View/ViewDiagnostics.cs
+++ b/Terminal.Gui/View/ViewDiagnostics.cs
@@ -1,11 +1,10 @@
-using Terminal.Gui.Analyzers.Internal.Attributes;
+
namespace Terminal.Gui;
/// Enables diagnostic functions for .
[Flags]
-[GenerateEnumExtensionMethods(FastHasFlags = true)]
public enum ViewDiagnosticFlags : uint
{
/// All diagnostics off
diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs
index f6acd3338..81d70ba9f 100644
--- a/Terminal.Gui/Views/Button.cs
+++ b/Terminal.Gui/Views/Button.cs
@@ -39,7 +39,7 @@ public class Button : View, IDesignable
/// Gets or sets whether s are shown with a shadow effect by default.
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
diff --git a/Terminal.Gui/Views/Dialog.cs b/Terminal.Gui/Views/Dialog.cs
index 7e6d82ffd..bcdca4fa8 100644
--- a/Terminal.Gui/Views/Dialog.cs
+++ b/Terminal.Gui/Views/Dialog.cs
@@ -19,13 +19,13 @@ public class Dialog : Window
/// The default for .
/// This property can be set in a Theme.
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public static Alignment DefaultButtonAlignment { get; set; } = Alignment.End;
/// The default for .
/// This property can be set in a Theme.
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public static AlignmentModes DefaultButtonAlignmentModes { get; set; } = AlignmentModes.StartToEnd | AlignmentModes.AddSpaceBetweenItems;
///
@@ -47,7 +47,7 @@ public class Dialog : Window
/// Gets or sets whether all s are shown with a shadow effect by default.
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public new static ShadowStyle DefaultShadow { get; set; } = ShadowStyle.None;
///
@@ -56,7 +56,7 @@ public class Dialog : Window
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public new static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
private readonly List
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
///
diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs
index 802631d52..7ddbe7c5a 100644
--- a/Terminal.Gui/Views/Shortcut.cs
+++ b/Terminal.Gui/Views/Shortcut.cs
@@ -104,7 +104,7 @@ public class Shortcut : View
void OnInitialized (object sender, EventArgs e)
{
SuperViewRendersLineCanvas = true;
- Border.ShowTitle = false;
+ Border.Settings &= ~BorderSettings.Title;
ShowHide ();
diff --git a/Terminal.Gui/Views/Window.cs b/Terminal.Gui/Views/Window.cs
index 1b1cea2fc..1a4caa266 100644
--- a/Terminal.Gui/Views/Window.cs
+++ b/Terminal.Gui/Views/Window.cs
@@ -73,6 +73,6 @@ public class Window : Toplevel
/// s.
///
[SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
- [JsonConverter (typeof (JsonStringEnumConverter))]
+ [JsonConverter (typeof (JsonStringEnumConverter))]
public static LineStyle DefaultBorderStyle { get; set; } = LineStyle.Single;
}
diff --git a/Terminal.sln b/Terminal.sln
index a63762780..550bbe4ed 100644
--- a/Terminal.sln
+++ b/Terminal.sln
@@ -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}"
@@ -51,6 +43,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{C7A51224-5
README.md = README.md
EndProjectSection
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SelfContained", "SelfContained\SelfContained.csproj", "{524DEA78-7E7C-474D-B42D-52ED4C04FF14}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -61,14 +55,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,22 +71,19 @@ 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
{58FDCA8F-08F7-4D80-9DA3-6A9AED01E163}.Release|Any CPU.Build.0 = Release|Any CPU
+ {524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {524DEA78-7E7C-474D-B42D-52ED4C04FF14}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
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}
diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs
index c5a724ba7..f9ecf029a 100644
--- a/UICatalog/Scenario.cs
+++ b/UICatalog/Scenario.cs
@@ -93,6 +93,10 @@ public class Scenario : IDisposable
///
public string GetName () { return ScenarioMetadata.GetName (GetType ()); }
+ /// Helper to get the and the Name (defined in )
+ ///
+ public string GetQuitKeyAndName () { return $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"; }
+
///
/// Returns a list of all instanaces defined in the project, sorted by
/// .
@@ -132,90 +136,12 @@ public class Scenario : IDisposable
///
public virtual void Main ()
{
- Init ();
- Setup ();
- Run ();
}
- ///
- /// Helper that calls and creates the default
- /// implementation with a frame and label
- /// showing the name of the and logic to exit back to the Scenario picker UI. Override
- /// to provide any behavior needed.
- ///
- ///
- ///
- /// The base implementation calls and creates a for
- /// and adds it to .
- ///
- ///
- /// Overrides that do not call the base., must call before
- /// creating any views or calling other Terminal.Gui APIs.
- ///
- ///
- [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
- public virtual void Init ()
- {
- Application.Init ();
-
- ConfigurationManager.Themes.Theme = Theme;
- ConfigurationManager.Apply ();
-
- Top = new ();
-
- Win = new ()
- {
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
- X = 0,
- Y = 0,
- Width = Dim.Fill (),
- Height = Dim.Fill (),
- ColorScheme = Colors.ColorSchemes [TopLevelColorScheme]
- };
- Top.Add (Win);
- }
-
- ///
- /// Runs the . Override to start the using a
- /// different than `Top`.
- ///
- ///
- /// Overrides that do not call the base., must call before
- /// returning.
- ///
- [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
- public virtual void Run ()
- {
- // Must explicitly call Application.Shutdown method to shutdown.
- Application.Run (Top);
- Top.Dispose ();
- Application.Shutdown ();
- }
-
- /// Override this to implement the setup logic (create controls, etc...).
- /// This is typically the best place to put scenario logic code.
- [ObsoleteAttribute ("This method is obsolete and will be removed in v2. Use Main instead.", false)]
- public virtual void Setup () { }
-
- ///
- /// The Toplevel for the . This should be set to .
- ///
-
- //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)]
- public Toplevel Top { get; set; }
-
/// Gets the Scenario Name + Description with the Description padded based on the longest known Scenario name.
///
public override string ToString () { return $"{GetName ().PadRight (_maxScenarioNameLen)}{GetDescription ()}"; }
- ///
- /// The Window for the . This should be set to in
- /// most cases.
- ///
-
- //[ObsoleteAttribute ("This property is obsolete and will be removed in v2. Use Main instead.", false)]
- public Window Win { get; set; }
-
#region IDispose
public void Dispose ()
@@ -231,8 +157,6 @@ public class Scenario : IDisposable
{
if (disposing)
{
- Top?.Dispose ();
- Win?.Dispose ();
}
_disposedValue = true;
diff --git a/UICatalog/Scenarios/ASCIICustomButton.cs b/UICatalog/Scenarios/ASCIICustomButton.cs
index 59e8924f0..8d25f9470 100644
--- a/UICatalog/Scenarios/ASCIICustomButton.cs
+++ b/UICatalog/Scenarios/ASCIICustomButton.cs
@@ -149,7 +149,7 @@ public class ASCIICustomButtonTest : Scenario
public ScrollViewTestWindow ()
{
- Title = "ScrollViewTestWindow";
+ Title = $"{Application.QuitKey} to Quit - Scenario: ScrollViewTestWindow";
Label titleLabel = null;
diff --git a/UICatalog/Scenarios/Adornments.cs b/UICatalog/Scenarios/Adornments.cs
index 8e19ecaaa..43d12a9a9 100644
--- a/UICatalog/Scenarios/Adornments.cs
+++ b/UICatalog/Scenarios/Adornments.cs
@@ -13,7 +13,7 @@ public class Adornments : Scenario
Window app = new ()
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+ Title = GetQuitKeyAndName ()
};
var editor = new AdornmentsEditor
diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs
index 5e0b8d45d..cc440b820 100644
--- a/UICatalog/Scenarios/AllViewsTester.cs
+++ b/UICatalog/Scenarios/AllViewsTester.cs
@@ -53,7 +53,7 @@ public class AllViewsTester : Scenario
var app = new Window
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+ Title = GetQuitKeyAndName (),
ColorScheme = Colors.ColorSchemes ["TopLevel"]
};
diff --git a/UICatalog/Scenarios/Animation.cs b/UICatalog/Scenarios/AnimationScenario.cs
similarity index 98%
rename from UICatalog/Scenarios/Animation.cs
rename to UICatalog/Scenarios/AnimationScenario.cs
index 42ad540c1..08add3f0a 100644
--- a/UICatalog/Scenarios/Animation.cs
+++ b/UICatalog/Scenarios/AnimationScenario.cs
@@ -13,7 +13,7 @@ namespace UICatalog.Scenarios;
[ScenarioMetadata ("Animation", "Demonstration of how to render animated images with threading.")]
[ScenarioCategory ("Threading")]
[ScenarioCategory ("Drawing")]
-public class Animation : Scenario
+public class AnimationScenario : Scenario
{
private bool _isDisposed;
@@ -23,7 +23,7 @@ public class Animation : Scenario
var win = new Window
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+ Title = GetQuitKeyAndName (),
X = 0,
Y = 0,
Width = Dim.Fill (),
diff --git a/UICatalog/Scenarios/Bars.cs b/UICatalog/Scenarios/Bars.cs
index 995e55ceb..c2027d8ec 100644
--- a/UICatalog/Scenarios/Bars.cs
+++ b/UICatalog/Scenarios/Bars.cs
@@ -28,7 +28,7 @@ public class Bars : Scenario
// QuitKey and it only sticks if changed after init
private void App_Loaded (object sender, EventArgs e)
{
- Application.Top.Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}";
+ Application.Top.Title = GetQuitKeyAndName ();
ObservableCollection eventSource = new ();
ListView eventLog = new ListView ()
diff --git a/UICatalog/Scenarios/BasicColors.cs b/UICatalog/Scenarios/BasicColors.cs
index b45cbec3c..0fc284621 100644
--- a/UICatalog/Scenarios/BasicColors.cs
+++ b/UICatalog/Scenarios/BasicColors.cs
@@ -14,7 +14,7 @@ public class BasicColors : Scenario
Window app = new ()
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+ Title = GetQuitKeyAndName (),
};
var vx = 30;
diff --git a/UICatalog/Scenarios/BorderEditor.cs b/UICatalog/Scenarios/BorderEditor.cs
index a5ccae212..5e0a6e77a 100644
--- a/UICatalog/Scenarios/BorderEditor.cs
+++ b/UICatalog/Scenarios/BorderEditor.cs
@@ -9,29 +9,30 @@ public class BorderEditor : AdornmentEditor
{
private CheckBox _ckbTitle;
private RadioGroup _rbBorderStyle;
+ private CheckBox _ckbGradient;
public BorderEditor ()
{
Title = "_Border";
Initialized += BorderEditor_Initialized;
AdornmentChanged += BorderEditor_AdornmentChanged;
-
}
private void BorderEditor_AdornmentChanged (object sender, EventArgs e)
{
- _ckbTitle.State = ((Border)AdornmentToEdit).ShowTitle ? CheckState.Checked : CheckState.UnChecked;
+ _ckbTitle.State = ((Border)AdornmentToEdit).Settings.FastHasFlags (BorderSettings.Title) ? CheckState.Checked : CheckState.UnChecked;
_rbBorderStyle.SelectedItem = (int)((Border)AdornmentToEdit).LineStyle;
+ _ckbGradient.State = ((Border)AdornmentToEdit).Settings.FastHasFlags (BorderSettings.Gradient) ? CheckState.Checked : CheckState.UnChecked;
}
private void BorderEditor_Initialized (object sender, EventArgs e)
{
-
List borderStyleEnum = Enum.GetValues (typeof (LineStyle)).Cast ().ToList ();
- _rbBorderStyle = new RadioGroup
+ _rbBorderStyle = new()
{
X = 0,
+
// BUGBUG: Hack until dimauto is working properly
Y = Pos.Bottom (Subviews [^1]),
Width = Dim.Width (Subviews [^2]) + Dim.Width (Subviews [^1]) - 1,
@@ -46,21 +47,34 @@ public class BorderEditor : AdornmentEditor
_rbBorderStyle.SelectedItemChanged += OnRbBorderStyleOnSelectedItemChanged;
- _ckbTitle = new CheckBox
+ _ckbTitle = new()
{
X = 0,
Y = Pos.Bottom (_rbBorderStyle),
State = CheckState.Checked,
SuperViewRendersLineCanvas = true,
- Text = "Show Title",
+ Text = "Title",
Enabled = AdornmentToEdit is { }
};
-
_ckbTitle.Toggle += OnCkbTitleOnToggle;
Add (_ckbTitle);
+ _ckbGradient = new ()
+ {
+ X = 0,
+ Y = Pos.Bottom (_ckbTitle),
+
+ State = CheckState.Checked,
+ SuperViewRendersLineCanvas = true,
+ Text = "Gradient",
+ Enabled = AdornmentToEdit is { }
+ };
+
+ _ckbGradient.Toggle += OnCkbGradientOnToggle;
+ Add (_ckbGradient);
+
return;
void OnRbBorderStyleOnSelectedItemChanged (object s, SelectedItemChangedArgs e)
@@ -81,6 +95,32 @@ public class BorderEditor : AdornmentEditor
LayoutSubviews ();
}
- void OnCkbTitleOnToggle (object sender, CancelEventArgs args) { ((Border)AdornmentToEdit).ShowTitle = args.NewValue == CheckState.Checked; }
+ void OnCkbTitleOnToggle (object sender, CancelEventArgs args)
+ {
+ if (args.NewValue == CheckState.Checked)
+
+ {
+ ((Border)AdornmentToEdit).Settings |= BorderSettings.Title;
+ }
+ else
+
+ {
+ ((Border)AdornmentToEdit).Settings &= ~BorderSettings.Title;
+ }
+ }
+
+ void OnCkbGradientOnToggle (object sender, CancelEventArgs args)
+ {
+ if (args.NewValue == CheckState.Checked)
+
+ {
+ ((Border)AdornmentToEdit).Settings |= BorderSettings.Gradient;
+ }
+ else
+
+ {
+ ((Border)AdornmentToEdit).Settings &= ~BorderSettings.Gradient;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs
index d719c9a45..aab815a96 100644
--- a/UICatalog/Scenarios/Buttons.cs
+++ b/UICatalog/Scenarios/Buttons.cs
@@ -18,7 +18,7 @@ public class Buttons : Scenario
Window main = new ()
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+ Title = GetQuitKeyAndName ()
};
// Add a label & text field so we can demo IsDefault
diff --git a/UICatalog/Scenarios/ChineseUI.cs b/UICatalog/Scenarios/ChineseUI.cs
index 96c2ea56e..059b6143c 100644
--- a/UICatalog/Scenarios/ChineseUI.cs
+++ b/UICatalog/Scenarios/ChineseUI.cs
@@ -12,7 +12,7 @@ public class ChineseUI : Scenario
var win = new Window
{
- Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
+ Title = GetQuitKeyAndName (),
X = 0,
Y = 0,
Width = Dim.Fill (),
diff --git a/UICatalog/Scenarios/ClassExplorer.cs b/UICatalog/Scenarios/ClassExplorer.cs
index 7cc3537f2..204ef01b5 100644
--- a/UICatalog/Scenarios/ClassExplorer.cs
+++ b/UICatalog/Scenarios/ClassExplorer.cs
@@ -17,11 +17,15 @@ public class ClassExplorer : Scenario
private TextView _textView;
private TreeView
\ No newline at end of file
diff --git a/UnitTests/Drawing/FillPairTests.cs b/UnitTests/Drawing/FillPairTests.cs
new file mode 100644
index 000000000..cfe8d192d
--- /dev/null
+++ b/UnitTests/Drawing/FillPairTests.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Terminal.Gui.DrawingTests;
+
+public class FillPairTests
+{
+ [Fact]
+ public void GetAttribute_ReturnsCorrectColors ()
+ {
+ // Arrange
+ var foregroundColor = new Color (100, 150, 200);
+ var backgroundColor = new Color (50, 75, 100);
+ var foregroundFill = new SolidFill (foregroundColor);
+ var backgroundFill = new SolidFill (backgroundColor);
+
+ var fillPair = new FillPair (foregroundFill, backgroundFill);
+
+ // Act
+ Attribute resultAttribute = fillPair.GetAttribute (new (0, 0));
+
+ // Assert
+ Assert.Equal (foregroundColor, resultAttribute.Foreground);
+ Assert.Equal (backgroundColor, resultAttribute.Background);
+ }
+}
diff --git a/UnitTests/Drawing/GradientFillTests.cs b/UnitTests/Drawing/GradientFillTests.cs
new file mode 100644
index 000000000..75bc65bbc
--- /dev/null
+++ b/UnitTests/Drawing/GradientFillTests.cs
@@ -0,0 +1,118 @@
+namespace Terminal.Gui.DrawingTests;
+
+public class GradientFillTests
+{
+ private readonly Gradient _gradient;
+
+ public GradientFillTests ()
+ {
+ // Define the colors of the gradient stops
+ List stops = new List
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ // Define the number of steps between each color
+ List steps = new() { 10 }; // 10 steps between Red -> Blue
+
+ _gradient = new (stops, steps);
+ }
+
+ [Fact]
+ public void TestGradientFillCorners_AtOrigin ()
+ {
+ var area = new Rectangle (0, 0, 10, 10);
+ var gradientFill = new GradientFill (area, _gradient, GradientDirection.Diagonal);
+
+ // Test the corners
+ var topLeft = new Point (0, 0);
+ var topRight = new Point (area.Width - 1, 0);
+ var bottomLeft = new Point (0, area.Height - 1);
+ var bottomRight = new Point (area.Width - 1, area.Height - 1);
+
+ Color topLeftColor = gradientFill.GetColor (topLeft);
+ Color topRightColor = gradientFill.GetColor (topRight);
+ Color bottomLeftColor = gradientFill.GetColor (bottomLeft);
+ Color bottomRightColor = gradientFill.GetColor (bottomRight);
+
+ // Expected colors
+ var expectedTopLeftColor = new Color (255, 0); // Red
+ var expectedBottomRightColor = new Color (0, 0, 255); // Blue
+
+ Assert.Equal (expectedTopLeftColor, topLeftColor);
+ Assert.Equal (expectedBottomRightColor, bottomRightColor);
+ }
+
+ [Fact]
+ public void TestGradientFillCorners_NotAtOrigin ()
+ {
+ var area = new Rectangle (5, 5, 10, 10);
+ var gradientFill = new GradientFill (area, _gradient, GradientDirection.Diagonal);
+
+ // Test the corners
+ var topLeft = new Point (5, 5);
+ var topRight = new Point (area.Right - 1, 5);
+ var bottomLeft = new Point (5, area.Bottom - 1);
+ var bottomRight = new Point (area.Right - 1, area.Bottom - 1);
+
+ Color topLeftColor = gradientFill.GetColor (topLeft);
+ Color topRightColor = gradientFill.GetColor (topRight);
+ Color bottomLeftColor = gradientFill.GetColor (bottomLeft);
+ Color bottomRightColor = gradientFill.GetColor (bottomRight);
+
+ // Expected colors
+ var expectedTopLeftColor = new Color (255, 0); // Red
+ var expectedBottomRightColor = new Color (0, 0, 255); // Blue
+
+ Assert.Equal (expectedTopLeftColor, topLeftColor);
+ Assert.Equal (expectedBottomRightColor, bottomRightColor);
+ }
+
+ [Fact]
+ public void TestGradientFillColorTransition ()
+ {
+ var area = new Rectangle (0, 0, 10, 10);
+ var gradientFill = new GradientFill (area, _gradient, GradientDirection.Diagonal);
+
+ for (var row = 0; row < area.Height; row++)
+ {
+ var previousRed = 255;
+ var previousBlue = 0;
+
+ for (var col = 0; col < area.Width; col++)
+ {
+ var point = new Point (col, row);
+ Color color = gradientFill.GetColor (point);
+
+ // Check if the current color is 'more blue' and 'less red' as it goes right and down
+ Assert.True (color.R <= previousRed, $"Failed at ({col}, {row}): {color.R} > {previousRed}");
+ Assert.True (color.B >= previousBlue, $"Failed at ({col}, {row}): {color.B} < {previousBlue}");
+
+ // Update the previous color values for the next iteration
+ previousRed = color.R;
+ previousBlue = color.B;
+ }
+ }
+
+ for (var col = 0; col < area.Width; col++)
+ {
+ var previousRed = 255;
+ var previousBlue = 0;
+
+ for (var row = 0; row < area.Height; row++)
+ {
+ var point = new Point (col, row);
+ Color color = gradientFill.GetColor (point);
+
+ // Check if the current color is 'more blue' and 'less red' as it goes right and down
+ Assert.True (color.R <= previousRed, $"Failed at ({col}, {row}): {color.R} > {previousRed}");
+ Assert.True (color.B >= previousBlue, $"Failed at ({col}, {row}): {color.B} < {previousBlue}");
+
+ // Update the previous color values for the next iteration
+ previousRed = color.R;
+ previousBlue = color.B;
+ }
+ }
+ }
+}
diff --git a/UnitTests/Drawing/GradientTests.cs b/UnitTests/Drawing/GradientTests.cs
new file mode 100644
index 000000000..0174a7ff9
--- /dev/null
+++ b/UnitTests/Drawing/GradientTests.cs
@@ -0,0 +1,173 @@
+namespace Terminal.Gui.DrawingTests;
+
+public class GradientTests
+{
+ // Static method to provide all enum values
+ public static IEnumerable GradientDirectionValues ()
+ {
+ return typeof (GradientDirection).GetEnumValues ()
+ .Cast ()
+ .Select (direction => new object [] { direction });
+ }
+
+ [Theory]
+ [MemberData (nameof (GradientDirectionValues))]
+ public void GradientIsInclusive_2_by_2 (GradientDirection direction)
+ {
+ // Define the colors of the gradient stops
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ // Define the number of steps between each color
+ List steps = new() { 10 }; // 10 steps between Red -> Blue
+
+ var g = new Gradient (stops, steps);
+ Assert.Equal (4, g.BuildCoordinateColorMapping (1, 1, direction).Count);
+ }
+
+ [Theory]
+ [MemberData (nameof (GradientDirectionValues))]
+ public void GradientIsInclusive_1_by_1 (GradientDirection direction)
+ {
+ // Define the colors of the gradient stops
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ // Define the number of steps between each color
+ List steps = new() { 10 }; // 10 steps between Red -> Blue
+
+ var g = new Gradient (stops, steps);
+
+ // Note that maxRow and maxCol are inclusive so this results in 1x1 area i.e. a single cell.
+ KeyValuePair c = Assert.Single (g.BuildCoordinateColorMapping (0, 0, direction));
+ Assert.Equal (c.Key, new (0, 0));
+ Assert.Equal (c.Value, new (0, 0, 255));
+ }
+
+ [Fact]
+ public void SingleColorStop ()
+ {
+ List stops = new() { new (255, 0) }; // Red
+ List steps = new ();
+
+ var g = new Gradient (stops, steps);
+ Assert.All (g.Spectrum, color => Assert.Equal (new (255, 0), color));
+ }
+
+ [Fact]
+ public void LoopingGradient_CorrectColors ()
+ {
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ List steps = new() { 10 };
+
+ var g = new Gradient (stops, steps, true);
+ Assert.Equal (new (255, 0), g.Spectrum.First ());
+ Assert.Equal (new (255, 0), g.Spectrum.Last ());
+ }
+
+ [Fact]
+ public void DifferentStepSizes ()
+ {
+ List stops = new List
+ {
+ new (255, 0), // Red
+ new (0, 255), // Green
+ new (0, 0, 255) // Blue
+ };
+
+ List steps = new() { 5, 15 }; // Different steps
+
+ var g = new Gradient (stops, steps);
+ Assert.Equal (22, g.Spectrum.Count);
+ }
+
+ [Fact]
+ public void FractionOutOfRange_ThrowsException ()
+ {
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ List steps = new() { 10 };
+
+ var g = new Gradient (stops, steps);
+
+ Assert.Throws (() => g.GetColorAtFraction (-0.1));
+ Assert.Throws (() => g.GetColorAtFraction (1.1));
+ }
+
+ [Fact]
+ public void NaNFraction_ReturnsLastColor ()
+ {
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ List steps = new() { 10 };
+
+ var g = new Gradient (stops, steps);
+ Assert.Equal (new (0, 0, 255), g.GetColorAtFraction (double.NaN));
+ }
+
+ [Fact]
+ public void Constructor_SingleStepProvided_ReplicatesForAllPairs ()
+ {
+ List stops = new List
+ {
+ new (255, 0), // Red
+ new (0, 255), // Green
+ new (0, 0, 255) // Blue
+ };
+
+ List singleStep = new() { 5 }; // Single step provided
+ var gradient = new Gradient (stops, singleStep);
+
+ Assert.NotNull (gradient.Spectrum);
+ Assert.Equal (12, gradient.Spectrum.Count); // 5 steps Red -> Green + 5 steps Green -> Blue + 2 end colors
+ }
+
+ [Fact]
+ public void Constructor_InvalidStepsLength_ThrowsArgumentException ()
+ {
+ List stops = new()
+ {
+ new (255, 0), // Red
+ new (0, 0, 255) // Blue
+ };
+
+ List invalidSteps = new() { 5, 5 }; // Invalid length (N-1 expected)
+ Assert.Throws (() => new Gradient (stops, invalidSteps));
+ }
+
+ [Fact]
+ public void Constructor_ValidStepsLength_DoesNotThrow ()
+ {
+ List stops = new List
+ {
+ new (255, 0), // Red
+ new (0, 255), // Green
+ new (0, 0, 255) // Blue
+ };
+
+ List validSteps = new() { 5, 5 }; // Valid length (N-1)
+ var gradient = new Gradient (stops, validSteps);
+
+ Assert.NotNull (gradient.Spectrum);
+ Assert.Equal (12, gradient.Spectrum.Count); // 5 steps Red -> Green + 5 steps Green -> Blue + 2 end colors
+ }
+}
diff --git a/UnitTests/Drawing/LineCanvasTests.cs b/UnitTests/Drawing/LineCanvasTests.cs
index 8426d3952..90a2f4123 100644
--- a/UnitTests/Drawing/LineCanvasTests.cs
+++ b/UnitTests/Drawing/LineCanvasTests.cs
@@ -3,7 +3,7 @@ using Xunit.Abstractions;
namespace Terminal.Gui.DrawingTests;
-public class LineCanvasTests (ITestOutputHelper output)
+public class LineCanvasTests (ITestOutputHelper _output)
{
[Theory]
@@ -294,7 +294,7 @@ public class LineCanvasTests (ITestOutputHelper output)
lc.AddLine (new (x1, y1), len1, o1, s1);
lc.AddLine (new (x2, y2), len2, o2, s2);
- TestHelpers.AssertEqual (output, expected, lc.ToString ());
+ TestHelpers.AssertEqual (_output, expected, lc.ToString ());
v.Dispose ();
}
@@ -503,7 +503,7 @@ public class LineCanvasTests (ITestOutputHelper output)
Assert.Equal (new (x, y, 4, 2), lc.Viewport);
TestHelpers.AssertEqual (
- output,
+ _output,
@"
╔╡╞╗
║ ║",
@@ -553,7 +553,7 @@ public class LineCanvasTests (ITestOutputHelper output)
Assert.Equal (new (x, y, 4, 2), lc.Viewport);
TestHelpers.AssertEqual (
- output,
+ _output,
@"
╔╡╞╗
║ ║",
@@ -596,7 +596,7 @@ public class LineCanvasTests (ITestOutputHelper output)
// Add a line at 5, 5 that's has length of 1
canvas.AddLine (new (x, y), 1, orientation, LineStyle.Single);
- TestHelpers.AssertEqual (output, $"{expected}", $"{canvas}");
+ TestHelpers.AssertEqual (_output, $"{expected}", $"{canvas}");
}
// X is offset by 2
@@ -653,7 +653,7 @@ public class LineCanvasTests (ITestOutputHelper output)
canvas.AddLine (new (x, y), length, orientation, LineStyle.Single);
var result = canvas.ToString ();
- TestHelpers.AssertEqual (output, expected, result);
+ TestHelpers.AssertEqual (_output, expected, result);
}
[Fact]
@@ -680,7 +680,7 @@ public class LineCanvasTests (ITestOutputHelper output)
// Add a line at 0, 0 that's has length of 0
lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
- TestHelpers.AssertEqual (output, expected, $"{lc}");
+ TestHelpers.AssertEqual (_output, expected, $"{lc}");
}
[InlineData (Orientation.Horizontal, "┼")]
@@ -701,7 +701,7 @@ public class LineCanvasTests (ITestOutputHelper output)
// Add a line at 0, 0 that's has length of 0
lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
- TestHelpers.AssertEqual (output, expected, $"{lc}");
+ TestHelpers.AssertEqual (_output, expected, $"{lc}");
}
[InlineData (Orientation.Horizontal, "╥")]
@@ -724,7 +724,7 @@ public class LineCanvasTests (ITestOutputHelper output)
// Add a line at 0, 0 that's has length of 0
lc.AddLine (Point.Empty, 0, orientation, LineStyle.Single);
- TestHelpers.AssertEqual (output, expected, $"{lc}");
+ TestHelpers.AssertEqual (_output, expected, $"{lc}");
}
[Fact]
@@ -740,7 +740,7 @@ public class LineCanvasTests (ITestOutputHelper output)
@"
┌─
│ ";
- TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
+ TestHelpers.AssertEqual (_output, looksLike, $"{Environment.NewLine}{canvas}");
}
[Fact]
@@ -767,7 +767,7 @@ public class LineCanvasTests (ITestOutputHelper output)
┣━━━━╋━━━┫
┃ ┃ ┃
┗━━━━┻━━━┛";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -798,7 +798,7 @@ public class LineCanvasTests (ITestOutputHelper output)
│ │ │
┕━━━━┷━━━┙
";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -830,7 +830,7 @@ public class LineCanvasTests (ITestOutputHelper output)
┖────┸───┚
";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -848,7 +848,7 @@ public class LineCanvasTests (ITestOutputHelper output)
@"
┌─
│ ";
- TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
+ TestHelpers.AssertEqual (_output, looksLike, $"{Environment.NewLine}{canvas}");
}
[Fact]
@@ -878,7 +878,7 @@ public class LineCanvasTests (ITestOutputHelper output)
Assert.Equal (2, map.Count);
TestHelpers.AssertEqual (
- output,
+ _output,
@"
─
─",
@@ -891,7 +891,7 @@ public class LineCanvasTests (ITestOutputHelper output)
public void ToString_Empty ()
{
var lc = new LineCanvas ();
- TestHelpers.AssertEqual (output, string.Empty, lc.ToString ());
+ TestHelpers.AssertEqual (_output, string.Empty, lc.ToString ());
}
// 012
@@ -910,7 +910,7 @@ public class LineCanvasTests (ITestOutputHelper output)
{
var lc = new LineCanvas ();
lc.AddLine (new (x, y), 3, Orientation.Horizontal, LineStyle.Double);
- TestHelpers.AssertEqual (output, expected, $"{lc}");
+ TestHelpers.AssertEqual (_output, expected, $"{lc}");
}
[InlineData (0, 0, 0, 0, "═══")]
@@ -935,7 +935,7 @@ public class LineCanvasTests (ITestOutputHelper output)
lc.AddLine (new (x1, y1), 3, Orientation.Horizontal, LineStyle.Double);
lc.AddLine (new (x2, y2), 3, Orientation.Horizontal, LineStyle.Double);
- TestHelpers.AssertEqual (output, expected, $"{lc}");
+ TestHelpers.AssertEqual (_output, expected, $"{lc}");
}
// [Fact, SetupFakeDriver]
@@ -995,7 +995,7 @@ public class LineCanvasTests (ITestOutputHelper output)
v.Draw ();
- TestHelpers.AssertDriverContentsAre (expected, output);
+ TestHelpers.AssertDriverContentsAre (expected, _output);
v.Dispose ();
}
@@ -1014,7 +1014,7 @@ public class LineCanvasTests (ITestOutputHelper output)
@"
┌─
│";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1037,7 +1037,7 @@ public class LineCanvasTests (ITestOutputHelper output)
──
│
│";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1055,7 +1055,7 @@ public class LineCanvasTests (ITestOutputHelper output)
var looksLike =
@"
──";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1071,7 +1071,7 @@ public class LineCanvasTests (ITestOutputHelper output)
var looksLike =
@"
══";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1090,7 +1090,7 @@ public class LineCanvasTests (ITestOutputHelper output)
@"
│
│";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1107,7 +1107,7 @@ public class LineCanvasTests (ITestOutputHelper output)
@"
║
║";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1135,7 +1135,7 @@ public class LineCanvasTests (ITestOutputHelper output)
╠════╬═══╣
║ ║ ║
╚════╩═══╝";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1166,7 +1166,7 @@ public class LineCanvasTests (ITestOutputHelper output)
│ │ │
╘════╧═══╛
";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1203,7 +1203,7 @@ public class LineCanvasTests (ITestOutputHelper output)
├────┼───┤
│ │ │
╰────┴───╯";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1235,7 +1235,7 @@ public class LineCanvasTests (ITestOutputHelper output)
╙────╨───╜
";
- TestHelpers.AssertDriverContentsAre (looksLike, output);
+ TestHelpers.AssertDriverContentsAre (looksLike, _output);
v.Dispose ();
}
@@ -1262,7 +1262,7 @@ public class LineCanvasTests (ITestOutputHelper output)
├────┼───┤
│ │ │
└────┴───┘";
- TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{canvas}");
+ TestHelpers.AssertEqual (_output, looksLike, $"{Environment.NewLine}{canvas}");
}
[Fact]
@@ -1300,7 +1300,93 @@ public class LineCanvasTests (ITestOutputHelper output)
var looksLike = @"
╔╡╞══╗
║ ║";
- TestHelpers.AssertEqual (output, looksLike, $"{Environment.NewLine}{lc}");
+ TestHelpers.AssertEqual (_output, looksLike, $"{Environment.NewLine}{lc}");
+ }
+
+ [Fact]
+ public void LineCanvas_UsesFillCorrectly ()
+ {
+ // Arrange
+ var foregroundColor = new Color (255, 0); // Red
+ var backgroundColor = new Color (0, 0); // Black
+ var foregroundFill = new SolidFill (foregroundColor);
+ var backgroundFill = new SolidFill (backgroundColor);
+ var fillPair = new FillPair (foregroundFill, backgroundFill);
+
+ var lineCanvas = new LineCanvas
+ {
+ Fill = fillPair
+ };
+
+ // Act
+ lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single);
+ Dictionary cellMap = lineCanvas.GetCellMap ();
+
+ // Assert
+ foreach (Cell? cell in cellMap.Values)
+ {
+ Assert.NotNull (cell);
+ Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
+ Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
+ }
+ }
+
+ [Fact]
+ public void LineCanvas_LineColorIgnoredBecauseOfFill ()
+ {
+ // Arrange
+ var foregroundColor = new Color (255, 0); // Red
+ var backgroundColor = new Color (0, 0); // Black
+ var lineColor = new Attribute (new Color (0, 255), new Color (255, 255, 255)); // Green on White
+ var foregroundFill = new SolidFill (foregroundColor);
+ var backgroundFill = new SolidFill (backgroundColor);
+ var fillPair = new FillPair (foregroundFill, backgroundFill);
+
+ var lineCanvas = new LineCanvas
+ {
+ Fill = fillPair
+ };
+
+ // Act
+ lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single, lineColor);
+ Dictionary cellMap = lineCanvas.GetCellMap ();
+
+ // Assert
+ foreach (Cell? cell in cellMap.Values)
+ {
+ Assert.NotNull (cell);
+ Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
+ Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
+ }
+ }
+
+ [Fact]
+ public void LineCanvas_IntersectingLinesUseFillCorrectly ()
+ {
+ // Arrange
+ var foregroundColor = new Color (255, 0); // Red
+ var backgroundColor = new Color (0, 0); // Black
+ var foregroundFill = new SolidFill (foregroundColor);
+ var backgroundFill = new SolidFill (backgroundColor);
+ var fillPair = new FillPair (foregroundFill, backgroundFill);
+
+ var lineCanvas = new LineCanvas
+ {
+ Fill = fillPair
+ };
+
+ // Act
+ lineCanvas.AddLine (new (0, 0), 5, Orientation.Horizontal, LineStyle.Single);
+ lineCanvas.AddLine (new (2, -2), 5, Orientation.Vertical, LineStyle.Single);
+ Dictionary cellMap = lineCanvas.GetCellMap ();
+
+ // Assert
+ foreach (Cell? cell in cellMap.Values)
+ {
+ Assert.NotNull (cell);
+ Assert.Equal (foregroundColor, cell.Value.Attribute.Value.Foreground);
+ Assert.Equal (backgroundColor, cell.Value.Attribute.Value.Background);
+ }
}
// TODO: Remove this and make all LineCanvas tests independent of View
diff --git a/UnitTests/Drawing/SolidFillTests.cs b/UnitTests/Drawing/SolidFillTests.cs
new file mode 100644
index 000000000..749a87c49
--- /dev/null
+++ b/UnitTests/Drawing/SolidFillTests.cs
@@ -0,0 +1,37 @@
+namespace Terminal.Gui.DrawingTests;
+
+public class SolidFillTests
+{
+ [Fact]
+ public void GetColor_ReturnsCorrectColor ()
+ {
+ // Arrange
+ var expectedColor = new Color (100, 150, 200);
+ var solidFill = new SolidFill (expectedColor);
+
+ // Act
+ Color resultColor = solidFill.GetColor (new (0, 0));
+
+ // Assert
+ Assert.Equal (expectedColor, resultColor);
+ }
+
+ [Theory]
+ [InlineData (0, 0)]
+ [InlineData (1, 1)]
+ [InlineData (-1, -1)]
+ [InlineData (100, 100)]
+ [InlineData (-100, -100)]
+ public void GetColor_ReturnsSameColorForDifferentPoints (int x, int y)
+ {
+ // Arrange
+ var expectedColor = new Color (50, 100, 150);
+ var solidFill = new SolidFill (expectedColor);
+
+ // Act
+ Color resultColor = solidFill.GetColor (new (x, y));
+
+ // Assert
+ Assert.Equal (expectedColor, resultColor);
+ }
+}
diff --git a/UnitTests/Drawing/StraightLineExtensionsTests.cs b/UnitTests/Drawing/StraightLineExtensionsTests.cs
index b7a5f36b1..865ae805a 100644
--- a/UnitTests/Drawing/StraightLineExtensionsTests.cs
+++ b/UnitTests/Drawing/StraightLineExtensionsTests.cs
@@ -2,11 +2,8 @@
namespace Terminal.Gui.DrawingTests;
-public class StraightLineExtensionsTests
+public class StraightLineExtensionsTests (ITestOutputHelper output)
{
- private readonly ITestOutputHelper _output;
- public StraightLineExtensionsTests (ITestOutputHelper output) { _output = output; }
-
[Fact]
[AutoInitShutdown]
public void LineCanvasIntegrationTest ()
@@ -18,7 +15,7 @@ public class StraightLineExtensionsTests
lc.AddLine (new Point (0, 4), -5, Orientation.Vertical, LineStyle.Single);
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────┐
│ │
@@ -32,7 +29,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (Point.Empty, 10, Orientation.Horizontal));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
│ │
│ │
@@ -44,7 +41,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (0, 1), 10, Orientation.Horizontal));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────┐
@@ -57,7 +54,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (0, 2), 10, Orientation.Horizontal));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────┐
│ │
@@ -70,7 +67,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (0, 3), 10, Orientation.Horizontal));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────┐
│ │
@@ -83,7 +80,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (0, 4), 10, Orientation.Horizontal));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────┐
│ │
@@ -95,7 +92,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (Point.Empty, 10, Orientation.Vertical));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
────────┐
│
@@ -108,7 +105,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (1, 0), 10, Orientation.Vertical));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌ ───────┐
│ │
@@ -121,7 +118,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (8, 0), 10, Orientation.Vertical));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌─────── ┐
│ │
@@ -134,7 +131,7 @@ public class StraightLineExtensionsTests
lc = new LineCanvas (origLines.Exclude (new Point (9, 0), 10, Orientation.Vertical));
TestHelpers.AssertEqual (
- _output,
+ output,
@"
┌────────
│
diff --git a/UnitTests/Drawing/StraightLineTests.cs b/UnitTests/Drawing/StraightLineTests.cs
index bb6870821..4395ea0c1 100644
--- a/UnitTests/Drawing/StraightLineTests.cs
+++ b/UnitTests/Drawing/StraightLineTests.cs
@@ -2,10 +2,9 @@
namespace Terminal.Gui.DrawingTests;
-public class StraightLineTests
+public class StraightLineTests (ITestOutputHelper output)
{
- private readonly ITestOutputHelper output;
- public StraightLineTests (ITestOutputHelper output) { this.output = output; }
+ private readonly ITestOutputHelper _output = output;
[InlineData (
Orientation.Horizontal,
@@ -320,8 +319,8 @@ public class StraightLineTests
int expectedHeight
)
{
- var sl = new StraightLine (new Point (x, y), length, orientation, LineStyle.Single);
+ var sl = new StraightLine (new (x, y), length, orientation, LineStyle.Single);
- Assert.Equal (new Rectangle (expectedX, expectedY, expectedWidth, expectedHeight), sl.Viewport);
+ Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), sl.Viewport);
}
}
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index 716afb0fa..2a9fbc394 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -29,16 +29,17 @@
true
-
-
-
-
-
-
+
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/UnitTests/Views/DateFieldTests.cs b/UnitTests/Views/DateFieldTests.cs
index f421d9448..3f17e8950 100644
--- a/UnitTests/Views/DateFieldTests.cs
+++ b/UnitTests/Views/DateFieldTests.cs
@@ -194,6 +194,10 @@ public class DateFieldTests
{
separator = separator.Replace ("\u200f", "");
}
+ else if (culture.Name == "ar-SA" && RuntimeInformation.IsOSPlatform (OSPlatform.OSX))
+ {
+ separator = " ";
+ }
string format = culture.DateTimeFormat.ShortDatePattern;
@@ -207,6 +211,14 @@ public class DateFieldTests
case "ar-SA":
Assert.Equal ($" 04{separator}11{separator}1390", df.Text);
+ break;
+ case "en-SA" when RuntimeInformation.IsOSPlatform (OSPlatform.OSX):
+ Assert.Equal ($" 04{separator}11{separator}1390", df.Text);
+
+ break;
+ case "en-TH" when RuntimeInformation.IsOSPlatform (OSPlatform.OSX):
+ Assert.Equal ($" 01{separator}01{separator}2514", df.Text);
+
break;
case "th":
case "th-TH":
diff --git a/docfx/images/Example.png b/docfx/images/Example.png
index bf3570f1c..aa02ecc36 100644
Binary files a/docfx/images/Example.png and b/docfx/images/Example.png differ
diff --git a/docfx/images/sample.gif b/docfx/images/sample.gif
index b540b876f..5027de6ae 100644
Binary files a/docfx/images/sample.gif and b/docfx/images/sample.gif differ