Skip to content

Commit

Permalink
Fix last test
Browse files Browse the repository at this point in the history
  • Loading branch information
k94ll13nn3 committed Oct 7, 2023
1 parent 069b970 commit 89f0bc2
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 83 deletions.
140 changes: 60 additions & 80 deletions src/AutoConstructor.Generator/AutoConstructorGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,36 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
i.AddSource(Source.InjectAttributeFullName, SourceText.From(Source.InjectAttributeText, Encoding.UTF8));
});

IncrementalValuesProvider<(MainNamedTypeSymbolInfo? symbol, EquatableArray<FieldInfo> fields, Options options, EquatableArray<Diagnostic> diagnostics)> valueProvider = context.SyntaxProvider
IncrementalValuesProvider<GeneratorExectutionResult?> valueProvider = context.SyntaxProvider
.ForAttributeWithMetadataName(
Source.AttributeFullName,
static (node, _) => IsSyntaxTargetForGeneration(node),
static (context, _) => (ClassDeclarationSyntax)context.TargetNode)
.Where(static m => m is not null)
.Collect()
.Combine(context.AnalyzerConfigOptionsProvider.Select((c, _) => c.GlobalOptions))
.Combine(context.CompilationProvider)
.SelectMany((c, _) =>
.Select((c, _) =>
{
(ImmutableArray<ClassDeclarationSyntax> classes, AnalyzerConfigOptions options, Compilation compilation) = (c.Left.Left, c.Left.Right, c.Right);
return Execute(compilation, classes, options);
(ClassDeclarationSyntax classSyntax, AnalyzerConfigOptions options, Compilation compilation) = (c.Left.Left, c.Left.Right, c.Right);
return Execute(compilation, classSyntax, options);
});

context.RegisterSourceOutput(valueProvider, static (context, item) =>
{
if (!item.diagnostics.IsEmpty)
if (item is not null)
{
foreach (Diagnostic diagnostic in item.diagnostics)
if (!item.Diagnostics.IsEmpty)
{
context.ReportDiagnostic(diagnostic);
foreach (Diagnostic diagnostic in item.Diagnostics)
{
context.ReportDiagnostic(diagnostic);
}
}
else
{
CodeGenerator codeGenerator = GenerateAutoConstructor(item.Symbol!, item.Fields, item.Options);
context.AddSource($"{item.Symbol!.Filename}.g.cs", codeGenerator.ToString());
}
}
else
{
CodeGenerator codeGenerator = GenerateAutoConstructor(item.symbol!, item.fields, item.options);
context.AddSource($"{item.symbol!.Filename}.g.cs", codeGenerator.ToString());
}
});
}
Expand All @@ -62,23 +64,8 @@ private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
return node is ClassDeclarationSyntax classDeclarationSyntax && classDeclarationSyntax.Modifiers.Any(SyntaxKind.PartialKeyword);
}

private static IEnumerable<(MainNamedTypeSymbolInfo? symbol, EquatableArray<FieldInfo> fields, Options options, EquatableArray<Diagnostic> diagnostics)> Execute(Compilation compilation, ImmutableArray<ClassDeclarationSyntax> classes, AnalyzerConfigOptions analyzerOptions)
private static GeneratorExectutionResult? Execute(Compilation compilation, ClassDeclarationSyntax classSyntax, AnalyzerConfigOptions analyzerOptions)
{
if (classes.IsDefaultOrEmpty)
{
yield break;
}

IEnumerable<IGrouping<ISymbol?, ClassDeclarationSyntax>> classesBySymbol = Enumerable.Empty<IGrouping<ISymbol?, ClassDeclarationSyntax>>();
try
{
classesBySymbol = classes.GroupBy(c => compilation.GetSemanticModel(c.SyntaxTree).GetDeclaredSymbol(c), SymbolEqualityComparer.Default);
}
catch (ArgumentException)
{
yield break;
}

bool generateConstructorDocumentation = false;
if (analyzerOptions.TryGetValue("build_property.AutoConstructor_GenerateConstructorDocumentation", out string? generateConstructorDocumentationSwitch))
{
Expand All @@ -95,69 +82,61 @@ private static bool IsSyntaxTargetForGeneration(SyntaxNode node)

Options options = new(generateConstructorDocumentation, constructorDocumentationComment, emitNullChecks);

foreach (IGrouping<ISymbol?, ClassDeclarationSyntax> groupedClasses in classesBySymbol)
INamedTypeSymbol? symbol = compilation.GetSemanticModel(classSyntax.SyntaxTree).GetDeclaredSymbol(classSyntax);
if (symbol is null)
{
INamedTypeSymbol? symbol = groupedClasses.Key as INamedTypeSymbol;
if (symbol is not null)
{
string filename = string.Empty;
return null;
}

if (symbol.ContainingType is not null)
{
filename = $"{string.Join(".", symbol.GetContainingTypes().Select(c => c.Name))}.";
}
string filename = string.Empty;
if (symbol.ContainingType is not null)
{
filename = $"{string.Join(".", symbol.GetContainingTypes().Select(c => c.Name))}.";
}

filename += $"{symbol.Name}";
filename += $"{symbol.Name}";

if (symbol.TypeArguments.Length > 0)
{
filename += string.Concat(symbol.TypeArguments.Select(tp => $".{tp.Name}"));
}
if (symbol.TypeArguments.Length > 0)
{
filename += string.Concat(symbol.TypeArguments.Select(tp => $".{tp.Name}"));
}

if (!symbol.ContainingNamespace.IsGlobalNamespace)
{
filename = $"{symbol.ContainingNamespace.ToDisplayString()}.{filename}";
}
if (!symbol.ContainingNamespace.IsGlobalNamespace)
{
filename = $"{symbol.ContainingNamespace.ToDisplayString()}.{filename}";
}

List<FieldInfo> concatenatedFields = GetFieldsFromSymbol(compilation, symbol, emitNullChecks);
List<FieldInfo> concatenatedFields = GetFieldsFromSymbol(compilation, symbol, emitNullChecks);

ExtractFieldsFromParent(compilation, symbol, emitNullChecks, concatenatedFields);
ExtractFieldsFromParent(compilation, symbol, emitNullChecks, concatenatedFields);

EquatableArray<FieldInfo> fields = concatenatedFields.ToImmutableArray();
EquatableArray<FieldInfo> fields = concatenatedFields.ToImmutableArray();

if (fields.IsEmpty)
{
// No need to report diagnostic, taken care by the analyzers.
continue;
}
if (fields.IsEmpty)
{
// No need to report diagnostic, taken care by the analyzers.
return null;
}

var diagnotics = new List<Diagnostic>();
var diagnotics = new List<Diagnostic>();

if (fields.GroupBy(x => x.ParameterName).Any(g =>
g.Where(c => c.Type is not null).Select(c => c.Type).Count() > 1
|| (g.All(c => c.Type is null) && g.Select(c => c.FallbackType).Count() > 1)
))
{
foreach (ClassDeclarationSyntax classDeclaration in groupedClasses)
{
diagnotics.Add(Diagnostic.Create(DiagnosticDescriptors.MistmatchTypesRule, classDeclaration.GetLocation()));
}
if (fields.GroupBy(x => x.ParameterName).Any(g =>
g.Where(c => c.Type is not null).Select(c => c.Type).Count() > 1
|| (g.All(c => c.Type is null) && g.Select(c => c.FallbackType).Count() > 1)
))
{
diagnotics.Add(Diagnostic.Create(DiagnosticDescriptors.MistmatchTypesRule, classSyntax.GetLocation()));

yield return (null, fields, options, diagnotics.ToImmutableArray());
continue;
}
return new(null, fields, options, diagnotics.ToImmutableArray());
}

bool hasParameterlessConstructor =
groupedClasses
.SelectMany(c => c
.ChildNodes()
.Where(n => n is ConstructorDeclarationSyntax constructor && !constructor.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword))))
.Count() == 1
&& symbol.Constructors.Any(d => !d.IsStatic && d.Parameters.Length == 0);
bool hasParameterlessConstructor =
classSyntax
.ChildNodes()
.Count(n => n is ConstructorDeclarationSyntax constructor && !constructor.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword))) == 1
&& symbol.Constructors.Any(d => !d.IsStatic && d.Parameters.Length == 0);

yield return (new MainNamedTypeSymbolInfo(symbol, hasParameterlessConstructor, filename), fields, options, Array.Empty<Diagnostic>().ToImmutableArray());
}
}
return new(new MainNamedTypeSymbolInfo(symbol, hasParameterlessConstructor, filename), fields, options, Array.Empty<Diagnostic>().ToImmutableArray());
}

private static CodeGenerator GenerateAutoConstructor(MainNamedTypeSymbolInfo symbol, EquatableArray<FieldInfo> fields, Options options)
Expand All @@ -166,7 +145,8 @@ private static CodeGenerator GenerateAutoConstructor(MainNamedTypeSymbolInfo sym
string? constructorDocumentationComment = options.ConstructorDocumentationComment;
if (string.IsNullOrWhiteSpace(constructorDocumentationComment))
{
constructorDocumentationComment = $"Initializes a new instance of the {{0}} class. // Counter: {Interlocked.Increment(ref _counter)}";
constructorDocumentationComment = "Initializes a new instance of the {0} class.";
//constructorDocumentationComment = $"Initializes a new instance of the {{0}} class. // Counter: {Interlocked.Increment(ref _counter)}";

Check warning on line 149 in src/AutoConstructor.Generator/AutoConstructorGenerator.cs

View workflow job for this annotation

GitHub Actions / windows-latest

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)

Check warning on line 149 in src/AutoConstructor.Generator/AutoConstructorGenerator.cs

View workflow job for this annotation

GitHub Actions / windows-latest

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)
}

var codeGenerator = new CodeGenerator();
Expand Down Expand Up @@ -336,7 +316,7 @@ private static void ExtractFieldsFromGeneratedParent(Compilation compilation, bo
string.Empty,
string.Empty,
parameter.FallbackType,
false,//IsNullable(parameter.FallbackType),
parameter.Nullable,
null,
false,
FieldType.PassedToBase));
Expand Down
9 changes: 9 additions & 0 deletions src/AutoConstructor.Generator/GeneratorExectutionResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Microsoft.CodeAnalysis;

namespace AutoConstructor.Generator;

internal record GeneratorExectutionResult(
MainNamedTypeSymbolInfo? Symbol,
EquatableArray<FieldInfo> Fields,
Options Options,
EquatableArray<Diagnostic> Diagnostics);
1 change: 1 addition & 0 deletions tests/AutoConstructor.Tests/AutoConstructor.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);CS1591</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
5 changes: 2 additions & 3 deletions tests/AutoConstructor.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ public Test(int i1)
}

[Fact]
public async Task Run_WithMismatchingTypesWithTwoPartialParts_ShouldReportDiagnosticOnEachPart()
public async Task Run_WithMismatchingTypesWithTwoPartialParts_ShouldReportDiagnosticOnFirstPart()
{
const string code = @"
namespace Test
Expand All @@ -1028,8 +1028,7 @@ internal partial class Test
}";

DiagnosticResult diagnosticResultFirstPart = new DiagnosticResult(DiagnosticDescriptors.MistmatchTypesDiagnosticId, DiagnosticSeverity.Error).WithSpan(4, 5, 9, 6);
DiagnosticResult diagnosticResultSecondPart = new DiagnosticResult(DiagnosticDescriptors.MistmatchTypesDiagnosticId, DiagnosticSeverity.Error).WithSpan(11, 5, 14, 6);
await VerifySourceGenerator.RunAsync(code, diagnostics: new[] { diagnosticResultFirstPart, diagnosticResultSecondPart });
await VerifySourceGenerator.RunAsync(code, diagnostics: new[] { diagnosticResultFirstPart });
}

[Theory]
Expand Down

0 comments on commit 89f0bc2

Please sign in to comment.