Skip to content

kzu/AnalyzerSettings

Repository files navigation

AnalyzerSettings from MSBuild

Version Downloads Build Status License CI NuGet Feed

Analyzers typically need some sort of configuration to tweak how they work. In order to avoid inventing your own mecanism for settings, the AnalyzerSettings package provides the basic targets to allow the settings to be driven by MSBuild properties and items, with full support for incremental builds and both design-time and compile-time analyzer settings.

Your analyzer targets can simply declare settings to persist as AnalyzerSetting items, and this package will automatically persist and expose those to your analyzers:

<!-- In your analyzer package .targets  -->
<ItemGroup>
    <AnalyzerSetting Include="SingleFileCodeGeneration" Value="$([MSBuild]::ValueOrDefault('$(SingleFileCodeGeneration)', 'true'))" />
</ItemGroup>

Note how you can even leverage ValueOrDefault to easily provide sensible defaults for your analyzer setting. Of course, any of the built-in MSBuild property functions can similarly be used.

Consuming the settings is equally straightforward, and requires no dependency with this package from your analyzer:

public class MyCodeGenAnalyzer : DiagnosticAnalyzer
{
    public override void Initialize(AnalysisContext context)
    {
        // Just to show *all* analyzer contexts are supported via their AnalyzerOptions
        context.RegisterCompilationAction(AnalyzeCompilation);
        context.RegisterSemanticModelAction(AnalyzeSemanticModel);
        context.RegisterOperationAction(AnalyzeOperation/*, params OperationKind[] */);
        context.RegisterSymbolAction(AnalyzeSymbol /*, params SymbolKind[] */);
        context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode/*, params SyntaxKind[] */);
    }

    // Simply converts the additional file that ends in `AnalyzerSettings.ini` into a Dictionary<string, string>
    private Dictionary<string, string> GetAnalyzerSettings(AnalyzerOptions options)
    {
        var settingsFile = options.AdditionalFiles.FirstOrDefault(x => x.Path.EndsWith("AnalyzerSettings.ini", StringComparison.OrdinalIgnoreCase));
        if (settingsFile == null)
            return new Dictionary<string, string>();

        // Added some extra precautions in parsing each line.
        // You could also filter lines for settings starting with your known ones only...
        return settingsFile
            .GetText()
            .Lines.Select(line => line.ToString())
            .Where(line => !string.IsNullOrEmpty(line))
            .Select(line => line.Split('='))
            .Where(pair => pair.Length == 2)
            .ToDictionary(pair => pair[0].Trim(), pair => pair[1].Trim());
    }

    private void AnalyzeCompilation(CompilationAnalysisContext context)
    {
        var settings = GetAnalyzerSettings(context.Options);
        var useSingleFile = settings.TryGetValue("SingleFileCodeGeneration", out var singleFileString) &&
            bool.TryParse(singleFileString, out var singleFile) && singleFile;
        // ... 
    }

    private void RegisterSemanticModelAction(SemanticModelAnalysisContext context)
    {
        var settings = GetAnalyzerSettings(context.Options);
        // ... 
    }

    private void RegisterOperationAction(OperationAnalysisContext context)
    {
        var settings = GetAnalyzerSettings(context.Options);
        // ... 
    }
    
    private void RegisterSymbolAction(SymbolAnalysisContext context)
    {
        var settings = GetAnalyzerSettings(context.Options);
        // ... 
    }

    private void RegisterSyntaxNodeAction(SyntaxNodeAnalysisContext context)
    {
        var settings = GetAnalyzerSettings(context.Options);
        // ... 
    }    
}

Unless disabled by setting the MSBuild property EnableDefaultOutputPathsAnalyzerSettings to false, all output properties from the .NET SDK are included as analyzer settings since they are generally useful.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages