2

I'm writing my codefixer with roslyn. I want it to work in such way:
Before:

IEnumerable<int> list = new List<int> {1, 2, 3, 4};
list = list.Where(x => x%2 == 0);

After:

...
IEnumerable<int> list = new List<int> {1, 2, 3, 4};
list = list.Where(lambdaMethod);
...
private static bool lamdaMethod(int x)
{
    return x % 2 == 0;
}

The problem is that I can't find the proper way to get return type for the method and type of argument.
My method from analyzer template:

public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            // TODO: Replace the following code with your own analysis, generating a CodeAction for each fix to suggest
            var diagnostic = context.Diagnostics.FirstOrDefault();
            var diagnosticSpan = diagnostic.Location.SourceSpan;

            // Find the type declaration identified by the diagnostic.
            var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf()
                .OfType<LambdaExpressionSyntax>().FirstOrDefault();
            if (declaration == null)
                return;
            // Register a code action that will invoke the fix.

            context.RegisterCodeFix(
                CodeAction.Create(
                    title: $"{"Just Title"}",
                    createChangedDocument: c => MakeLambdaOptimization(context.Document, declaration, c),
                    equivalenceKey: nameof(CodeFixResources.CodeFixTitle)),
                diagnostic);
        }

As you see, I'm working with LambdaExpressionSyntax. There are also SimpleLambdaExpressionSyntax and ParenthesizedLambdaExpressionSyntax which help me to get ParameterSyntax. In the ParameterSyntax I can find Type, but it's null and I get NullReferenceException.
I tried to get the whole type of lambda (e.g. Func<int, bool>), I guess it would help me. How can I do it? I've heard about SemanticModel, but I don't know how to use it

1
  • The syntax nodes can only tell you what is visible in your code. To get the meaning of it you will need to use the samentic model, which you can get from context.Document.GetSemanticModelAsync() (csharp.hotexamples.com/de/examples/…) Commented Apr 10, 2022 at 20:40

1 Answer 1

2

You can use SemanticModel.GetSymbolInfo(ExpressionSyntax) to get the lambda symbol. From the lambda symbol you can find the information you need (return type and parameter types). Here is a code snippet (written in the context of a Console Application instead of a codefix for simplicity - you'll be able to get it working for codefixes):

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

// You don't need to create or get a compilation yourself. I'm creating it manually since I'm in a console app.
CSharpCompilation comp = CSharpCompilation.Create(null, new[] { SyntaxFactory.ParseSyntaxTree("System.Func<int, bool> f = x => x % 2 == 0;") }, new[] { MetadataReference.CreateFromFile(typeof(Func<>).Assembly.Location) });

// You already have the LambdaExpressionSyntax, ignore the following two lines, which again because I'm in a console app.
var root = comp.SyntaxTrees[0].GetRoot();
var lambda = root.DescendantNodes().OfType<LambdaExpressionSyntax>().Single();

// Here you'll need to get a semantic model via 'await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);'
var model = comp.GetSemanticModel(lambda.SyntaxTree);

// That's the core of what you want to do.
if (model.GetSymbolInfo(lambda).Symbol is IMethodSymbol lambdaSymbol)
{
    // prints 'bool'
    Console.WriteLine(lambdaSymbol.ReturnType.ToDisplayString());
    foreach (var parameter in lambdaSymbol.Parameters)
    {
        // prints 'int' (loop is entered once since my lambda has a single parameter).
        Console.WriteLine(parameter.Type.ToDisplayString());
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot! It's actually what I need!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.