ReSharper File Layout for Explicit Interface Implementation

I'm trying to configure the File Layout of ReSharper in such a way that formatting the code does respect the 'StyleCop SA1202' rule.
See https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md for more information.

Basically, this rule says that the order of elements is required to match a given pattern.
First 'Public', followed by 'Internal' ...

When I have a class that implements an interface explicit, it's in fact 'public'.
See the following code:

void IDisposable.Dispose()
{
// Implementation
}

When I configure ReSharper File Layout with the following configuration:

<Entry DisplayName="Methods">
<Entry.Match>
<Kind Is="Method" />
</Entry.Match>
<Entry.SortBy>
<Access Order="Public Internal Protected" />
</Entry.SortBy>
</Entry>

The explicit implemented interface is placed as the after any public methods.

Is there any way to configure ReSharper's File Layout so that rule SA1202 is respected when using explicit interface implementations?

 

 

Kind regards

4
2 comments

For anyone stumbling on this:

The issue seems to be that explicit interface implementations do not carry an access modifier in C# (they are semi-public, meaning you can only access them through the interface).

So ReSharper thinks they are private (which in IL they actually are).

The fix is to place explicit interface implementations before public methods like so (which satisfies SA1202):

<Entry DisplayName="Explicit interface implementations">
 <Entry.Match>
   <And>
     <Kind Is="Method" />
     <ImplementsInterface />
     <Access Is="Private" />
   </And>
 </Entry.Match>
 <Entry.SortBy>
   <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
   <Static />
   <Readonly />
   <Name />
 </Entry.SortBy>
</Entry>
<Entry DisplayName="Methods">
 <Entry.Match>
   <Kind Is="Method" />
 </Entry.Match>
 <Entry.SortBy>
   <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
   <Static />
   <Readonly />
   <Name />
 </Entry.SortBy>
</Entry>
0

Here is a complete ReSharper file layout XML that complies with StyleCop's SA1202 rule:

<?xml version="1.0" encoding="utf-16"?>
<Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
 <TypePattern DisplayName="Types marked [NoReorder]" Priority="100">
   <TypePattern.Match>
     <HasAttribute Name="JetBrains.Annotations.NoReorderAttribute" />
   </TypePattern.Match>
 </TypePattern>
 <TypePattern DisplayName="StyleCop order" RemoveRegions="None">
   <Entry DisplayName="Constants">
     <Entry.Match>
       <Kind Is="Constant" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Fields">
     <Entry.Match>
       <Kind Is="Field" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Constructors">
     <Entry.Match>
       <Kind Is="Constructor" />
     </Entry.Match>
     <Entry.SortBy>
       <Static />
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Finalizers">
     <Entry.Match>
       <Kind Is="Destructor" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Delegates">
     <Entry.Match>
       <Kind Is="Delegate" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Events">
     <Entry.Match>
       <Kind Is="Event" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Enums">
     <Entry.Match>
       <Kind Is="Enum" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Interfaces">
     <Entry.Match>
       <Kind Is="Interface" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Explicit interface properties">
     <Entry.Match>
       <And>
         <Kind Is="Property" />
         <ImplementsInterface />
         <Access Is="Private" />
       </And>
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Properties">
     <Entry.Match>
       <Kind Is="Property" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Explicit interface indexers">
     <Entry.Match>
       <And>
         <Kind Is="Indexer" />
         <ImplementsInterface />
         <Access Is="Private" />
       </And>
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Indexers">
     <Entry.Match>
       <Kind Is="Indexer" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Conversion operators">
     <Entry.Match>
       <And>
         <Kind Is="Operator" />
         <Or>
           <Name Is="op_Implicit" />
           <Name Is="op_Explicit" />
         </Or>
       </And>
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Operators">
     <Entry.Match>
       <Kind Is="Operator" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Explicit interface methods">
     <Entry.Match>
       <And>
         <Kind Is="Method" />
         <ImplementsInterface />
         <Access Is="Private" />
       </And>
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Methods">
     <Entry.Match>
       <Kind Is="Method" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Structs">
     <Entry.Match>
       <Kind Is="Struct" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
   <Entry DisplayName="Classes">
     <Entry.Match>
       <Kind Is="Class" />
     </Entry.Match>
     <Entry.SortBy>
       <Access Order="Public Internal ProtectedInternal Protected PrivateProtected Private" />
       <Static />
       <Readonly />
       <Name />
     </Entry.SortBy>
   </Entry>
 </TypePattern>
</Patterns>
0

Please sign in to leave a comment.