@@ -121,19 +121,6 @@ public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDec
121121 return base . VisitPropertyDeclaration ( propertyDeclaration ) ;
122122 }
123123
124- public override AstNode VisitCustomEventDeclaration ( CustomEventDeclaration eventDeclaration )
125- {
126- // first apply transforms to the accessor bodies
127- base . VisitCustomEventDeclaration ( eventDeclaration ) ;
128- if ( context . Settings . AutomaticEvents )
129- {
130- AstNode ? result = TransformAutomaticEvents ( eventDeclaration ) ;
131- if ( result != null )
132- return result ;
133- }
134- return eventDeclaration ;
135- }
136-
137124 public override AstNode VisitEventDeclaration ( EventDeclaration eventDeclaration )
138125 {
139126 // A field-like event declaration hides its backing field; remove the field declaration
@@ -922,276 +909,11 @@ static bool NameCouldBeBackingFieldOfAutomaticProperty(string name, [NotNullWhen
922909 }
923910
924911 #region Automatic Events
925- static readonly Expression fieldReferencePattern = new Choice {
926- new IdentifierExpression ( Pattern . AnyString ) ,
927- new MemberReferenceExpression {
928- Target = new Choice { new ThisReferenceExpression ( ) , new TypeReferenceExpression { Type = new AnyNode ( ) } } ,
929- MemberName = Pattern . AnyString
930- }
931- } ;
932-
933- static readonly Accessor automaticEventPatternV2 = new Accessor {
934- Attributes = { new Repeat ( new AnyNode ( ) ) } ,
935- Body = new BlockStatement {
936- new AssignmentExpression {
937- Left = new NamedNode ( "field" , fieldReferencePattern ) ,
938- Operator = AssignmentOperatorType . Assign ,
939- Right = new CastExpression (
940- new AnyNode ( "type" ) ,
941- new InvocationExpression ( new AnyNode ( "delegateCombine" ) . ToExpression ( ) , new Backreference ( "field" ) , new IdentifierExpression ( "value" ) )
942- )
943- } ,
944- }
945- } ;
946-
947- static readonly Accessor automaticEventPatternV4 = new Accessor {
948- Attributes = { new Repeat ( new AnyNode ( ) ) } ,
949- Body = new BlockStatement {
950- new AssignmentExpression {
951- Left = new NamedNode ( "var1" , new IdentifierExpression ( Pattern . AnyString ) ) ,
952- Operator = AssignmentOperatorType . Assign ,
953- Right = new NamedNode ( "field" , fieldReferencePattern )
954- } ,
955- new DoWhileStatement {
956- EmbeddedStatement = new BlockStatement {
957- new AssignmentExpression ( new NamedNode ( "var2" , new IdentifierExpression ( Pattern . AnyString ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
958- new AssignmentExpression {
959- Left = new NamedNode ( "var3" , new IdentifierExpression ( Pattern . AnyString ) ) ,
960- Operator = AssignmentOperatorType . Assign ,
961- Right = new CastExpression ( new AnyNode ( "type" ) , new InvocationExpression ( new AnyNode ( "delegateCombine" ) . ToExpression ( ) , new IdentifierExpressionBackreference ( "var2" ) , new IdentifierExpression ( "value" ) ) )
962- } ,
963- new AssignmentExpression {
964- Left = new IdentifierExpressionBackreference ( "var1" ) ,
965- Right = new InvocationExpression ( new MemberReferenceExpression ( new TypeReferenceExpression ( new TypePattern ( typeof ( System . Threading . Interlocked ) ) . ToType ( ) ) ,
966- "CompareExchange" ) ,
967- new Expression [ ] { // arguments
968- new DirectionExpression { FieldDirection = FieldDirection . Ref , Expression = new Backreference ( "field" ) } ,
969- new IdentifierExpressionBackreference ( "var3" ) ,
970- new IdentifierExpressionBackreference ( "var2" )
971- }
972- ) }
973- } ,
974- Condition = new BinaryOperatorExpression {
975- Left = new CastExpression ( new TypePattern ( typeof ( object ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
976- Operator = BinaryOperatorType . InEquality ,
977- Right = new IdentifierExpressionBackreference ( "var2" )
978- } ,
979- }
980- }
981- } ;
982-
983- static readonly Accessor automaticEventPatternV4AggressivelyInlined = new Accessor {
984- Attributes = { new Repeat ( new AnyNode ( ) ) } ,
985- Body = new BlockStatement {
986- new AssignmentExpression {
987- Left = new NamedNode ( "var1" , new IdentifierExpression ( Pattern . AnyString ) ) ,
988- Operator = AssignmentOperatorType . Assign ,
989- Right = new NamedNode ( "field" , fieldReferencePattern )
990- } ,
991- new DoWhileStatement {
992- EmbeddedStatement = new BlockStatement {
993- new AssignmentExpression ( new NamedNode ( "var2" , new IdentifierExpression ( Pattern . AnyString ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
994- new AssignmentExpression {
995- Left = new IdentifierExpressionBackreference ( "var1" ) ,
996- Right = new InvocationExpression ( new MemberReferenceExpression ( new TypeReferenceExpression ( new TypePattern ( typeof ( System . Threading . Interlocked ) ) . ToType ( ) ) ,
997- "CompareExchange" ) ,
998- new Expression [ ] { // arguments
999- new NamedArgumentExpression ( "value" , new CastExpression ( new AnyNode ( "type" ) , new InvocationExpression ( new AnyNode ( "delegateCombine" ) . ToExpression ( ) , new IdentifierExpressionBackreference ( "var2" ) , new IdentifierExpression ( "value" ) ) ) ) ,
1000- new NamedArgumentExpression ( "location1" , new DirectionExpression { FieldDirection = FieldDirection . Ref , Expression = new Backreference ( "field" ) } ) ,
1001- new NamedArgumentExpression ( "comparand" , new IdentifierExpressionBackreference ( "var2" ) )
1002- }
1003- ) }
1004- } ,
1005- Condition = new BinaryOperatorExpression {
1006- Left = new CastExpression ( new TypePattern ( typeof ( object ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
1007- Operator = BinaryOperatorType . InEquality ,
1008- Right = new IdentifierExpressionBackreference ( "var2" )
1009- } ,
1010- }
1011- }
1012- } ;
1013-
1014- static readonly Accessor automaticEventPatternV4MCS = new Accessor {
1015- Attributes = { new Repeat ( new AnyNode ( ) ) } ,
1016- Body = new BlockStatement {
1017- new AssignmentExpression {
1018- Left = new NamedNode ( "var1" , new IdentifierExpression ( Pattern . AnyString ) ) ,
1019- Operator = AssignmentOperatorType . Assign ,
1020- Right = new NamedNode (
1021- "field" ,
1022- new MemberReferenceExpression {
1023- Target = new Choice { new ThisReferenceExpression ( ) , new TypeReferenceExpression { Type = new AnyNode ( ) } } ,
1024- MemberName = Pattern . AnyString
1025- }
1026- )
1027- } ,
1028- new DoWhileStatement {
1029- EmbeddedStatement = new BlockStatement {
1030- new AssignmentExpression ( new NamedNode ( "var2" , new IdentifierExpression ( Pattern . AnyString ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
1031- new AssignmentExpression {
1032- Left = new IdentifierExpressionBackreference ( "var1" ) ,
1033- Right = new InvocationExpression ( new MemberReferenceExpression ( new TypeReferenceExpression ( new TypePattern ( typeof ( System . Threading . Interlocked ) ) . ToType ( ) ) ,
1034- "CompareExchange" ,
1035- new AstType [ ] { new Repeat ( new AnyNode ( ) ) } ) , // optional type arguments
1036- new Expression [ ] { // arguments
1037- new DirectionExpression { FieldDirection = FieldDirection . Ref , Expression = new Backreference ( "field" ) } ,
1038- new CastExpression ( new AnyNode ( "type" ) , new InvocationExpression ( new AnyNode ( "delegateCombine" ) . ToExpression ( ) , new IdentifierExpressionBackreference ( "var2" ) , new IdentifierExpression ( "value" ) ) ) ,
1039- new IdentifierExpressionBackreference ( "var1" )
1040- }
1041- )
1042- }
1043- } ,
1044- Condition = new BinaryOperatorExpression {
1045- Left = new CastExpression ( new TypePattern ( typeof ( object ) ) , new IdentifierExpressionBackreference ( "var1" ) ) ,
1046- Operator = BinaryOperatorType . InEquality ,
1047- Right = new IdentifierExpressionBackreference ( "var2" )
1048- } ,
1049- }
1050- }
1051- } ;
1052-
1053- bool CheckAutomaticEventMatch ( Match m , CustomEventDeclaration ev , bool isAddAccessor )
1054- {
1055- if ( ! m . Success )
1056- return false ;
1057- Expression fieldExpression = m . Get < Expression > ( "field" ) . Single ( ) ;
1058- IField ? eventField = fieldExpression . GetSymbol ( ) as IField ;
1059- if ( eventField == null )
1060- return false ;
1061- var module = eventField . ParentModule as MetadataModule ;
1062- if ( module == null )
1063- return false ;
1064- if ( ! module . MetadataFile . PropertyAndEventBackingFieldLookup . IsEventBackingField ( ( FieldDefinitionHandle ) eventField . MetadataToken , out _ ) )
1065- return false ;
1066- var returnType = ev . ReturnType . GetResolveResult ( ) . Type ;
1067- var eventType = m . Get < AstType > ( "type" ) . Single ( ) . GetResolveResult ( ) . Type ;
1068- // ignore tuple element names, dynamic and nullability
1069- if ( ! NormalizeTypeVisitor . TypeErasure . EquivalentTypes ( returnType , eventType ) )
1070- return false ;
1071- var combineMethod = m . Get < AstNode > ( "delegateCombine" ) . Single ( ) . Parent ! . GetSymbol ( ) as IMethod ;
1072- if ( combineMethod == null || combineMethod . Name != ( isAddAccessor ? "Combine" : "Remove" ) )
1073- return false ;
1074- return combineMethod . DeclaringType . FullName == "System.Delegate" ;
1075- }
1076-
1077- static readonly string [ ] attributeTypesToRemoveFromAutoEvents = new [ ] {
1078- "System.Runtime.CompilerServices.CompilerGeneratedAttribute" ,
1079- "System.Diagnostics.DebuggerBrowsableAttribute" ,
1080- "System.Runtime.CompilerServices.MethodImplAttribute"
1081- } ;
1082-
1083912 internal static readonly string [ ] attributeTypesToRemoveFromAutoProperties = new [ ] {
1084913 "System.Runtime.CompilerServices.CompilerGeneratedAttribute" ,
1085914 "System.Diagnostics.DebuggerBrowsableAttribute"
1086915 } ;
1087916
1088- bool CheckAutomaticEventV4 ( CustomEventDeclaration ev )
1089- {
1090- Match addMatch = automaticEventPatternV4 . Match ( ev . AddAccessor ) ;
1091- if ( ! CheckAutomaticEventMatch ( addMatch , ev , isAddAccessor : true ) )
1092- return false ;
1093- Match removeMatch = automaticEventPatternV4 . Match ( ev . RemoveAccessor ) ;
1094- if ( ! CheckAutomaticEventMatch ( removeMatch , ev , isAddAccessor : false ) )
1095- return false ;
1096- return true ;
1097- }
1098-
1099- bool CheckAutomaticEventV4AggressivelyInlined ( CustomEventDeclaration ev )
1100- {
1101- if ( ! context . Settings . AggressiveInlining )
1102- return false ;
1103- Match addMatch = automaticEventPatternV4AggressivelyInlined . Match ( ev . AddAccessor ) ;
1104- if ( ! CheckAutomaticEventMatch ( addMatch , ev , isAddAccessor : true ) )
1105- return false ;
1106- Match removeMatch = automaticEventPatternV4AggressivelyInlined . Match ( ev . RemoveAccessor ) ;
1107- if ( ! CheckAutomaticEventMatch ( removeMatch , ev , isAddAccessor : false ) )
1108- return false ;
1109- return true ;
1110- }
1111-
1112- bool CheckAutomaticEventV2 ( CustomEventDeclaration ev )
1113- {
1114- Match addMatch = automaticEventPatternV2 . Match ( ev . AddAccessor ) ;
1115- if ( ! CheckAutomaticEventMatch ( addMatch , ev , isAddAccessor : true ) )
1116- return false ;
1117- Match removeMatch = automaticEventPatternV2 . Match ( ev . RemoveAccessor ) ;
1118- if ( ! CheckAutomaticEventMatch ( removeMatch , ev , isAddAccessor : false ) )
1119- return false ;
1120- return true ;
1121- }
1122-
1123- bool CheckAutomaticEventV4MCS ( CustomEventDeclaration ev )
1124- {
1125- Match addMatch = automaticEventPatternV4MCS . Match ( ev . AddAccessor ) ;
1126- if ( ! CheckAutomaticEventMatch ( addMatch , ev , true ) )
1127- return false ;
1128- Match removeMatch = automaticEventPatternV4MCS . Match ( ev . RemoveAccessor ) ;
1129- if ( ! CheckAutomaticEventMatch ( removeMatch , ev , false ) )
1130- return false ;
1131- return true ;
1132- }
1133-
1134- EventDeclaration ? TransformAutomaticEvents ( CustomEventDeclaration ev )
1135- {
1136- if ( ev . PrivateImplementationType is not null )
1137- return null ;
1138- const Modifiers withoutBody = Modifiers . Abstract | Modifiers . Extern ;
1139- if ( ev . GetSymbol ( ) is not IEvent symbol )
1140- return null ;
1141- if ( ( ev . Modifiers & withoutBody ) == 0 )
1142- {
1143- if ( ! CheckAutomaticEventV4AggressivelyInlined ( ev ) && ! CheckAutomaticEventV4 ( ev ) && ! CheckAutomaticEventV2 ( ev ) && ! CheckAutomaticEventV4MCS ( ev ) )
1144- return null ;
1145- }
1146- if ( ev . AddAccessor is not { } )
1147- return null ;
1148- context . Step ( "Convert custom event to field-like event" , ev ) ;
1149- var fieldDecl = ev . Parent ? . Children . OfType < FieldDeclaration > ( )
1150- . FirstOrDefault ( fd => IsEventBackingFieldDeclaration ( fd , symbol ) ) ;
1151- fieldDecl ? . Remove ( ) ;
1152- EventDeclaration ed = ConvertToFieldLikeEvent ( ev , fieldDecl ) ;
1153- ev . ReplaceWith ( ed ) ;
1154- context . EndStep ( ed ) ;
1155- return ed ;
1156- }
1157-
1158- /// <summary>
1159- /// Builds a field-like event declaration from a custom event declaration whose accessors
1160- /// are compiler-generated: moves the event attributes, the add-accessor attributes
1161- /// (as "method:" sections) and the backing-field attributes (as "field:" sections) over,
1162- /// dropping the attributes the compiler puts on automatic events.
1163- /// The caller is responsible for detaching <paramref name="backingFieldDecl"/> from the
1164- /// syntax tree and for replacing <paramref name="ev"/> with the returned declaration.
1165- /// </summary>
1166- internal static EventDeclaration ConvertToFieldLikeEvent ( CustomEventDeclaration ev , EntityDeclaration ? backingFieldDecl )
1167- {
1168- var addAccessor = ev . AddAccessor ! ;
1169- RemoveCompilerGeneratedAttribute ( addAccessor . Attributes , attributeTypesToRemoveFromAutoEvents ) ;
1170- EventDeclaration ed = new EventDeclaration ( ) ;
1171- ev . Attributes . MoveTo ( ed . Attributes ) ;
1172- foreach ( var attr in addAccessor . Attributes )
1173- {
1174- attr . AttributeTarget = "method" ;
1175- ed . Attributes . Add ( attr . Detach ( ) ) ;
1176- }
1177- ed . ReturnType = ev . ReturnType . Detach ( ) ;
1178- ed . Modifiers = ev . Modifiers ;
1179- ed . Variables . Add ( new VariableInitializer ( ev . Name ) ) ;
1180- ed . CopyAnnotationsFrom ( ev ) ;
1181-
1182- if ( backingFieldDecl != null )
1183- {
1184- CSharpDecompiler . RemoveAttribute ( backingFieldDecl , KnownAttribute . CompilerGenerated ) ;
1185- CSharpDecompiler . RemoveAttribute ( backingFieldDecl , KnownAttribute . DebuggerBrowsable ) ;
1186- foreach ( var section in backingFieldDecl . Attributes )
1187- {
1188- section . AttributeTarget = "field" ;
1189- ed . Attributes . Add ( section . Detach ( ) ) ;
1190- }
1191- }
1192- return ed ;
1193- }
1194-
1195917 static bool IsEventBackingFieldDeclaration ( FieldDeclaration fd , IEvent ev )
1196918 {
1197919 if ( fd . Variables . Count > 1 )
0 commit comments