Search code examples
c#genetic-programmingroslyn

Roslyn CTP - Random Code Modification


I have been experimenting with the Roslyn API in a genetic programming type of scenario. It appears like a great way to do that type of programming, but the actual implementation of simple scenarios doesn't seem very straightforward, which means I probably don't have a good understanding of how to use this API properly. Here is a simple program I am trying to modify in my experiments:

string treeText = @"using System;
                                using System.Collections.Generic;

                                namespace TestProgram
                                {
                                    class Program
                                    {
                                        static void Main(string[] args)
                                        {
                                            var myVar = 3;
                                            string myString = ""Hello World"";
                                            List<string> stringList = new List<string>();
                                            Console.WriteLine(myString + myVar);
                                            Console.ReadLine();
                                        }
                                    }
                                }";

SyntaxTree tree = SyntaxTree.ParseText(treeText);

var compilation = Compilation.Create("test.exe",
        syntaxTrees: new[] { tree },
        references: new[]
            {
                new MetadataFileReference(typeof(object).Assembly.Location),
                new MetadataFileReference(typeof(Enumerable).Assembly.Location),
            });

        SemanticModel model = compilation.GetSemanticModel(tree);

Just as a simple example let's say I somehow "randomly" decided I want to insert a new method invocation using the myString instance. What would be an efficient way to figure out what methods I could invoke off of that instance? What would then be the best way to create the necessary MethodInvocationSyntax (once I chose a specific method to use) from the symbol information? I found a method called ResolveOverloads on the SemanticModel class which appears where I need to end up, but I am having some difficulty figuring out an efficient path to the parameters this method requires. Is that even the right path to go down?


Solution

  • First, get the VariableDeclaratorSyntax for your variable, for example:

    var variable = tree.GetRoot().DescendantNodes()
                       .OfType<VariableDeclaratorSyntax>()
                       .Single(v => v.Identifier.ValueText == "myString");
    

    Next, get the LocalSymbol for this variable from the SemanticModel:

    var variableSymbol = (LocalSymbol)model.GetDeclaredSymbol(variable);
    

    Then you can get a list of methods you can invoke on this variable based on its type. You can either simply get all members of the type that are instance methods:

    var methods =
        variableSymbol.Type.GetMembers()
                      .OfType<MethodSymbol>()
                      .Where(m => !m.IsStatic && m.MethodKind == MethodKind.Ordinary);
    

    Or, if you wanted to include extension methods, you could use LookupSymbols():

    var methods = model.LookupSymbols(
        variable.GetLocation().SourceSpan.Start, variableSymbol.Type,
        options: LookupOptions.IncludeExtensionMethods)
                       .Where(m => !m.IsStatic);
    

    You can then choose one of the available methods based on your logic and create InvocationExpressionSyntax (the following code assumes it's a parameterless method):

    var invocationExpression =
        Syntax.InvocationExpression(
            Syntax.MemberAccessExpression(
                SyntaxKind.MemberAccessExpression,
                Syntax.IdentifierName(variableSymbol.Name),
                (SimpleNameSyntax)Syntax.ParseName(selectedMethod.Name)));
    

    You would then need to figure out where in your method to add the expression and what to do with its result (if anything).