如何将额外的文件添加到专门的Roslyn工作区中,以将它们公开给分析器

本文关键字:工作区 分析器 文件 添加 Roslyn | 更新日期: 2023-09-27 18:25:25

我正在创建一些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功能无关?

如何将额外的文件添加到专门的Roslyn工作区中,以将它们公开给分析器

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

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));
  }
}