@@ -318,7 +318,9 @@ public static bool MemberIsHidden(MetadataFile module, EntityHandle member, Deco
318318 return true ;
319319 if ( settings . FixedBuffers && name . StartsWith ( "<" , StringComparison . Ordinal ) && name . Contains ( "__FixedBuffer" ) )
320320 return true ;
321- if ( settings . InlineArrays && name . StartsWith ( "<>y__InlineArray" , StringComparison . Ordinal ) && name . EndsWith ( "`1" ) )
321+ if ( settings . InlineArrays && name . StartsWith ( "<>y__InlineArray" , StringComparison . Ordinal ) && name . EndsWith ( "`1" , StringComparison . Ordinal ) )
322+ return true ;
323+ if ( settings . ExtensionMembers && name . StartsWith ( "<>E__" , StringComparison . Ordinal ) )
322324 return true ;
323325 }
324326 else if ( type . IsCompilerGenerated ( metadata ) )
@@ -1037,7 +1039,7 @@ public SyntaxTree Decompile(IEnumerable<EntityHandle> definitions)
10371039 break ;
10381040 case HandleKind . MethodDefinition :
10391041 IMethod method = module . GetDefinition ( ( MethodDefinitionHandle ) entity ) ;
1040- syntaxTree . Members . Add ( DoDecompile ( method , decompileRun , new SimpleTypeResolveContext ( method ) ) ) ;
1042+ syntaxTree . Members . Add ( DoDecompile ( method , decompileRun , new SimpleTypeResolveContext ( method ) , null ) ) ;
10411043 if ( first )
10421044 {
10431045 parentTypeDef = method . DeclaringTypeDefinition ;
@@ -1054,7 +1056,7 @@ public SyntaxTree Decompile(IEnumerable<EntityHandle> definitions)
10541056 break ;
10551057 case HandleKind . PropertyDefinition :
10561058 IProperty property = module . GetDefinition ( ( PropertyDefinitionHandle ) entity ) ;
1057- syntaxTree . Members . Add ( DoDecompile ( property , decompileRun , new SimpleTypeResolveContext ( property ) ) ) ;
1059+ syntaxTree . Members . Add ( DoDecompile ( property , decompileRun , new SimpleTypeResolveContext ( property ) , null ) ) ;
10581060 if ( first )
10591061 {
10601062 parentTypeDef = property . DeclaringTypeDefinition ;
@@ -1361,14 +1363,44 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun
13611363 partialTypeInfo = null ;
13621364 }
13631365
1366+ if ( settings . ExtensionMembers )
1367+ {
1368+ foreach ( var group in typeDef . ExtensionInfo ? . GetGroups ( ) ?? [ ] )
1369+ {
1370+ var ext = new ExtensionDeclaration ( ) ;
1371+ ext . TypeParameters . AddRange ( group . Key . DeclaringTypeDefinition . TypeParameters . Select ( tp => typeSystemAstBuilder . ConvertTypeParameter ( tp ) ) ) ;
1372+ ext . ReceiverParameters . Add ( typeSystemAstBuilder . ConvertParameter ( group . Key . Parameters . Single ( ) ) ) ;
1373+ ext . Constraints . AddRange ( group . Key . DeclaringTypeDefinition . TypeParameters . Select ( c => typeSystemAstBuilder . ConvertTypeParameterConstraint ( c ) ) ) ;
1374+
1375+ foreach ( var member in group )
1376+ {
1377+ IMember extMember = member . ExtensionMember ;
1378+ if ( member . ExtensionMember . IsAccessor )
1379+ {
1380+ extMember = member . ExtensionMember . AccessorOwner ;
1381+ }
1382+ if ( entityMap . Contains ( extMember ) || extMember . MetadataToken . IsNil )
1383+ {
1384+ // Member is already decompiled.
1385+ continue ;
1386+ }
1387+ EntityDeclaration extMemberDecl = DoDecompileExtensionMember ( extMember , typeDef . ExtensionInfo , decompileRun , decompilationContext ) ;
1388+ ext . Members . Add ( extMemberDecl ) ;
1389+ entityMap . Add ( extMember , extMemberDecl ) ;
1390+ }
1391+
1392+ typeDecl . Members . Add ( ext ) ;
1393+ }
1394+ }
1395+
13641396 // Decompile members that are not compiler-generated.
13651397 foreach ( var entity in allOrderedEntities )
13661398 {
13671399 if ( entity . MetadataToken . IsNil || MemberIsHidden ( module . MetadataFile , entity . MetadataToken , settings ) )
13681400 {
13691401 continue ;
13701402 }
1371- DoDecompileMember ( entity , recordDecompiler , partialTypeInfo ) ;
1403+ DoDecompileMember ( entity , recordDecompiler , partialTypeInfo , typeDef . ExtensionInfo ) ;
13721404 }
13731405
13741406 // Decompile compiler-generated members that are still needed.
@@ -1380,7 +1412,7 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun
13801412 // Member is already decompiled.
13811413 continue ;
13821414 }
1383- DoDecompileMember ( entity , recordDecompiler , partialTypeInfo ) ;
1415+ DoDecompileMember ( entity , recordDecompiler , partialTypeInfo , typeDef . ExtensionInfo ) ;
13841416 }
13851417
13861418 // Add all decompiled members to syntax tree in the correct order.
@@ -1470,13 +1502,18 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun
14701502 Instrumentation . DecompilerEventSource . Log . DoDecompileTypeDefinition ( typeDef . FullName , watch . ElapsedMilliseconds ) ;
14711503 }
14721504
1473- void DoDecompileMember ( IEntity entity , RecordDecompiler recordDecompiler , PartialTypeInfo partialType )
1505+ void DoDecompileMember ( IEntity entity , RecordDecompiler recordDecompiler , PartialTypeInfo partialType , ExtensionInfo extensionInfo )
14741506 {
14751507 if ( partialType != null && partialType . IsDeclaredMember ( entity . MetadataToken ) )
14761508 {
14771509 return ;
14781510 }
14791511
1512+ if ( settings . ExtensionMembers && extensionInfo != null && entity is IMethod m && extensionInfo . InfoOfImplementationMember ( m ) . HasValue )
1513+ {
1514+ return ;
1515+ }
1516+
14801517 EntityDeclaration entityDecl ;
14811518 switch ( entity )
14821519 {
@@ -1497,15 +1534,15 @@ void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler, Partia
14971534 {
14981535 return ;
14991536 }
1500- entityDecl = DoDecompile ( property , decompileRun , decompilationContext . WithCurrentMember ( property ) ) ;
1537+ entityDecl = DoDecompile ( property , decompileRun , decompilationContext . WithCurrentMember ( property ) , null ) ;
15011538 entityMap . Add ( property , entityDecl ) ;
15021539 break ;
15031540 case IMethod method :
15041541 if ( recordDecompiler ? . MethodIsGenerated ( method ) == true )
15051542 {
15061543 return ;
15071544 }
1508- entityDecl = DoDecompile ( method , decompileRun , decompilationContext . WithCurrentMember ( method ) ) ;
1545+ entityDecl = DoDecompile ( method , decompileRun , decompilationContext . WithCurrentMember ( method ) , null ) ;
15091546 entityMap . Add ( method , entityDecl ) ;
15101547 foreach ( var helper in AddInterfaceImplHelpers ( entityDecl , method , typeSystemAstBuilder ) )
15111548 {
@@ -1543,6 +1580,19 @@ void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler, Partia
15431580 }
15441581 }
15451582
1583+ private EntityDeclaration DoDecompileExtensionMember ( IMember extMember , ExtensionInfo info , DecompileRun decompileRun , ITypeResolveContext decompilationContext )
1584+ {
1585+ switch ( extMember )
1586+ {
1587+ case IProperty p :
1588+ return DoDecompile ( p , decompileRun , decompilationContext . WithCurrentMember ( p ) , info ) ;
1589+ case IMethod m :
1590+ return DoDecompile ( m , decompileRun , decompilationContext . WithCurrentMember ( m ) , info ) ;
1591+ }
1592+
1593+ throw new NotSupportedException ( $ "Extension member { extMember } is not supported for decompilation.") ;
1594+ }
1595+
15461596 EnumValueDisplayMode DetectBestEnumValueDisplayMode ( ITypeDefinition typeDef , MetadataFile module )
15471597 {
15481598 if ( typeDef . HasAttribute ( KnownAttribute . Flags ) )
@@ -1604,7 +1654,7 @@ EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, Met
16041654 return firstValue == 0 ? EnumValueDisplayMode . None : EnumValueDisplayMode . FirstOnly ;
16051655 }
16061656
1607- EntityDeclaration DoDecompile ( IMethod method , DecompileRun decompileRun , ITypeResolveContext decompilationContext )
1657+ EntityDeclaration DoDecompile ( IMethod method , DecompileRun decompileRun , ITypeResolveContext decompilationContext , ExtensionInfo extensionInfo )
16081658 {
16091659 Debug . Assert ( decompilationContext . CurrentMember == method ) ;
16101660 var watch = System . Diagnostics . Stopwatch . StartNew ( ) ;
@@ -1630,7 +1680,7 @@ EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeRe
16301680 }
16311681 if ( methodDefinition . HasBody ( ) )
16321682 {
1633- DecompileBody ( method , methodDecl , decompileRun , decompilationContext ) ;
1683+ DecompileBody ( method , methodDecl , decompileRun , decompilationContext , extensionInfo ) ;
16341684 }
16351685 else if ( ! method . IsAbstract && method . DeclaringType . Kind != TypeKind . Interface )
16361686 {
@@ -1699,7 +1749,7 @@ internal static bool IsWindowsFormsInitializeComponentMethod(IMethod method)
16991749 return method . ReturnType . Kind == TypeKind . Void && method . Name == "InitializeComponent" && method . DeclaringTypeDefinition . GetNonInterfaceBaseTypes ( ) . Any ( t => t . FullName == "System.Windows.Forms.Control" ) ;
17001750 }
17011751
1702- void DecompileBody ( IMethod method , EntityDeclaration entityDecl , DecompileRun decompileRun , ITypeResolveContext decompilationContext )
1752+ void DecompileBody ( IMethod method , EntityDeclaration entityDecl , DecompileRun decompileRun , ITypeResolveContext decompilationContext , ExtensionInfo extensionInfo )
17031753 {
17041754 try
17051755 {
@@ -1708,6 +1758,14 @@ void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun de
17081758 UseRefLocalsForAccurateOrderOfEvaluation = settings . UseRefLocalsForAccurateOrderOfEvaluation ,
17091759 DebugInfo = DebugInfoProvider
17101760 } ;
1761+ int parameterOffset = 0 ;
1762+ if ( extensionInfo != null )
1763+ {
1764+ if ( ! method . IsStatic )
1765+ parameterOffset = 1 ; // implementation method has an additional receiver parameter
1766+ method = extensionInfo . InfoOfExtensionMember ( method ) . Value . ImplementationMethod ;
1767+ }
1768+
17111769 var methodDef = metadata . GetMethodDefinition ( ( MethodDefinitionHandle ) method . MetadataToken ) ;
17121770 var body = BlockStatement . Null ;
17131771 MethodBodyBlock methodBody ;
@@ -1727,7 +1785,7 @@ void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun de
17271785 var function = ilReader . ReadIL ( ( MethodDefinitionHandle ) method . MetadataToken , methodBody , cancellationToken : CancellationToken ) ;
17281786 function . CheckInvariant ( ILPhase . Normal ) ;
17291787
1730- AddAnnotationsToDeclaration ( method , entityDecl , function ) ;
1788+ AddAnnotationsToDeclaration ( method , entityDecl , function , parameterOffset ) ;
17311789
17321790 var localSettings = settings . Clone ( ) ;
17331791 if ( IsWindowsFormsInitializeComponentMethod ( method ) )
@@ -1786,9 +1844,9 @@ void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun de
17861844 }
17871845 }
17881846
1789- internal static void AddAnnotationsToDeclaration ( IMethod method , EntityDeclaration entityDecl , ILFunction function )
1847+ internal static void AddAnnotationsToDeclaration ( IMethod method , EntityDeclaration entityDecl , ILFunction function , int parameterOffset = 0 )
17901848 {
1791- int i = 0 ;
1849+ int i = parameterOffset ;
17921850 var parameters = function . Variables . Where ( v => v . Kind == VariableKind . Parameter ) . ToDictionary ( v => v . Index ) ;
17931851 foreach ( var parameter in entityDecl . GetChildrenByRole ( Roles . Parameter ) )
17941852 {
@@ -2023,7 +2081,7 @@ internal static bool IsFixedField(IField field, out IType type, out int elementC
20232081 return false ;
20242082 }
20252083
2026- EntityDeclaration DoDecompile ( IProperty property , DecompileRun decompileRun , ITypeResolveContext decompilationContext )
2084+ EntityDeclaration DoDecompile ( IProperty property , DecompileRun decompileRun , ITypeResolveContext decompilationContext , ExtensionInfo extensionInfo )
20272085 {
20282086 Debug . Assert ( decompilationContext . CurrentMember == property ) ;
20292087 var watch = System . Diagnostics . Stopwatch . StartNew ( ) ;
@@ -2053,11 +2111,11 @@ EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITy
20532111 bool setterHasBody = property . CanSet && property . Setter . HasBody ;
20542112 if ( getterHasBody )
20552113 {
2056- DecompileBody ( property . Getter , getter , decompileRun , decompilationContext ) ;
2114+ DecompileBody ( property . Getter , getter , decompileRun , decompilationContext , extensionInfo ) ;
20572115 }
20582116 if ( setterHasBody )
20592117 {
2060- DecompileBody ( property . Setter , setter , decompileRun , decompilationContext ) ;
2118+ DecompileBody ( property . Setter , setter , decompileRun , decompilationContext , extensionInfo ) ;
20612119 }
20622120 if ( ! getterHasBody && ! setterHasBody && ! property . IsAbstract && property . DeclaringType . Kind != TypeKind . Interface )
20632121 {
@@ -2113,11 +2171,11 @@ EntityDeclaration DoDecompile(IEvent ev, DecompileRun decompileRun, ITypeResolve
21132171 }
21142172 if ( adderHasBody )
21152173 {
2116- DecompileBody ( ev . AddAccessor , ( ( CustomEventDeclaration ) eventDecl ) . AddAccessor , decompileRun , decompilationContext ) ;
2174+ DecompileBody ( ev . AddAccessor , ( ( CustomEventDeclaration ) eventDecl ) . AddAccessor , decompileRun , decompilationContext , null ) ;
21172175 }
21182176 if ( removerHasBody )
21192177 {
2120- DecompileBody ( ev . RemoveAccessor , ( ( CustomEventDeclaration ) eventDecl ) . RemoveAccessor , decompileRun , decompilationContext ) ;
2178+ DecompileBody ( ev . RemoveAccessor , ( ( CustomEventDeclaration ) eventDecl ) . RemoveAccessor , decompileRun , decompilationContext , null ) ;
21212179 }
21222180 if ( ! adderHasBody && ! removerHasBody && ! ev . IsAbstract && ev . DeclaringType . Kind != TypeKind . Interface )
21232181 {
0 commit comments