Skip to content

Commit 5cc4028

Browse files
committed
don't run the analysis if there are no analyzers
1 parent 4d5bee0 commit 5cc4028

File tree

3 files changed

+111
-67
lines changed

3 files changed

+111
-67
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ object EO:
2828
analyzed <- cfg.filteredAnalyzers.traverse(a =>
2929
a.analyze(
3030
tmpDir = cfg.tempDir,
31-
// TODO: make sure cfg input is always converted to directory
3231
pathToSrcRoot = cfg.input,
3332
pathToCode = codePath,
3433
code = code,
3534
).handleError(e =>
3635
OdinAnalysisResult.AnalyzerFailure(a.ruleId, e)
3736
)
3837
)
39-
yield (codePath, analyzed)
38+
yield (codePath, analyzed.toList)
4039
}
4140

4241
def writeToDirs(
Lines changed: 105 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.polystat.cli
22

33
import cats.data.NonEmptyList
4+
import cats.data.ValidatedNel
45
import cats.effect.ExitCode
56
import cats.effect.IO
67
import cats.effect.IOApp
@@ -32,18 +33,56 @@ object Main extends IOApp:
3233
)
3334
yield exitCode
3435

35-
def warnMissingKeys(
36+
def findMissingKeys(
3637
givenKeys: List[String],
3738
availableKeys: List[String],
39+
): ValidatedNel[ValidationError, Unit] =
40+
val missingKeys = givenKeys.filterNot(rule => availableKeys.contains(rule))
41+
missingKeys.toNel match
42+
case Some(keys) => ValidationError.MissingAnalyzersKeys(keys).invalidNel
43+
case None => ().validNel
44+
45+
def validateInex(
46+
inex: Option[IncludeExclude]
47+
): ValidatedNel[ValidationError, NonEmptyList[EOAnalyzer]] =
48+
val filtered = filterAnalyzers(inex).toNel
49+
val parsedKeys =
50+
inex
51+
.map {
52+
case Include(list) => list.toList
53+
case Exclude(list) => list.toList
54+
}
55+
.getOrElse(List())
56+
(
57+
findMissingKeys(parsedKeys, EOAnalyzer.analyzers.map(_.ruleId)),
58+
filtered match
59+
case Some(filtered) => filtered.valid
60+
case None => ValidationError.NoAnalyzers(inex.get).invalidNel,
61+
).mapN { case (_, filtered) =>
62+
filtered
63+
}
64+
65+
def reportValidationErrors(
66+
errors: NonEmptyList[ValidationError]
3867
): IO[Unit] =
39-
givenKeys.traverse_(rule =>
40-
if availableKeys.contains(rule) then IO.unit
41-
else
42-
IO.println(
43-
s"WARNING: The analyzer with the key '$rule' does not exist. " +
44-
s"Run 'polystat list' to get the list of the available keys."
45-
)
46-
)
68+
errors
69+
.traverse_ {
70+
case ValidationError.NoAnalyzers(inex) =>
71+
val message = inex match
72+
case Include(include) =>
73+
s"WARNING: The 'includeRules' key with values \"${include.mkString_(", ")}\" excludes all the analyzers, so none were run!"
74+
case Exclude(exclude) =>
75+
s"WARNING: The 'excludeRules' key with values \"${exclude.mkString_(", ")}\" excludes all the analyzers, so none were run!"
76+
IO.println(message)
77+
78+
case ValidationError.MissingAnalyzersKeys(missing) =>
79+
missing.traverse_(rule =>
80+
IO.println(
81+
s"WARNING: The analyzer with the key '$rule' does not exist. " +
82+
s"Run 'polystat list' to get the list of the available keys."
83+
)
84+
)
85+
}
4786

4887
def filterAnalyzers(
4988
inex: Option[IncludeExclude]
@@ -74,6 +113,7 @@ object Main extends IOApp:
74113
configFile <- config match
75114
case Some(file) => IO.pure(file)
76115
case None => File.fromPathFailFast(Path(".polystat.conf"))
116+
_ <- IO.println(s"Reading configuration from $configFile...")
77117
config <- readConfigFromFile(configFile)
78118
result <- execute(config)
79119
yield result
@@ -85,66 +125,67 @@ object Main extends IOApp:
85125
case SupportedLanguage.Java(_, _) => ".java"
86126
case SupportedLanguage.Python => ".py"
87127
case SupportedLanguage.EO => ".eo"
88-
for
89-
tempDir <- tmp match
90-
case Some(path) =>
91-
IO.println(s"Cleaning ${path.absolute}...") *>
92-
path.createDirIfDoesntExist.flatMap(_.clean)
93-
case None =>
94-
Files[IO].createTempDirectory.flatMap(Directory.fromPathFailFast)
95-
parsedKeys = inex
96-
.map {
97-
case Include(list) => list.toList
98-
case Exclude(list) => list.toList
99-
}
100-
.getOrElse(List())
101128

102-
_ <- warnMissingKeys(parsedKeys, EOAnalyzer.analyzers.map(_.ruleId))
103-
input <- input match
104-
case Input.FromDirectory(dir) => dir.pure[IO]
105-
case Input.FromFile(file) =>
106-
for
107-
singleFileTmpDir <-
108-
(tempDir / "singleFile").unsafeToDirectory.createDirIfDoesntExist
109-
singleFileTmpPath =
110-
(singleFileTmpDir / (file.filenameNoExt + ext)).unsafeToFile
111-
_ <- singleFileTmpPath.unsafeToFile.createFileIfDoesntExist
112-
_ <- readCodeFromFile(ext, file)
113-
.map(_._2)
114-
.through(fs2.text.utf8.encode)
115-
.through(Files[IO].writeAll(singleFileTmpPath))
116-
.compile
117-
.drain
118-
yield singleFileTmpDir
119-
case Input.FromStdin =>
120-
for
121-
stdinTmpDir <-
122-
(tempDir / "stdin").unsafeToDirectory.createDirIfDoesntExist
123-
stdinTmpFilePath =
124-
(stdinTmpDir / ("stdin" + ext)).unsafeToFile
125-
_ <- stdinTmpFilePath.createFileIfDoesntExist
126-
_ <-
127-
readCodeFromStdin
129+
def analyze(filtered: NonEmptyList[EOAnalyzer]): IO[Unit] =
130+
for
131+
tempDir <- tmp match
132+
case Some(path) =>
133+
IO.println(s"Cleaning ${path.absolute}...") *>
134+
path.createDirIfDoesntExist.flatMap(_.clean)
135+
case None =>
136+
Files[IO].createTempDirectory.flatMap(
137+
Directory.fromPathFailFast
138+
)
139+
input <- input match
140+
case Input.FromDirectory(dir) => dir.pure[IO]
141+
case Input.FromFile(file) =>
142+
for
143+
singleFileTmpDir <-
144+
(tempDir / "singleFile").unsafeToDirectory.createDirIfDoesntExist
145+
singleFileTmpPath =
146+
(singleFileTmpDir / (file.filenameNoExt + ext)).unsafeToFile
147+
_ <- singleFileTmpPath.unsafeToFile.createFileIfDoesntExist
148+
_ <- readCodeFromFile(ext, file)
149+
.map(_._2)
128150
.through(fs2.text.utf8.encode)
129-
.through(Files[IO].writeAll(stdinTmpFilePath))
151+
.through(Files[IO].writeAll(singleFileTmpPath))
130152
.compile
131153
.drain
132-
yield stdinTmpDir
154+
yield singleFileTmpDir
155+
case Input.FromStdin =>
156+
for
157+
stdinTmpDir <-
158+
(tempDir / "stdin").unsafeToDirectory.createDirIfDoesntExist
159+
stdinTmpFilePath =
160+
(stdinTmpDir / ("stdin" + ext)).unsafeToFile
161+
_ <- stdinTmpFilePath.createFileIfDoesntExist
162+
_ <-
163+
readCodeFromStdin
164+
.through(fs2.text.utf8.encode)
165+
.through(Files[IO].writeAll(stdinTmpFilePath))
166+
.compile
167+
.drain
168+
yield stdinTmpDir
169+
processedConfig =
170+
ProcessedConfig(
171+
filteredAnalyzers = filtered,
172+
tempDir = tempDir,
173+
output = out,
174+
input = input,
175+
fmts = fmts,
176+
)
177+
_ <-
178+
lang match
179+
case SupportedLanguage.EO => EO.analyze(processedConfig)
180+
case SupportedLanguage.Java(j2eo, j2eoVersion) =>
181+
Java.analyze(j2eoVersion, j2eo, processedConfig)
182+
case SupportedLanguage.Python => Python.analyze(processedConfig)
183+
yield ()
133184

134-
processedConfig = ProcessedConfig(
135-
filteredAnalyzers = filterAnalyzers(inex),
136-
tempDir = tempDir,
137-
output = out,
138-
input = input,
139-
fmts = fmts,
140-
)
141-
analysisResults <-
142-
lang match
143-
case SupportedLanguage.EO => EO.analyze(processedConfig)
144-
case SupportedLanguage.Java(j2eo, j2eoVersion) =>
145-
Java.analyze(j2eoVersion, j2eo, processedConfig)
146-
case SupportedLanguage.Python => Python.analyze(processedConfig)
147-
yield ()
185+
validateInex(inex).fold(
186+
errors => reportValidationErrors(errors),
187+
filtered => analyze(filtered),
188+
)
148189
end execute
149190

150191
end Main

src/main/scala/org/polystat/cli/PolystatConfig.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ object PolystatConfig:
2020
output: Output,
2121
)
2222

23+
enum ValidationError:
24+
case NoAnalyzers(inex: IncludeExclude)
25+
case MissingAnalyzersKeys(keys: NonEmptyList[String])
26+
2327
final case class ProcessedConfig(
24-
filteredAnalyzers: List[EOAnalyzer],
28+
filteredAnalyzers: NonEmptyList[EOAnalyzer],
2529
tempDir: Directory,
2630
input: Directory,
2731
fmts: List[OutputFormat],

0 commit comments

Comments
 (0)