Skip to content

Commit b28281c

Browse files
Refactor semi-auto properties to simplify simple accessors to get; and set;
Co-authored-by: christophwille <[email protected]>
1 parent 382ee0f commit b28281c

File tree

2 files changed

+73
-9
lines changed

2 files changed

+73
-9
lines changed

ICSharpCode.Decompiler.Tests/TestCases/Pretty/SemiAutoProperties.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
2323
internal class SemiAutoProperties
2424
{
2525
public int ValidatedProperty {
26-
get {
27-
return field;
28-
}
26+
get;
2927
set {
3028
if (value < 0)
3129
{
@@ -43,15 +41,11 @@ public string LazyProperty {
4341
}
4442
return field;
4543
}
46-
set {
47-
field = value;
48-
}
44+
set;
4945
}
5046

5147
public int NotifyProperty {
52-
get {
53-
return field;
54-
}
48+
get;
5549
set {
5650
if (field != value)
5751
{

ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,8 @@ PropertyDeclaration TransformAutomaticProperty(PropertyDeclaration propertyDecla
671671
/// Transforms a property that uses the backing field into a semi-auto property
672672
/// by removing the backing field declaration. The field keyword replacements
673673
/// are already done in ReplaceBackingFieldUsage during child visiting.
674+
/// Also simplifies simple accessors like `get { return field; }` to `get;`
675+
/// and `set { field = value; }` to `set;`.
674676
/// </summary>
675677
void TransformSemiAutoProperty(PropertyDeclaration propertyDeclaration)
676678
{
@@ -711,6 +713,74 @@ void TransformSemiAutoProperty(PropertyDeclaration propertyDeclaration)
711713
}
712714
fieldDecl.Remove();
713715
}
716+
// Now simplify simple accessors: get { return field; } -> get; and set { field = value; } -> set;
717+
SimplifySemiAutoPropertyAccessors(propertyDeclaration);
718+
}
719+
720+
/// <summary>
721+
/// Checks if a getter body is simply `{ return field; }` and if so, removes the body.
722+
/// Checks if a setter body is simply `{ field = value; }` and if so, removes the body.
723+
/// </summary>
724+
void SimplifySemiAutoPropertyAccessors(PropertyDeclaration propertyDeclaration)
725+
{
726+
// Simplify getter: get { return field; } -> get;
727+
if (!propertyDeclaration.Getter.IsNull && !propertyDeclaration.Getter.Body.IsNull)
728+
{
729+
if (IsSimpleFieldGetter(propertyDeclaration.Getter.Body))
730+
{
731+
RemoveCompilerGeneratedAttribute(propertyDeclaration.Getter.Attributes);
732+
propertyDeclaration.Getter.Body = null;
733+
}
734+
}
735+
// Simplify setter: set { field = value; } -> set;
736+
if (!propertyDeclaration.Setter.IsNull && !propertyDeclaration.Setter.Body.IsNull)
737+
{
738+
if (IsSimpleFieldSetter(propertyDeclaration.Setter.Body))
739+
{
740+
RemoveCompilerGeneratedAttribute(propertyDeclaration.Setter.Attributes);
741+
propertyDeclaration.Setter.Body = null;
742+
}
743+
}
744+
}
745+
746+
/// <summary>
747+
/// Checks if the block is simply `{ return field; }` where field has the SemiAutoPropertyFieldKeywordAnnotation.
748+
/// </summary>
749+
bool IsSimpleFieldGetter(BlockStatement body)
750+
{
751+
if (body.Statements.Count != 1)
752+
return false;
753+
if (body.Statements.Single() is not ReturnStatement returnStmt)
754+
return false;
755+
if (returnStmt.Expression is not IdentifierExpression identExpr)
756+
return false;
757+
return identExpr.IdentifierToken.Annotation<SemiAutoPropertyFieldKeywordAnnotation>() != null
758+
&& identExpr.Identifier == "field";
759+
}
760+
761+
/// <summary>
762+
/// Checks if the block is simply `{ field = value; }` where field has the SemiAutoPropertyFieldKeywordAnnotation.
763+
/// </summary>
764+
bool IsSimpleFieldSetter(BlockStatement body)
765+
{
766+
if (body.Statements.Count != 1)
767+
return false;
768+
if (body.Statements.Single() is not ExpressionStatement exprStmt)
769+
return false;
770+
if (exprStmt.Expression is not AssignmentExpression assignExpr)
771+
return false;
772+
if (assignExpr.Operator != AssignmentOperatorType.Assign)
773+
return false;
774+
// Check left side is "field" with annotation
775+
if (assignExpr.Left is not IdentifierExpression leftIdent)
776+
return false;
777+
if (leftIdent.IdentifierToken.Annotation<SemiAutoPropertyFieldKeywordAnnotation>() == null
778+
|| leftIdent.Identifier != "field")
779+
return false;
780+
// Check right side is "value"
781+
if (assignExpr.Right is not IdentifierExpression rightIdent)
782+
return false;
783+
return rightIdent.Identifier == "value";
714784
}
715785

716786
void RemoveCompilerGeneratedAttribute(AstNodeCollection<AttributeSection> attributeSections)

0 commit comments

Comments
 (0)