SharpDevelop Community

Get your problems solved!
Welcome to SharpDevelop Community Sign in | Join | Help
in Search

Resolving spurious FxCop warnings in async code

Last post 06-19-2017 10:44 AM by sbridewell. 0 replies.
Page 1 of 1 (1 items)
Sort Posts: Previous Next
  • 06-19-2017 10:44 AM

    Resolving spurious FxCop warnings in async code

    Since I started working with WPF and the MVVM pattern, and specifically the async and await keywords, I've been getting spurious FxCop warnings which I don't seem to be able to suppress without excluding the rule being violated entirely, which I don't really want to do. In this post I describe how I fixed this.

    Example code:

    using System;
    using System.Threading;
    using System.Threading.Tasks;

    namespace AsyncFxCop
    {
        public class Class1
        {
            private readonly string _didSomething = "didSomething";
           
            public async Task<string> DoSomethingAsync()
            {
                await Task.Run(() => Thread.Sleep(500));
                return _didSomething;
            }
        }
    }



    When I use SharpDevelop to FxCop the project containing this class, I get a spurious warning:


    Modify 'Class1.<DoSomethingAsync>d__1.MoveNext()' to catch a more specific exception than 'Exception' or rethrow the exception. (CA1031)


    Obviously my code isn't catching any exceptions, it's the code generated by the compiler as a result of me using the asnc and await keywords which is. According to this StackOverflow answer, FxCopCmd.exe isn't clever enough to ignore compiler generated code, and when SharpDevelop uses FxCop to check a project, effectively it's running a MSBuild task in the ICSharpCode.Build.Tasks project, which is a wrapper around FxCopCmd.exe.

    The StackOverflow answer also points us to an assembly called fxcoptask.dll, which is what Visual Studio uses for code analysis, and which is clever enough to ignore compiler generated code. So I thought I'd see if I could get SharpDevelop to use fxcoptask.dll for code analysis rather than FxCopCmd.exe.

    It turns out that this can be achieved by changing the SharpDevelop.CodeAnalysis.targets file in the ICSharpCode.Build.Tasks project (or by changing this file in SharpDevelop's bin folder if you don't want to rebuild SharpDevelop). I changed this


        <UsingTask TaskName="ICSharpCode.Build.Tasks.FxCop"
                   AssemblyFile="$(SharpDevelopBinPath)\ICSharpCode.Build.Tasks.dll"/>



    to this


        <UsingTask TaskName="Microsoft.Build.Tasks.CodeAnalysis"
                   AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\CodeAnalysis\fxcoptask.dll" />



    And this


            <FxCop ToolPath       = "$(FxCopDir)"
                   InputAssembly  = "$(SharpDevelopFxCopAssembly)"
                   Rules          = "$(CodeAnalysisRules)"
                   RuleAssemblies = "$(CodeAnalysisRuleAssemblies)"
                   LogFile        = "$(SharpDevelopFxCopLogFile)"
                   ReferencePaths = "@(ReferencePath)"
                   Dictionary     = "@(CodeAnalysisDictionary)"/>



    to this


            <CodeAnalysis ToolPath            = "$(FxCopDir)"
                          Assemblies          = "$(SharpDevelopFxCopAssembly)"
                          Rules               = "$(CodeAnalysisRules)"
                          RuleAssemblies      = "$(CodeAnalysisRuleAssemblies)"
                          RuleSet             = "$(CodeAnalysisRuleSet)"
                          LogFile             = "$(SharpDevelopFxCopLogFile)"
                          References          = "@(ReferencePath)"
                          Dictionaries        = "@(CodeAnalysisDictionary)"
                          IgnoreGeneratedCode = "true" />



    So the "Check with FxCop" in SharpDevelop is now running the CodeAnalysis task in the fxcoptask.dll assembly, rather than the FxCop task in the ICSharpCode.Build.Tasks assembly. Success! FxCop is no longer reporting spurious warnings for my async methods (but it's still reporting other violations in my code which I want FxCop to alert me to).

    But now I have a new FxCop warning:

    CA0503 : The CodeAnalysisRules property is deprecated. Use the CodeAnalysisRuleSet property instead.

    This is due to me having excluded a rule from code analysis via the project properties -> Code Analysis screen, which results in something similar to the following being added to the project file

    <CodeAnalysisRules>-Microsoft.Globalization#CA1303</CodeAnalysisRules>

    This version of FxCop, rather than including or excluding individual rules on a per-project basis, prefers us to use ruleset files to define a set of rules to be run, and to reference the ruleset file from the project. Visual Studio 2015 includes a UI for editing ruleset files, similar to the way in which the AnalysisProjectOptionsPanel class in SharpDevelop's CodeAnalysis project allows us to include or exclude rules from code analysis. A complete solution would include rewriting that class to create and edit ruleset files, but for now I'll create my ruleset file and edit my .csproj file using a text editor.

    First, the RuleSet file. In this example I want to run all the available rules except for CA1303, because I'm checking a unit test project and my unit tests pass literal values to various Assert methods in the NUnit framework.


    <?xml version="1.0" encoding="utf-8"?>
    <RuleSet Name="My rule set" Description="Rule set for unit test projects." ToolsVersion="10.0">
      <IncludeAll Action="Warning" />
      <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
        <Rule Id="CA1303" Action="None" />
      </Rules>
    </RuleSet>



    The IncludeAll element tells FxCop to run all available rules, and its Action="Warning" attribute means that any violations found should be treated as compiler warnings, which is how FxCop rule violations are normally shown in SharpDevelop.

    The Rule element overrides the previous behaviour of rule CA1303. The meaningful values I've found for the Action attribute element are Error, Warning and None. In this case, setting it to "None" effectively suppresses the rule.

    Instead of the IncludeAll element, we can import the contents of one or more ruleset files.

    <Include Path="AllRules.ruleset" Action="Default" />



    There are some ruleset files which come with Visual Studio, I found them in C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\Rule Sets and I think they are installed as part of Microsoft Build Tools 2015. You may want to examine them and import some of them or base your own ruleset files on them.

    For now, I'll save my ruleset file as "MyRules.ruleset.xml" (adding the .xml extension means that SharpDevelop recognises it as a XML file, which makes editing it a bit easier). And now I need to edit my .csproj file, removing the CodeAnalysisRules property which causes the CA0503 warning above, and replacing it with a CodeAnalysisRuleSet property pointing to my ruleset file.

    <CodeAnalysisRuleSet>MyRules.ruleset.xml</CodeAnalysisRuleSet>



    I'm not sure exactly how FxCop resolves this to a fully qualified path, but if I provide a relative path from the folder which contains my .csproj file then it seems to work.

    This isn't a complete solution of course. There's more work needed in the CodeAnalysis project, not only changing the AnalysisProjectOptionsPanel class so that it edits a ruleset file, but also potentially changing the AnalysisIdeOptions panel to allow the user to browse to the location of the fxcoptask.dll file rather than the location of FxCopCmd.exe. I suspect that this change also makes some of the code in the ICSharpCode.Build.Tasks and CodeAnalysis projects redundant. However, it's a fairly quick way of getting rid of all those spurious FxCop warnings so that you can once again see the genuine warnings which need fixing.

     

    Filed under:
Page 1 of 1 (1 items)
Powered by Community Server (Commercial Edition), by Telligent Systems
Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.