in components/RunStore.ts [37:107]
constructor(readonly run: Run, readonly logIndex, readonly filter: MobxFilter, readonly groupByAge?: IObservableValue<boolean>, readonly hideBaseline?: boolean, readonly showAge?: boolean) {
const {driver} = run.tool
this.driverName = run.properties && run.properties['logFileName'] || driver.name.replace(/^Microsoft.CodeAnalysis.Sarif.PatternMatcher$/, 'CredScan on Push')
if (!run._augmented) {
run._rulesInUse = new Map<string, Rule>()
run._agesInUse = new Map([
['Past SLA' , { results: [], treeItem: null, name: 'Past SLA (31+ days)' , isAge: true }],
['Within SLA', { results: [], treeItem: null, name: 'Within SLA (0 - 30 days)', isAge: true }],
])
const rules = driver.rules || []
const rulesListed = new Map<string, Rule>(rules.map(rule => [rule.id, rule] as any)) // Unable to express [[string, RuleEx]].
run.results?.forEach(result => {
// Collate by Rule
const {ruleIndex} = result
const ruleId = result.ruleId ?? '(No Rule)' // Ignores 3.5.4 Hierarchical strings.
if (!run._rulesInUse.has(ruleId)) {
// Need to generate rules for some like Microsoft.CodeAnalysis.Sarif.PatternMatcher.
const rule = ruleIndex !== undefined && rules[ruleIndex] as Rule || rulesListed.get(ruleId) || { id: ruleId } as Rule
rule.isRule = true
rule.run = run // For taxa.
run._rulesInUse.set(ruleId, rule)
}
const rule = run._rulesInUse.get(ruleId)
rule.results = rule.results || []
rule.results.push(result)
// Collate by Age
const firstDetection = result.provenance?.firstDetectionTimeUtc
result.firstDetection = firstDetection ? new Date(firstDetection) : new Date()
const age = (new Date().getTime() - result.firstDetection.getTime()) / (24 * 60 * 60 * 1000) // 1 day in milliseconds
result.sla = age > 31 ? 'Past SLA' : 'Within SLA'
run._agesInUse.get(result.sla).results.push(result)
// Fill-in url from run.artifacts as needed.
const artLoc = tryOr(() => result.locations[0].physicalLocation.artifactLocation)
if (artLoc && artLoc.uri === undefined) {
const art = tryOr<Artifact>(() => run.artifacts[artLoc.index])
artLoc.uri = art.location?.uri
}
result.run = run // For result renderer to get to run.artifacts.
result._rule = rule
})
run._augmented = true
}
autorun(() => {
this.showAllRevision // Read.
const rules = this.groupByAge.get() // Slice to satisfy ref rulesTruncated.
? this.agesFiltered.slice()
: this.rulesFiltered.slice()
rules.forEach(ruleTreeItem => {
const maxLength = 3
ruleTreeItem.childItems = !ruleTreeItem.isShowAll && ruleTreeItem.childItemsAll.length > maxLength
? [
...ruleTreeItem.childItemsAll.slice(0, maxLength),
{ data: { onClick: () => {
ruleTreeItem.isShowAll = true
this.showAllRevision++
}}}
]
: ruleTreeItem.childItemsAll
})
this.rulesTruncated = rules
}, { name: 'Truncation' })
}