如何将其他文件添加到临时 Roslyn 工作区以将它们公开给分析器

How to add additional files to an ad hoc Roslyn workspace to expose them to analyzers

我正在创建一些 Roslyn 分析器,它们使用 AdditionFiles 功能来访问设置文件。我正在尝试测试分析仪是否正确使用它。

我有一个设置临时测试工作区的方法,我尝试通过两种途径添加额外的文档:

private static Project CreateProject(IEnumerable<string> sources)
{
    var projectId = ProjectId.CreateNewId(TestProjectName);

    var solution = new AdhocWorkspace()
        .CurrentSolution
        .AddProject(projectId, TestProjectName, TestProjectName, LanguageNames.CSharp)
        .AddMetadataReference(projectId, CorlibReference)
        .AddMetadataReference(projectId, SystemCoreReference)
        .AddAdditionalDocument(DocumentInfo.Create(DocumentId.CreateNewId(projectId),
                                                    "arnolyzer.yaml",
                                                    filePath: @"..\..\arnolyzer.yaml"));

    var count = 0;
    foreach (var source in sources)
    {
        var newFileName = $"{DefaultFilePathPrefix}{count++}.{CSharpDefaultFileExt}";
        var documentId = DocumentId.CreateNewId(projectId, newFileName);
        solution = solution.AddDocument(documentId, newFileName, SourceText.From(source));
    }
    var settingsFileId = DocumentId.CreateNewId(projectId, "arnolyzer.yaml");
    solution = solution.AddAdditionalDocument(settingsFileId, "arnolyzer.yaml", SourceText.From(@"..\..\arnolyzer.yaml"));
    return solution.GetProject(projectId);
}

检查 Project 实例,我可以看到两个附加文档都已添加。

但是,在 AnalysisContext.RegisterCompilationStartAction 操作中检查 CompilationStartAnalysisContext.Options.AdditionalFiles 时,AdditionalFiles 是空的。

有谁知道这种方法是否有效以及我是否哪里出错了?还是添加到 Project 的附加文档与 AditionalFiles 功能无关?

这不会直接回答您的问题,但您提到您正在尝试测试分析器是否使用附加文件。所以,我们是这样解决的:

var compilationWithAnalyzer = compilation.WithAnalyzers(
  diagnosticAnalyzers,
  new AnalyzerOptions(ImmutableArray.Create<AdditionalText>(new AnalyzerAdditionalFile(configuration.Path))),
  tokenSource.Token);
var diagnostics = await compilationWithAnalyzer.GetAnalyzerDiagnosticsAsync();

其中 AnalyzerAdditionalFile 只是扩展了 AdditionalText:

public sealed class AnalyzerAdditionalFile : AdditionalText
{
  private readonly string path;

  public AnalyzerAdditionalFile(string path)
  {
    this.path = path;
  }

  public override string Path => path;

  public override SourceText GetText(CancellationToken cancellationToken)
  {
    return SourceText.From(File.ReadAllText(path));
  }
}