constructor()

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' })
	}