Skip to content

Commit a7deedd

Browse files
committed
Implementando AutoPropertiesAttribute
1 parent c590eb2 commit a7deedd

22 files changed

Lines changed: 670 additions & 33 deletions

src/AnalyzerReleases.Shipped.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ Rule ID | Category | Severity | Notes
77
RCSS000 | Usage | Error | RCSS000_Invalid_model_type, [Documentation](https://google.com)
88
RCSS001 | Usage | Error | RCSS001_It_is_not_possible_to_determine_a_corresponding_property_for_the_other_type, [Documentation](https://google.com)
99
RCSS002 | Usage | Error | RCSS002_Incompatible_property_types, [Documentation](https://google.com)
10+
RCSS003 | Usage | Error | RCSS003_Invalid_auto_property, [Documentation](https://google.com)

src/Directory.Build.props

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
<GenFrwkVer>netstandard2.0</GenFrwkVer>
66
</PropertyGroup>
77
<PropertyGroup>
8-
<DotNetCoreVersion>8.0.15</DotNetCoreVersion>
8+
<DotNetCoreVersion>8.0.20</DotNetCoreVersion>
9+
<ExtSrcGenVer>0.1.7</ExtSrcGenVer>
910
</PropertyGroup>
1011
<PropertyGroup>
11-
<Ver>0.0.1</Ver>
12-
<Prev>-betha-1</Prev>
12+
<Ver>0.1.0</Ver>
13+
<Prev></Prev>
1314
</PropertyGroup>
1415
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
namespace RoyalCode.SmartSelector.Benchmarks.Benchmarks;
4+
5+
internal static class Logger
6+
{
7+
public static ILoggerFactory CreateLoggerFactory() =>
8+
LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Warning));
9+
}

src/RoyalCode.SmartSelector.Benchmarks/Benchmarks/ProductMappingBenchmark.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ public void Setup()
2525
.ToList();
2626

2727
// AutoMapper configuration
28-
var mapperConfig = new MapperConfiguration(cfg => cfg.CreateMap<Product, ProductDetails>());
28+
var mapperConfig = new MapperConfiguration(
29+
cfg => cfg.CreateMap<Product, ProductDetails>(),
30+
Logger.CreateLoggerFactory());
2931
_autoMapper = mapperConfig.CreateMapper();
3032

3133
// Mapster configuration

src/RoyalCode.SmartSelector.Benchmarks/Benchmarks/ProductQueryableBenchmark.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ public void Setup()
2525
_queryable = data.AsQueryable();
2626

2727
// AutoMapper configuration
28-
var mapperConfig = new AutoMapper.MapperConfiguration(cfg => cfg.CreateMap<Product, ProductDetails>());
28+
var mapperConfig = new AutoMapper.MapperConfiguration(
29+
cfg => cfg.CreateMap<Product, ProductDetails>(),
30+
Logger.CreateLoggerFactory());
2931
_autoMapper = mapperConfig.CreateMapper();
3032

3133
// Mapster configuration for projection

src/RoyalCode.SmartSelector.Benchmarks/Benchmarks/ProductToDetailsBenchmark.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ public void Setup()
2222
product = new Product("Sample Product");
2323

2424
// AutoMapper configuration
25-
var mapperConfig = new MapperConfiguration(cfg => cfg.CreateMap<Product, ProductDetails>());
25+
var mapperConfig = new MapperConfiguration(
26+
cfg => cfg.CreateMap<Product, ProductDetails>(),
27+
Logger.CreateLoggerFactory());
2628
_autoMapper = mapperConfig.CreateMapper();
2729

2830
// Mapster configuration

src/RoyalCode.SmartSelector.Benchmarks/RoyalCode.SmartSelector.Benchmarks.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818

1919
<ProjectReference Include="..\RoyalCode.SmartSelector.Generators\RoyalCode.SmartSelector.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
2020

21-
<PackageReference Include="RoyalCode.Extensions.SourceGenerator" Version="0.1.4" PrivateAssets="all" ReferenceOutputAssembly="false" />
21+
<PackageReference Include="RoyalCode.Extensions.SourceGenerator" Version="$(ExtSrcGenVer)" PrivateAssets="all" ReferenceOutputAssembly="false" />
2222
</ItemGroup>
2323
<ItemGroup>
24-
<Analyzer Include="$(NuGetPackageRoot)royalcode.extensions.sourcegenerator\0.1.4\lib\netstandard2.0\RoyalCode.Extensions.SourceGenerator.dll" />
24+
<Analyzer Include="$(NuGetPackageRoot)royalcode.extensions.sourcegenerator\$(ExtSrcGenVer)\lib\netstandard2.0\RoyalCode.Extensions.SourceGenerator.dll" />
2525
</ItemGroup>
2626
</Project>

src/RoyalCode.SmartSelector.Demo/RoyalCode.SmartSelector.Demo.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
OutputItemType="Analyzer"
1414
ReferenceOutputAssembly="false" />
1515

16-
<PackageReference Include="RoyalCode.Extensions.SourceGenerator" Version="0.1.4"
16+
<PackageReference Include="RoyalCode.Extensions.SourceGenerator" Version="$(ExtSrcGenVer)"
1717
PrivateAssets="all"
1818
ReferenceOutputAssembly="false" />
1919
</ItemGroup>
2020
<ItemGroup>
21-
<Analyzer Include="$(NuGetPackageRoot)royalcode.extensions.sourcegenerator\0.1.4\lib\netstandard2.0\RoyalCode.Extensions.SourceGenerator.dll" />
21+
<Analyzer Include="$(NuGetPackageRoot)royalcode.extensions.sourcegenerator\$(ExtSrcGenVer)\lib\netstandard2.0\RoyalCode.Extensions.SourceGenerator.dll" />
2222
</ItemGroup>
2323

2424
<PropertyGroup>
@@ -43,7 +43,7 @@
4343
</ItemGroup>
4444

4545
<ItemGroup>
46-
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.16" />
46+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="$(DotNetCoreVersion)" />
4747
</ItemGroup>
4848

4949
<ItemGroup>

src/RoyalCode.SmartSelector.Generators/AnalyzerDiagnostics.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,12 @@ internal static class AnalyzerDiagnostics
3030
defaultSeverity: DiagnosticSeverity.Error,
3131
isEnabledByDefault: true);
3232

33+
public static readonly DiagnosticDescriptor InvalidAutoProperty = new(
34+
id: "RCSS003",
35+
title: "Invalid Auto Property attribute usage",
36+
messageFormat: "Invalid use of AutoPropertyAttribute<TFrom> in class {0}, when using AutoSelectAttribute, use the non-generic version AutoPropertyAttribute",
37+
category: Category,
38+
defaultSeverity: DiagnosticSeverity.Error,
39+
isEnabledByDefault: true);
40+
3341
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using Microsoft.CodeAnalysis.CSharp.Syntax;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace RoyalCode.SmartSelector.Generators.Generators;
5+
6+
internal static class AttributeSyntaxExtensions
7+
{
8+
public static IEnumerable<string> GetConstructorStrings(this AttributeSyntax attr)
9+
{
10+
if (attr.ArgumentList is not { Arguments.Count: > 0 }) yield break;
11+
foreach (var arg in attr.ArgumentList.Arguments)
12+
{
13+
if (arg.NameEquals is not null) continue; // skip named
14+
if (TryReadSingle(arg.Expression, out var value))
15+
yield return value;
16+
else if (arg.Expression is ArrayCreationExpressionSyntax acs && acs.Initializer is not null)
17+
{
18+
foreach (var expr in acs.Initializer.Expressions)
19+
if (TryReadSingle(expr, out var v)) yield return v;
20+
}
21+
else if (arg.Expression is ImplicitArrayCreationExpressionSyntax iacs && iacs.Initializer is not null)
22+
{
23+
foreach (var expr in iacs.Initializer.Expressions)
24+
if (TryReadSingle(expr, out var v)) yield return v;
25+
}
26+
else if (arg.Expression is InitializerExpressionSyntax init)
27+
{
28+
foreach (var expr in init.Expressions)
29+
if (TryReadSingle(expr, out var v)) yield return v;
30+
}
31+
}
32+
}
33+
34+
public static IEnumerable<string> GetConstructorStringSet(this AttributeSyntax attr)
35+
=> attr.GetConstructorStrings().Distinct(StringComparer.Ordinal);
36+
37+
public static IEnumerable<string> GetNamedArgumentStrings(this AttributeSyntax attr, string name)
38+
{
39+
if (attr.ArgumentList is not { Arguments.Count: > 0 }) yield break;
40+
foreach (var arg in attr.ArgumentList.Arguments)
41+
{
42+
if (arg.NameEquals?.Name.Identifier.Text != name) continue;
43+
var expr = arg.Expression;
44+
if (TryReadSingle(expr, out var value))
45+
{
46+
yield return value;
47+
continue;
48+
}
49+
if (expr is ArrayCreationExpressionSyntax acs && acs.Initializer is not null)
50+
{
51+
foreach (var item in acs.Initializer.Expressions)
52+
if (TryReadSingle(item, out var v)) yield return v;
53+
}
54+
else if (expr is ImplicitArrayCreationExpressionSyntax iacs && iacs.Initializer is not null)
55+
{
56+
foreach (var item in iacs.Initializer.Expressions)
57+
if (TryReadSingle(item, out var v)) yield return v;
58+
}
59+
else if (expr is InitializerExpressionSyntax init)
60+
{
61+
foreach (var item in init.Expressions)
62+
if (TryReadSingle(item, out var v)) yield return v;
63+
}
64+
}
65+
}
66+
67+
public static IEnumerable<string> GetNamedArgumentStringSet(this AttributeSyntax attr, string name)
68+
=> attr.GetNamedArgumentStrings(name).Distinct(StringComparer.Ordinal);
69+
70+
private static bool TryReadSingle(ExpressionSyntax expr, out string value)
71+
{
72+
switch (expr)
73+
{
74+
case LiteralExpressionSyntax { Token.Value: string s }:
75+
value = s; return true;
76+
case InvocationExpressionSyntax { Expression: IdentifierNameSyntax id } inv when id.Identifier.Text == "nameof":
77+
if (inv.ArgumentList.Arguments.Count == 1)
78+
{
79+
var inner = inv.ArgumentList.Arguments[0].Expression;
80+
if (inner is IdentifierNameSyntax ins)
81+
{ value = ins.Identifier.Text; return true; }
82+
if (inner is MemberAccessExpressionSyntax ma)
83+
{ value = ma.Name.Identifier.Text; return true; }
84+
}
85+
break;
86+
}
87+
value = string.Empty; return false;
88+
}
89+
}

0 commit comments

Comments
 (0)