Skip to content

Commit

Permalink
Remove RunResultGroup class, convert to single function
Browse files Browse the repository at this point in the history
  • Loading branch information
jckoenen committed Dec 8, 2023
1 parent 773b64e commit 0662825
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 133 deletions.
113 changes: 113 additions & 0 deletions sarif/src/main/java/com/jetbrains/qodana/sarif/baseline/Baseline.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package com.jetbrains.qodana.sarif.baseline

import com.jetbrains.qodana.sarif.baseline.BaselineCalculation.Options
import com.jetbrains.qodana.sarif.model.Result
import com.jetbrains.qodana.sarif.model.Result.BaselineState
import com.jetbrains.qodana.sarif.model.Run

private typealias Fingerprint = String
private typealias StrictIndex = MultiMap<Fingerprint, Result>
private typealias LaxIndex = MultiMap<ResultKey, Result>

private inline fun <T> MutableIterable<T>.each(crossinline f: MutableIterator<T>.(T) -> Unit) =
with(iterator()) { forEachRemaining { f(it) } }

private fun <T : Any> Iterable<T?>?.noNulls(): Sequence<T> =
this?.asSequence().orEmpty().filterNotNull()

internal data class BaselineSummary(val added: Int, val unchanged: Int, val absent: Int)

/** CAUTION: This mutates results in report and baseline **/
internal fun applyBaseline(report: Run, baseline: Run, options: Options): BaselineSummary {
fun Iterable<Result>.withBaselineState(state: BaselineState) =
if (options.fillBaselineState) onEach { it.baselineState = state } else this

val reportDescriptors = DescriptorLookup(report)
val baselineDescriptors = DescriptorLookup(baseline)
val reportIndex = StrictIndex()
val baselineIndex = LaxIndex()

// shallow copies, to not mess with the underlying reports
val undecidedFromReport = report.results.noNulls()
.filterNot { it.baselineState == BaselineState.ABSENT }
.onEach { result ->
result.partialFingerprints
?.getValues(BaselineCalculation.EQUAL_INDICATOR)
?.values
.noNulls()
.forEach { print -> reportIndex.add(print, result) }
}
.toMutableSet()

val undecidedFromBaseline = baseline.results.noNulls()
.filterNot { it.baselineState == BaselineState.ABSENT }
.onEach { result -> baselineIndex.add(ResultKey(result), result) }
.toMutableSet()

val unchanged = mutableSetOf<Result>()
val notChecked = mutableSetOf<Result>()
val added = mutableSetOf<Result>()
val absent = mutableSetOf<Result>()

undecidedFromBaseline.each { result ->
val foundInReport = result.partialFingerprints?.getValues(BaselineCalculation.EQUAL_INDICATOR)
.orEmpty()
.asSequence()
.flatMap { (_, print) -> reportIndex.getOrEmpty(print) }
.onEach(undecidedFromReport::remove)
.onEach(unchanged::add)
.count() != 0

when {
foundInReport -> remove()
!options.wasChecked.apply(result) -> {
notChecked.add(result)
remove()
}
}
}

undecidedFromReport.each { result ->
val inBaseline = baselineIndex.getOrEmpty(ResultKey(result))
if (inBaseline.isEmpty()) {
added.add(result)
} else {
unchanged.add(result)
undecidedFromBaseline.remove(inBaseline.removeFirst())
}
}

undecidedFromBaseline.each { result ->
if (options.wasChecked.apply(result)) {
absent.add(result)
} else {
unchanged.add(result)
}
}

if (options.includeAbsent) {
absent.asSequence()
.filter { reportDescriptors.findById(it.ruleId) == null }
.mapNotNull { baselineDescriptors.findById(it.ruleId) }
.forEach { it.addTo(report) }
}

val theDiff = mutableListOf<Result>().apply {
addAll(added.withBaselineState(BaselineState.NEW))
if (options.includeUnchanged) {
addAll(unchanged.withBaselineState(BaselineState.UNCHANGED))
addAll(notChecked.withBaselineState(BaselineState.UNCHANGED))
}
if (options.includeAbsent) {
addAll(absent.withBaselineState(BaselineState.ABSENT))
}
}

report.withResults(theDiff)

return BaselineSummary(
added = added.size,
unchanged = if (options.includeUnchanged) unchanged.size + notChecked.size else 0,
absent = if (options.includeAbsent) absent.size else 0
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
public class BaselineCalculation {
public static final String EQUAL_INDICATOR = "equalIndicator";

int newResults = 0;
int absentResults = 0;
int unchangedResults = 0;
final Options options;
private int newResults = 0;
private int absentResults = 0;
private int unchangedResults = 0;
private final Options options;

private BaselineCalculation(Options options) {
this.options = options;
Expand Down Expand Up @@ -57,7 +57,7 @@ public void fillBaselineState(SarifReport report, SarifReport baseline) {

if (first.isPresent()) {
Run baselineRun = first.get();
new RunResultGroup(this, run, baselineRun).build();
applyBaseline(run, baselineRun);
baselineRuns.remove(baselineRun);
} else {
unmatched.add(run);
Expand All @@ -71,10 +71,17 @@ public void fillBaselineState(SarifReport report, SarifReport baseline) {
markRunAsNew(run);
continue;
}
new RunResultGroup(this, run, baselineRun).build();
applyBaseline(run, baselineRun);
}
}

private void applyBaseline(Run run, Run baseline) {
BaselineSummary summary = BaselineKt.applyBaseline(run, baseline, options);
unchangedResults += summary.getUnchanged();
newResults += summary.getAdded();
absentResults += summary.getAbsent();
}

private void markRunAsNew(Run run) {
for (Result result : run.getResults()) {
result.setBaselineState(NEW);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ public void testDifferentToolName() throws IOException {
}

@Test
@Disabled("Testdata was artificial: Same results with different hashes - need new testdata")
public void testAbsentResultWithChangedIdAndSameVersion() throws IOException {
SarifReport report = readReport("src/test/resources/testData/AbsentBaselineTest/report.json");
SarifReport baseline = readReport("src/test/resources/testData/AbsentBaselineTest/baseline.json");
Expand Down

0 comments on commit 0662825

Please sign in to comment.