@@ -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