diff --git a/src/.idea/.idea.SaaStack/.idea/inspectionProfiles/Project_Default.xml b/src/.idea/.idea.SaaStack/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 00000000..85ed4b44
--- /dev/null
+++ b/src/.idea/.idea.SaaStack/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ApiHost1/ApiHost1.csproj b/src/ApiHost1/ApiHost1.csproj
index 598312ef..35543e18 100644
--- a/src/ApiHost1/ApiHost1.csproj
+++ b/src/ApiHost1/ApiHost1.csproj
@@ -11,9 +11,7 @@
-
+
diff --git a/src/CarsApi/CarsApi.csproj b/src/CarsApi/CarsApi.csproj
index 53db2ed1..5fe1d942 100644
--- a/src/CarsApi/CarsApi.csproj
+++ b/src/CarsApi/CarsApi.csproj
@@ -14,9 +14,7 @@
-
+
diff --git a/src/Common/Common.csproj b/src/Common/Common.csproj
index 65c71b6b..e0c07d50 100644
--- a/src/Common/Common.csproj
+++ b/src/Common/Common.csproj
@@ -27,10 +27,4 @@
-
-
-
-
diff --git a/src/Common/Error.cs b/src/Common/Error.cs
index 00714d07..3a4b316b 100644
--- a/src/Common/Error.cs
+++ b/src/Common/Error.cs
@@ -1,5 +1,8 @@
namespace Common;
+///
+/// Defines a error, used for result return values
+///
public struct Error
{
private Error(ErrorCode code, string? message = null)
@@ -63,8 +66,13 @@ public static Error Unexpected(string? message = null)
}
}
+///
+/// Defines the common types (codes) of errors that can happen in code at any layer,
+/// that return
+///
public enum ErrorCode
{
+ // EXTEND: add other kinds of errors you want to support in Result
Validation,
RuleViolation,
RoleViolation,
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 837edadb..c56a378a 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -64,10 +64,10 @@
- Debug
- AnyCPU
+ Debug
+ AnyCPU
-
+
true
full
false
@@ -77,7 +77,7 @@
4
-
+
pdbonly
true
bin\$(Configuration)\
@@ -86,7 +86,7 @@
4
-
+
pdbonly
true
bin\$(Configuration)\
@@ -95,4 +95,9 @@
4
+
+
+
+
+
diff --git a/src/Infrastructure.WebApi.Common.IntegrationTests/Infrastructure.WebApi.Common.IntegrationTests.csproj b/src/Infrastructure.WebApi.Common.IntegrationTests/Infrastructure.WebApi.Common.IntegrationTests.csproj
index 503aa153..1ab2fc6b 100644
--- a/src/Infrastructure.WebApi.Common.IntegrationTests/Infrastructure.WebApi.Common.IntegrationTests.csproj
+++ b/src/Infrastructure.WebApi.Common.IntegrationTests/Infrastructure.WebApi.Common.IntegrationTests.csproj
@@ -2,6 +2,7 @@
net7.0
+ true
diff --git a/src/SaaStack.sln b/src/SaaStack.sln
index 7e680075..6a59c665 100644
--- a/src/SaaStack.sln
+++ b/src/SaaStack.sln
@@ -7,7 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.props = Directory.Build.props
GlobalAssemblyInfo.cs = GlobalAssemblyInfo.cs
..\CHANGELOG.md = ..\CHANGELOG.md
- ..\README_PROJECT.md = ..\README_PROJECT.md
+ ..\README_DERIVATIVE.md = ..\README_DERIVATIVE.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{508E7DA4-4DF2-4201-955D-CCF70C41AD05}"
@@ -70,7 +70,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.Interfaces", "A
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTesting.WebApi.Common", "IntegrationTesting.WebApi.Common\IntegrationTesting.WebApi.Common.csproj", "{A7CA7AD7-70CA-43F0-BE73-75A01342D571}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure.WebApi.Generators", "Infrastructure.WebApi.Generators\Infrastructure.WebApi.Generators.csproj", "{7AB39FD6-660F-4400-9955-B92684378492}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools.Generators.WebApi", "Tools.Generators.WebApi\Tools.Generators.WebApi.csproj", "{7AB39FD6-660F-4400-9955-B92684378492}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{19ADDB2F-B589-49EF-9BDA-BD9908057D60}"
EndProject
@@ -108,6 +108,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application.Persistence.Int
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CarsInfrastructure", "CarsInfrastructure\CarsInfrastructure.csproj", "{ED71C769-CDA7-4C58-B252-8218DCE3D2B5}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{BAE0D6F2-6920-4B02-9F30-D71B04B7170D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools.Analyzers.Core", "Tools.Analyzers.Core\Tools.Analyzers.Core.csproj", "{DE31F486-AE81-49C0-BA00-3A6A325B7C42}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{A25A3BA8-5602-4825-9595-2CF96B166920}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools.Analyzers.Core.UnitTests", "Tools.Analyzers.Core.UnitTests\Tools.Analyzers.Core.UnitTests.csproj", "{3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -271,6 +279,18 @@ Global
{ED71C769-CDA7-4C58-B252-8218DCE3D2B5}.Release|Any CPU.Build.0 = Release|Any CPU
{ED71C769-CDA7-4C58-B252-8218DCE3D2B5}.ReleaseForDeploy|Any CPU.ActiveCfg = ReleaseForDeploy|Any CPU
{ED71C769-CDA7-4C58-B252-8218DCE3D2B5}.ReleaseForDeploy|Any CPU.Build.0 = ReleaseForDeploy|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.ReleaseForDeploy|Any CPU.ActiveCfg = ReleaseForDeploy|Any CPU
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42}.ReleaseForDeploy|Any CPU.Build.0 = ReleaseForDeploy|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.ReleaseForDeploy|Any CPU.ActiveCfg = ReleaseForDeploy|Any CPU
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD}.ReleaseForDeploy|Any CPU.Build.0 = ReleaseForDeploy|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{F5C77A86-38AF-40E4-82FC-617E624B2754} = {508E7DA4-4DF2-4201-955D-CCF70C41AD05}
@@ -299,7 +319,6 @@ Global
{B76CF102-CE56-4321-9060-F81E63B982D6} = {57FDFB31-D6B6-4369-A78C-6F3D3AEA0D79}
{23FF9513-1B26-41F4-A7FE-1D8A9F0808AE} = {BA1AEAEC-68CD-4855-A8CB-0DC2070B6A8C}
{A7CA7AD7-70CA-43F0-BE73-75A01342D571} = {5838EE94-374F-4A6F-A231-1BC1C87985F4}
- {7AB39FD6-660F-4400-9955-B92684378492} = {B68592DF-E8E8-452A-A46F-5C8ECB178FDF}
{19ADDB2F-B589-49EF-9BDA-BD9908057D60} = {B68592DF-E8E8-452A-A46F-5C8ECB178FDF}
{4CF7C7E2-C95D-4440-9ECF-5D1CE2A46D7A} = {19ADDB2F-B589-49EF-9BDA-BD9908057D60}
{AE57212B-9A30-4577-A795-7B411621BCDA} = {19ADDB2F-B589-49EF-9BDA-BD9908057D60}
@@ -319,5 +338,11 @@ Global
{23A93A15-21B8-4CA5-B128-1FF4B0C6A861} = {57FDFB31-D6B6-4369-A78C-6F3D3AEA0D79}
{F6C71F8B-AFDE-471A-B1DE-6E1E8F3499C6} = {BA1AEAEC-68CD-4855-A8CB-0DC2070B6A8C}
{ED71C769-CDA7-4C58-B252-8218DCE3D2B5} = {57FDFB31-D6B6-4369-A78C-6F3D3AEA0D79}
+ {BAE0D6F2-6920-4B02-9F30-D71B04B7170D} = {9270A12C-E16F-4932-89C4-F4ADDDA55AF3}
+ {DE31F486-AE81-49C0-BA00-3A6A325B7C42} = {BAE0D6F2-6920-4B02-9F30-D71B04B7170D}
+ {A25A3BA8-5602-4825-9595-2CF96B166920} = {BAE0D6F2-6920-4B02-9F30-D71B04B7170D}
+ {3E6AA34C-02F9-4B8B-8307-FC9CA25DB7AD} = {A25A3BA8-5602-4825-9595-2CF96B166920}
+ {33E2D4C7-525A-41CE-858C-F6A944160618} = {864DED88-9252-46EB-9D13-00269C7333F9}
+ {7AB39FD6-660F-4400-9955-B92684378492} = {BAE0D6F2-6920-4B02-9F30-D71B04B7170D}
EndGlobalSection
EndGlobal
diff --git a/src/SaaStack.sln.DotSettings b/src/SaaStack.sln.DotSettings
index dd0677b7..097468e4 100644
--- a/src/SaaStack.sln.DotSettings
+++ b/src/SaaStack.sln.DotSettings
@@ -1,4 +1,8 @@
+ ExplicitlyExcluded
+ ExplicitlyExcluded
+
+
WARNING
WARNING
WARNING
diff --git a/src/Tools.Analyzers.Core.UnitTests/MissingDocsAnalyzerSpec.cs b/src/Tools.Analyzers.Core.UnitTests/MissingDocsAnalyzerSpec.cs
new file mode 100644
index 00000000..4ad30fdb
--- /dev/null
+++ b/src/Tools.Analyzers.Core.UnitTests/MissingDocsAnalyzerSpec.cs
@@ -0,0 +1,502 @@
+using JetBrains.Annotations;
+using Xunit;
+
+namespace Tools.Analyzers.Core.UnitTests;
+
+[UsedImplicitly]
+public class MissingDocsAnalyzerSpec
+{
+ [Trait("Category", "Unit")]
+ public class GivenAType
+ {
+ [Fact]
+ public async Task WhenInJetbrainsAnnotationsNamespace_ThenNoAlert()
+ {
+ const string input = @"namespace JetBrains.Annotations;
+public class AClass
+{
+}";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenInApiHost1Namespace_ThenNoAlert()
+ {
+ const string input = @"namespace ApiHost1;
+public class AClass
+{
+}";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenPublicDelegate_ThenAlerts()
+ {
+ const string input = @"public delegate void ADelegate();";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 22, "ADelegate");
+ }
+
+ [Fact]
+ public async Task WhenInternalDelegate_ThenAlerts()
+ {
+ const string input = @"internal delegate void ADelegate();";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 24, "ADelegate");
+ }
+
+ [Fact]
+ public async Task WhenPublicInterface_ThenAlerts()
+ {
+ const string input = @"public interface AnInterface
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 18, "AnInterface");
+ }
+
+ [Fact]
+ public async Task WhenInternalInterface_ThenAlerts()
+ {
+ const string input = @"internal interface AnInterface
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 20, "AnInterface");
+ }
+
+ [Fact]
+ public async Task WhenPublicEnum_ThenAlerts()
+ {
+ const string input = @"public enum AnEnum
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 13, "AnEnum");
+ }
+
+ [Fact]
+ public async Task WhenInternalEnum_ThenAlerts()
+ {
+ const string input = @"internal enum AnEnum
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 15, "AnEnum");
+ }
+
+ [Fact]
+ public async Task WhenPublicStruct_ThenAlerts()
+ {
+ const string input = @"public struct AStruct
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 15, "AStruct");
+ }
+
+ [Fact]
+ public async Task WhenInternalStruct_ThenAlerts()
+ {
+ const string input = @"internal struct AStruct
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 17, "AStruct");
+ }
+
+ [Fact]
+ public async Task WhenPublicReadOnlyStruct_ThenAlerts()
+ {
+ const string input = @"public readonly struct AStruct
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 24, "AStruct");
+ }
+
+ [Fact]
+ public async Task WhenInternalReadOnlyStruct_ThenAlerts()
+ {
+ const string input = @"internal readonly struct AStruct
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 26, "AStruct");
+ }
+
+ [Fact]
+ public async Task WhenPublicRecord_ThenAlerts()
+ {
+ const string input = @"public record ARecord()
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 15, "ARecord");
+ }
+
+ [Fact]
+ public async Task WhenInternalRecord_ThenAlerts()
+ {
+ const string input = @"internal record ARecord
+{
+}";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 17, "ARecord");
+ }
+
+ [Fact]
+ public async Task WhenPublicStaticClass_ThenNoAlert()
+ {
+ const string input = @"public static class AClass
+{
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenInternalStaticClass_ThenNoAlert()
+ {
+ const string input = @"internal static class AClass
+{
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenNestedPublicStaticClass_ThenNoAlert()
+ {
+ const string input = @"public static class AClass1
+{
+ public static class AClass2
+ {
+ }
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenNestedPrivateStaticClass_ThenNoAlert()
+ {
+ const string input = @"
+///
+/// avalue
+///
+public static class AClass1
+{
+ private static class AClass2
+ {
+ }
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenNestedPublicInstanceClass_ThenAlerts()
+ {
+ const string input = @"
+///
+/// avalue
+///
+public class AClass1
+{
+ public class AClass2
+ {
+ }
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 7, 18, "AClass2");
+ }
+
+ [Fact]
+ public async Task WhenNestedPrivateInstanceClass_ThenNoAlert()
+ {
+ const string input = @"
+///
+/// avalue
+///
+public class AClass1
+{
+ private class AClass2
+ {
+ }
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassNoSummary_ThenAlerts()
+ {
+ const string input = @"public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 14);
+ }
+
+ [Fact]
+ public async Task WhenInternalClassNoSummary_ThenAlerts()
+ {
+ const string input = @"internal class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 1, 16);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasEmptyLine_ThenAlerts()
+ {
+ const string input = @"
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 2, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasBlankLine_ThenAlerts()
+ {
+ const string input = @"
+
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 3, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasEmptyOtherTag_ThenAlerts()
+ {
+ const string input = @"
+///
+///
+///
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 5, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasSomeOtherTag_ThenAlerts()
+ {
+ const string input = @"
+///
+/// avalue
+///
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 5, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasEmptySummary_ThenAlerts()
+ {
+ const string input = @"
+///
+///
+///
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 5, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasWhitespaceSummary_ThenAlerts()
+ {
+ const string input = @"
+///
+///
+///
+public class AClass
+{
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.TypeDiagnosticId, input, 5, 14);
+ }
+
+ [Fact]
+ public async Task WhenPublicClassHasASummary_ThenNoAlert()
+ {
+ const string input = @"
+///
+/// avalue
+///
+public class AClass
+{
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+ }
+
+ [Trait("Category", "Unit")]
+ public class GivenAMethod
+ {
+ [Fact]
+ public async Task WhenInJetbrainsAnnotationsNamespace_ThenNoAlert()
+ {
+ const string input = @"namespace JetBrains.Annotations;
+public static class AClass
+{
+ public static void AMethod(){}
+}";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenInApiHost1Namespace_ThenNoAlert()
+ {
+ const string input = @"namespace ApiHost1;
+public static class AClass
+{
+ public static void AMethod(){}
+}";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenInsideInternalStaticClass_ThenNoAlert()
+ {
+ const string input = @"internal static class AClass
+{
+ public static void AMethod1(){}
+ public static void AMethod2(this string value){}
+}";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenPublicStaticMethod_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ public static void AMethod(){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 24, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenInternalStaticMethod_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ internal static void AMethod(){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 26, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenPublicStaticMethodWithParams_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ public static void AMethod(string value){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 24, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenInternalStaticMethodWithParams_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ internal static void AMethod(string value){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 26, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenInternalExtension_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ internal static void AMethod(this string value){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 26, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenPrivateExtension_ThenNoAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ private static void AMethod(this string value){}
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+
+ [Fact]
+ public async Task WhenPublicExtensionHasNoSummary_ThenAlerts()
+ {
+ const string input = @"public static class AClass
+{
+ public static void AMethod(this string value){}
+}
+";
+
+ await Verify.DiagnosticExists(MissingDocsAnalyzer.ExtensionMethodDiagnosticId, input, 3, 24, "AMethod");
+ }
+
+ [Fact]
+ public async Task WhenPublicExtensionHasASummary_ThenNoAlert()
+ {
+ const string input = @"
+public static class AClass
+{
+ ///
+ /// avalue
+ ///
+ private static void AMethod(this string value){}
+}
+";
+
+ await Verify.NoDiagnosticExists(input);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core.UnitTests/Tools.Analyzers.Core.UnitTests.csproj b/src/Tools.Analyzers.Core.UnitTests/Tools.Analyzers.Core.UnitTests.csproj
new file mode 100644
index 00000000..71ed50e6
--- /dev/null
+++ b/src/Tools.Analyzers.Core.UnitTests/Tools.Analyzers.Core.UnitTests.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net7.0
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Tools.Analyzers.Core.UnitTests/Verify.cs b/src/Tools.Analyzers.Core.UnitTests/Verify.cs
new file mode 100644
index 00000000..cecf0784
--- /dev/null
+++ b/src/Tools.Analyzers.Core.UnitTests/Verify.cs
@@ -0,0 +1,21 @@
+using Microsoft.CodeAnalysis.CSharp.Testing;
+using Microsoft.CodeAnalysis.Testing;
+
+namespace Tools.Analyzers.Core.UnitTests;
+
+public static class Verify
+{
+ public static async Task DiagnosticExists(string diagnosticId, string inputSnippet, int locationX, int locationY,
+ string argument = "AClass")
+ {
+ var expected = CSharpAnalyzerVerifier.Diagnostic(diagnosticId)
+ .WithLocation(locationX, locationY)
+ .WithArguments(argument);
+ await CSharpAnalyzerVerifier.VerifyAnalyzerAsync(inputSnippet, expected);
+ }
+
+ public static async Task NoDiagnosticExists(string inputSnippet)
+ {
+ await CSharpAnalyzerVerifier.VerifyAnalyzerAsync(inputSnippet);
+ }
+}
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/AnalyzerReleases.Shipped.md b/src/Tools.Analyzers.Core/AnalyzerReleases.Shipped.md
new file mode 100644
index 00000000..c4493a49
--- /dev/null
+++ b/src/Tools.Analyzers.Core/AnalyzerReleases.Shipped.md
@@ -0,0 +1,8 @@
+## Release 1.0
+
+### New Rules
+
+ Rule ID | Category | Severity | Notes
+---------|---------------|----------|-----------------------------------------------
+ SAS001 | Documentation | Warning | The class must have documentation.
+ SAS002 | Documentation | Warning | The extension method must have documentation.
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/AnalyzerReleases.Unshipped.md b/src/Tools.Analyzers.Core/AnalyzerReleases.Unshipped.md
new file mode 100644
index 00000000..dd633832
--- /dev/null
+++ b/src/Tools.Analyzers.Core/AnalyzerReleases.Unshipped.md
@@ -0,0 +1,4 @@
+### New Rules
+
+ Rule ID | Category | Severity | Notes
+---------|----------|----------|-------
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/MissingDocsAnalyzer.cs b/src/Tools.Analyzers.Core/MissingDocsAnalyzer.cs
new file mode 100644
index 00000000..e230b167
--- /dev/null
+++ b/src/Tools.Analyzers.Core/MissingDocsAnalyzer.cs
@@ -0,0 +1,376 @@
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+
+namespace Tools.Analyzers.Core;
+
+///
+/// An analyzer to find public declarations that are missing a documentation <summary> node.
+/// Document declarations are only enforced for Core common/interfaces projects.
+/// All public/internal classes, structs, records, interfaces, delegates and enums
+/// All public/internal static methods and all public/internal extension methods (in public types)
+///
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public class MissingDocsAnalyzer : DiagnosticAnalyzer
+{
+ public const string ExtensionMethodDiagnosticId = "SAS002";
+ private const string RoslynCategory = "Documentation";
+ private const string SummaryXmlElementName = "summary";
+ public const string TypeDiagnosticId = "SAS001";
+
+ private static readonly string[] IncludedNamespaces =
+ {
+#if TESTINGONLY
+ "",
+#endif
+ "Common", "UnitTesting.Common", "IntegrationTesting.Common",
+ "Infrastructure.Common", "Infrastructure.Interfaces",
+ "Infrastructure.Persistence.Common", "Infrastructure.Persistence.Interfaces",
+ "Infrastructure.WebApi.Common", "Infrastructure.WebApi.Interfaces",
+ "Domain.Common", "Domain.Interfaces", "Application.Common", "Application.Interfaces"
+ };
+
+ private static readonly DiagnosticDescriptor TypeRule = new(TypeDiagnosticId,
+ GetResource(nameof(Resources.SAS001Title)), GetResource(nameof(Resources.SAS001MessageFormat)), RoslynCategory,
+ DiagnosticSeverity.Warning, true, GetResource(nameof(Resources.SAS001Description)));
+
+ private static readonly DiagnosticDescriptor ExtensionMethodRule = new(ExtensionMethodDiagnosticId,
+ GetResource(nameof(Resources.SAS002Title)), GetResource(nameof(Resources.SAS002MessageFormat)), RoslynCategory,
+ DiagnosticSeverity.Warning, true, GetResource(nameof(Resources.SAS002Description)));
+
+ public override ImmutableArray SupportedDiagnostics =>
+ ImmutableArray.Create(TypeRule, ExtensionMethodRule);
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+ context.RegisterSyntaxNodeAction(AnalyzeType, SyntaxKind.StructDeclaration, SyntaxKind.ClassDeclaration,
+ SyntaxKind.InterfaceDeclaration, SyntaxKind.RecordDeclaration, SyntaxKind.DelegateDeclaration,
+ SyntaxKind.EnumDeclaration);
+ context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.MethodDeclaration);
+ }
+
+ private static void AnalyzeType(SyntaxNodeAnalysisContext context)
+ {
+ var typeSyntax = context.Node;
+ if (typeSyntax is not MemberDeclarationSyntax typeDeclarationSyntax) //class, struct, interface, record
+ {
+ return;
+ }
+
+ if (IsIgnoredNamespace(context))
+ {
+ return;
+ }
+
+ if (IsNotPublicNorInternalInstanceType(typeDeclarationSyntax))
+ {
+ return;
+ }
+
+ if (IsNestedAndNotPublicType(typeDeclarationSyntax))
+ {
+ return;
+ }
+
+ var docs = typeDeclarationSyntax.GetDocumentationCommentTriviaSyntax();
+ if (docs is null)
+ {
+ ReportDiagnostic(context, typeDeclarationSyntax);
+ return;
+ }
+
+ if (!IsXmlDocsForCSharp(docs))
+ {
+ ReportDiagnostic(context, typeDeclarationSyntax);
+ return;
+ }
+
+ var xmlContent = docs.Content;
+ var summary = xmlContent.GetFirstXmlElement(SummaryXmlElementName);
+ if (summary is null)
+ {
+ ReportDiagnostic(context, typeDeclarationSyntax);
+ return;
+ }
+
+ if (IsEmptyNode(summary))
+ {
+ ReportDiagnostic(context, typeDeclarationSyntax);
+ }
+ }
+
+ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context)
+ {
+ var methodSyntax = context.Node;
+ if (methodSyntax is not MethodDeclarationSyntax methodDeclarationSyntax)
+ {
+ return;
+ }
+
+ if (IsIgnoredNamespace(context))
+ {
+ return;
+ }
+
+ if (IsParentTypeNotPublic(methodDeclarationSyntax))
+ {
+ return;
+ }
+
+ if (IsNotPublicOrInternalStaticMethod(methodDeclarationSyntax))
+ {
+ return;
+ }
+
+ var docs = methodDeclarationSyntax.GetDocumentationCommentTriviaSyntax();
+ if (docs is null)
+ {
+ ReportDiagnostic(context, methodDeclarationSyntax);
+ return;
+ }
+
+ if (!IsXmlDocsForCSharp(docs))
+ {
+ ReportDiagnostic(context, methodDeclarationSyntax);
+ return;
+ }
+
+ var xmlContent = docs.Content;
+ var summary = xmlContent.GetFirstXmlElement(SummaryXmlElementName);
+ if (summary is null)
+ {
+ ReportDiagnostic(context, methodDeclarationSyntax);
+ return;
+ }
+
+ if (IsEmptyNode(summary))
+ {
+ ReportDiagnostic(context, methodDeclarationSyntax);
+ }
+ }
+
+ private static LocalizableResourceString GetResource(string name)
+ {
+ return new LocalizableResourceString(name, Resources.ResourceManager, typeof(Resources));
+ }
+
+ private static void ReportDiagnostic(SyntaxNodeAnalysisContext context,
+ MemberDeclarationSyntax memberDeclarationSyntax)
+ {
+ var location = Location.None;
+ var text = "Unknown";
+
+ if (memberDeclarationSyntax is BaseTypeDeclarationSyntax baseType)
+ {
+ location = baseType.Identifier.GetLocation();
+ text = baseType.Identifier.Text;
+ }
+
+ if (memberDeclarationSyntax is DelegateDeclarationSyntax delegateType)
+ {
+ location = delegateType.Identifier.GetLocation();
+ text = delegateType.Identifier.Text;
+ }
+
+ var diagnostic = Diagnostic.Create(TypeRule, location, text);
+ context.ReportDiagnostic(diagnostic);
+ }
+
+ private static void ReportDiagnostic(SyntaxNodeAnalysisContext context,
+ MethodDeclarationSyntax methodDeclarationSyntax)
+ {
+ var identifier = methodDeclarationSyntax.Identifier;
+ var diagnostic = Diagnostic.Create(ExtensionMethodRule, identifier.GetLocation(), identifier.Text);
+ context.ReportDiagnostic(diagnostic);
+ }
+
+ private static bool IsEmptyNode(XmlNodeSyntax nodeSyntax)
+ {
+ if (nodeSyntax is XmlTextSyntax textSyntax)
+ {
+ return textSyntax.TextTokens.All(token => string.IsNullOrWhiteSpace(token.ToString()));
+ }
+
+ if (nodeSyntax is XmlElementSyntax xmlElementSyntax)
+ {
+ var content = xmlElementSyntax.Content;
+ return content.All(IsEmptyNode);
+ }
+
+ return true;
+ }
+
+ private static bool IsIgnoredNamespace(SyntaxNodeAnalysisContext context)
+ {
+ var parentContext = context.ContainingSymbol;
+ if (parentContext is null)
+ {
+ return true;
+ }
+
+ var containingNamespace = parentContext.ContainingNamespace.ToDisplayString();
+ var included = IncludedNamespaces.Contains(containingNamespace);
+
+ return !included;
+ }
+
+ private static bool IsNotPublicNorInternalInstanceType(MemberDeclarationSyntax memberDeclaration)
+ {
+ var accessibility = new Accessibility(memberDeclaration.Modifiers);
+ if (accessibility is { IsPublic: false, IsInternal: false })
+ {
+ return true;
+ }
+
+ if (accessibility.IsStatic)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool IsNestedAndNotPublicType(MemberDeclarationSyntax memberDeclaration)
+ {
+ var isNested = memberDeclaration.Parent.IsKind(SyntaxKind.ClassDeclaration);
+ if (!isNested)
+ {
+ return false;
+ }
+
+ var accessibility = new Accessibility(memberDeclaration.Modifiers);
+ if (accessibility.IsPublic)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool IsParentTypeNotPublic(MemberDeclarationSyntax memberDeclaration)
+ {
+ var parent = memberDeclaration.Parent;
+ if (parent is not BaseTypeDeclarationSyntax typeDeclaration)
+ {
+ return false;
+ }
+
+ var accessibility = new Accessibility(typeDeclaration.Modifiers);
+ if (accessibility.IsPublic)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool IsNotPublicOrInternalStaticMethod(MethodDeclarationSyntax methodDeclarationSyntax)
+ {
+ var accessibility = new Accessibility(methodDeclarationSyntax.Modifiers);
+ if (accessibility is { IsPublic: false, IsInternal: false })
+ {
+ return true;
+ }
+
+ if (!accessibility.IsStatic)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static bool IsPublicOrInternalExtensionMethod(MethodDeclarationSyntax methodDeclarationSyntax)
+ {
+ var isNotPublicOrInternal = IsNotPublicOrInternalStaticMethod(methodDeclarationSyntax);
+ if (isNotPublicOrInternal)
+ {
+ return false;
+ }
+
+ var firstParameter = methodDeclarationSyntax.ParameterList.Parameters.FirstOrDefault();
+ if (firstParameter is null)
+ {
+ return false;
+ }
+
+ var isExtension = firstParameter.Modifiers.Any(mod => mod.IsKind(SyntaxKind.ThisKeyword));
+ if (!isExtension)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool IsXmlDocsForCSharp(SyntaxNode docs)
+ {
+ return docs.Language == "C#";
+ }
+}
+
+internal static class SyntaxExtensions
+{
+ public static DocumentationCommentTriviaSyntax? GetDocumentationCommentTriviaSyntax(this SyntaxNode node)
+ {
+ foreach (var leadingTrivia in node.GetLeadingTrivia())
+ {
+ if (leadingTrivia.GetStructure() is DocumentationCommentTriviaSyntax structure)
+ {
+ return structure;
+ }
+ }
+
+ return null;
+ }
+
+ public static XmlNodeSyntax? GetFirstXmlElement(this SyntaxList content, string elementName)
+ {
+ return content.GetXmlElements(elementName)
+ .FirstOrDefault();
+ }
+
+ private static IEnumerable GetXmlElements(this SyntaxList content, string elementName)
+ {
+ foreach (var syntax in content)
+ {
+ if (syntax is XmlEmptyElementSyntax emptyElement)
+ {
+ if (string.Equals(elementName, emptyElement.Name.ToString(), StringComparison.Ordinal))
+ {
+ yield return emptyElement;
+ }
+
+ continue;
+ }
+
+ if (syntax is XmlElementSyntax elementSyntax)
+ {
+ if (string.Equals(elementName, elementSyntax.StartTag?.Name?.ToString(), StringComparison.Ordinal))
+ {
+ yield return elementSyntax;
+ }
+ }
+ }
+ }
+}
+
+public class Accessibility
+{
+ public Accessibility(SyntaxTokenList modifiers)
+ {
+ IsPublic = modifiers.Any(mod => mod.IsKind(SyntaxKind.PublicKeyword));
+ IsInternal = modifiers.Any(mod => mod.IsKind(SyntaxKind.InternalKeyword));
+ IsStatic = modifiers.Any(mod => mod.IsKind(SyntaxKind.StaticKeyword));
+ }
+
+ public bool IsInternal { get; }
+
+ public bool IsPublic { get; }
+
+ public bool IsStatic { get; }
+}
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/Properties/launchSettings.json b/src/Tools.Analyzers.Core/Properties/launchSettings.json
new file mode 100644
index 00000000..78c2ecd4
--- /dev/null
+++ b/src/Tools.Analyzers.Core/Properties/launchSettings.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "CodingStandards-Analyzers-Development": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "../ApiHost1/ApiHost1.csproj"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/Resources.Designer.cs b/src/Tools.Analyzers.Core/Resources.Designer.cs
new file mode 100644
index 00000000..489d1daa
--- /dev/null
+++ b/src/Tools.Analyzers.Core/Resources.Designer.cs
@@ -0,0 +1,116 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Tools.Analyzers.Core {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tools.Analyzers.Core.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This type should have a <summary> to describe what it designed to do..
+ ///
+ internal static string SAS001Description {
+ get {
+ return ResourceManager.GetString("SAS001Description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Type '{0}' requires a documentation <summary/>.
+ ///
+ internal static string SAS001MessageFormat {
+ get {
+ return ResourceManager.GetString("SAS001MessageFormat", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Missing documentation.
+ ///
+ internal static string SAS001Title {
+ get {
+ return ResourceManager.GetString("SAS001Title", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This method should have a <summary> to describe what it designed to do..
+ ///
+ internal static string SAS002Description {
+ get {
+ return ResourceManager.GetString("SAS002Description", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Extension method '{0}' requires a documentation <summary/>.
+ ///
+ internal static string SAS002MessageFormat {
+ get {
+ return ResourceManager.GetString("SAS002MessageFormat", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Missing documentation.
+ ///
+ internal static string SAS002Title {
+ get {
+ return ResourceManager.GetString("SAS002Title", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/Tools.Analyzers.Core/Resources.resx b/src/Tools.Analyzers.Core/Resources.resx
new file mode 100644
index 00000000..7b42a4fc
--- /dev/null
+++ b/src/Tools.Analyzers.Core/Resources.resx
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
+ PublicKeyToken=b77a5c561934e089
+
+
+
+ This type should have a <summary> to describe what it designed to do.
+
+
+ Type '{0}' requires a documentation <summary/>
+
+
+ Missing documentation
+
+
+ This method should have a <summary> to describe what it designed to do.
+
+
+ Extension method '{0}' requires a documentation <summary/>
+
+
+ Missing documentation
+
+
\ No newline at end of file
diff --git a/src/Tools.Analyzers.Core/Tools.Analyzers.Core.csproj b/src/Tools.Analyzers.Core/Tools.Analyzers.Core.csproj
new file mode 100644
index 00000000..9723b41f
--- /dev/null
+++ b/src/Tools.Analyzers.Core/Tools.Analyzers.Core.csproj
@@ -0,0 +1,42 @@
+
+
+
+ .net7.0
+ true
+ true
+
+
+
+ RS2007
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+
+
+
+
diff --git a/src/Infrastructure.WebApi.Generators/Extensions/StringExtensions.cs b/src/Tools.Generators.WebApi/Extensions/StringExtensions.cs
similarity index 91%
rename from src/Infrastructure.WebApi.Generators/Extensions/StringExtensions.cs
rename to src/Tools.Generators.WebApi/Extensions/StringExtensions.cs
index e65169db..6d403682 100644
--- a/src/Infrastructure.WebApi.Generators/Extensions/StringExtensions.cs
+++ b/src/Tools.Generators.WebApi/Extensions/StringExtensions.cs
@@ -1,4 +1,4 @@
-namespace Infrastructure.WebApi.Generators.Extensions;
+namespace Tools.Generators.WebApi.Extensions;
public static class StringExtensions
{
diff --git a/src/Infrastructure.WebApi.Generators/MinimalApiMediatRGenerator.cs b/src/Tools.Generators.WebApi/MinimalApiMediatRGenerator.cs
similarity index 97%
rename from src/Infrastructure.WebApi.Generators/MinimalApiMediatRGenerator.cs
rename to src/Tools.Generators.WebApi/MinimalApiMediatRGenerator.cs
index ea209b26..bb5754cf 100644
--- a/src/Infrastructure.WebApi.Generators/MinimalApiMediatRGenerator.cs
+++ b/src/Tools.Generators.WebApi/MinimalApiMediatRGenerator.cs
@@ -1,11 +1,15 @@
using System.Text;
-using Infrastructure.WebApi.Generators.Extensions;
using Infrastructure.WebApi.Interfaces;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
+using Tools.Generators.WebApi.Extensions;
-namespace Infrastructure.WebApi.Generators;
+namespace Tools.Generators.WebApi;
+///
+/// A source generators for converting to
+/// Minimal API registrations and MediatR handlers
+///
[Generator]
public class MinimalApiMediatRGenerator : ISourceGenerator
{
diff --git a/src/Infrastructure.WebApi.Generators/README.md b/src/Tools.Generators.WebApi/README.md
similarity index 100%
rename from src/Infrastructure.WebApi.Generators/README.md
rename to src/Tools.Generators.WebApi/README.md
diff --git a/src/Infrastructure.WebApi.Generators/Infrastructure.WebApi.Generators.csproj b/src/Tools.Generators.WebApi/Tools.Generators.WebApi.csproj
similarity index 100%
rename from src/Infrastructure.WebApi.Generators/Infrastructure.WebApi.Generators.csproj
rename to src/Tools.Generators.WebApi/Tools.Generators.WebApi.csproj
index 2a71650d..e77bea4c 100644
--- a/src/Infrastructure.WebApi.Generators/Infrastructure.WebApi.Generators.csproj
+++ b/src/Tools.Generators.WebApi/Tools.Generators.WebApi.csproj
@@ -2,8 +2,8 @@
net7.0
- true
true
+ true
diff --git a/src/Infrastructure.WebApi.Generators/WebApiAssemblyVisitor.cs b/src/Tools.Generators.WebApi/WebApiAssemblyVisitor.cs
similarity index 99%
rename from src/Infrastructure.WebApi.Generators/WebApiAssemblyVisitor.cs
rename to src/Tools.Generators.WebApi/WebApiAssemblyVisitor.cs
index 7d6bc4e4..b4190b16 100644
--- a/src/Infrastructure.WebApi.Generators/WebApiAssemblyVisitor.cs
+++ b/src/Tools.Generators.WebApi/WebApiAssemblyVisitor.cs
@@ -1,9 +1,9 @@
-using Infrastructure.WebApi.Generators.Extensions;
using Infrastructure.WebApi.Interfaces;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Tools.Generators.WebApi.Extensions;
-namespace Infrastructure.WebApi.Generators;
+namespace Tools.Generators.WebApi;
///
/// Visits all namespaces, and types in the current assembly (only),