Skip to content

Commit

Permalink
missing parameter attributes for set/add/remove..
Browse files Browse the repository at this point in the history
  • Loading branch information
beakona committed Apr 8, 2024
1 parent a13fbc5 commit 8bf6269
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 33 deletions.
54 changes: 48 additions & 6 deletions AutoInterfaceSample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using TestInterfacesNetStandard;
#nullable enable
using System.Diagnostics.CodeAnalysis;

namespace AutoInterfaceSample.Test
{
Expand All @@ -10,19 +11,60 @@ public static void Main()
}
}

partial record TestRecord
public class MyDb : IDb
{
//[BeaKona.AutoInterface(IncludeBaseInterfaces = true)]
public ITestable2? Testable { get; set; }
public string ConnectionString { get; [param: AllowNull] set; } = default!;

public string this[int a, [AllowNull] string b]
{
get => b ?? "";
[param: AllowNull]
set
{
}
}
}

partial record TestDb([property: BeaKona.AutoInterface(typeof(IDb), IncludeBaseInterfaces = true)] IDb Inner) //: IDb
{
}

//partial record TecProgDbConnection
//{
//[AllowNull]
//[DisallowNull]
//string IDb.ConnectionString
//{
// get => (this.Inner as System.Data.IDbConnection)!.ConnectionString;
// //[param:MaybeNull]
// set => (this.Inner as System.Data.IDbConnection)!.ConnectionString = value;
//}
//}

public interface IDb
{
string ConnectionString
{
get;
[param: AllowNull]
set;
}

string this[int a, [AllowNull] string b]
{
get;
[param: AllowNull]
set;
}
}
}

namespace System.Diagnostics.CodeAnalysis
/*namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute(bool returnValue) : Attribute
{
public bool ReturnValue { get; } = returnValue;
}
}
}*/
53 changes: 49 additions & 4 deletions AutoInterfaceSampleNetStandard/TestRecord.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,49 @@
using TestInterfacesNetStandard;
using System.Diagnostics.CodeAnalysis;

namespace AutoInterfaceSampleNetStandard
{
partial class TestRecord
partial class TestDb
{
[BeaKona.AutoInterface(IncludeBaseInterfaces = true)]
public ITestable2? Testable { get; set; }
[property: BeaKona.AutoInterface(typeof(IDb), IncludeBaseInterfaces = true)]
public IDb Inner { get; set; } = default!;
}

public class MyDb : IDb
{
public string ConnectionString { get; [param: AllowNull] set; } = default!;

public string this[int a, [AllowNull] string b]
{
get => b ?? "";
[param: AllowNull]
set
{
}
}
}

public interface IDb
{
string ConnectionString
{
get;
[param: AllowNull]
set;
}

string this[int a, [AllowNull] string b]
{
get;
[param: AllowNull]
set;
}
}

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

namespace System.Diagnostics.CodeAnalysis
Expand All @@ -22,4 +59,12 @@ public NotNullWhenAttribute(bool returnValue)

public bool ReturnValue { get; }
}

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, Inherited = false)]
internal sealed class AllowNullAttribute : Attribute
{
public AllowNullAttribute()
{
}
}
}
77 changes: 54 additions & 23 deletions BeaKona.AutoInterfaceGenerator/CSharpCodeTextWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public void WriteParameterAttributes(SourceBuilder builder, ScopeInfo scope, IPa

foreach (var attribute in GetParameterAttributes(parameter))
{
this.WriteAttribute(builder, scope, attribute, false);
this.WriteAttribute(builder, scope, attribute, false, null);
any = true;
}

Expand Down Expand Up @@ -288,7 +288,7 @@ private void WriteForwardAttributes(SourceBuilder builder, ScopeInfo scope, ISym
foreach (var attribute in this.GetForwardAttributes(member))
{
builder.AppendIndentation();
this.WriteAttribute(builder, scope, attribute, true);
this.WriteAttribute(builder, scope, attribute, true, null);
builder.AppendLine();
}
}
Expand All @@ -300,7 +300,20 @@ private void WriteReturnAttributes(SourceBuilder builder, ScopeInfo scope, IEnum
foreach (var attribute in attributes)
{
builder.AppendIndentation();
this.WriteAttribute(builder, scope, attribute, false, true);
this.WriteAttribute(builder, scope, attribute, false, "return");
builder.AppendLine();
}
}
}

private void WriteParamAttributes(SourceBuilder builder, ScopeInfo scope, IEnumerable<AttributeData> attributes)
{
if (attributes != null)
{
foreach (var attribute in attributes)
{
builder.AppendIndentation();
this.WriteAttribute(builder, scope, attribute, false, "param");
builder.AppendLine();
}
}
Expand Down Expand Up @@ -371,12 +384,13 @@ private void WriteAttributeReference(SourceBuilder builder, ScopeInfo scope, Att
}
}

private void WriteAttribute(SourceBuilder builder, ScopeInfo scope, AttributeData attribute, bool strict, bool isReturn = false)
private void WriteAttribute(SourceBuilder builder, ScopeInfo scope, AttributeData attribute, bool strict, string? type)
{
builder.Append('[');
if (isReturn)
if (type != null && string.IsNullOrEmpty(type) == false)
{
builder.Append("return: ");
builder.Append(type);
builder.Append(": ");
}
this.WriteAttributeReference(builder, scope, attribute, strict);
builder.Append(']');
Expand Down Expand Up @@ -431,29 +445,37 @@ private IEnumerable<AttributeData> GetReturnAttributes(IMethodSymbol method)
}
}

private bool HasAttributes(params ISymbol?[] members)
private IEnumerable<AttributeData> GetParamAttributes(IMethodSymbol? method)
{
if (members != null)
if (method != null && method.Parameters.Length > 0)
{
foreach (var member in members)
foreach (var attribute in method.Parameters.Last().GetAttributes())
{
if (member != null)
if (attribute.AttributeClass is INamedTypeSymbol attributeClass)
{
if (this.GetForwardAttributes(member).Any())
{
return true;
}

if (member is IMethodSymbol method)
if (this.forwardAttributeNamespaces.Contains(attributeClass.ContainingNamespace.ToDisplayString()))
{
if (this.GetReturnAttributes(method).Any())
{
return true;
}
yield return attribute;
}
}
}
}
}

private bool HasAttributes(IMethodSymbol? method)
{
if (method != null)
{
if (this.GetForwardAttributes(method).Any())
{
return true;
}

if (this.GetReturnAttributes(method).Any())
{
return true;
}
}

return false;
}
Expand Down Expand Up @@ -628,6 +650,10 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope
this.WriteTypeReference(builder, @interface, scope);
builder.Append('.');

var setParamAttributes = this.GetParamAttributes(property.SetMethod);
var hasAttributes = setParamAttributes.Any() || this.HasAttributes(property.GetMethod) || this.HasAttributes(property.SetMethod);
var noAttributes = hasAttributes == false;

if (property.IsIndexer)
{
builder.Append("this[");
Expand All @@ -639,8 +665,6 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope
this.WriteIdentifier(builder, property);
}

bool noAttributes = this.HasAttributes(property.GetMethod, property.SetMethod) == false;

if (property.SetMethod == null && getterTemplate == null && noAttributes)
{
builder.Append(" => ");
Expand Down Expand Up @@ -672,6 +696,7 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope
if (property.SetMethod is not null)
{
this.WriteForwardAttributes(builder, scope, property.SetMethod);
this.WriteParamAttributes(builder, scope, setParamAttributes);

builder.AppendIndentation();
builder.Append("set => ");
Expand Down Expand Up @@ -728,6 +753,7 @@ public void WritePropertyDefinition(SourceBuilder builder, IPropertySymbol prope
if (property.SetMethod is not null)
{
this.WriteForwardAttributes(builder, scope, property.SetMethod);
this.WriteParamAttributes(builder, scope, setParamAttributes);

builder.AppendIndentation();
builder.AppendLine("set");
Expand Down Expand Up @@ -802,7 +828,10 @@ public void WriteEventDefinition(SourceBuilder builder, IEventSymbol @event, Sco
builder.IncrementIndentation();
try
{
bool noAttributes = this.HasAttributes(@event.AddMethod, @event.RemoveMethod) == false;
var addParamAttributes = this.GetParamAttributes(@event.AddMethod);
var removeParamAttributes = this.GetParamAttributes(@event.RemoveMethod);
var hasAttributes = addParamAttributes.Any() || removeParamAttributes.Any() || this.HasAttributes(@event.AddMethod) || this.HasAttributes(@event.RemoveMethod);
var noAttributes = hasAttributes == false;

if (references.Count() == 1 && adderTemplate == null && removerTemplate == null && noAttributes)
{
Expand All @@ -825,6 +854,7 @@ public void WriteEventDefinition(SourceBuilder builder, IEventSymbol @event, Sco
if (@event.AddMethod != null)
{
this.WriteForwardAttributes(builder, scope, @event.AddMethod);
this.WriteParamAttributes(builder, scope, addParamAttributes);

builder.AppendIndentation();
builder.AppendLine("add");
Expand Down Expand Up @@ -869,6 +899,7 @@ public void WriteEventDefinition(SourceBuilder builder, IEventSymbol @event, Sco
if (@event.RemoveMethod != null)
{
this.WriteForwardAttributes(builder, scope, @event.RemoveMethod);
this.WriteParamAttributes(builder, scope, removeParamAttributes);

builder.AppendIndentation();
builder.AppendLine("remove");
Expand Down
15 changes: 15 additions & 0 deletions BeaKona.AutoInterfaceGenerator/IDictionaryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace BeaKona.AutoInterfaceGenerator;

internal static class IDictionaryExtensions
{
public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key) where TKey : notnull where TValue : new()
{
if (@this.TryGetValue(key, out var value) == false)
{
value = new();
@this.Add(key, value);
}

return value;
}
}

0 comments on commit 8bf6269

Please sign in to comment.