diff --git a/AutomaticInterface/AutomaticInterface/Builder.cs b/AutomaticInterface/AutomaticInterface/Builder.cs
index 2649b8f..f430967 100644
--- a/AutomaticInterface/AutomaticInterface/Builder.cs
+++ b/AutomaticInterface/AutomaticInterface/Builder.cs
@@ -176,9 +176,16 @@ InterfaceBuilder codeGenerator
private static string GetMethodSignature(IParameterSymbol x)
{
+ var syntaxReference = x.DeclaringSyntaxReferences.FirstOrDefault();
+
+ var name =
+ syntaxReference != null
+ ? ((ParameterSyntax)syntaxReference.GetSyntax()).Identifier.Text
+ : x.Name;
+
if (!x.HasExplicitDefaultValue)
{
- return $"{x.Type.ToDisplayString()} {x.Name}";
+ return $"{x.Type.ToDisplayString()} {name}";
}
var optionalValue = x.ExplicitDefaultValue switch
@@ -189,7 +196,7 @@ private static string GetMethodSignature(IParameterSymbol x)
null => " = null",
_ => $" = {x.ExplicitDefaultValue}"
};
- return $"{x.Type.ToDisplayString()} {x.Name}{optionalValue}";
+ return $"{x.Type.ToDisplayString()} {name}{optionalValue}";
}
private static void AddPropertiesToInterface(
@@ -204,6 +211,8 @@ InterfaceBuilder interfaceGenerator
.Where(x => x.DeclaredAccessibility == Accessibility.Public)
.Where(x => !x.IsStatic)
.Where(x => !x.IsIndexer)
+ .GroupBy(x => x.Name)
+ .Select(g => g.First())
.ToList()
.ForEach(prop =>
{
@@ -212,6 +221,7 @@ InterfaceBuilder interfaceGenerator
var name = prop.Name;
var hasGet = prop.GetMethod?.DeclaredAccessibility == Accessibility.Public;
var hasSet = prop.SetMethod?.DeclaredAccessibility == Accessibility.Public;
+ var isRef = prop.ReturnsByRef;
ActivateNullableIfNeeded(interfaceGenerator, type);
@@ -220,6 +230,7 @@ InterfaceBuilder interfaceGenerator
type.ToDisplayString(),
hasGet,
hasSet,
+ isRef,
InheritDoc
);
});
diff --git a/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs b/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs
index 845172d..c7d9660 100644
--- a/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs
+++ b/AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs
@@ -9,6 +9,7 @@ internal sealed record PropertyInfo(
string Ttype,
bool HasGet,
bool HasSet,
+ bool IsRef,
string Documentation
);
@@ -50,10 +51,11 @@ public void AddPropertyToInterface(
string ttype,
bool hasGet,
bool hasSet,
+ bool isRef,
string documentation
)
{
- propertyInfos.Add(new(name, ttype, hasGet, hasSet, documentation));
+ propertyInfos.Add(new(name, ttype, hasGet, hasSet, isRef, documentation));
}
public void AddGeneric(string v)
@@ -122,9 +124,10 @@ public string Build()
foreach (var prop in propertyInfos)
{
cb.AppendAndNormalizeMultipleLines(prop.Documentation);
+ var @ref = prop.IsRef ? "ref " : string.Empty;
var get = prop.HasGet ? "get; " : string.Empty;
var set = prop.HasSet ? "set; " : string.Empty;
- cb.AppendLine($"{prop.Ttype} {prop.Name} {{ {get}{set}}}");
+ cb.AppendLine($"{@ref}{prop.Ttype} {prop.Name} {{ {get}{set}}}");
cb.AppendLine("");
}
cb.Dedent();
diff --git a/AutomaticInterface/Tests/GeneratorTests.cs b/AutomaticInterface/Tests/GeneratorTests.cs
index f528adb..6d59195 100644
--- a/AutomaticInterface/Tests/GeneratorTests.cs
+++ b/AutomaticInterface/Tests/GeneratorTests.cs
@@ -2066,4 +2066,148 @@ public partial interface IDemoClass
""";
GenerateCode(code).Should().Be(expected);
}
+
+ [Fact]
+ public void WorksWithRef()
+ {
+ const string code = """
+
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample;
+ [GenerateAutomaticInterface]
+ public class DemoClass
+ {
+ private string _aProperty;
+ public ref string AProperty => ref _aProperty;
+ }
+
+ """;
+
+ const string expected = """
+ //--------------------------------------------------------------------------------------------------
+ //
+ // This code was generated by a tool.
+ //
+ // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
+ //
+ //--------------------------------------------------------------------------------------------------
+
+ using System.CodeDom.Compiler;
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample
+ {
+ [GeneratedCode("AutomaticInterface", "")]
+ public partial interface IDemoClass
+ {
+ ///
+ ref string AProperty { get; }
+
+ }
+ }
+
+ """;
+ GenerateCode(code).Should().Be(expected);
+ }
+
+ [Fact]
+ public void WorksWithReservedNames()
+ {
+ const string code = """
+
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample;
+ [GenerateAutomaticInterface]
+ public class DemoClass
+ {
+ public void AMethod(int @event)
+ {
+ }
+ }
+
+ """;
+
+ const string expected = """
+ //--------------------------------------------------------------------------------------------------
+ //
+ // This code was generated by a tool.
+ //
+ // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
+ //
+ //--------------------------------------------------------------------------------------------------
+
+ using System.CodeDom.Compiler;
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample
+ {
+ [GeneratedCode("AutomaticInterface", "")]
+ public partial interface IDemoClass
+ {
+ ///
+ void AMethod(int @event);
+
+ }
+ }
+
+ """;
+ GenerateCode(code).Should().Be(expected);
+ }
+
+ [Fact]
+ public void WorksWithNewKeyword()
+ {
+ const string code = """
+
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample;
+
+ public abstract class FirstClass
+ {
+ public int AProperty { get; set; }
+ }
+
+ [GenerateAutomaticInterface]
+ public partial class SecondClass : FirstClass
+ {
+ public new int AProperty { get; set; }
+ }
+
+ """;
+
+ const string expected = """
+ //--------------------------------------------------------------------------------------------------
+ //
+ // This code was generated by a tool.
+ //
+ // Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
+ //
+ //--------------------------------------------------------------------------------------------------
+
+ using System.CodeDom.Compiler;
+ using AutomaticInterfaceAttribute;
+ using System.Threading.Tasks;
+
+ namespace AutomaticInterfaceExample
+ {
+ [GeneratedCode("AutomaticInterface", "")]
+ public partial interface ISecondClass
+ {
+ ///
+ int AProperty { get; set; }
+
+ }
+ }
+
+ """;
+ GenerateCode(code).Should().Be(expected);
+ }
}