Skip to content

Commit 8625d2c

Browse files
committed
Add a global flag to suppress deprecation warnings
1 parent 51bebb0 commit 8625d2c

File tree

23 files changed

+322
-85
lines changed

23 files changed

+322
-85
lines changed

modules/build/src/main/scala/scala/build/preprocessing/DeprecatedDirectives.scala

+26-28
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@ import scala.build.Logger
44
import scala.build.errors.Diagnostic.TextEdit
55
import scala.build.internal.Constants
66
import scala.build.internal.util.WarningMessages.{deprecatedToolkitLatest, deprecatedWarning}
7-
import scala.build.preprocessing.directives.{
8-
DirectiveHandler,
9-
DirectiveUtil,
10-
StrictDirective,
11-
Toolkit
12-
}
7+
import scala.build.options.SuppressWarningOptions
8+
import scala.build.preprocessing.directives.{DirectiveHandler, StrictDirective, Toolkit}
139
import scala.build.warnings.DeprecatedWarning
1410

1511
object DeprecatedDirectives {
@@ -20,27 +16,27 @@ object DeprecatedDirectives {
2016
* @param values
2117
* representation of deprecated value
2218
*/
23-
case class DirectiveTemplate(keys: Seq[String], values: Option[Seq[String]]) {
19+
private case class DirectiveTemplate(keys: Seq[String], values: Option[Seq[String]]) {
2420
def appliesTo(foundKey: String, foundValues: Seq[String]): Boolean =
2521
(keys.isEmpty || keys.contains(foundKey)) &&
2622
// FIXME values.contains is not perfect, but is enough for now since we don't look for specific multiple values
2723
(values.isEmpty || values.contains(foundValues))
2824
}
2925

30-
type WarningAndReplacement = (String, DirectiveTemplate)
26+
private type WarningAndReplacement = (String, DirectiveTemplate)
3127

3228
private def keyReplacement(replacement: String)(warning: String): WarningAndReplacement =
3329
(warning, DirectiveTemplate(Seq(replacement), None))
3430

3531
private def valueReplacement(replacements: String*)(warning: String): WarningAndReplacement =
3632
(warning, DirectiveTemplate(Nil, Some(replacements.toSeq)))
3733

38-
private def allAliasesOf(key: String, handler: DirectiveHandler[_]): Seq[String] =
34+
private def allAliasesOf(key: String, handler: DirectiveHandler[?]): Seq[String] =
3935
handler.keys.find(_.nameAliases.contains(key))
4036
.toSeq
4137
.flatMap(_.nameAliases)
4238

43-
private def allKeysFrom(handler: DirectiveHandler[_]): Seq[String] =
39+
private def allKeysFrom(handler: DirectiveHandler[?]): Seq[String] =
4440
handler.keys.flatMap(_.nameAliases)
4541

4642
private val deprecatedCombinationsAndReplacements = Map[DirectiveTemplate, WarningAndReplacement](
@@ -73,33 +69,35 @@ object DeprecatedDirectives {
7369
)
7470
)
7571

76-
def warningAndReplacement(directive: StrictDirective): Option[WarningAndReplacement] =
72+
private def warningAndReplacement(directive: StrictDirective): Option[WarningAndReplacement] =
7773
deprecatedCombinationsAndReplacements
7874
.find(_._1.appliesTo(directive.key, directive.toStringValues))
7975
.map(_._2) // grab WarningAndReplacement
8076

8177
def issueWarnings(
8278
path: Either[String, os.Path],
8379
directives: Seq[StrictDirective],
80+
suppressWarningOptions: SuppressWarningOptions,
8481
logger: Logger
85-
) =
86-
directives.map(d => d -> warningAndReplacement(d))
87-
.foreach {
88-
case (directive, Some(warning, replacement)) =>
89-
val newKey = replacement.keys.headOption.getOrElse(directive.key)
90-
val newValues = replacement.values.getOrElse(directive.toStringValues)
91-
val newText = s"$newKey ${newValues.mkString(" ")}"
82+
): Unit =
83+
if !suppressWarningOptions.suppressDeprecatedFeatureWarning.getOrElse(false) then
84+
directives.map(d => d -> warningAndReplacement(d))
85+
.foreach {
86+
case (directive, Some(warning, replacement)) =>
87+
val newKey = replacement.keys.headOption.getOrElse(directive.key)
88+
val newValues = replacement.values.getOrElse(directive.toStringValues)
89+
val newText = s"$newKey ${newValues.mkString(" ")}"
9290

93-
// TODO use key and/or value positions instead of whole directive
94-
val position = directive.position(path)
91+
// TODO use key and/or value positions instead of whole directive
92+
val position = directive.position(path)
9593

96-
val diagnostic = DeprecatedWarning(
97-
warning,
98-
Seq(position),
99-
Some(TextEdit(s"Change to: $newText", newText))
100-
)
101-
logger.log(Seq(diagnostic))
102-
case _ => ()
103-
}
94+
val diagnostic = DeprecatedWarning(
95+
warning,
96+
Seq(position),
97+
Some(TextEdit(s"Change to: $newText", newText))
98+
)
99+
logger.log(Seq(diagnostic))
100+
case _ => ()
101+
}
104102

105103
}

modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala

+8-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,14 @@ case class DirectivesPreprocessor(
3838
using ScalaCliInvokeData
3939
) {
4040
def preprocess(content: String): Either[BuildException, PreprocessedDirectives] = for {
41-
directives <- ExtractedDirectives.from(content.toCharArray, path, logger, maybeRecoverOnError)
42-
res <- preprocess(directives)
41+
directives <- ExtractedDirectives.from(
42+
content.toCharArray,
43+
path,
44+
suppressWarningOptions,
45+
logger,
46+
maybeRecoverOnError
47+
)
48+
res <- preprocess(directives)
4349
} yield res
4450

4551
def preprocess(extractedDirectives: ExtractedDirectives)

modules/build/src/main/scala/scala/build/preprocessing/ExtractedDirectives.scala

+14-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import com.virtuslab.using_directives.custom.model.{
88
UsingDirectives,
99
Value
1010
}
11-
import com.virtuslab.using_directives.custom.utils.ast._
11+
import com.virtuslab.using_directives.custom.utils.ast.*
1212

1313
import scala.annotation.targetName
1414
import scala.build.errors.*
15+
import scala.build.options.SuppressWarningOptions
1516
import scala.build.preprocessing.UsingDirectivesOps.*
1617
import scala.build.preprocessing.directives.{DirectiveUtil, ScopedDirective, StrictDirective}
1718
import scala.build.{Logger, Position}
@@ -34,16 +35,22 @@ object ExtractedDirectives {
3435
def from(
3536
contentChars: Array[Char],
3637
path: Either[String, os.Path],
38+
suppressWarningOptions: SuppressWarningOptions,
3739
logger: Logger,
3840
maybeRecoverOnError: BuildException => Option[BuildException]
3941
): Either[BuildException, ExtractedDirectives] = {
4042
val errors = new mutable.ListBuffer[Diagnostic]
41-
val reporter = CustomDirectivesReporter.create(path) { diag =>
42-
if (diag.severity == Severity.Warning)
43-
logger.log(Seq(diag))
44-
else
45-
errors += diag
46-
}
43+
val reporter = CustomDirectivesReporter
44+
.create(path) {
45+
case diag
46+
if diag.severity == Severity.Warning &&
47+
diag.message.toLowerCase.contains("deprecated") &&
48+
suppressWarningOptions.suppressDeprecatedFeatureWarning.getOrElse(false) =>
49+
() // skip deprecated feature warnings if suppressed
50+
case diag if diag.severity == Severity.Warning =>
51+
logger.log(Seq(diag))
52+
case diag => errors += diag
53+
}
4754
val processor = new UsingDirectivesProcessor(reporter)
4855
val allDirectives = processor.extract(contentChars).asScala
4956
val malformedDirectiveErrors =

modules/build/src/main/scala/scala/build/preprocessing/MarkdownCodeBlockProcessor.scala

+3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import scala.build.EitherCps.{either, value}
44
import scala.build.Logger
55
import scala.build.errors.BuildException
66
import scala.build.internal.markdown.MarkdownCodeBlock
7+
import scala.build.options.SuppressWarningOptions
78

89
object MarkdownCodeBlockProcessor {
910
def process(
1011
codeBlocks: Seq[MarkdownCodeBlock],
1112
reportingPath: Either[String, os.Path],
1213
scopePath: ScopePath,
14+
suppressWarningOptions: SuppressWarningOptions,
1315
logger: Logger,
1416
maybeRecoverOnError: BuildException => Option[BuildException]
1517
): Either[BuildException, PreprocessedMarkdown] = either {
@@ -23,6 +25,7 @@ object MarkdownCodeBlockProcessor {
2325
ExtractedDirectives.from(
2426
contentChars = cb.body.toCharArray,
2527
path = reportingPath,
28+
suppressWarningOptions = suppressWarningOptions,
2629
logger = logger,
2730
maybeRecoverOnError = maybeRecoverOnError
2831
)

modules/build/src/main/scala/scala/build/preprocessing/MarkdownPreprocessor.scala

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ case object MarkdownPreprocessor extends Preprocessor {
120120
codeBlocks,
121121
reportingPath,
122122
scopePath,
123+
suppressWarningOptions,
123124
logger,
124125
maybeRecoverOnError
125126
))

modules/build/src/main/scala/scala/build/preprocessing/ScalaPreprocessor.scala

+11-5
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,11 @@ case object ScalaPreprocessor extends Preprocessor {
190190
)(using ScalaCliInvokeData): Either[BuildException, Option[ProcessingOutput]] = either {
191191
val (contentWithNoShebang, _) = SheBang.ignoreSheBangLines(content)
192192
val extractedDirectives: ExtractedDirectives = value(ExtractedDirectives.from(
193-
contentWithNoShebang.toCharArray,
194-
path,
195-
logger,
196-
maybeRecoverOnError
193+
contentChars = contentWithNoShebang.toCharArray,
194+
path = path,
195+
suppressWarningOptions = suppressWarningOptions,
196+
logger = logger,
197+
maybeRecoverOnError = maybeRecoverOnError
197198
))
198199
value {
199200
processSources(
@@ -219,7 +220,12 @@ case object ScalaPreprocessor extends Preprocessor {
219220
suppressWarningOptions: SuppressWarningOptions,
220221
maybeRecoverOnError: BuildException => Option[BuildException]
221222
)(using ScalaCliInvokeData): Either[BuildException, Option[ProcessingOutput]] = either {
222-
DeprecatedDirectives.issueWarnings(path, extractedDirectives.directives, logger)
223+
DeprecatedDirectives.issueWarnings(
224+
path,
225+
extractedDirectives.directives,
226+
suppressWarningOptions,
227+
logger
228+
)
223229

224230
val (content0, isSheBang) = SheBang.ignoreSheBangLines(content)
225231
val preprocessedDirectives: PreprocessedDirectives =

modules/cli/src/main/scala/scala/cli/commands/RestrictableCommand.scala

+7-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ trait RestrictableCommand[T](implicit myParser: Parser[T]) {
1111
self: Command[T] =>
1212

1313
def shouldSuppressExperimentalFeatureWarnings: Boolean
14+
def shouldSuppressDeprecatedFeatureWarnings: Boolean
1415
def logger: Logger
1516
protected def invokeData: ScalaCliInvokeData
1617
override def parser: Parser[T] =
17-
RestrictedCommandsParser(myParser, logger, shouldSuppressExperimentalFeatureWarnings)(using
18-
invokeData
19-
)
18+
RestrictedCommandsParser(
19+
parser = myParser,
20+
logger = logger,
21+
shouldSuppressExperimentalWarnings = shouldSuppressExperimentalFeatureWarnings,
22+
shouldSuppressDeprecatedWarnings = shouldSuppressDeprecatedFeatureWarnings
23+
)(using invokeData)
2024

2125
final def isRestricted: Boolean = scalaSpecificationLevel == SpecificationLevel.RESTRICTED
2226

modules/cli/src/main/scala/scala/cli/commands/RestrictedCommandsParser.scala

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ object RestrictedCommandsParser {
1717
def apply[T](
1818
parser: Parser[T],
1919
logger: Logger,
20-
shouldSuppressExperimentalWarnings: Boolean
20+
shouldSuppressExperimentalWarnings: Boolean,
21+
shouldSuppressDeprecatedWarnings: Boolean
2122
)(using ScalaCliInvokeData): Parser[T] =
2223
new Parser[T] {
2324

@@ -37,7 +38,8 @@ object RestrictedCommandsParser {
3738
RestrictedCommandsParser(
3839
parser.withDefaultOrigin(origin),
3940
logger,
40-
shouldSuppressExperimentalWarnings
41+
shouldSuppressExperimentalWarnings,
42+
shouldSuppressDeprecatedWarnings
4143
)
4244

4345
override def step(
@@ -58,7 +60,7 @@ object RestrictedCommandsParser {
5860
logger.experimentalWarning(passedOption, FeatureType.Option)
5961
r
6062
case (r @ Right(Some(_, arg: Arg, _)), passedOption :: _)
61-
if arg.isDeprecated =>
63+
if arg.isDeprecated && !shouldSuppressDeprecatedWarnings =>
6264
// TODO implement proper deprecation logic: https://github.com/VirtusLab/scala-cli/issues/3258
6365
arg.deprecatedOptionAliases.find(_ == passedOption)
6466
.foreach { deprecatedAlias =>

modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala

+8
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,14 @@ abstract class ScalaCommand[T <: HasGlobalOptions](implicit myParser: Parser[T],
352352
}
353353
.getOrElse(false)
354354

355+
override def shouldSuppressDeprecatedFeatureWarnings: Boolean =
356+
globalOptions.globalSuppress.suppressDeprecatedFeatureWarning
357+
.orElse {
358+
configDb.toOption
359+
.flatMap(_.getOpt(Keys.suppressDeprecatedFeatureWarning))
360+
}
361+
.getOrElse(false)
362+
355363
override def logger: Logger = globalOptions.logging.logger
356364

357365
final override def main(progName: String, args: Array[String]): Unit = {

modules/cli/src/main/scala/scala/cli/commands/fix/BuiltInRules.scala

+23-10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ object BuiltInRules extends CommandHelpers {
3232

3333
def runRules(
3434
inputs: Inputs,
35+
buildOptions: BuildOptions,
3536
logger: Logger
3637
)(using ScalaCliInvokeData): Unit = {
3738
val (mainSources, testSources) = getProjectSources(inputs, logger)
@@ -57,8 +58,9 @@ object BuiltInRules extends CommandHelpers {
5758

5859
// Deal with directives from the Main scope
5960
val (directivesFromWritableMainInputs, testDirectivesFromMain) = {
60-
val originalMainDirectives = getExtractedDirectives(mainSources)
61-
.filterNot(hasTargetDirectives)
61+
val originalMainDirectives =
62+
getExtractedDirectives(mainSources, buildOptions.suppressWarningOptions)
63+
.filterNot(hasTargetDirectives)
6264

6365
val transformedMainDirectives = unifyCorrespondingNameAliases(originalMainDirectives)
6466

@@ -83,8 +85,9 @@ object BuiltInRules extends CommandHelpers {
8385
if (
8486
testSources.paths.nonEmpty || testSources.inMemory.nonEmpty || testDirectivesFromMain.nonEmpty
8587
) {
86-
val originalTestDirectives = getExtractedDirectives(testSources)
87-
.filterNot(hasTargetDirectives)
88+
val originalTestDirectives =
89+
getExtractedDirectives(testSources, buildOptions.suppressWarningOptions)
90+
.filterNot(hasTargetDirectives)
8891

8992
val transformedTestDirectives = unifyCorrespondingNameAliases(originalTestDirectives)
9093
.pipe(maybeTransformIntoTestEquivalent)
@@ -145,15 +148,24 @@ object BuiltInRules extends CommandHelpers {
145148
(mainSources, testSources).traverseN
146149
}
147150

148-
private def getExtractedDirectives(sources: Sources)(
151+
private def getExtractedDirectives(
152+
sources: Sources,
153+
suppressWarningOptions: SuppressWarningOptions
154+
)(
149155
using loggingUtilities: LoggingUtilities
150156
): Seq[ExtractedDirectives] = {
151157
val logger = loggingUtilities.logger
152158

153159
val fromPaths = sources.paths.map { (path, _) =>
154160
val (_, content) = SheBang.partitionOnShebangSection(os.read(path))
155161
logger.debug(s"Extracting directives from ${loggingUtilities.relativePath(path)}")
156-
ExtractedDirectives.from(content.toCharArray, Right(path), logger, _ => None).orExit(logger)
162+
ExtractedDirectives.from(
163+
contentChars = content.toCharArray,
164+
path = Right(path),
165+
suppressWarningOptions = suppressWarningOptions,
166+
logger = logger,
167+
maybeRecoverOnError = _ => None
168+
).orExit(logger)
157169
}
158170

159171
val fromInMemory = sources.inMemory.map { inMem =>
@@ -177,10 +189,11 @@ object BuiltInRules extends CommandHelpers {
177189
val (_, contentWithNoShebang) = SheBang.partitionOnShebangSection(content)
178190

179191
ExtractedDirectives.from(
180-
contentWithNoShebang.toCharArray,
181-
originOrPath,
182-
logger,
183-
_ => None
192+
contentChars = contentWithNoShebang.toCharArray,
193+
path = originOrPath,
194+
suppressWarningOptions = suppressWarningOptions,
195+
logger = logger,
196+
maybeRecoverOnError = _ => None
184197
).orExit(logger)
185198
}
186199

modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala

+5-3
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ object Fix extends ScalaCommand[FixOptions] {
2525

2626
override def runCommand(options: FixOptions, args: RemainingArgs, logger: Logger): Unit = {
2727
if options.areAnyRulesEnabled then {
28-
val inputs = options.shared.inputs(args.all).orExit(logger)
29-
val configDb = ConfigDbUtils.configDb.orExit(logger)
28+
val inputs = options.shared.inputs(args.all).orExit(logger)
29+
val buildOpts = buildOptionsOrExit(options)
30+
val configDb = ConfigDbUtils.configDb.orExit(logger)
3031
if options.enableBuiltInRules then {
3132
logger.message("Running built-in rules...")
3233
BuiltInRules.runRules(
3334
inputs = inputs,
35+
buildOptions = buildOpts,
3436
logger = logger
3537
)
3638
logger.message("Built-in rules completed.")
@@ -45,7 +47,7 @@ object Fix extends ScalaCommand[FixOptions] {
4547
.orElse(configDb.get(Keys.actions).getOrElse(None))
4648
val scalafixExitCode: Int = value {
4749
ScalafixRules.runRules(
48-
buildOptions = buildOptionsOrExit(options),
50+
buildOptions = buildOpts,
4951
scalafixOptions = options.scalafix,
5052
inputs = inputs,
5153
check = options.check,

modules/cli/src/main/scala/scala/cli/commands/pgp/PgpCommand.scala

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ abstract class PgpCommand[T](implicit myParser: Parser[T], help: Help[T])
2929
override def shouldSuppressExperimentalFeatureWarnings: Boolean =
3030
false // TODO add handling for scala-cli-signing
3131

32+
override def shouldSuppressDeprecatedFeatureWarnings: Boolean =
33+
false // TODO add handling for scala-cli-signing
34+
3235
override def logger: Logger = CliLogger.default // TODO add handling for scala-cli-signing
3336

3437
override def hidden = true

0 commit comments

Comments
 (0)