Skip to content

Commit 21e7ac1

Browse files
committed
generating (primitive) aggregated sarif
1 parent 59497db commit 21e7ac1

File tree

4 files changed

+75
-9
lines changed

4 files changed

+75
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ polystat_out/
1010
j2eo.jar
1111
sarif/**
1212
polystat-x86_64-pc-linux
13+
out/

.polystat.conf

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
polystat {
2-
lang = java
3-
input = sandbox_java
2+
lang = eo
3+
input = sandbox
44
tempDir = tmp
55
outputFormats = [sarif]
66
outputs = {
7-
console = true,
87
dirs = [out],
9-
files = [./results/out.txt],
8+
files = [all.json]
109
}
1110
}

src/main/scala/org/polystat/EO.scala

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import org.polystat.odin.analysis.EOOdinAnalyzer
88
import org.polystat.odin.parser.EoParser.sourceCodeEoParser
99
import cats.syntax.traverse.*
1010
import cats.syntax.foldable.*
11+
import io.circe.syntax.*
1112

1213
object EO:
1314

@@ -21,14 +22,25 @@ object EO:
2122

2223
def analyze(cfg: ProcessedConfig): IO[Unit] =
2324
val inputFiles = readCodeFromInput(".eo", cfg.input)
24-
inputFiles
25+
val analyzed = inputFiles
26+
.evalMap { case (codePath, code) =>
27+
for analyzed <- runAnalyzers(cfg.filteredAnalyzers)(code)
28+
yield (codePath, analyzed)
29+
}
30+
.compile
31+
.toVector
32+
.map(_.toMap)
33+
val analyzeToDirs = inputFiles
2534
.evalMap { case (codePath, code) =>
2635
for
2736
_ <- IO.println(s"Analyzing $codePath...")
2837
analyzed <- runAnalyzers(cfg.filteredAnalyzers)(code)
2938
_ <- if cfg.output.console then IO.println(analyzed) else IO.unit
3039
_ <- cfg.fmts.traverse_ { case OutputFormat.Sarif =>
31-
val sarifJson = SarifOutput(analyzed).json.toString
40+
val sarifJson = SarifOutput(
41+
codePath,
42+
analyzed,
43+
).json.toString
3244
cfg.output.dirs.traverse_(out =>
3345
val outPath =
3446
out / "sarif" / codePath.replaceExt(".sarif.json")
@@ -41,5 +53,21 @@ object EO:
4153
}
4254
.compile
4355
.drain
56+
val analyzeAggregate = cfg.output.files.traverse_ { outputPath =>
57+
cfg.fmts.traverse_ { case OutputFormat.Sarif =>
58+
for
59+
_ <- IO.println(s"Writing aggregated output to $outputPath...")
60+
analyzed <- analyzed
61+
sariOutput = AggregatedSarifOutput
62+
.fromAnalyzed(analyzed)
63+
.asJson
64+
.deepDropNullValues
65+
.toString
66+
_ <- writeOutputTo(outputPath)(sariOutput)
67+
yield ()
68+
}
69+
}
70+
71+
analyzeToDirs *> analyzeAggregate
4472
end analyze
4573
end EO

src/main/scala/org/polystat/Sarif.scala

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,31 @@ import io.circe.Decoder
55
import io.circe.Encoder
66
import io.circe.Json
77
import io.circe.syntax.*
8+
import fs2.io.file.Path
89
import org.polystat.odin.analysis.EOOdinAnalyzer.OdinAnalysisResult
910
import cats.syntax.foldable.*
11+
import cats.syntax.functorFilter.*
1012

1113
import scala.CanEqual.derived
1214

1315
import OdinAnalysisResult.*
1416
import Sarif.*
1517

16-
final case class SarifOutput(errors: List[OdinAnalysisResult]):
18+
object AggregatedSarifOutput:
19+
def fromAnalyzed(
20+
analyzed: Map[Path, List[OdinAnalysisResult]]
21+
): Seq[SarifLog] =
22+
analyzed.toSeq.map { case (path, results) =>
23+
SarifOutput(path, results).sarif
24+
}
25+
end AggregatedSarifOutput
26+
27+
final case class SarifOutput(filePath: Path, errors: List[OdinAnalysisResult]):
1728
def json: Json = sarif.asJson.deepDropNullValues
1829

1930
private val sarifRun: SarifRun = SarifRun(
2031
SarifTool(SarifDriver()),
21-
results = errors.flatMap(sarifResult),
32+
results = errors.mapFilter(sarifResult),
2233
invocations = errors.map(sarifInvocation),
2334
)
2435

@@ -84,6 +95,13 @@ final case class SarifOutput(errors: List[OdinAnalysisResult]):
8495
level = SarifLevel.ERROR,
8596
kind = SarifKind.FAIL,
8697
message = SarifMessage(message.mkString_("\n")),
98+
locations = Seq(
99+
SarifLocation(physicalLocation =
100+
SarifPhysicalLocation(artifactLocation =
101+
SarifArtifactLocation(uri = filePath.toNioPath.toUri.toString)
102+
)
103+
)
104+
),
87105
)
88106
)
89107
case Ok(ruleId) =>
@@ -93,11 +111,18 @@ final case class SarifOutput(errors: List[OdinAnalysisResult]):
93111
level = SarifLevel.NONE,
94112
kind = SarifKind.PASS,
95113
message = SarifMessage("No errors were found."),
114+
locations = Seq(
115+
SarifLocation(physicalLocation =
116+
SarifPhysicalLocation(artifactLocation =
117+
SarifArtifactLocation(uri = filePath.toNioPath.toUri.toString)
118+
)
119+
)
120+
),
96121
)
97122
)
98123
end SarifOutput
99124

100-
object Sarif extends App:
125+
object Sarif:
101126

102127
final val SARIF_VERSION = "2.1.0"
103128
final val SARIF_SCHEMA =
@@ -128,6 +153,19 @@ object Sarif extends App:
128153
level: SarifLevel,
129154
kind: SarifKind,
130155
message: SarifMessage,
156+
locations: Seq[SarifLocation],
157+
) derives Codec.AsObject
158+
159+
final case class SarifLocation(
160+
physicalLocation: SarifPhysicalLocation
161+
) derives Codec.AsObject
162+
163+
final case class SarifPhysicalLocation(
164+
artifactLocation: SarifArtifactLocation
165+
) derives Codec.AsObject
166+
167+
final case class SarifArtifactLocation(
168+
uri: String
131169
) derives Codec.AsObject
132170

133171
enum SarifLevel:

0 commit comments

Comments
 (0)