-
Notifications
You must be signed in to change notification settings - Fork 86
/
Result.cs
174 lines (147 loc) · 6.04 KB
/
Result.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.CodeAnalysis.Sarif
{
public partial class Result
{
/// <summary>
/// Reference to the Run containing this Result, if available.
/// </summary>
/// <remarks>
/// Used to look up Result details which may be on Run collections (ex: Run.Tool.Driver.Rules)
/// </remarks>
public Run Run { get; set; }
public bool ShouldSerializeWorkItemUris()
{
return this.WorkItemUris != null && this.WorkItemUris.Any((s) => s != null);
}
public bool ShouldSerializeLevel()
{
return this.Level != FailureLevel.Warning;
}
public void EnsureRunProvided()
{
if (this.Run == null)
{
throw new ArgumentException("Result.Run was required but not provided. Ensure Result.Run properties are populated by calling Run.SetRunOnResults().");
}
}
/// <summary>
/// Resolve the RuleId for this Result, from direct properties or via Run.Rules lookup.
/// </summary>
/// <param name="run">Run containing this Result</param>
/// <returns>RuleId of this Result</returns>
public string ResolvedRuleId(Run run)
{
return RuleId ?? Rule?.Id ?? GetRule(run ?? this.Run)?.Id;
}
/// <summary>
/// Look up the ReportingDescriptor for this Result.
/// </summary>
/// <param name="run">Run instance containing this Result</param>
/// <returns>ReportingDescriptor for Result Rule, if available</returns>
public ReportingDescriptor GetRule(Run run = null)
{
// Follows SARIF Spec 3.52.3 (reportingDescriptor lookup)
// Ensure run argument or Result.Run was set
if (run == null)
{
EnsureRunProvided();
run = this.Run;
}
if (run != null)
{
// Find the 'ToolComponent' for this Result (Run.Tool.Driver if absent)
ToolComponent component = run.GetToolComponentFromReference(this.Rule?.ToolComponent);
IList<ReportingDescriptor> rules = component?.Rules;
// Look up by this.RuleIndex, if present
if (this.RuleIndex >= 0)
{
return GetRuleByIndex(rules, this.RuleIndex);
}
// Look up by this.Rule.Index, if present
if (this.Rule?.Index >= 0)
{
return GetRuleByIndex(rules, this.Rule.Index);
}
// Look up by this.Rule.Guid, if present
if (!string.IsNullOrEmpty(this.Rule?.Guid) && rules != null)
{
ReportingDescriptor rule = component.GetRuleByGuid(this.Rule.Guid);
if (rule != null) { return rule; }
}
// Look up by this.RuleId or this.Rule.Id, if present
string ruleId = this.RuleId ?? this.Rule?.Id;
if (ruleId != null && rules != null)
{
ReportingDescriptor rule = component.GetRuleById(ruleId);
if (rule != null) { return rule; }
}
}
// Otherwise, metadata is not available and RuleId is the only available property
return new ReportingDescriptor() { Id = this.RuleId ?? this.Rule?.Id };
}
public bool TryIsSuppressed(out bool isSuppressed)
{
isSuppressed = false;
if (this == null)
{
return false;
}
IList<Suppression> suppressions = this.Suppressions;
if (suppressions == null)
{
return false;
}
if (suppressions.Count == 0)
{
return true;
}
// If the status of any of the suppressions is "underReview" or "rejected",
// then the result should not be considered suppressed. Otherwise, the result should be considered suppressed.
// https://github.com/microsoft/sarif-tutorials/blob/main/docs/Displaying-results-in-a-viewer.md#determining-suppression-status
isSuppressed = !suppressions.Any(s => s.Status == SuppressionStatus.UnderReview || s.Status == SuppressionStatus.Rejected);
return true;
}
private static ReportingDescriptor GetRuleByIndex(IList<ReportingDescriptor> rules, int ruleIndex)
{
if (rules == null)
{
throw new ArgumentException("ToolComponent referred to by Result has no Rules collection.");
}
if (ruleIndex < 0 || ruleIndex >= rules.Count)
{
throw new ArgumentOutOfRangeException($"Result refers to rule index {ruleIndex}, but ToolComponent.Rules has only {rules.Count} rules.");
}
return rules[ruleIndex];
}
#if DEBUG
public override string ToString()
{
var sb = new System.Text.StringBuilder();
sb.Append(this.Locations?[0].PhysicalLocation?.ArtifactLocation?.Uri);
sb.Append(" : ").Append(this.RuleId);
sb.Append(" : ").Append(this.Level);
sb.Append(" : ").Append(this.Kind);
if (!string.IsNullOrEmpty(this.Message?.Text))
{
sb.Append(" : ").Append(this.Message.Text);
}
else if (this.Message?.Arguments != null)
{
sb.Append(" : {");
foreach (string argument in this.Message.Arguments)
{
sb.Append(argument).Append(',');
}
sb.Length -= 1;
sb.Append('}');
}
return sb.ToString();
}
#endif
}
}