Skip to content

Commit 7e7449b

Browse files
committed
Warn on output multiply set
1 parent 1ef6ad9 commit 7e7449b

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

compiler/src/dotty/tools/dotc/config/Settings.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,11 @@ object Settings:
146146
case arg :: rest =>
147147
val path = Directory(arg)
148148
val isJar = path.extension == "jar"
149-
if (!isJar && !path.isDirectory) fail(s"'$arg' does not exist or is not a directory or .jar file", rest)
149+
if !isJar && !path.isDirectory then fail(s"'$arg' does not exist or is not a directory or .jar file", rest)
150150
else
151-
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
152-
update(output, rest)
151+
val output = if isJar then JarArchive.create(path) else PlainDirectory(path)
152+
if changed && output != valueIn(sstate).asInstanceOf[AbstractFile] then update(output, rest).warn(s"Option $name was updated")
153+
else update(output, rest)
153154
case _ => missingArg
154155
case IntTag if argRest.nonEmpty => setInt(argRest, args)
155156
case IntTag =>

compiler/test/dotty/tools/dotc/SettingsTests.scala

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@ import reporting.StoreReporter
77
import vulpix.TestConfiguration
88

99
import core.Contexts.{Context, ContextBase}
10-
import dotty.tools.dotc.config.Settings._
10+
import dotty.tools.Useables.given
11+
import dotty.tools.dotc.config.Settings.*
1112
import dotty.tools.vulpix.TestConfiguration.mkClasspath
1213

13-
import java.nio.file._
14+
import java.nio.file.*, Files.*
1415

1516
import org.junit.Test
16-
import org.junit.Assert._
17+
import org.junit.Assert.*
1718

18-
class SettingsTests {
19+
import scala.util.Using
20+
21+
class SettingsTests:
1922

2023
@Test def missingOutputDir: Unit =
2124
val options = Array("-d", "not_here")
@@ -227,10 +230,25 @@ class SettingsTests {
227230
assertFalse("Multiple conflicting options is a warning", summary.warnings.isEmpty)
228231
assertTrue(summary.warnings.forall(_.contains("updated")))
229232

233+
@Test def `dir option also warns`: Unit =
234+
import java.nio.file.Paths
235+
import io.PlainFile, PlainFile.*
236+
val abc: PlainFile = Paths.get("a", "b", "c").toPlainFile
237+
object Settings extends SettingGroup:
238+
val option = OutputSetting("-option", "out", "A file", Paths.get("a", "b", "c").toPlainFile)
239+
Using.resource(createTempDirectory("i13887")) { dir =>
240+
val target = createDirectory(dir.resolve("x"))
241+
val mistake = createDirectory(dir.resolve("y"))
242+
val args = List("-option", target.toString, "-option", mistake.toString)
243+
val summary = Settings.processArguments(args, processAll = true)
244+
assertTrue("Multiple options is not an error", summary.errors.isEmpty)
245+
assertFalse("Multiple conflicting options is a warning", summary.warnings.isEmpty)
246+
assertTrue(summary.warnings.forall(_.contains("updated")))
247+
}
248+
230249
// use the supplied summary for evaluating settings
231250
private def withProcessedArgs(summary: ArgsSummary)(f: SettingsState ?=> Unit) = f(using summary.sstate)
232251

233252
// evaluate a setting using only a SettingsState (instead of a full-blown Context)
234253
extension [T](setting: Setting[T])
235254
private def value(using ss: SettingsState): T = setting.valueIn(ss)
236-
}

compiler/test/dotty/tools/utils.scala

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import java.nio.file.{Files, Path => JPath}
1111
import scala.io.Source
1212
import scala.jdk.StreamConverters._
1313
import scala.reflect.ClassTag
14-
import scala.util.Using.resource
14+
import scala.util.Using.{Releasable, resource}
1515
import scala.util.chaining.given
1616
import scala.util.control.{ControlThrowable, NonFatal}
1717

@@ -35,6 +35,24 @@ def withFile[T](file: File)(action: Source => T): T = resource(Source.fromFile(f
3535
def readLines(f: File): List[String] = withFile(f)(_.getLines.toList)
3636
def readFile(f: File): String = withFile(f)(_.mkString)
3737

38+
// Make common types useable with Using.
39+
object Useables:
40+
import java.io.IOException
41+
import java.nio.file.{FileVisitResult, SimpleFileVisitor}, FileVisitResult.{CONTINUE => Continue}
42+
import java.nio.file.attribute.*
43+
import scala.util.Properties
44+
45+
// delete the result of createTempDirectory
46+
given Releasable[JPath] with
47+
override def release(released: JPath) = if (!Properties.isWin) remove(released)
48+
private def remove(path: JPath): Unit = if Files.isDirectory(path) then removeRecursively(path) else Files.delete(path)
49+
private def removeRecursively(path: JPath): Unit = Files.walkFileTree(path, ZappingFileVisitor())
50+
private class ZappingFileVisitor extends SimpleFileVisitor[JPath]:
51+
private def zap(path: JPath) = { Files.delete(path) ; Continue }
52+
override def postVisitDirectory(path: JPath, e: IOException): FileVisitResult = if e != null then throw e else zap(path)
53+
override def visitFile(path: JPath, attrs: BasicFileAttributes): FileVisitResult = zap(path)
54+
end Useables
55+
3856
private object Unthrown extends ControlThrowable
3957

4058
def assertThrows[T <: Throwable: ClassTag](p: T => Boolean)(body: => Any): Unit =
@@ -68,4 +86,4 @@ def toolArgsParse(lines: List[String]): List[String] = {
6886
// but avoid picking up comments like "% scalac ./a.scala" and "$ scalac a.scala"
6987
}.map(stripped).headOption
7088
args.map(dotc.config.CommandLineParser.tokenize).getOrElse(Nil)
71-
}
89+
}

0 commit comments

Comments
 (0)