Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stepping through the Roslyn C# compiler

Tags:

c#

roslyn

I've built the Roslyn source as described here.

I'd like to add a breakpoint in the C# compiler and step through the compliation of this simple program:

using System;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = 1 + 2;

            Console.WriteLine(result);
        }
    }
}

Where should I set a breakpoint? It should be early in the compilation process as I'd like to step through parsing and even lexing.

If I set CompilerExtension as the startup project and hit F5 (Start Debugging), a copy of Visual Studio is launched running the newly built compiler. I'd like to avoid having to launch a new instance of Visual Studio each time I'd like to step through the compiler. What's a good way to setup a small program which invokes the compiler code on the above source directly?

like image 336
dharmatech Avatar asked Mar 05 '16 22:03

dharmatech


2 Answers

Here's one approach as suggested by Josh in a comment above.

  • Add a new "Console Application" project to the Roslyn solution.

  • Add these two references to the project:

enter image description here

A simple program to test the parser:

using Microsoft.CodeAnalysis.CSharp;

namespace TestCompiler
{
    class Program
    {
        static void Main(string[] args)
        {
            var program_text = @"

                using System;

                namespace ConsoleApplication2
                {
                    class Program
                    {
                        static void Main(string[] args) 
                        { var result = 2 + 3; Console.WriteLine(result); }
                    }
                }
            ";

            var result = CSharpSyntaxTree.ParseText(program_text);
        }
    }
}
  • Add a breakpoint to the line that calls ParseText.

  • "Start Debugging" and step into that line to delve into the parser.

A simple program to test the compiler via Emit:

using System;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace TestCompiler
{
    class Program
    {
        static void Main(string[] args)
        {
            var program_text = @"

                using System;

                namespace ConsoleApplication2
                {
                    class Program
                    {
                        static void Main(string[] args) 
                        { var result = 2 + 3; Console.WriteLine(result); }
                    }
                }
            ";

            var syntax_tree = CSharpSyntaxTree.ParseText(program_text);

            var compilation = CSharpCompilation.Create(
                Guid.NewGuid().ToString("D"),
                new[] { syntax_tree },
                new[] { MetadataReference.CreateFromFile(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\mscorlib.dll") });

            var emit_result = compilation.Emit(new MemoryStream());
        }
    }
}
like image 110
dharmatech Avatar answered Oct 15 '22 07:10

dharmatech


If you want to have a simple program that invokes the compiler, just consider using csc as your startup project. You can specify the arguments to pass (like source files) from the debug settings on the project.

like image 44
Jason Malinowski Avatar answered Oct 15 '22 08:10

Jason Malinowski