Skip to content

Commit

Permalink
支持C#11(NET7+)的 泛型特性GenericAttribute 标注生成DTO #4
Browse files Browse the repository at this point in the history
  • Loading branch information
vipwan committed Nov 7, 2023
1 parent a5b6197 commit 8a49c57
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 57 deletions.
18 changes: 18 additions & 0 deletions Biwen.AutoClassGen.Attributes/AutoDtoAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,22 @@ public AutoDtoAttribute(Type fromType, params string[] excludeProps)
ExcludeProps = excludeProps;
}
}

#if NET7_0_OR_GREATER

/// <summary>
/// 自动创建Dto
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
#pragma warning disable SA1402 // File may only contain a single type
public class AutoDtoAttribute<T> : AutoDtoAttribute
#pragma warning restore SA1402 // File may only contain a single type
{
public AutoDtoAttribute(params string[] excludeProps) : base(typeof(T), excludeProps)
{
}
}

#endif

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks>netstandard2.0;net7.0</TargetFrameworks>
<PackageVersion>1.1.0.3</PackageVersion>
<PackageProjectUrl>https://github.com/vipwan/Biwen.AutoClassGen</PackageProjectUrl>
<Authors>万雅虎</Authors>
Expand Down Expand Up @@ -32,7 +32,7 @@
</Choose>
<ItemGroup>

<PackageReference Include="Biwen.AutoClassGen" Version="1.1.0.3" PrivateAssets="contentfiles;analyzers" />
<!--<PackageReference Include="Biwen.AutoClassGen" Version="1.1.0.3" PrivateAssets="contentfiles;analyzers" />-->

<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.507">
<PrivateAssets>all</PrivateAssets>
Expand Down
148 changes: 97 additions & 51 deletions Biwen.AutoClassGen.Gen/SourceGenAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Biwen.AutoClassGen
{
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
Expand All @@ -18,6 +19,7 @@ public class SourceGenAnalyzer : DiagnosticAnalyzer
public const string GEN011 = "GEN011";
public const string GEN021 = "GEN021";
public const string GEN031 = "GEN031"; // 推荐生成
public const string GEN041 = "GEN041"; // 重复标注

/// <summary>
/// 无法生成类的错误
Expand Down Expand Up @@ -53,7 +55,6 @@ public class SourceGenAnalyzer : DiagnosticAnalyzer
helpLinkUri: Helplink,
isEnabledByDefault: true);


/// <summary>
/// 推荐使用自动生成
/// </summary>
Expand All @@ -66,15 +67,35 @@ public class SourceGenAnalyzer : DiagnosticAnalyzer
isEnabledByDefault: true);


/// <summary>
/// Dto特性重复标注
/// </summary>
private static readonly DiagnosticDescriptor MutiMarkedAutoDtoError = new(id: GEN041,
title: "重复标注[AutoDto]",
messageFormat: "重复标注了[AutoDto],请删除多余的标注",
category: typeof(SourceGenerator).Assembly.GetName().Name,
DiagnosticSeverity.Error,
helpLinkUri: Helplink,
isEnabledByDefault: true);




#endregion

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
InvalidDeclareError,
InvalidDeclareNameError,
SuggestDeclareNameWarning,
SuggestAutoGen);
SuggestAutoGen,
MutiMarkedAutoDtoError);

private const string AttributeValueMetadataName = "AutoGen";
/// <summary>
/// Dto特性名称,注意存在泛型的情况
/// </summary>
private const string AttributeValueMetadataNameDto = "AutoDto";


public override void Initialize(AnalysisContext context)
{
Expand All @@ -83,67 +104,92 @@ public override void Initialize(AnalysisContext context)
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(ctx =>
{
// Find implicitly typed interface declarations.
var declaration = (InterfaceDeclarationSyntax)ctx.Node;
if (declaration == null) return;

if (declaration.AttributeLists.Count > 0)
var kind = ctx.Node.Kind();
// InterfaceDeclarationSyntax
if (kind == SyntaxKind.InterfaceDeclaration)
{
foreach (var attr in declaration.AttributeLists.AsEnumerable())
var declaration = (InterfaceDeclarationSyntax)ctx.Node;

if (declaration.AttributeLists.Count > 0)
{
if (attr.Attributes.Any(x => x.Name.ToString() == AttributeValueMetadataName))
foreach (var attr in declaration.AttributeLists.AsEnumerable())
{
if (declaration.BaseList == null || !declaration.BaseList.Types.Any())
if (attr.Attributes.Any(x => x.Name.ToString() == AttributeValueMetadataName))
{
// issue error
ctx.ReportDiagnostic(Diagnostic.Create(InvalidDeclareError, attr.GetLocation()));
}

var arg0 = attr.Attributes.First(x => x.Name.ToString() == AttributeValueMetadataName)
.ArgumentList!.Arguments[0];

var arg1 = attr.Attributes.First(x => x.Name.ToString() == AttributeValueMetadataName)
.ArgumentList!.Arguments[1];

if (declaration.Identifier.Text == arg0.GetText().ToString().Replace("\"", ""))
{
var location = arg0?.GetLocation();
// issue error
ctx.ReportDiagnostic(Diagnostic.Create(InvalidDeclareNameError, location));
}

// NamespaceDeclarationSyntax
if (declaration.Parent is NamespaceDeclarationSyntax @namespace &&
@namespace?.Name.ToString() != arg1?.GetText().ToString().Replace("\"", ""))
{
var location = arg1?.GetLocation();
// issue warning
ctx.ReportDiagnostic(Diagnostic.Create(SuggestDeclareNameWarning, location));
}
// FileScopedNamespaceDeclaration
if (declaration.Parent is FileScopedNamespaceDeclarationSyntax @namespace2 &&
@namespace2?.Name.ToString() != arg1?.GetText().ToString().Replace("\"", ""))
{
var location = arg1?.GetLocation();
// issue warning
ctx.ReportDiagnostic(Diagnostic.Create(SuggestDeclareNameWarning, location));
if (declaration.BaseList == null || !declaration.BaseList.Types.Any())
{
// issue error
ctx.ReportDiagnostic(Diagnostic.Create(InvalidDeclareError, attr.GetLocation()));
}

var arg0 = attr.Attributes.First(x => x.Name.ToString() == AttributeValueMetadataName)
.ArgumentList!.Arguments[0];

var arg1 = attr.Attributes.First(x => x.Name.ToString() == AttributeValueMetadataName)
.ArgumentList!.Arguments[1];

if (declaration.Identifier.Text == arg0.GetText().ToString().Replace("\"", ""))
{
var location = arg0?.GetLocation();
// issue error
ctx.ReportDiagnostic(Diagnostic.Create(InvalidDeclareNameError, location));
}

// NamespaceDeclarationSyntax
if (declaration.Parent is NamespaceDeclarationSyntax @namespace &&
@namespace?.Name.ToString() != arg1?.GetText().ToString().Replace("\"", ""))
{
var location = arg1?.GetLocation();
// issue warning
ctx.ReportDiagnostic(Diagnostic.Create(SuggestDeclareNameWarning, location));
}
// FileScopedNamespaceDeclaration
if (declaration.Parent is FileScopedNamespaceDeclarationSyntax @namespace2 &&
@namespace2?.Name.ToString() != arg1?.GetText().ToString().Replace("\"", ""))
{
var location = arg1?.GetLocation();
// issue warning
ctx.ReportDiagnostic(Diagnostic.Create(SuggestDeclareNameWarning, location));
}
}
}
}
// suggest
if (declaration.BaseList != null && declaration.BaseList.Types.Any(x => x.IsKind(SyntaxKind.SimpleBaseType)))
{
var haveAttr = declaration.AttributeLists.Any(x => x.Attributes.Any(x => x.Name.ToString() == AttributeValueMetadataName));
if (!haveAttr)
{
var location = declaration.GetLocation();
// issue suggest
ctx.ReportDiagnostic(Diagnostic.Create(SuggestAutoGen, location));
}
}
}

// suggest
if (declaration.BaseList != null && declaration.BaseList.Types.Any(x => x.IsKind(SyntaxKind.SimpleBaseType)))
// ClassDeclarationSyntax
if (kind == SyntaxKind.ClassDeclaration)
{
var haveAttr = declaration.AttributeLists.Any(x => x.Attributes.Any(x => x.Name.ToString() == AttributeValueMetadataName));
if (!haveAttr)
var declaration = (ClassDeclarationSyntax)ctx.Node;
if (declaration.AttributeLists.Count > 0)
{
var location = declaration.GetLocation();
// issue suggest
ctx.ReportDiagnostic(Diagnostic.Create(SuggestAutoGen, location));
foreach (var attr in declaration.AttributeLists.AsEnumerable())
{
if (attr.Attributes.Where(x => x.Name.ToString().IndexOf(
AttributeValueMetadataNameDto, StringComparison.Ordinal) == 0).Count() > 1)
{
var location = declaration.GetLocation();

// issue error
ctx.ReportDiagnostic(Diagnostic.Create(MutiMarkedAutoDtoError, location));
}
}
}
}
}, SyntaxKind.InterfaceDeclaration);

},
SyntaxKind.InterfaceDeclaration,
SyntaxKind.ClassDeclaration);

}
}
}
Loading

0 comments on commit 8a49c57

Please sign in to comment.