【问题标题】:Stepping through the Roslyn C# compiler单步调试 Roslyn C# 编译器
【发布时间】:2016-06-19 15:33:52
【问题描述】:

我已将 Roslyn 源代码构建为 described here

我想在 C# 编译器中添加一个断点,并逐步完成这个简单程序的编译:

using System;

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

            Console.WriteLine(result);
        }
    }
}

我应该在哪里设置断点?它应该在编译过程的早期,因为我想逐步完成解析甚至词法分析。

如果我将 CompilerExtension 设置为启动项目并按 F5(开始调试),则会启动 Visual Studio 的副本并运行新构建的编译器。我想避免每次我想单步调试编译器时都必须启动一个新的 Visual Studio 实例。有什么好的方法来设置一个小程序直接调用上述源码上的编译器代码?

【问题讨论】:

  • 您可以向 Roslyn 解决方案添加一个新项目,添加对正确 Microsoft.CodeAnalysis 项目的引用,然后调用 CSharpSyntaxTree.ParseText()Compilation.Emit()。然后,您可以单步执行您感兴趣的解析或发出代码。
  • 谢谢乔希!我添加了一个演示 ParseText 的答案。 @JoshVarty
  • 我写了一篇博客文章,有点基于@JoshVarty 在这里和他的一篇博客文章中的建议。任何想要玩弄 Roslyn 内部的人都可能会感兴趣。 renniestechblog.com/information/…

标签: c# roslyn


【解决方案1】:

这是 Josh 在上面的评论中建议的一种方法。

  • 向 Roslyn 解决方案添加一个新的“控制台应用程序”项目。

  • 将这两个引用添加到项目中:

一个测试解析器的简单程序:

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);
        }
    }
}
  • 在调用ParseText的行中添加断点。

  • “开始调试”并进入该行以深入研究解析器。

一个通过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());
        }
    }
}

【讨论】:

  • 对于当前版本的 Roslyn 和 Visual Studio 2017,您还需要为 System.Reflection.Metadata,版本 = 1.4.2 添加对 NuGet 包的引用。直到我确定(我花了很长时间)我得到“应用程序处于中断模式”,并且根本无法做任何事情。这可能是由于 Visual Studio developercommunity.visualstudio.com/content/problem/104485/… 中的错误最终提供了真正问题的线索是当我双击生成的 .exe 文件时 - 然后在控制台窗口中出现错误。
【解决方案2】:

如果您想要一个调用编译器的简单程序,只需考虑使用 csc 作为您的启动项目。您可以从项目的调试设置中指定要传递的参数(如源文件)。

【讨论】:

  • 谢谢杰森!我目前正在探索 Josh 在上面的评论中提到的方法。到目前为止,它似乎运作良好。我添加了一个描述该方法的答案。
  • 这似乎是在 Visual Studio 调试器下测试 Roslyn 编译器的合乎逻辑的方式。但是 csc.exe 有很多可能的参数。您是否有关于需要哪些参数以及哪些附加参数可能是一个好主意的链接或建议?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-11
  • 1970-01-01
  • 2015-06-19
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多