0

As for a learning experience for defining a Roslyn Analyzer rule, let's say I have interfaces defined like

//These are a marker interfaces.
public interface ISomethingRoot1 {}
public interface ISomethingRoot2 {}

public interface ISomething: ISomethingRoot1
{
    int SomeOperation();    
}

public interface ISomething2: ISomethingRoot2
{
    int SomeOperation2();
}

How could I check function signatures of all the interfaces (maybe even classes that implement these interfaces and classes that inherit from the implementing classes, but that's secondary now) that inherit from the marker interfaces ISomethingRoot1 and ISomethingRoot2? I see there is at least one question related to this Finding all class declarations than inherit from another with Roslyn, but I haven't got the hang of it. It looks like I should register to SymbolKind.NamedType actions, but what would the AnalyzeSymbol part look like to find the function signatures inheriting from ISomethingRoot1 and ISomethingRoot2?

Here is some code I'm doing currently to make the question more clear:

[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public class PublicInterfaceAnalyzer: DiagnosticAnalyzer
{               
    private static ImmutableArray<DiagnosticDescriptor> SupportedRules { get; } = 
        new ImmutableArray<DiagnosticsDescriptor>(new DiagnosticDescriptor(id: "CheckId1",
            title: "Check1",
            messageFormat: "Placeholder text",
            category: "Usage",
            defaultSeverity: DiagnosticSeverity.Warning,
            isEnabledByDefault: true));

    public override void Initialize(AnalysisContext context)
    {
        context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);
    }

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => SupportedRules;


    private void AnalyzeSymbol(SymbolAnalysisContext context)
    {                     
        //How to check that the functions have, say, a certain kind of
        //of a return value or parameters or naming? I think I know how
        //to do that, but I'm not sure how to get a hold of the correct
        //interfaces and have a collection or their (public) methods to check.

        //This could be one way to go, but then in Initialize
        //should be "SymbolKind.Method", would that be the route to take?
        //The following omits the code to get the interfaces and do some
        //of the checks as this is code in progress and the main problem
        //is getting hold of the function signatures of interfaces that  
        //inherit from the marker interfaces.
        var symbol = (IMethodSymbol)context.Symbol;                                   
        context.ReportDiagnostic(Diagnostic.Create(SupportedRules[0], symbol.Locations[0], symbol.Name));          
    }                                        
}
Community
  • 1
  • 1
Veksi
  • 3,556
  • 3
  • 30
  • 69
  • 2
    _"that inherit from `ISomethingRoot1` and `ISomethingRoot1`"_ -- did you mean to write _"`ISomethingRoot1` and **`ISomethingRoot2`**"_? In what way do you want to _"check function signatures"_? What have you tried? Please provide [a good, _minimal_, _complete_ code example](http://stackoverflow.com/help/mcve) that shows clearly what you've tried, with a precise explanation of what that code does and how that's different from what you want. – Peter Duniho Nov 22 '15 at 00:03
  • Indeed, I misstyped the interface name. I included also code I'm currently having, basically I'm trying to find a way to get hold of the correct interfaces, all that implement `ISomethingRoot1` and `ISomethingRoot2` in this code. I don't know if it should matter if there is one or two of them. It looks like generics is a bit of a complication, but this is a learning experience, so I can tackle it later. – Veksi Nov 22 '15 at 06:45

1 Answers1

2

You can get a reference to the marker interface with the following:

var marker1 = context.SemanticModel.Compilation.GetTypeByMetadataName("NS.ISomethingRoot1");

Then if you are in a SymbolAction for NamedTypes, you can check if the current processed symbol implements this marker1 or not:

var symbol = context.Symbol as INamedTypeSymbol;
var implements = symbol.AllInterfaces.Any(@interface => @interface.Equals(marker1));

And then you can do whatever you want to check on the members of the type. You can get the members by calling symbol.GetMembers().

Tamas
  • 6,260
  • 19
  • 30
  • Looks straightforward. I'm away from computer about twelve hours, but I'm sure to check this later. Thanks! – Veksi Nov 23 '15 at 09:24
  • I got delayed by life, new try today. I don't like let you hanging without giving a notice though as I promised to check. :) – Veksi Nov 24 '15 at 13:13
  • I think I have a hunch, albeit this looks like being more complicated than what I thought about initially. Thanks though, this provided a little jump start to find more about these APIs! – Veksi Nov 29 '15 at 10:50