如何将其他文件添加到临时 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));
}
}
我正在创建一些 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));
}
}