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 index ac98304b4f..7ce7639101 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/fix/Fix.scala @@ -68,9 +68,11 @@ object Fix extends ScalaCommand[FixOptions] { val projectFileContents = new StringBuilder() + given LoggingUtilities(logger, inputs.workspace) + // Deal with directives from the Main scope { - val originalMainDirectives = getExtractedDirectives(mainSources, logger) + val originalMainDirectives = getExtractedDirectives(mainSources) .filterNot(hasTargetDirectives) val transformedMainDirectives = unifyCorrespondingNameAliases(originalMainDirectives) @@ -80,14 +82,16 @@ object Fix extends ScalaCommand[FixOptions] { directivesFromWritableMainInputs.foreach(d => removeDirectivesFrom(d.positions)) - projectFileContents.append("// Main") - .append(newLine) - val allDirectives = for { transformedMainDirective <- transformedMainDirectives directive <- transformedMainDirective.directives } yield directive + if (allDirectives.nonEmpty) + projectFileContents + .append("// Main") + .append(newLine) + allDirectives .flatMap(_.explodeToStrings) .distinct @@ -97,7 +101,7 @@ object Fix extends ScalaCommand[FixOptions] { // Deal with directives from the Test scope if (testSources.paths.nonEmpty || testSources.inMemory.nonEmpty) { - val originalTestDirectives = getExtractedDirectives(testSources, logger) + val originalTestDirectives = getExtractedDirectives(testSources) .filterNot(hasTargetDirectives) val transformedTestDirectives = unifyCorrespondingNameAliases(originalTestDirectives) @@ -130,20 +134,25 @@ object Fix extends ScalaCommand[FixOptions] { os.write.over(inputs.workspace / Constants.projectFileName, projectFileContents.toString) } - def getExtractedDirectives( - sources: Sources, - logger: Logger + def getExtractedDirectives(sources: Sources)( + using loggingUtilities: LoggingUtilities ): Seq[ExtractedDirectives] = { + val logger = loggingUtilities.logger + val fromPaths = sources.paths.map { (path, _) => val content = os.read(path).toCharArray + logger.debug(s"Extracting directives from ${loggingUtilities.relativePath(path)}") ExtractedDirectives.from(content, 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) => os.read(path).toCharArray + case Right(path) => + logger.debug(s"Extracting directives from ${loggingUtilities.relativePath(path)}") + os.read(path).toCharArray 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) @@ -215,11 +224,21 @@ object Fix extends ScalaCommand[FixOptions] { def removeDirectivesFrom( position: Option[Position.File], toKeep: Seq[StrictDirective] = Nil + )( + using loggingUtilities: LoggingUtilities ): Unit = { position match { case Some(Position.File(Right(path), _, _, offset)) => - val keepLines = toKeep.mkString("", newLine, newLine * 2) - val newContents = keepLines + os.read(path).drop(offset).stripLeading() + val keepLines = toKeep.mkString("", newLine, newLine * 2) + val newContents = keepLines + os.read(path).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 _ => () } @@ -230,4 +249,11 @@ object Fix extends ScalaCommand[FixOptions] { noTestPrefixAvailable: Seq[StrictDirective], positions: Option[Position.File] ) + + case class LoggingUtilities( + logger: Logger, + workspacePath: os.Path + ) { + def relativePath(path: os.Path) = path.relativeTo(workspacePath) + } } diff --git a/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala b/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala index 097fdb7a17..f41821c290 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/FixTests.scala @@ -8,6 +8,8 @@ class FixTests extends ScalaCliSuite { val projectFileName = "project.scala" + val extraOptions = Seq("--suppress-experimental-feature-warning") + test("fix basic") { val mainFileName = "Main.scala" val inputs = TestInputs( @@ -27,8 +29,15 @@ class FixTests extends ScalaCliSuite { ) inputs.fromRoot { root => - os.proc(TestUtil.cli, "--power", "fix", ".") - .call(cwd = root).out.trim() + + val fixOutput = os.proc(TestUtil.cli, "--power", "fix", ".", "-v", "-v", extraOptions) + .call(cwd = root, mergeErrIntoOut = true).out.trim() + + expect(fixOutput == + """Extracting directives from Main.scala + |Extracting directives from project.scala + |Removing directives from Main.scala + |Removing directives from project.scala""".stripMargin) val projectFileContents = os.read(root / projectFileName) val mainFileContents = os.read(root / mainFileName) @@ -50,7 +59,7 @@ class FixTests extends ScalaCliSuite { |} |""".stripMargin) - val runProc = os.proc(TestUtil.cli, "--power", "compile", ".") + 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")) @@ -90,8 +99,17 @@ class FixTests extends ScalaCliSuite { ) inputs.fromRoot { root => - os.proc(TestUtil.cli, "--power", "fix", ".") - .call(cwd = root).out.trim() + + val fixOutput = os.proc(TestUtil.cli, "--power", "fix", ".", "-v", "-v", extraOptions) + .call(cwd = root, mergeErrIntoOut = true).out.trim() + + expect(fixOutput == + """Extracting directives from project.scala + |Extracting directives from src/Main.scala + |Removing directives from project.scala + |Removing directives from src/Main.scala + |Extracting directives from test/MyTests.scala + |Removing directives from test/MyTests.scala""".stripMargin) val projectFileContents = os.read(root / projectFileName) val mainFileContents = os.read(root / mainSubPath) @@ -128,7 +146,7 @@ class FixTests extends ScalaCliSuite { |} |""".stripMargin) - val runProc = os.proc(TestUtil.cli, "--power", "compile", ".") + 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")) @@ -185,15 +203,30 @@ class FixTests extends ScalaCliSuite { ) inputs.fromRoot { root => - os.proc( + val res = os.proc( TestUtil.cli, "--power", "fix", ".", "--script-snippet", - "//> using toolkit latest" + "//> using toolkit latest", + "-v", + "-v", + extraOptions ).call(cwd = root, stderr = os.Pipe) + expect(res.err.trim() == + """Extracting directives from project.scala + |Extracting directives from src/Main.scala + |Extracting directives from src/UsedTarget.scala + |Extracting directives from snippet + |Removing directives from project.scala + |Removing directives from src/Main.scala + |Extracting directives from test/MyTests.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) @@ -238,7 +271,7 @@ class FixTests extends ScalaCliSuite { expect(withUsedTargetContents == withUsedTargetContentsRead) expect(withUnusedTargetContents == withUnusedTargetContentsRead) - val runProc = os.proc(TestUtil.cli, "--power", "compile", ".") + 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"))