Skip to content

Commit

Permalink
Merge pull request #69 from WeihanLi/add-source-generator
Browse files Browse the repository at this point in the history
Add source generator for repository-pattern code
  • Loading branch information
WeihanLi authored Dec 21, 2024
2 parents 1b09ec7 + f942987 commit a25ff2a
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<CommonVersion>1.0.72</CommonVersion>
<CommonVersion>1.0.73</CommonVersion>
<EFVersion>9.0.0</EFVersion>

<PublishRepositoryUrl>true</PublishRepositoryUrl>
Expand Down
15 changes: 15 additions & 0 deletions WeihanLi.EntityFramework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WeihanLi.EntityFramework.Te
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{A1756F80-F25E-4ADC-A079-048FFCA5DBA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WeihanLi.EntityFramework.SourceGenerator", "src\WeihanLi.EntityFramework.SourceGenerator\WeihanLi.EntityFramework.SourceGenerator.csproj", "{010A98BE-1871-4E6F-8129-7A1C44C73423}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -61,6 +63,18 @@ Global
{9DF6D464-63A7-487C-9763-4A212ADDFC4B}.Release|x64.Build.0 = Release|Any CPU
{9DF6D464-63A7-487C-9763-4A212ADDFC4B}.Release|x86.ActiveCfg = Release|Any CPU
{9DF6D464-63A7-487C-9763-4A212ADDFC4B}.Release|x86.Build.0 = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|Any CPU.Build.0 = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|x64.ActiveCfg = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|x64.Build.0 = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|x86.ActiveCfg = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Debug|x86.Build.0 = Debug|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|Any CPU.ActiveCfg = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|Any CPU.Build.0 = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|x64.ActiveCfg = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|x64.Build.0 = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|x86.ActiveCfg = Release|Any CPU
{010A98BE-1871-4E6F-8129-7A1C44C73423}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -69,6 +83,7 @@ Global
{0BB1C3F3-50C6-4924-894C-0A9A7BA4E54A} = {40B7673F-5ACD-42E4-AE04-6C3AEEBC8546}
{0E013C55-6D52-4B68-B188-460B97DB1E48} = {46AED92E-94FC-409A-9CFB-C9CD4E59717D}
{9DF6D464-63A7-487C-9763-4A212ADDFC4B} = {A1756F80-F25E-4ADC-A079-048FFCA5DBA6}
{010A98BE-1871-4E6F-8129-7A1C44C73423} = {40B7673F-5ACD-42E4-AE04-6C3AEEBC8546}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {201A8B4F-A16D-44B7-BB29-F9B9CFC2A467}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using System.Text;

namespace WeihanLi.EntityFramework.SourceGenerator;

[Generator]

Check warning on line 9 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably. (https://github.com/dotnet/roslyn-analyzers/blob/main/docs/rules/RS1041.md)

Check warning on line 9 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably. (https://github.com/dotnet/roslyn-analyzers/blob/main/docs/rules/RS1041.md)

Check warning on line 9 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably. (https://github.com/dotnet/roslyn-analyzers/blob/main/docs/rules/RS1041.md)

Check warning on line 9 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

This compiler extension should not be implemented in an assembly with target framework '.NET 8.0'. References to other target frameworks will cause the compiler to behave unpredictably. (https://github.com/dotnet/roslyn-analyzers/blob/main/docs/rules/RS1041.md)
public sealed class EFRepositorySourceGenerator : IIncrementalGenerator

Check warning on line 10 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

'WeihanLi.EntityFramework.SourceGenerator.EFRepositorySourceGenerator': A project containing analyzers or source generators should specify the property '<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>'

Check warning on line 10 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

'WeihanLi.EntityFramework.SourceGenerator.EFRepositorySourceGenerator': A project containing analyzers or source generators should specify the property '<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>'

Check warning on line 10 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

'WeihanLi.EntityFramework.SourceGenerator.EFRepositorySourceGenerator': A project containing analyzers or source generators should specify the property '<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>'

Check warning on line 10 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

'WeihanLi.EntityFramework.SourceGenerator.EFRepositorySourceGenerator': A project containing analyzers or source generators should specify the property '<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>'
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var additionalFiles = context.AdditionalTextsProvider
.Where(file => file.Path.EndsWith(".template"))
.Select((file, cancellationToken) => file.GetText(cancellationToken)?.ToString())
.Where(content => !string.IsNullOrEmpty(content));

var dbContextDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => IsDbContextDeclaration(s),
transform: static (ctx, _) => GetDbContextDeclaration(ctx))
.Where(static m => m is not null);

var combined = dbContextDeclarations.Combine(additionalFiles.Collect());

context.RegisterSourceOutput(combined, (spc, source) =>
{
var (dbContextDeclaration, templates) = source;
var dbContextName = dbContextDeclaration!.Identifier.Text;
var repositoryNamespace = dbContextDeclaration.Parent!.GetNamespace();
var generatedCode = GenerateRepositoryCode(dbContextName, repositoryNamespace, templates);

Check warning on line 32 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Argument of type 'ImmutableArray<string?>' cannot be used for parameter 'templates' of type 'ImmutableArray<string>' in 'string EFRepositorySourceGenerator.GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)' due to differences in the nullability of reference types.

Check warning on line 32 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Argument of type 'ImmutableArray<string?>' cannot be used for parameter 'templates' of type 'ImmutableArray<string>' in 'string EFRepositorySourceGenerator.GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)' due to differences in the nullability of reference types.

Check warning on line 32 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Argument of type 'ImmutableArray<string?>' cannot be used for parameter 'templates' of type 'ImmutableArray<string>' in 'string EFRepositorySourceGenerator.GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)' due to differences in the nullability of reference types.

Check warning on line 32 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Argument of type 'ImmutableArray<string?>' cannot be used for parameter 'templates' of type 'ImmutableArray<string>' in 'string EFRepositorySourceGenerator.GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)' due to differences in the nullability of reference types.

Check warning on line 32 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Argument of type 'ImmutableArray<string?>' cannot be used for parameter 'templates' of type 'ImmutableArray<string>' in 'string EFRepositorySourceGenerator.GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)' due to differences in the nullability of reference types.
spc.AddSource($"{dbContextName}Repository.g.cs", SourceText.From(generatedCode, Encoding.UTF8));
});
}

private static bool IsDbContextDeclaration(SyntaxNode node)
{
return node is ClassDeclarationSyntax classDeclaration &&
classDeclaration.BaseList?.Types.Any(t => t.ToString().Contains("DbContext")) == true;
}

private static ClassDeclarationSyntax? GetDbContextDeclaration(GeneratorSyntaxContext context)
{
var classDeclaration = (ClassDeclarationSyntax)context.Node;
return classDeclaration;
}

private static string GenerateRepositoryCode(string dbContextName, string repositoryNamespace, ImmutableArray<string> templates)
{
var builder = new StringBuilder();
builder.AppendLine("using WeihanLi.EntityFramework;");
builder.AppendLine($"namespace {repositoryNamespace}");
builder.AppendLine("{");

foreach (var template in templates)
{
var code = template.Replace("{{DbContextName}}", dbContextName);
builder.AppendLine(code);
}

builder.AppendLine("}");
return builder.ToString();
}
}

internal static class SyntaxNodeExtensions
{
public static string GetNamespace(this SyntaxNode node)
{
while (node != null)
{
if (node is NamespaceDeclarationSyntax namespaceDeclaration)
{
return namespaceDeclaration.Name.ToString();
}

node = node.Parent;

Check warning on line 78 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 78 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 78 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 78 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.

Check warning on line 78 in src/WeihanLi.EntityFramework.SourceGenerator/EFRepositorySourceGenerator.cs

View workflow job for this annotation

GitHub Actions / build

Converting null literal or possible null value to non-nullable type.
}

return string.Empty;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>WeihanLi.EntityFramework.SourceGenerator</Title>
<Description>Source generator for WeihanLi.EntityFramework</Description>
<Authors>WeihanLi</Authors>
<Company>WeihanLi</Company>
<Product>WeihanLi.EntityFramework</Product>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryUrl>https://github.com/WeihanLi/WeihanLi.EntityFramework</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Copyright>Copyright 2019-2024 (c) WeihanLi</Copyright>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions src/WeihanLi.EntityFramework/WeihanLi.EntityFramework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="$(EFVersion)" />
<PackageReference Include="WeihanLi.Common" Version="$(CommonVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WeihanLi.EntityFramework.SourceGenerator\WeihanLi.EntityFramework.SourceGenerator.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="$(EFVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(EFVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
</ItemGroup>

Expand Down

0 comments on commit a25ff2a

Please sign in to comment.