Skip to content

Commit

Permalink
attribute generation bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
beakona committed Mar 16, 2024
1 parent 0540103 commit ff4ff62
Show file tree
Hide file tree
Showing 20 changed files with 409 additions and 183 deletions.
12 changes: 12 additions & 0 deletions AutoInterface.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeaKona.AutoInterfaceAttributes", "BeaKona.AutoInterfaceAttributes\BeaKona.AutoInterfaceAttributes.csproj", "{8EB5E4A3-F09E-42A8-9846-C000B2D5286C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestInterfacesNetStandard", "TestInterfacesNetStandard\TestInterfacesNetStandard.csproj", "{FD5316C0-B9E2-48C9-8597-19D241D2CCE4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoInterfaceSampleNetStandard", "AutoInterfaceSampleNetStandard\AutoInterfaceSampleNetStandard.csproj", "{FFDE2B7B-1B86-4FFD-800F-0682B5144560}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -39,6 +43,14 @@ Global
{8EB5E4A3-F09E-42A8-9846-C000B2D5286C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EB5E4A3-F09E-42A8-9846-C000B2D5286C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EB5E4A3-F09E-42A8-9846-C000B2D5286C}.Release|Any CPU.Build.0 = Release|Any CPU
{FD5316C0-B9E2-48C9-8597-19D241D2CCE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD5316C0-B9E2-48C9-8597-19D241D2CCE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD5316C0-B9E2-48C9-8597-19D241D2CCE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD5316C0-B9E2-48C9-8597-19D241D2CCE4}.Release|Any CPU.Build.0 = Release|Any CPU
{FFDE2B7B-1B86-4FFD-800F-0682B5144560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFDE2B7B-1B86-4FFD-800F-0682B5144560}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFDE2B7B-1B86-4FFD-800F-0682B5144560}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFDE2B7B-1B86-4FFD-800F-0682B5144560}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
5 changes: 4 additions & 1 deletion AutoInterfaceSample/AutoInterfaceSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="Serilog" Version="3.1.1" />
<ProjectReference Include="..\BeaKona.AutoInterfaceAttributes\BeaKona.AutoInterfaceAttributes.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
<ProjectReference Include="..\TestInterfacesNetStandard\TestInterfacesNetStandard.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TestInterfaces\TestInterfaces.csproj" />
<ProjectReference Include="..\TestInterfaces\TestInterfaces.csproj">
<Aliases></Aliases>
</ProjectReference>
</ItemGroup>

</Project>
58 changes: 12 additions & 46 deletions AutoInterfaceSample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,62 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
using TestInterfacesNetStandard;

namespace AutoInterfaceSample.Test
{
public partial record TestRecord(
[property: BeaKona.AutoInterface(IncludeBaseInterfaces = true)] NLog.ILogger nlog,
[property: BeaKona.AutoInterface(IncludeBaseInterfaces = true)] Serilog.ILogger slog,
[property: BeaKona.AutoInterface(IncludeBaseInterfaces = true)] Microsoft.Extensions.Logging.ILogger melog

) : NLog.ILogger;

public class Program
{
public static void Main()
{
//System.Diagnostics.Debug.WriteLine(BeaKona.Output.Debug_TestRecord.Info);

ITestInterfaceObsolete r = new TestObsoleteRecord(null);
r.TestObsoleteMethod("");
// ITestable p = new TestRecord(new SimpleLogger());

// p.Test();

//p.Log<int?>(LogLevel.Debug, default, 1, null, null);
//var result = p.BindProperty<int>("test", 1, false, out var property, 1, 2, 3);
}
}

partial record TestObsoleteRecord(
[property: BeaKona.AutoInterface(IncludeBaseInterfaces = true)]
ITestInterfaceObsolete Testable) : ITestInterfaceObsolete;
interface ITestInterfaceObsolete
partial record TestRecord
{
[Obsolete]
[DoesNotReturn]
[return: MaybeNull]
[return: NotNullIfNotNull(nameof(test))]
[return: TestReturn]
ResObject? TestObsoleteMethod(string? test);

[Obsolete]
[DisallowNull]
ResObject? TestObsoleteProperty
{
get;
}

[DisallowNull]
ResObject? TestExpandedProperty
{
[return: MaybeNull]
get;
}

//[BeaKona.AutoInterface(IncludeBaseInterfaces = true)]
public ITestable2? Testable { get; set; }
}
}

class ResObject;
namespace System.Diagnostics.CodeAnalysis
{

[AttributeUsage(AttributeTargets.All)]
class TestReturnAttribute : Attribute;
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute(bool returnValue) : Attribute
{
public bool ReturnValue { get; } = returnValue;
}
}
11 changes: 0 additions & 11 deletions AutoInterfaceSample/SimpleLogger.cs

This file was deleted.

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

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<Analyzer Include="..\BeaKona.AutoInterfaceGenerator\bin\Debug\netstandard2.0\BeaKona.AutoInterfaceGenerator.dll" />
<ProjectReference Include="..\BeaKona.AutoInterfaceAttributes\BeaKona.AutoInterfaceAttributes.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
<ProjectReference Include="..\TestInterfacesNetStandard\TestInterfacesNetStandard.csproj" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions AutoInterfaceSampleNetStandard/TestRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using TestInterfacesNetStandard;

namespace AutoInterfaceSampleNetStandard
{
partial class TestRecord
{
[BeaKona.AutoInterface(IncludeBaseInterfaces = true)]
public ITestable2? Testable { get; set; }
}
}

namespace System.Diagnostics.CodeAnalysis
{

[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
public NotNullWhenAttribute(bool returnValue)
{
this.ReturnValue = returnValue;
}

public bool ReturnValue { get; }
}
}
14 changes: 14 additions & 0 deletions BeaKona.AutoInterfaceGenerator/AliasRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Collections;

namespace BeaKona.AutoInterfaceGenerator;

public sealed class AliasRegistry : IEnumerable<string>
{
private readonly HashSet<string> aliases = [];

public void Add(string alias) => this.aliases.Add(alias);

IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();

public IEnumerator<string> GetEnumerator() => this.aliases.GetEnumerator();
}
27 changes: 27 additions & 0 deletions BeaKona.AutoInterfaceGenerator/AutoInterfaceResource.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions BeaKona.AutoInterfaceGenerator/AutoInterfaceResource.resx
Original file line number Diff line number Diff line change
Expand Up @@ -261,4 +261,13 @@
<data name="AG16_title" xml:space="preserve">
<value>Multiple partial templates found.</value>
</data>
<data name="AG17_description" xml:space="preserve">
<value>AG17</value>
</data>
<data name="AG17_message" xml:space="preserve">
<value>Following attributes are missing and should be implemented or referenced: {0}.</value>
</data>
<data name="AG17_title" xml:space="preserve">
<value>Missing attributes.</value>
</data>
</root>
31 changes: 27 additions & 4 deletions BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public void Execute(GeneratorExecutionContext context)
records.AddRange(GetRecords(context, property, property.Type, autoInterfaceAttributeSymbol, autoInterfaceTemplateAttributeSymbol));
}

var missingAttributes = new TypeRegistry();

// group elements by the containing class, and generate the source
foreach (IGrouping<INamedTypeSymbol, AutoInterfaceRecord> recordsByContainingType in records.GroupBy<AutoInterfaceRecord, INamedTypeSymbol>(i => i.Member.ContainingType, SymbolEqualityComparer.Default))
{
Expand Down Expand Up @@ -115,7 +117,7 @@ public void Execute(GeneratorExecutionContext context)

try
{
string? code = AutoInterfaceSourceGenerator.ProcessClass(context, compilation, containingType, recordsByContainingType);
string? code = AutoInterfaceSourceGenerator.GetSourceCodeForType(context, compilation, containingType, recordsByContainingType, missingAttributes);
if (code != null)
{
string name = containingType.Arity > 0 ? $"{containingType.Name}_{containingType.Arity}" : containingType.Name;
Expand All @@ -132,6 +134,16 @@ public void Execute(GeneratorExecutionContext context)
ex.ToString().Replace("\r", "").Replace("\n", ""));
}
}

if (missingAttributes.Count() > 0)
{
var toEmit = missingAttributes.Where(i => compilation.IsVisible(i) == false).ToList();
if (toEmit.Count > 0)
{
Helpers.ReportDiagnostic(context, "BKAG17", nameof(AutoInterfaceResource.AG17_title), nameof(AutoInterfaceResource.AG17_message), nameof(AutoInterfaceResource.AG17_description), DiagnosticSeverity.Error, (Location?)null,
string.Join(", ", toEmit.Select(i => i.ToDisplayString())));
}
}
}
}
}
Expand Down Expand Up @@ -582,12 +594,14 @@ private static bool IsDuckImplementation(ITypeSymbol receiverType, ITypeSymbol i
}
}

private static string? ProcessClass(GeneratorExecutionContext context, Compilation compilation, INamedTypeSymbol type, IEnumerable<IMemberInfo> members)
private static string? GetSourceCodeForType(GeneratorExecutionContext context, Compilation compilation, INamedTypeSymbol type, IEnumerable<IMemberInfo> members, TypeRegistry missingAttributes)
{
var attributeRegistry = new TypeRegistry();

var scope = new ScopeInfo(type);

var options = SourceBuilderOptions.Load(context, null);
var builder = new SourceBuilder(options);
var builder = new SourceBuilder([], attributeRegistry, options);

ICodeTextWriter writer = new CSharpCodeTextWriter(context, compilation);
bool anyReasonToEmitSourceFile = false;
Expand All @@ -596,6 +610,7 @@ private static bool IsDuckImplementation(ITypeSymbol receiverType, ITypeSymbol i
builder.AppendLine("// <auto-generated />");
//bool isNullable = compilation.Options.NullableContextOptions == NullableContextOptions.Enable;
builder.AppendLine("#nullable enable");
builder.MarkPointForAliases();
builder.AppendLine();
bool namespaceGenerated = writer.WriteNamespaceBeginning(builder, type.ContainingNamespace);

Expand Down Expand Up @@ -838,7 +853,15 @@ EventModel CreateEvent(IEventSymbol @event)
builder.AppendLine();
}

return error == false && anyReasonToEmitSourceFile ? builder.ToString() : null;
if (error == false && anyReasonToEmitSourceFile)
{
missingAttributes.AddMany(attributeRegistry);
return builder.ToString();
}
else
{
return null;
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<RepositoryUrl>https://github.com/beakona/AutoInterface</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput</TargetsForTfmSpecificContentInPackage>
<Version>1.0.38</Version>
<Version>1.0.39</Version>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
Expand Down
Loading

0 comments on commit ff4ff62

Please sign in to comment.