Browse Source

Address code review feedback: add annotation for field keyword detection

Co-authored-by: christophwille <344208+christophwille@users.noreply.github.com>
copilot/add-field-keyword-auto-properties
copilot-swe-agent[bot] 4 months ago
parent
commit
4cbf5af09a
  1. 8
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  2. 14
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

8
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -335,4 +335,12 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
public static readonly UseImplicitlyTypedOutAnnotation Instance = new UseImplicitlyTypedOutAnnotation(); public static readonly UseImplicitlyTypedOutAnnotation Instance = new UseImplicitlyTypedOutAnnotation();
} }
/// <summary>
/// Annotates an Identifier when it was transformed from a backing field reference to the C# 14 'field' keyword.
/// </summary>
public class SemiAutoPropertyFieldKeywordAnnotation
{
public static readonly SemiAutoPropertyFieldKeywordAnnotation Instance = new SemiAutoPropertyFieldKeywordAnnotation();
}
} }

14
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -677,14 +677,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
IProperty property = propertyDeclaration.GetSymbol() as IProperty; IProperty property = propertyDeclaration.GetSymbol() as IProperty;
if (property == null) if (property == null)
return; return;
// Check if any accessor body contains the 'field' keyword (which was transformed from backing field) // Check if any accessor body contains an identifier with the SemiAutoPropertyFieldKeywordAnnotation
// (which indicates it was transformed from a backing field reference)
bool usesFieldKeyword = false; bool usesFieldKeyword = false;
foreach (var accessor in new[] { propertyDeclaration.Getter, propertyDeclaration.Setter }) foreach (var accessor in new[] { propertyDeclaration.Getter, propertyDeclaration.Setter })
{ {
if (accessor.IsNull || accessor.Body.IsNull) if (accessor.IsNull || accessor.Body.IsNull)
continue; continue;
usesFieldKeyword |= accessor.Body.Descendants.OfType<Identifier>() usesFieldKeyword |= accessor.Body.Descendants.OfType<Identifier>()
.Any(id => id.Name == "field"); .Any(id => id.Annotation<SemiAutoPropertyFieldKeywordAnnotation>() != null);
} }
if (!usesFieldKeyword) if (!usesFieldKeyword)
return; return;
@ -699,15 +700,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}); });
if (fieldDecl != null) if (fieldDecl != null)
{ {
fieldDecl.Remove(); // Remove compiler-generated attributes before detaching the node
// Move field attributes to the property with [field: ...] target
CSharpDecompiler.RemoveAttribute(fieldDecl, KnownAttribute.CompilerGenerated); CSharpDecompiler.RemoveAttribute(fieldDecl, KnownAttribute.CompilerGenerated);
CSharpDecompiler.RemoveAttribute(fieldDecl, KnownAttribute.DebuggerBrowsable); CSharpDecompiler.RemoveAttribute(fieldDecl, KnownAttribute.DebuggerBrowsable);
// Move remaining field attributes to the property with [field: ...] target
foreach (var section in fieldDecl.Attributes) foreach (var section in fieldDecl.Attributes)
{ {
section.AttributeTarget = "field"; section.AttributeTarget = "field";
propertyDeclaration.Attributes.Add(section.Detach()); propertyDeclaration.Attributes.Add(section.Detach());
} }
fieldDecl.Remove();
} }
} }
@ -801,7 +803,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// We're inside this property's accessor - use the field keyword if enabled // We're inside this property's accessor - use the field keyword if enabled
if (context.Settings.SemiAutoProperties) if (context.Settings.SemiAutoProperties)
{ {
return Identifier.Create("field"); var newIdentifier = Identifier.Create("field");
newIdentifier.AddAnnotation(SemiAutoPropertyFieldKeywordAnnotation.Instance);
return newIdentifier;
} }
return null; return null;
} }

Loading…
Cancel
Save