2016-03-16 2 views
1

При запуске различных анализаторов в отношении проекта с использованием MSBuild все сбои будут выводиться в формате «Формат статистического анализа результатов (SARIF)» (см., Например, https://github.com/sarif-standard/sarif-spec). Например накопление может привести следующийАнализ «Формат обмена результатами статистического анализа (SARIF)» в MSBuild

{ 
    "version": "0.1", 
    "toolInfo": { 
    "toolName": "Microsoft (R) Visual C# Compiler", 
    "productVersion": "1.1.0", 
    "fileVersion": "1.1.0" 
    }, 
    "issues": [ 
    { 
     "ruleId": "SA1401", 
     "locations": [ 
     { 
      "analysisTarget": [ 
      { 
       "uri": "C:\\SomeFile.cs", 
       "region": { 
       "startLine": 708, 
       "startColumn": 30, 
       "endLine": 708, 
       "endColumn": 36 
       } 
      } 
      ] 
     } 
     ], 
     "shortMessage": "Field must be private", 
     "fullMessage": "A field within a C# class has an access modifier other than private.", 
     "properties": { 
     "severity": "Warning", 
     "warningLevel": "1", 
     "defaultSeverity": "Warning", 
     "title": "Fields must be private", 
     "category": "StyleCop.CSharp.MaintainabilityRules", 
     "helpLink": "https:\/\/github.com\/DotNetAnalyzers\/StyleCopAnalyzers\/blob\/master\/documentation\/SA1401.md", 
     "isEnabledByDefault": "True", 
     "isSuppressedInSource": "True" 
     } 
    } 
    ] 
} 

Теперь я хотел бы, чтобы иметь возможность анализировать данные выше в наиболее простом способе (и прерывание сборки, если какие-либо не-подавлены вопросы встречаются). Как это сделать?

PS. Я также хотел бы избежать реализации моих собственных задач MSBuild и установки специального программного обеспечения (например, PowerShell 3.0 - ConvertFrom-Json).

ответ

0

Поскольку, по-видимому нет встроенного способа сделать это, я в конечном итоге, используя задачу рядного MSBuild (https://msdn.microsoft.com/en-US/library/dd722601.aspx), определяются как

<UsingTask TaskName="ParseUnsupressedAnalysisIssues" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" > 
    <ParameterGroup> 
     <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" /> 
     <Result ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" /> 
    </ParameterGroup> 
    <Task> 
     <Reference Include="System.Runtime.Serialization" /> 
     <Reference Include="System.Xml" /> 
     <Reference Include="System.Xml.Linq" /> 
     <Using Namespace="System"/> 
     <Using Namespace="System.Collections.Generic"/> 
     <Using Namespace="System.IO"/> 
     <Using Namespace="System.Linq"/> 
     <Using Namespace="System.Runtime.Serialization.Json"/> 
     <Using Namespace="System.Xml"/> 
     <Using Namespace="System.Xml.Linq"/> 
     <Code Type="Fragment" Language="cs"> 
      <![CDATA[ 
      List<TaskItem> taskItems = new List<TaskItem>(); 
      foreach(ITaskItem item in Files) 
      { 
       try 
       { 
        string path = item.GetMetadata("FullPath"); 
        using (FileStream fs = new FileStream(path, FileMode.Open)) 
        using (XmlDictionaryReader reader = JsonReaderWriterFactory.CreateJsonReader(fs, XmlDictionaryReaderQuotas.Max)) 
        { 
         XElement doc = XElement.Load(reader); 
         XElement issuesRoot = doc.Elements("issues").SingleOrDefault(); 
         List<XElement> unsupressedIssues = issuesRoot.Elements("item").Where(e => !"True".Equals((string)e.Element("properties").Element("isSuppressedInSource"), StringComparison.Ordinal)).ToList(); 
         string unsupressedIssuesString = string.Join(Environment.NewLine, unsupressedIssues); 
         if(!string.IsNullOrEmpty(unsupressedIssuesString)) 
         { 
          taskItems.Add(new TaskItem(item.ItemSpec)); 
          Console.WriteLine(unsupressedIssuesString); 
         } 
        } 
       } 
       catch(Exception e) 
       { 
        taskItems.Add(new TaskItem(item.ItemSpec)); 
        Console.WriteLine(e.ToString()); 
       } 
      } 

      Result = taskItems.ToArray(); 
      ]]> 
     </Code> 
    </Task> 
</UsingTask> 

, который затем может быть вызван в качестве

<ParseUnsupressedAnalysisIssues Files="@(AnalyzerFiles)"> 
    <Output ItemName="FailedAnalyzerFiles" TaskParameter="Result" /> 
</ParseUnsupressedAnalysisIssues> 
<Error Text="FxCopAll: Following assemblies had analyzer errors @(FailedAnalyzerFiles)" Condition="'@(FailedAnalyzerFiles->Count())' &gt; 0" Code="2"/> 
3

Существует SARIF SDK для работы с файлами SARIF. Он доступен как пакет NuGet Sarif.Sdk, а исходный код находится в GitHub в проекте Microsoft/sarif-sdk. Там есть документ How-To docs/how-to.md, который показывает, как читать файл SARIF с диска и десериализовать его в объект SarifLog; то вы можете перемещаться по объектной модели SARIF для изучения отдельных результатов.

В вашем случае, вы заинтересованы в isSuppressedInSource собственности в результате в этом документе How-To объясняет, как вы бы получить эту собственность «собственность мешок.»:

Result result = …; 

string isSuppressedInSource = result.GetProperty("isSuppressedInSource"); 

Sarif спецификация available online, и есть SARIF home page со ссылками на дополнительную информацию.

И наконец: имейте в виду, что формат SARIF значительно изменился между обновлением Visual Studio 2015 Update 2 и обновлением 3. Формат теперь находится в стабильной версии 1.0.0.

(ПРИМЕЧАНИЕ: Извините за отсутствие прямых ссылок на SDK, пакет NuGet и How-To. У меня недостаточно точек репутации для размещения более двух ссылок.)