C# 解析;静态分析结果交换格式(SARIF)";在MSBuild中
在使用MSBuild对项目运行各种分析器时,所有失败都将以“静态分析结果交换格式(SARIF)”格式输出(参见示例)。例如,构建可能会产生以下结果C# 解析;静态分析结果交换格式(SARIF)";在MSBuild中,c#,msbuild,static-code-analysis,C#,Msbuild,Static Code Analysis,在使用MSBuild对项目运行各种分析器时,所有失败都将以“静态分析结果交换格式(SARIF)”格式输出(参见示例)。例如,构建可能会产生以下结果 { "version": "0.1", "toolInfo": { "toolName": "Microsoft (R) Visual C# Compiler", "productVersion": "1.1.0", "fileVersion": "1.1.0" }, "issues": [ {
{
"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"
}
}
]
}
现在,我希望能够以最简单的方式解析上面的数据(如果遇到任何非抑制问题,则中断构建)。怎么做呢
另外,我还希望避免实现自己的MSBuild任务和安装特定软件(例如PowerShell 3.0-从Json转换而来)。因为显然没有内置的方法来实现这一点,我最终使用了内联MSBuild任务(),定义为
<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>
taskItems=新列表();
foreach(文件中的ITaskItem项)
{
尝试
{
字符串路径=item.GetMetadata(“完整路径”);
使用(FileStream fs=newfilestream(路径,FileMode.Open))
使用(XmlDictionaryReader=JsonReaderWriterFactory.CreateJsonReader(fs,XmlDictionaryReaderQuotas.Max))
{
XElement doc=XElement.Load(读卡器);
XElement issueroot=doc.Elements(“问题”).SingleOrDefault();
List unpressedissues=issueroot.Elements(“item”)。其中(e=>!“True”。等于((string)e.Element(“properties”)。Element(“isSuppressedInSource”),StringComparison.Ordinal)。ToList();
string unpressedissuessstring=string.Join(Environment.NewLine,unpressedissues);
如果(!string.IsNullOrEmpty(unpresseDissuessString))
{
添加(新任务项(item.ItemSpec));
Console.WriteLine(未按下的字符串);
}
}
}
捕获(例外e)
{
添加(新任务项(item.ItemSpec));
Console.WriteLine(如ToString());
}
}
结果=taskItems.ToArray();
]]>
然后可以作为
<ParseUnsupressedAnalysisIssues Files="@(AnalyzerFiles)">
<Output ItemName="FailedAnalyzerFiles" TaskParameter="Result" />
</ParseUnsupressedAnalysisIssues>
<Error Text="FxCopAll: Following assemblies had analyzer errors @(FailedAnalyzerFiles)" Condition="'@(FailedAnalyzerFiles->Count())' > 0" Code="2"/>
有一个SARIF SDK可用于处理SARIF文件。它作为一个NuGet包Sarif.Sdk提供,源代码位于Microsoft/Sarif Sdk项目的GitHub上。有一个How-To-document docs/How-To.md,显示如何从磁盘读取一个SARIF文件,并将其反序列化为一个
sarilog
对象;然后,您可以在SARIF对象模型中导航以检查各个结果
在您的情况下,您对结果的“属性包”中的isSuppressedInSource
属性感兴趣。“操作方法”文档解释了如何检索该属性:
Result result = …;
string isSuppressedInSource = result.GetProperty("isSuppressedInSource");
SARIF规范是,并且有一个链接到更多信息
最后:请注意,在Visual Studio 2015更新2和更新3之间,SARIF格式发生了显著变化。该格式现在是稳定的1.0.0版本
(注意:很抱歉没有提供SDK、NuGet软件包和How to的直接链接。我没有足够的信誉点发布两个以上的链接。)