11package org .polystat .cli
22
3+ import cats .data .NonEmptyList as Nel
34import cats .effect .IO
45import cats .syntax .all .*
56import fs2 .io .file .Path
67import io .circe .syntax .*
8+ import org .polystat .cli .util .FileTypes .*
79import org .polystat .cli .util .InputUtils .*
810import org .polystat .odin .analysis .ASTAnalyzer
911import org .polystat .odin .analysis .EOOdinAnalyzer
1012import org .polystat .odin .analysis .EOOdinAnalyzer .OdinAnalysisResult
1113import org .polystat .odin .parser .EoParser .sourceCodeEoParser
1214import org .polystat .sarif .AggregatedSarifOutput
1315import org .polystat .sarif .SarifOutput
14- import org .polystat .cli .util .FileTypes .*
1516
1617import PolystatConfig .*
1718
1819object EO :
1920
21+ private def displayResult (
22+ result : OdinAnalysisResult ,
23+ indentDepth : Int ,
24+ ): String =
25+ def indent (d : Int ) = " \n " + " " * d
26+ val indent1 = indent(indentDepth)
27+ val indent2 = indent(indentDepth + 1 )
28+ val messages : Nel [String ] = result match
29+ case OdinAnalysisResult .Ok (ruleId) =>
30+ Nel .one(s """ $indent1$ruleId: OK. """ )
31+ case OdinAnalysisResult .DefectsDetected (ruleId, defects) =>
32+ defects.map(msg => s """ $indent2$msg""" ).prepend(s " $indent1$ruleId: " )
33+ case OdinAnalysisResult .AnalyzerFailure (ruleId, reason) =>
34+ val reasonLines = reason.getMessage.trim
35+ .split(scala.util.Properties .lineSeparator)
36+ .map(" " * (indentDepth + 1 ) + " -- " + _)
37+ .mkString(scala.util.Properties .lineSeparator)
38+ Nel .one(
39+ s """ $indent1$ruleId: Analyzer failed with the following reason:\n ${reasonLines}"""
40+ )
41+
42+ messages.mkString_(" " )
43+
44+ private def displayAnalyzed (
45+ analyzed : Vector [(File , List [OdinAnalysisResult ])]
46+ ): IO [Unit ] =
47+ analyzed.traverse_ { case (file, results) =>
48+ IO .println(
49+ s """ $file: ${results.map(res => displayResult(res, 1 )).mkString}
50+ """ .stripMargin
51+ )
52+ }
53+
2054 def analyze (cfg : ProcessedConfig ): IO [Unit ] =
2155 def runAnalyzers (
2256 inputFiles : Vector [(File , String )]
@@ -43,9 +77,7 @@ object EO:
4377 analyzed : Vector [(File , List [OdinAnalysisResult ])],
4478 ): IO [Unit ] =
4579 analyzed.traverse_ { case (codePath, results) =>
46- for
47- _ <- if cfg.output.console then IO .println(analyzed) else IO .unit
48- _ <- cfg.fmts.traverse_ { case OutputFormat .Sarif =>
80+ for _ <- cfg.fmts.traverse_ { case OutputFormat .Sarif =>
4981 val sarifJson = SarifOutput (
5082 codePath,
5183 results,
@@ -95,6 +127,7 @@ object EO:
95127 outputFiles <- cfg.output.files.traverse(_.createFileIfDoesntExist)
96128 _ <- writeToDirs(outputDirs, analyzed)
97129 _ <- writeAggregate(outputFiles, analyzed)
130+ _ <- if cfg.output.console then displayAnalyzed(analyzed) else IO .unit
98131 yield ()
99132 end for
100133 end analyze
0 commit comments