Roslyn CodeFix - MSBuild 属性/元数据和单元测试

标签 roslyn roslyn-code-analysis microsoft.codeanalysis

我正在构建 roslyn 分析器/代码修复,但我不想访问 MSBuild 属性和元数据(来自 Directory.build.props 和 .csproj)以了解如何应用代码修复。我只找到了在源代码生成器中执行此操作的文档,但在分析器中找不到。

更具体地说,我想知道项目是否配置为使用新的 ImplicitUsings,但如果能访问所有内容也会很有用。

还有我们有什么办法让所有的项目全局使用吗?

使用新的 Microsoft.CodeAnalysis.Testing 如何添加 MSBuild 属性以便我可以实际测试它?

问候。

最佳答案

DiagnosticAnalyzer 中访问 MSBuild 属性和元数据s 实际上与它们在 ISourceGenerator 中的读取和测试方式非常相似。 s/IIncrementalGenerator s,因为 Source Generators 在技术上也是 .NET 分析器

我假设您提到的文档是 Source Generators Cookbook .

首先,我们需要使 MSBuild 属性可用于分析器的全局分析器配置选项:

<Project>
  <ItemGroup>
    <CompilerVisibleProperty Include="MyAnalyzer_MyProperty" />
  </ItemGroup>
</Project>

然后,我们可以从 AnalyzerConfigOptionsProvider 中读取该属性的值的 GlobalOptions .您会在 AnalysisContext.Register* 的参数中找到它您在覆盖的 DiagnosticAnalyzer.Initialize(AnalysisContext) 中使用的选择方法方法。 例如RegisterCompilationAction :

bool isEnabled = false;
if (compilationAnalysisContext.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.MyAnalyzer_MyProperty", out string? value))
{
    isEnabled = value.Equals("true", StringComparison.OrdinalIgnoreCase) || value.Equals("enable", StringComparison.OrdinalIgnoreCase);
}

ImmutableDictionary<string, string?>.Builder properties = ImmutableDictionary.CreateBuilder<string, string?>();
if (isEnabled)
{
    properties.Add("IsEnabled", value);
}

var diagnostic = Diagnostic.Create(Rule, location, properties.ToImmutable());
compilationAnalysisContext.ReportDiagnostic(diagnostic);

CodeFixProviderCodeFixContext没有专用的 AnalyzerOptions Options属性,但您可以通过 Diagnostic.Properties 传递值:

foreach (Diagnostic diagnostic in context.Diagnostics)
{
    if (diagnostic.Properties.TryGetValue("IsEnabled", out string? value))
    {
        var action = CodeAction.Create(Title, cancellationToken => OnCreateChangedDocument(context.Document, cancellationToken), diagnostic.Id);
        context.RegisterCodeFix(action, diagnostic);
    }
}

... 或者,我刚刚在撰写此答案时发现的内容,访问 AnalyzerConfigOptionsProvider通过CodeFixContext.Document.Project.AnalyzerOptions .这适用于任何你有 Document 的地方(或 Project )可用:

public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
    bool hasValue = context.Document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.MyAnalyzer_MyProperty", out string? value);
}

此外,它还适用于 CodeRefactoringProvider :

public override Task ComputeRefactoringsAsync(CodeRefactoringContext context)
{
    bool hasValue = context.Document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.MyAnalyzer_MyProperty", out string? value);

    return Task.CompletedTask;
}

... 和 CompletionProvider :

public override Task ProvideCompletionsAsync(CompletionContext context)
{
    bool hasValue = context.Document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.MyAnalyzer_MyProperty", out string? value);

    return Task.CompletedTask;
}

... 还有 DiagnosticSuppressor :

public override void ReportSuppressions(SuppressionAnalysisContext context)
{
    bool hasValue = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.MyAnalyzer_MyProperty", out string? value);
}

并通过 Microsoft.CodeAnalysis.Testing 进行测试,您可以通过 ProjectState.AnalyzerConfigFiles 添加全局分析器配置选项的 AnalyzerTest<TVerifier>SolutionState TestState属性:

string config = $"is_global = true{Environment.NewLine}build_property.MyAnalyzer_MyProperty = {true}";
analyzerTest.TestState.AnalyzerConfigFiles.Add(("/.globalconfig", config));

上面我描述了自定义 MSBuild 属性的用法 MyAnalyzer_MyProperty , 但当然它适用于众所周知的 ImplicitUsings属性(property)也是。

关于Roslyn CodeFix - MSBuild 属性/元数据和单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69215975/

相关文章:

c# - Roslyn:如何在 Visual Studio 之外加载现有项目

c# - 查找方法中使用了哪些 using 指令

visual-studio - 来自同一解决方案的 DiagnosticAnalyzer 引用

c# - 确定是否使用 Roslyn 读取私有(private)字段

c# - Roslyn 代码操作 : How to check if preview or real execution?

C# -> Roslyn -> 查找所有类似 unix “strings” 命令的字符串并能够操作它们

roslyn - CA1801 与 IDE0060

c# - Roslyn CodeFixProvider 未在 Visual Studio IDE 中加载或运行。我错过了什么?

visual-studio - 如何使用 Roslyn Workspace 预编译项目

C# 静态分析,变量/参数的可能值