Skip to content

Commit e2a9823

Browse files
committed
Warn on output multiply set
1 parent 7a5ea25 commit e2a9823

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
@@ -145,10 +145,11 @@ object Settings:
145145
case arg :: rest =>
146146
val path = Directory(arg)
147147
val isJar = path.extension == "jar"
148-
if (!isJar && !path.isDirectory) fail(s"'$arg' does not exist or is not a directory or .jar file", rest)
148+
if !isJar && !path.isDirectory then fail(s"'$arg' does not exist or is not a directory or .jar file", rest)
149149
else
150-
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
151-
update(output, rest)
150+
val output = if isJar then JarArchive.create(path) else PlainDirectory(path)
151+
if changed && output != valueIn(sstate).asInstanceOf[AbstractFile] then update(output, rest).warn(s"Option $name was updated")
152+
else update(output, rest)
152153
case _ => missingArg
153154
case IntTag if argRest.nonEmpty => setInt(argRest, args)
154155
case IntTag =>

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

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

77
import core.Contexts.{Context, ContextBase}
8-
import dotty.tools.dotc.config.Settings._
8+
import dotty.tools.Useables.given
9+
import dotty.tools.dotc.config.Settings.*
910
import dotty.tools.vulpix.TestConfiguration.mkClasspath
1011

11-
import java.nio.file._
12+
import java.nio.file.*, Files.*
1213

1314
import org.junit.Test
14-
import org.junit.Assert._
15+
import org.junit.Assert.*
1516

16-
class SettingsTests {
17+
import scala.util.Using
18+
19+
class SettingsTests:
1720

1821
@Test def missingOutputDir: Unit =
1922
val options = Array("-d", "not_here")
@@ -225,10 +228,25 @@ class SettingsTests {
225228
assertFalse("Multiple conflicting options is a warning", summary.warnings.isEmpty)
226229
assertTrue(summary.warnings.forall(_.contains("updated")))
227230

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

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

compiler/test/dotty/tools/utils.scala

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

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

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

3856
def assertThrows[T <: Throwable: ClassTag](p: T => Boolean)(body: => Any): Unit =
@@ -66,4 +84,4 @@ def toolArgsParse(lines: List[String]): List[String] = {
6684
// but avoid picking up comments like "% scalac ./a.scala" and "$ scalac a.scala"
6785
}.map(stripped).headOption
6886
args.map(dotc.config.CommandLineParser.tokenize).getOrElse(Nil)
69-
}
87+
}

0 commit comments

Comments
 (0)