5

I'm implementing a Roslyn analyzer and I want to take different action based on how some properties are set within the csproj.

Currently I'm accomplishing this by setting "AdditionalFiles" node in a props file imported with the analyzer. This points to the .csproj and then I manually xml-parse the project file looking for the properties I care about.

    <ItemGroup>
      <AdditionalFiles Include="$(ProjectPath)" />
    </ItemGroup>   
        private void AnalyzeAdditionalFiles(CompilationStartAnalysisContext context)
        {
            ICompilationStartAnalysisContextWrapper wrappedContext = this.compilationStartAnalysisContextWrapperFactory.Create(context);

            if (wrappedContext.GetAdditionalTexts()
                              .Any(addtionalFile => <xml parse and validate csproj>))
            {
                context.RegisterSyntaxNodeAction(this.AnalyzeSyntaxNode, PossibleSyntaxKinds);
            }
        }

I've been told there may be a first-class supported way to do one or both of these actions without requiring what feels like hacky versions of:

  • Find the path to the csproj
  • Fetch properties from the csproj

Is this possible? Ideally I'd be looking for the moral equivalent of

AnalysisContext.Project.Properties["MyCustomProp"]
1
  • Did you try context.Options.AditionalFiles collection of AdditionalText what has property Path or method GetText() ? Or just context.Project.Documents Commented Apr 25, 2019 at 21:43

1 Answer 1

5

It's now possible to retrieve some project properties, starting with VS 16.7 preview3. It's based around the new csproj tag CompilerVisibleProperty. You can find more information on the source generator cookbook, but here's a quick example.

First, in your csproj file, you declare your property, and allow the analyzer to access it:

<!-- declare the property you want to access in your analyzer -->
<PropertyGroup>
    <MyCustomProp>Value from csproj</MyCustomProp>
</PropertyGroup>

<!-- explicitly allow the analyzer to access that variable -->
<ItemGroup>
    <CompilerVisibleProperty Include="MyCustomProp" />
</ItemGroup>

You can then access this variable from any analyzer context, via the AnalyzerConfigOptionsProvider.GlobalOptions. For example:

private static void CompilationStart(CompilationStartAnalysisContext context)
{
  // retrieve the global analyzer options 
  var globalOptions = context.Options.AnalyzerConfigOptionsProvider.GlobalOptions;

  // retrieve the actual build property 
  // -> wanted property name prefixed with "build_property."
  string myCustomProp = null;
  if (!globalOptions.TryGetValue("build_property.MyCustomProp", out myCustomProp))
        myCustomProp = "Default";
}

Nuget packages used for this example:

  • Microsoft.CodeAnalysis.Analyzers 3.3.3
  • Microsoft.CodeAnalysis.CSharp 4.0.1
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.