From a88b572d1dcda29b06ca4877bc835ead75c7cecf Mon Sep 17 00:00:00 2001 From: Maciej Gajek Date: Tue, 25 Jul 2023 12:39:12 +0200 Subject: [PATCH] Add Fix command -Add logging to Fix command -Format the copied directives in project.scala -Add support for test. directives in main scope -Add support for sources with shebang -Move removing directives as the last operation in Fix command -Remove ordering via hardcoded names -Apply review fixes --- .../scala/build/preprocessing/SheBang.scala | 13 + .../scala/scala/cli/ScalaCliCommands.scala | 1 + .../scala/scala/cli/commands/fix/Fix.scala | 366 ++++++++++++++++ .../scala/cli/commands/fix/FixOptions.scala | 33 ++ .../directives/StrictDirective.scala | 29 ++ .../preprocessing/directives/Tests.scala | 1 + .../scala/cli/integration/FixTests.scala | 407 ++++++++++++++++++ .../options/SuppressWarningOptions.scala | 6 + website/docs/reference/cli-options.md | 46 +- website/docs/reference/commands.md | 22 + 10 files changed, 901 insertions(+), 23 deletions(-) create mode 100644 modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala create mode 100644 modules/cli/src/main/scala/scala/cli/commands/fix/FixOptions.scala create mode 100644 modules/integration/src/test/scala/scala/cli/integration/FixTests.scala diff --git a/modules/build/src/main/scala/scala/build/preprocessing/SheBang.scala b/modules/build/src/main/scala/scala/build/preprocessing/SheBang.scala index 3b1b29fb56..a8ea735faa 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/SheBang.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/SheBang.scala @@ -7,6 +7,19 @@ object SheBang { def isShebangScript(content: String): Boolean = sheBangRegex.unanchored.matches(content) + /** Returns the shebang section and the content without the shebang section */ + def partitionOnShebangSection(content: String): (String, String) = + if (content.startsWith("#!")) { + val regexMatch = sheBangRegex.findFirstMatchIn(content) + regexMatch match { + case Some(firstMatch) => + (firstMatch.toString(), content.replaceFirst(firstMatch.toString(), "")) + case None => ("", content) + } + } + else + ("", content) + def ignoreSheBangLines(content: String): (String, Boolean) = if (content.startsWith("#!")) { val regexMatch = sheBangRegex.findFirstMatchIn(content) diff --git a/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala b/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala index c5c05f3802..f60a719d21 100644 --- a/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala +++ b/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala @@ -38,6 +38,7 @@ class ScalaCliCommands( directories.Directories, doc.Doc, export0.Export, + fix.Fix, fmt.Fmt, new HelpCmd(help), installcompletions.InstallCompletions, diff --git a/modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala b/modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala new file mode 100644 index 0000000000..3f42d6bb00 --- /dev/null +++ b/modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala @@ -0,0 +1,366 @@ +package scala.cli.commands.fix + +import caseapp.core.RemainingArgs + +import scala.build.Ops.EitherMap2 +import scala.build.errors.{BuildException, CompositeBuildException} +import scala.build.input.* +import scala.build.internal.Constants +import scala.build.options.{BuildOptions, Scope, SuppressWarningOptions} +import scala.build.preprocessing.directives.* +import scala.build.preprocessing.{ExtractedDirectives, SheBang} +import scala.build.{CrossSources, Logger, Position, Sources} +import scala.cli.commands.shared.SharedOptions +import scala.cli.commands.{ScalaCommand, SpecificationLevel} +import scala.collection.immutable.HashMap +import scala.util.chaining.scalaUtilChainingOps + +object Fix extends ScalaCommand[FixOptions] { + override def group = "Main" + override def scalaSpecificationLevel = SpecificationLevel.EXPERIMENTAL + override def sharedOptions(options: FixOptions): Option[SharedOptions] = Some(options.shared) + + lazy val targetDirectivesKeysSet = DirectivesPreprocessingUtils.requireDirectiveHandlers + .flatMap(_.keys.flatMap(_.nameAliases)).toSet + lazy val usingDirectivesKeysGrouped = DirectivesPreprocessingUtils.usingDirectiveHandlers + .flatMap(_.keys) + lazy val usingDirectivesWithTestPrefixKeysGrouped = + DirectivesPreprocessingUtils.usingDirectiveWithReqsHandlers + .flatMap(_.keys) + + val newLine = System.lineSeparator() + + override def runCommand(options: FixOptions, args: RemainingArgs, logger: Logger): Unit = { + val inputs = options.shared.inputs(args.remaining, () => Inputs.default()).orExit(logger) + + val (mainSources, testSources) = getProjectSources(inputs) + .left.map(CompositeBuildException(_)) + .orExit(logger) + + // Only initial inputs are used, new inputs discovered during processing of + // CrossSources.forInput may be shared between projects + val writableInputs: Seq[OnDisk] = inputs.flattened() + .collect { case onDisk: OnDisk => onDisk } + + def isExtractedFromWritableInput(position: Option[Position.File]): Boolean = { + val originOrPathOpt = position.map(_.path) + originOrPathOpt match { + case Some(Right(path)) => writableInputs.exists(_.path == path) + case _ => false + } + } + + val projectFileContents = new StringBuilder() + + given LoggingUtilities(logger, inputs.workspace) + + // Deal with directives from the Main scope + val (directivesFromWritableMainInputs, testDirectivesFromMain) = { + val originalMainDirectives = getExtractedDirectives(mainSources) + .filterNot(hasTargetDirectives) + + val transformedMainDirectives = unifyCorrespondingNameAliases(originalMainDirectives) + + val allDirectives = for { + transformedMainDirective <- transformedMainDirectives + directive <- transformedMainDirective.directives + } yield directive + + val (testScopeDirectives, allMainDirectives) = + allDirectives.partition(_.key.startsWith("test")) + + createFormattedLinesAndAppend(allMainDirectives, projectFileContents, isTest = false) + + ( + transformedMainDirectives.filter(d => isExtractedFromWritableInput(d.positions)), + testScopeDirectives + ) + } + + // Deal with directives from the Test scope + val directivesFromWritableTestInputs: Seq[TransformedTestDirectives] = + if ( + testSources.paths.nonEmpty || testSources.inMemory.nonEmpty || testDirectivesFromMain.nonEmpty + ) { + val originalTestDirectives = getExtractedDirectives(testSources) + .filterNot(hasTargetDirectives) + + val transformedTestDirectives = unifyCorrespondingNameAliases(originalTestDirectives) + .pipe(maybeTransformIntoTestEquivalent) + + val allDirectives = for { + directivesWithTestPrefix <- transformedTestDirectives.map(_.withTestPrefix) + directive <- directivesWithTestPrefix ++ testDirectivesFromMain + } yield directive + + createFormattedLinesAndAppend(allDirectives, projectFileContents, isTest = true) + + transformedTestDirectives + .filter(ttd => isExtractedFromWritableInput(ttd.positions)) + } + else Seq(TransformedTestDirectives(Nil, Nil, None)) + + projectFileContents.append(newLine) + + // Write extracted directives to project.scala + logger.message(s"Writing ${Constants.projectFileName}") + os.write.over(inputs.workspace / Constants.projectFileName, projectFileContents.toString) + + def isProjectFile(position: Option[Position.File]): Boolean = + position.exists(_.path.contains(inputs.workspace / Constants.projectFileName)) + + // Remove directives from their original files, skip the project.scala file + directivesFromWritableMainInputs + .filterNot(e => isProjectFile(e.positions)) + .foreach(d => removeDirectivesFrom(d.positions)) + directivesFromWritableTestInputs + .filterNot(ttd => isProjectFile(ttd.positions)) + .foreach(ttd => removeDirectivesFrom(ttd.positions, toKeep = ttd.noTestPrefixAvailable)) + } + + def getProjectSources(inputs: Inputs): Either[::[BuildException], (Sources, Sources)] = { + val buildOptions = BuildOptions() + + val (crossSources, _) = CrossSources.forInputs( + inputs, + preprocessors = Sources.defaultPreprocessors( + buildOptions.archiveCache, + buildOptions.internal.javaClassNameVersionOpt, + () => buildOptions.javaHome().value.javaCommand + ), + logger = logger, + suppressWarningOptions = SuppressWarningOptions.suppressAll, + exclude = buildOptions.internal.exclude + ).orExit(logger) + + val sharedOptions = crossSources.sharedOptions(buildOptions) + val scopedSources = crossSources.scopedSources(sharedOptions).orExit(logger) + + val mainSources = scopedSources.sources(Scope.Main, sharedOptions, inputs.workspace) + val testSources = scopedSources.sources(Scope.Test, sharedOptions, inputs.workspace) + + (mainSources, testSources).traverseN + } + + def getExtractedDirectives(sources: Sources)( + using loggingUtilities: LoggingUtilities + ): Seq[ExtractedDirectives] = { + val logger = loggingUtilities.logger + + val fromPaths = sources.paths.map { (path, _) => + val (_, content) = SheBang.partitionOnShebangSection(os.read(path)) + logger.debug(s"Extracting directives from ${loggingUtilities.relativePath(path)}") + ExtractedDirectives.from(content.toCharArray, Right(path), logger, _ => None).orExit(logger) + } + + val fromInMemory = sources.inMemory.map { inMem => + val originOrPath = inMem.originalPath.map((_, path) => path) + val content = originOrPath match { + case Right(path) => + logger.debug(s"Extracting directives from ${loggingUtilities.relativePath(path)}") + os.read(path) + case Left(origin) => + logger.debug(s"Extracting directives from $origin") + inMem.wrapperParamsOpt match { + // In case of script snippets, we need to drop the top wrapper lines + case Some(wrapperParams) => String(inMem.content) + .linesWithSeparators + .drop(wrapperParams.topWrapperLineCount) + .mkString + case None => String(inMem.content) + } + } + + val (_, contentWithNoShebang) = SheBang.partitionOnShebangSection(content) + + ExtractedDirectives.from( + contentWithNoShebang.toCharArray, + originOrPath, + logger, + _ => None + ).orExit(logger) + } + + fromPaths ++ fromInMemory + } + + def hasTargetDirectives(extractedDirectives: ExtractedDirectives): Boolean = { + // Filter out all elements that contain using target directives + val directivesInElement = extractedDirectives.directives.map(_.key) + directivesInElement.exists(key => targetDirectivesKeysSet.contains(key)) + } + + def unifyCorrespondingNameAliases(extractedDirectives: Seq[ExtractedDirectives]) = + extractedDirectives.map { extracted => + // All keys that we migrate, not all in general + val allKeysGrouped = usingDirectivesKeysGrouped ++ usingDirectivesWithTestPrefixKeysGrouped + val strictDirectives = extracted.directives + + val strictDirectivesWithNewKeys = strictDirectives.flatMap { strictDir => + val newKeyOpt = allKeysGrouped.find(_.nameAliases.contains(strictDir.key)) + .flatMap(_.nameAliases.headOption) + .map { key => + if (key.startsWith("test")) + val withTestStripped = key.stripPrefix("test").stripPrefix(".") + "test." + withTestStripped.take(1).toLowerCase + withTestStripped.drop(1) + else + key + } + + newKeyOpt.map(newKey => strictDir.copy(key = newKey)) + } + + extracted.copy(directives = strictDirectivesWithNewKeys) + } + + /** Transforms directives into their 'test.' equivalent if it exists + * + * @param extractedDirectives + * @return + * an instance of TransformedTestDirectives containing transformed directives and those that + * could not be transformed since they have no 'test.' equivalent + */ + def maybeTransformIntoTestEquivalent(extractedDirectives: Seq[ExtractedDirectives]) + : Seq[TransformedTestDirectives] = + for { + extractedFromSingleElement <- extractedDirectives + directives = extractedFromSingleElement.directives + } yield { + val (withTestEquivalent, noTestEquivalent) = directives.partition { directive => + usingDirectivesWithTestPrefixKeysGrouped.exists( + _.nameAliases.contains("test." + directive.key) + ) + } + + val transformedToTestEquivalents = withTestEquivalent.map { + case StrictDirective(key, values) => StrictDirective("test." + key, values) + } + + TransformedTestDirectives( + withTestPrefix = transformedToTestEquivalents, + noTestPrefixAvailable = noTestEquivalent, + positions = extractedFromSingleElement.positions + ) + } + + def removeDirectivesFrom( + position: Option[Position.File], + toKeep: Seq[StrictDirective] = Nil + )( + using loggingUtilities: LoggingUtilities + ): Unit = { + position match { + case Some(Position.File(Right(path), _, _, offset)) => + val (shebangSection, strippedContent) = SheBang.partitionOnShebangSection(os.read(path)) + + def ignoreOrAddNewLine(str: String) = if str.isBlank then "" else str + newLine + + val keepLines = ignoreOrAddNewLine(shebangSection) + ignoreOrAddNewLine(toKeep.mkString( + "", + newLine, + newLine + )) + val newContents = keepLines + strippedContent.drop(offset).stripLeading() + val relativePath = loggingUtilities.relativePath(path) + + loggingUtilities.logger.message(s"Removing directives from $relativePath") + if (toKeep.nonEmpty) { + loggingUtilities.logger.message(" Keeping:") + toKeep.foreach(d => loggingUtilities.logger.message(s" $d")) + } + + os.write.over(path, newContents.stripLeading()) + case _ => () + } + } + + def createFormattedLinesAndAppend( + strictDirectives: Seq[StrictDirective], + projectFileContents: StringBuilder, + isTest: Boolean + ): Unit = { + if (strictDirectives.nonEmpty) { + projectFileContents + .append(if (projectFileContents.nonEmpty) newLine else "") + .append(if isTest then "// Test" else "// Main") + .append(newLine) + + strictDirectives + // group by key to merge values + .groupBy(_.key) + .map { (key, directives) => + StrictDirective(key, directives.flatMap(_.values)) + } + // group by key prefixes to create splits between groups + .groupBy(dir => (if (isTest) dir.key.stripPrefix("test.") else dir.key).takeWhile(_ != '.')) + .map { (_, directives) => + directives.flatMap(_.explodeToStringsWithColLimit()).toSeq.sorted + } + .toSeq + .filter(_.nonEmpty) + .sortBy(_.head)(using directivesOrdering) + // append groups to the StringBuilder, add new lines between groups that are bigger than one line + .foldLeft(0) { (lastSize, directiveLines) => + val newSize = directiveLines.size + if (lastSize > 1 || (lastSize != 0 && newSize > 1)) projectFileContents.append(newLine) + + directiveLines.foreach(projectFileContents.append(_).append(newLine)) + + newSize + } + } + } + + case class TransformedTestDirectives( + withTestPrefix: Seq[StrictDirective], + noTestPrefixAvailable: Seq[StrictDirective], + positions: Option[Position.File] + ) + + case class LoggingUtilities( + logger: Logger, + workspacePath: os.Path + ) { + def relativePath(path: os.Path) = + if (path.startsWith(workspacePath)) path.relativeTo(workspacePath) + else path + } + + private val directivesOrdering: Ordering[String] = { + def directivesOrder(key: String): Int = { + val handlersOrder = Seq( + ScalaVersion.handler.keys, + Platform.handler.keys, + Jvm.handler.keys, + JavaHome.handler.keys, + ScalaNative.handler.keys, + ScalaJs.handler.keys, + ScalacOptions.handler.keys, + JavaOptions.handler.keys, + JavacOptions.handler.keys, + JavaProps.handler.keys, + MainClass.handler.keys, + scala.build.preprocessing.directives.Sources.handler.keys, + ObjectWrapper.handler.keys, + Toolkit.handler.keys, + Dependency.handler.keys + ) + + handlersOrder.zipWithIndex + .find(_._1.flatMap(_.nameAliases).contains(key)) + .map(_._2) + .getOrElse(if key.startsWith("publish") then 20 else 15) + } + + Ordering.by { directiveLine => + val key = directiveLine + .stripPrefix("//> using") + .stripLeading() + .stripPrefix("test.") + // separate key from value + .takeWhile(!_.isWhitespace) + + directivesOrder(key) + } + } +} diff --git a/modules/cli/src/main/scala/scala/cli/commands/fix/FixOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/fix/FixOptions.scala new file mode 100644 index 0000000000..a1a2400abd --- /dev/null +++ b/modules/cli/src/main/scala/scala/cli/commands/fix/FixOptions.scala @@ -0,0 +1,33 @@ +package scala.cli.commands.fix + +import caseapp.* +import caseapp.core.help.Help + +import scala.cli.ScalaCli +import scala.cli.commands.shared.{HasSharedOptions, HelpMessages, SharedOptions} +import scala.cli.commands.tags + +// format: off +@HelpMessage(FixOptions.helpMessage, "", FixOptions.detailedHelpMessage) +final case class FixOptions( + @Recurse + shared: SharedOptions = SharedOptions() +) extends HasSharedOptions +// format: on + +object FixOptions { + implicit lazy val parser: Parser[FixOptions] = Parser.derive + implicit lazy val help: Help[FixOptions] = Help.derive + + val cmdName = "fix" + private val helpHeader = "Perform fixes on a Scala CLI project." + val helpMessage: String = HelpMessages.shortHelpMessage(cmdName, helpHeader) + val detailedHelpMessage: String = + s"""$helpHeader + | + |${HelpMessages.commandConfigurations(cmdName)} + | + |${HelpMessages.acceptedInputs} + | + |${HelpMessages.commandDocWebsiteReference(cmdName)}""".stripMargin +} diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/StrictDirective.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/StrictDirective.scala index be4798ad8f..78b532243d 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/StrictDirective.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/StrictDirective.scala @@ -14,6 +14,35 @@ case class StrictDirective( val suffix = if validValues.isEmpty then "" else s" \"${validValues.mkString("\", \"")}\"" s"//> using $key$suffix" } + + /** Checks whether the directive with the sequence of values will fit into the given column limit, + * if it does then the function returns the single directive with all the values. If the + * directive does not fit then the function explodes it into a sequence of directives with + * distinct values, each with a single value. + */ + def explodeToStringsWithColLimit(colLimit: Int = 100): Seq[String] = { + val validValues = values.filter { + case _: EmptyValue => false + case _ => true + } + + val usingKeyString = s"//> using $key" + + if (validValues.isEmpty) + Seq(usingKeyString) + else { + val distinctValuesStrings = validValues + .map(v => s"\"${v.toString}\"") + .distinct + .sorted + + if (distinctValuesStrings.map(_.length).sum + usingKeyString.length < colLimit) + Seq(s"$usingKeyString ${distinctValuesStrings.mkString(" ")}") + else + distinctValuesStrings.map(v => s"$usingKeyString $v") + } + } + def stringValuesCount: Int = values.count { case _: StringValue => true diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/Tests.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/Tests.scala index ba898915a5..8e5501df59 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/Tests.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/Tests.scala @@ -16,6 +16,7 @@ import scala.cli.commands.SpecificationLevel @DirectiveLevel(SpecificationLevel.SHOULD) // format: off final case class Tests( + @DirectiveName("test.framework") testFramework: Option[String] = None ) extends HasBuildOptions { // format: on diff --git a/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala b/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala new file mode 100644 index 0000000000..0a342d8746 --- /dev/null +++ b/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala @@ -0,0 +1,407 @@ +package scala.cli.integration + +import com.eed3si9n.expecty.Expecty.expect + +class FixTests extends ScalaCliSuite { + + override def group: ScalaCliSuite.TestGroup = ScalaCliSuite.TestGroup.First + + val projectFileName = "project.scala" + + val extraOptions = Seq("--suppress-experimental-feature-warning") + + test("fix basic") { + val mainFileName = "Main.scala" + val inputs = TestInputs( + os.rel / mainFileName -> + s"""//> using objectWrapper + |//> using dep com.lihaoyi::os-lib:0.9.1 com.lihaoyi::upickle:3.1.2 + | + |package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin, + os.rel / projectFileName -> + s"""//> using lib "com.lihaoyi::pprint:0.6.6" + |""".stripMargin + ) + + inputs.fromRoot { root => + + val fixOutput = os.proc(TestUtil.cli, "--power", "fix", ".", "-v", "-v", extraOptions) + .call(cwd = root, mergeErrIntoOut = true).out.trim() + + assertNoDiff( + fixOutput, + """Extracting directives from Main.scala + |Extracting directives from project.scala + |Writing project.scala + |Removing directives from Main.scala""".stripMargin + ) + + val projectFileContents = os.read(root / projectFileName) + val mainFileContents = os.read(root / mainFileName) + + assertNoDiff( + projectFileContents, + """// Main + |//> using objectWrapper + | + |//> using dependency "com.lihaoyi::os-lib:0.9.1" + |//> using dependency "com.lihaoyi::pprint:0.6.6" + |//> using dependency "com.lihaoyi::upickle:3.1.2" + | + |""".stripMargin + ) + + assertNoDiff( + mainFileContents, + """package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin + ) + + val runProc = os.proc(TestUtil.cli, "--power", "compile", ".", extraOptions) + .call(cwd = root, stderr = os.Pipe) + + expect(!runProc.err.trim.contains("Using directives detected in multiple files")) + } + } + + test("fix script with shebang") { + val mainFileName = "main.sc" + val inputs = TestInputs( + os.rel / mainFileName -> + s"""#!/usr/bin/env -S scala-cli shebang + | + |//> using objectWrapper + |//> using dep com.lihaoyi::os-lib:0.9.1 com.lihaoyi::upickle:3.1.2 + | + |println(os.pwd) + |""".stripMargin, + os.rel / projectFileName -> + s"""//> using lib "com.lihaoyi::pprint:0.6.6" + |""".stripMargin + ) + + inputs.fromRoot { root => + + val fixOutput = os.proc(TestUtil.cli, "--power", "fix", ".", "-v", "-v", extraOptions) + .call(cwd = root, mergeErrIntoOut = true).out.trim() + + assertNoDiff( + fixOutput, + """Extracting directives from project.scala + |Extracting directives from main.sc + |Writing project.scala + |Removing directives from main.sc""".stripMargin + ) + + val projectFileContents = os.read(root / projectFileName) + val mainFileContents = os.read(root / mainFileName) + + assertNoDiff( + projectFileContents, + """// Main + |//> using objectWrapper + | + |//> using dependency "com.lihaoyi::os-lib:0.9.1" + |//> using dependency "com.lihaoyi::pprint:0.6.6" + |//> using dependency "com.lihaoyi::upickle:3.1.2" + | + |""".stripMargin + ) + + assertNoDiff( + mainFileContents, + """#!/usr/bin/env -S scala-cli shebang + | + |println(os.pwd) + |""".stripMargin + ) + + val runProc = os.proc(TestUtil.cli, "--power", "compile", ".", extraOptions) + .call(cwd = root, stderr = os.Pipe) + + expect(!runProc.err.trim.contains("Using directives detected in multiple files")) + } + } + + test("fix with test scope") { + val mainSubPath = os.rel / "src" / "Main.scala" + val testSubPath = os.rel / "test" / "MyTests.scala" + val inputs = TestInputs( + mainSubPath -> + s"""//> using objectWrapper + |//> using dep "com.lihaoyi::os-lib:0.9.1" + | + |//> using test.dep "org.typelevel::cats-core:2.9.0" + | + |package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin, + testSubPath -> + s"""//> using options -Xasync, -Xfatal-warnings + |//> using dep org.scalameta::munit::0.7.29 + | + |package com.foo.test.bar + | + |class MyTests extends munit.FunSuite { + | test("bar") { + | assert(2 + 2 == 4) + | println("Hello from " + "tests") + | } + |} + |""".stripMargin, + os.rel / projectFileName -> + s"""//> using lib com.lihaoyi::pprint:0.6.6 + |""".stripMargin + ) + + inputs.fromRoot { root => + + val fixOutput = os.proc(TestUtil.cli, "--power", "fix", ".", "-v", "-v", extraOptions) + .call(cwd = root, mergeErrIntoOut = true).out.trim() + + assertNoDiff( + fixOutput, + """Extracting directives from project.scala + |Extracting directives from src/Main.scala + |Extracting directives from test/MyTests.scala + |Writing project.scala + |Removing directives from src/Main.scala + |Removing directives from test/MyTests.scala""".stripMargin + ) + + val projectFileContents = os.read(root / projectFileName) + val mainFileContents = os.read(root / mainSubPath) + val testFileContents = os.read(root / testSubPath) + + assertNoDiff( + projectFileContents, + """// Main + |//> using objectWrapper + |//> using dependency "com.lihaoyi::os-lib:0.9.1" "com.lihaoyi::pprint:0.6.6" + | + |// Test + |//> using test.options "-Xasync" "-Xfatal-warnings" + |//> using test.dependency "org.scalameta::munit::0.7.29" "org.typelevel::cats-core:2.9.0" + |""".stripMargin + ) + + assertNoDiff( + mainFileContents, + """package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin + ) + + assertNoDiff( + testFileContents, + """package com.foo.test.bar + | + |class MyTests extends munit.FunSuite { + | test("bar") { + | assert(2 + 2 == 4) + | println("Hello from " + "tests") + | } + |} + |""".stripMargin + ) + + val runProc = os.proc(TestUtil.cli, "--power", "compile", ".", extraOptions) + .call(cwd = root, stderr = os.Pipe) + + expect(!runProc.err.trim.contains("Using directives detected in multiple files")) + } + } + + test("fix complex inputs") { + val mainSubPath = os.rel / "src" / "Main.scala" + val testSubPath = os.rel / "test" / "MyTests.scala" + + val withUsedTargetSubPath = os.rel / "src" / "UsedTarget.scala" + val withUsedTargetContents = + s"""//> using target.scala 3.3.0 + |//> using dep com.lihaoyi::upickle:3.1.2 + |case class UsedTarget(x: Int) + |""".stripMargin + val withUnusedTargetSubPath = os.rel / "src" / "UnusedTarget.scala" + val withUnusedTargetContents = + s"""//> using target.scala 2.13 + |//> using dep com.lihaoyi::upickle:3.1.2 + |case class UnusedTarget(x: Int) + |""".stripMargin + + val includedInputs = TestInputs( + os.rel / "Included.scala" -> + """//> using options -Werror + | + |case class Included(x: Int) + |""".stripMargin + ) + + includedInputs.fromRoot { includeRoot => + val includePath = (includeRoot / "Included.scala").toString.replace("\\", "\\\\") + + val inputs = TestInputs( + mainSubPath -> + s"""//> using platforms "jvm" + |//> using scala "3.3.0" + |//> using jvm "17" + |//> using objectWrapper + |//> using dep com.lihaoyi::os-lib:0.9.1 + |//> using file $includePath + | + |//> using test.dep "org.typelevel::cats-core:2.9.0" + | + |package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin, + withUsedTargetSubPath -> withUsedTargetContents, + withUnusedTargetSubPath -> withUnusedTargetContents, + testSubPath -> + s"""//> using options -Xasync, -Xfatal-warnings + |//> using dep "org.scalameta::munit::0.7.29" + |//> using scala 3.2.2 + | + |package com.foo.test.bar + | + |class MyTests extends munit.FunSuite { + | test("bar") { + | assert(2 + 2 == 4) + | println("Hello from " + "tests") + | } + |} + |""".stripMargin, + os.rel / projectFileName -> + s"""//> using lib com.lihaoyi::pprint:0.6.6 + | + |//> using publish.ci.password env:PUBLISH_PASSWORD + |//> using publish.ci.secretKey env:PUBLISH_SECRET_KEY + |//> using publish.ci.secretKeyPassword env:PUBLISH_SECRET_KEY_PASSWORD + |//> using publish.ci.user env:PUBLISH_USER + |""".stripMargin + ) + + inputs.fromRoot { root => + val res = os.proc( + TestUtil.cli, + "--power", + "fix", + ".", + "--script-snippet", + "//> using toolkit latest", + "-v", + "-v", + extraOptions + ).call(cwd = root, stderr = os.Pipe) + + assertNoDiff( + res.err.trim(), + s"""Extracting directives from project.scala + |Extracting directives from src/Main.scala + |Extracting directives from src/UsedTarget.scala + |Extracting directives from ${includeRoot / "Included.scala"} + |Extracting directives from snippet + |Extracting directives from test/MyTests.scala + |Writing project.scala + |Removing directives from src/Main.scala + |Removing directives from test/MyTests.scala + | Keeping: + | //> using scala "3.2.2"""".stripMargin + ) + + val projectFileContents = os.read(root / projectFileName) + val mainFileContents = os.read(root / mainSubPath) + val testFileContents = os.read(root / testSubPath) + val withUsedTargetContentsRead = os.read(root / withUsedTargetSubPath) + val withUnusedTargetContentsRead = os.read(root / withUnusedTargetSubPath) + + assertNoDiff( + projectFileContents, + s"""// Main + |//> using scala "3.3.0" + |//> using platforms "jvm" + |//> using jvm "17" + |//> using options "-Werror" + |//> using files "$includePath" + |//> using objectWrapper + |//> using toolkit "latest" + |//> using dependency "com.lihaoyi::os-lib:0.9.1" "com.lihaoyi::pprint:0.6.6" + | + |//> using publish.ci.password "env:PUBLISH_PASSWORD" + |//> using publish.ci.secretKey "env:PUBLISH_SECRET_KEY" + |//> using publish.ci.secretKeyPassword "env:PUBLISH_SECRET_KEY_PASSWORD" + |//> using publish.ci.user "env:PUBLISH_USER" + | + |// Test + |//> using test.options "-Xasync" "-Xfatal-warnings" + |//> using test.dependency "org.scalameta::munit::0.7.29" "org.typelevel::cats-core:2.9.0" + |""".stripMargin + ) + + assertNoDiff( + mainFileContents, + """package com.foo.main + | + |object Main extends App { + | println(os.pwd) + |} + |""".stripMargin + ) + + // Directives with no 'test.' equivalent are retained + assertNoDiff( + testFileContents, + """//> using scala "3.2.2" + | + |package com.foo.test.bar + | + |class MyTests extends munit.FunSuite { + | test("bar") { + | assert(2 + 2 == 4) + | println("Hello from " + "tests") + | } + |} + |""".stripMargin + ) + + assertNoDiff(withUsedTargetContents, withUsedTargetContentsRead) + assertNoDiff(withUnusedTargetContents, withUnusedTargetContentsRead) + + val runProc = os.proc(TestUtil.cli, "--power", "compile", ".") + .call(cwd = root, stderr = os.Pipe) + + val runErrOut = TestUtil.removeAnsiColors(runProc.err.trim) + expect(runErrOut.contains("Using directives detected in multiple files")) + expect(runErrOut.linesIterator.count(_.startsWith("[warn] //> using")) == 2) + expect(runErrOut.contains("[warn] //> using options -Werror")) + // TODO: Warning about using directives in multiple files for the test scope should not be displayed + expect(runErrOut.contains("[warn] //> using scala \"3.2.2\"")) + } + + assertNoDiff( + os.read(includeRoot / "Included.scala"), + """//> using options -Werror + | + |case class Included(x: Int) + |""".stripMargin + ) + } + } +} diff --git a/modules/options/src/main/scala/scala/build/options/SuppressWarningOptions.scala b/modules/options/src/main/scala/scala/build/options/SuppressWarningOptions.scala index dc7cba7690..7846debcf3 100644 --- a/modules/options/src/main/scala/scala/build/options/SuppressWarningOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/SuppressWarningOptions.scala @@ -9,4 +9,10 @@ final case class SuppressWarningOptions( object SuppressWarningOptions { implicit val hasHashData: HasHashData[SuppressWarningOptions] = HasHashData.derive implicit val monoid: ConfigMonoid[SuppressWarningOptions] = ConfigMonoid.derive + + val suppressAll = SuppressWarningOptions( + suppressDirectivesInMultipleFilesWarning = Some(true), + suppressOutdatedDependencyWarning = Some(true), + suppressExperimentalFeatureWarning = Some(true) + ) } diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index 44927081dd..196819983e 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -56,7 +56,7 @@ Set JMH version Available in commands: -[`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall) +[`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall) @@ -229,7 +229,7 @@ Run given command against all provided Scala versions and/or platforms Available in commands: -[`bloop`](./commands.md#bloop), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bloop`](./commands.md#bloop), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -249,7 +249,7 @@ Debug mode (attach by default) Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -424,7 +424,7 @@ Pass scalafmt version before running it (3.7.14 by default). If passed, this ove Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -438,7 +438,7 @@ Suppress warnings about using experimental features Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp create`](./commands.md#pgp-create), [`pgp key-id`](./commands.md#pgp-key-id), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`pgp sign`](./commands.md#pgp-sign), [`pgp verify`](./commands.md#pgp-verify), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp create`](./commands.md#pgp-create), [`pgp key-id`](./commands.md#pgp-key-id), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`pgp sign`](./commands.md#pgp-sign), [`pgp verify`](./commands.md#pgp-verify), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -462,7 +462,7 @@ Print help message, including hidden options, and exit Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -562,7 +562,7 @@ Add java properties. Note that options equal `-Dproperty=value` are assumed to b Available in commands: -[`bloop`](./commands.md#bloop), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bloop`](./commands.md#bloop), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -612,7 +612,7 @@ Port for BSP debugging Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -650,7 +650,7 @@ List main classes available in the current context Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1099,7 +1099,7 @@ Dummy mode - don't upload any secret to GitHub Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1202,7 +1202,7 @@ Run Java commands using a manifest-based class path (shortens command length) Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1288,7 +1288,7 @@ Whether to run the Scala.js CLI on the JVM or using a native executable Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1346,7 +1346,7 @@ Embed resources into the Scala Native binary (can be read with the Java resource Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1360,7 +1360,7 @@ Add a `scalac` option. Note that options starting with `-g`, `-language`, `-opt` Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1413,7 +1413,7 @@ Aliases: `-n` Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1514,7 +1514,7 @@ Force object wrapper for scripts Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1563,7 +1563,7 @@ A synonym to --markdown-snippet, which defaults the sub-command to `run` when no Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1577,7 +1577,7 @@ Generate BuildInfo for project Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -1698,7 +1698,7 @@ A github token used to access GitHub. Not needed in most cases. Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -1722,7 +1722,7 @@ Enable actionable diagnostics Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`version`](./commands.md#version) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`version`](./commands.md#version) @@ -1852,7 +1852,7 @@ Name of BSP Available in commands: -[`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall) +[`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall) @@ -1905,7 +1905,7 @@ Force overwriting destination files Available in commands: -[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) @@ -2107,7 +2107,7 @@ Available in commands: Available in commands: -[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) +[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`dependency-update`](./commands.md#dependency-update), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fix`](./commands.md#fix), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`package`](./commands.md#package), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test) diff --git a/website/docs/reference/commands.md b/website/docs/reference/commands.md index aa2eac6151..4ea9c14c83 100644 --- a/website/docs/reference/commands.md +++ b/website/docs/reference/commands.md @@ -117,6 +117,28 @@ If you encounter any bugs or have feedback to share, make sure to reach out to t Accepts option groups: [compilation server](./cli-options.md#compilation-server-options), [coursier](./cli-options.md#coursier-options), [debug](./cli-options.md#debug-options), [dependency](./cli-options.md#dependency-options), [export](./cli-options.md#export-options), [global suppress warning](./cli-options.md#global-suppress-warning-options), [help group](./cli-options.md#help-group-options), [input](./cli-options.md#input-options), [jvm](./cli-options.md#jvm-options), [logging](./cli-options.md#logging-options), [main class](./cli-options.md#main-class-options), [markdown](./cli-options.md#markdown-options), [python](./cli-options.md#python-options), [Scala.js](./cli-options.md#scalajs-options), [Scala Native](./cli-options.md#scala-native-options), [scalac](./cli-options.md#scalac-options), [scalac extra](./cli-options.md#scalac-extra-options), [shared](./cli-options.md#shared-options), [snippet](./cli-options.md#snippet-options), [source generator](./cli-options.md#source-generator-options), [suppress warning](./cli-options.md#suppress-warning-options), [verbosity](./cli-options.md#verbosity-options), [version](./cli-options.md#version-options), [workspace](./cli-options.md#workspace-options) +## fix + +Perform fixes on a Scala CLI project. + +Specific fix configurations can be specified with both command line options and using directives defined in sources. +Command line options always take priority over using directives when a clash occurs, allowing to override configurations defined in sources. +Using directives can be defined in all supported input source file types. + +Multiple inputs can be passed at once. +Paths to directories, URLs and supported file types are accepted as inputs. +Accepted file extensions: .scala, .sc, .java, .jar, .md, .jar, .c, .h, .zip +For piped inputs use the corresponding alias: _.scala, _.java, _.sc, _.md +All supported types of inputs can be mixed with each other. + +For detailed documentation refer to our website: https://scala-cli.virtuslab.org/docs/commands/fix + +The `fix` sub-command is experimental. +Please bear in mind that non-ideal user experience should be expected. +If you encounter any bugs or have feedback to share, make sure to reach out to the maintenance team at https://github.com/VirtusLab/scala-cli + +Accepts option groups: [compilation server](./cli-options.md#compilation-server-options), [coursier](./cli-options.md#coursier-options), [debug](./cli-options.md#debug-options), [dependency](./cli-options.md#dependency-options), [global suppress warning](./cli-options.md#global-suppress-warning-options), [help group](./cli-options.md#help-group-options), [input](./cli-options.md#input-options), [jvm](./cli-options.md#jvm-options), [logging](./cli-options.md#logging-options), [markdown](./cli-options.md#markdown-options), [python](./cli-options.md#python-options), [Scala.js](./cli-options.md#scalajs-options), [Scala Native](./cli-options.md#scala-native-options), [scalac](./cli-options.md#scalac-options), [scalac extra](./cli-options.md#scalac-extra-options), [shared](./cli-options.md#shared-options), [snippet](./cli-options.md#snippet-options), [source generator](./cli-options.md#source-generator-options), [suppress warning](./cli-options.md#suppress-warning-options), [verbosity](./cli-options.md#verbosity-options), [version](./cli-options.md#version-options), [workspace](./cli-options.md#workspace-options) + ## fmt Aliases: `format`, `scalafmt`