Skip to content

Commit

Permalink
Add check for right Tests traits in ScalaJS and Native (#2874)
Browse files Browse the repository at this point in the history
## Motivation

People get confused when they do things like:
```scala
import mill._
import mill.scalalib._
import mill.scalajslib._

object root extends ScalaJSModule {
  def scalaVersion: T[String] = "3.3.1"
  def scalaJSVersion: T[String] = "1.14.0"
  object test extends ScalaTests with TestModule.Utest
}
```

which doesn't work since we need to extend `ScalaJSTests` instead of
`ScalaTests`.
Now we crash with an exception:
```
[build.sc] [49/53] compile 
[info] compiling 1 Scala source to /Users/lorenzo/scala/repro/out/mill-build/compile.dest/classes ...
[info] done compiling
[build.sc] [53/53] methodCodeHashSignatures 
mill.api.MillException: root is a `ScalaJSModule`. root.test needs to extend `ScalaJSTests`.
    mill.scalalib.ScalaModule$ScalaTests.$init$(ScalaModule.scala:37)
    millbuild.build$root$test$.<init>(build.sc:8)
    millbuild.build$root$.test$lzycompute$1(build.sc:30)
    millbuild.build$root$.test(build.sc:30)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.base/java.lang.reflect.Method.invoke(Method.java:566)
    mill.resolve.ResolveCore$.$anonfun$resolveDirectChildren0$10(ResolveCore.scala:272)
```

Pull Request: #2874

---------

Co-authored-by: Tobias Roeser <le.petit.fou@web.de>
  • Loading branch information
lolgab and lefou authored Nov 15, 2023
1 parent b6240a9 commit e93f6bd
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
31 changes: 31 additions & 0 deletions scalajslib/test/src/mill/scalajslib/ScalaTestsErrorTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package mill.scalajslib

import mill._
import mill.define.Discover
import mill.scalalib.TestModule
import mill.util.TestUtil
import utest._

object ScalaTestsErrorTests extends TestSuite {
object ScalaTestsError extends TestUtil.BaseModule {
object scalaTestsError extends ScalaJSModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_3_3_VERSION", ???)
def scalaJSVersion = sys.props.getOrElse("TEST_SCALAJS_VERSION", ???)
object test extends ScalaTests with TestModule.Utest
}

override lazy val millDiscover = Discover[this.type]
}

def tests: Tests = Tests {
test("extends-ScalaTests") {
val error = intercept[ExceptionInInitializerError] {
ScalaTestsError.scalaTestsError.test
}
val message = error.getCause.getMessage
assert(
message == s"scalaTestsError is a `ScalaJSModule`. scalaTestsError.test needs to extend `ScalaJSTests`."
)
}
}
}
33 changes: 32 additions & 1 deletion scalalib/src/mill/scalalib/ScalaModule.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package mill
package scalalib

import mill.api.{DummyInputStream, JarManifest, PathRef, Result, SystemStreams, internal}
import mill.api.{
DummyInputStream,
JarManifest,
MillException,
PathRef,
Result,
SystemStreams,
internal
}
import mill.main.BuildInfo
import mill.util.{Jvm, Util}
import mill.util.Jvm.createJar
Expand All @@ -20,6 +28,29 @@ trait ScalaModule extends JavaModule with TestModule.ScalaModuleBase { outer =>
type ScalaModuleTests = ScalaTests

trait ScalaTests extends JavaModuleTests with ScalaModule {
try {
if (
Class.forName("mill.scalajslib.ScalaJSModule").isInstance(outer) && !Class.forName(
"mill.scalajslib.ScalaJSModule$ScalaJSTests"
).isInstance(this)
) throw new MillException(
s"$outer is a `ScalaJSModule`. $this needs to extend `ScalaJSTests`."
)
} catch {
case _: ClassNotFoundException => // if we can't find the classes, we certainly are not in a ScalaJSModule
}
try {
if (
Class.forName("mill.scalanativelib.ScalaNativeModule").isInstance(outer) && !Class.forName(
"mill.scalanativelib.ScalaNativeModule$ScalaNativeTests"
).isInstance(this)
) throw new MillException(
s"$outer is a `ScalaNativeModule`. $this needs to extend `ScalaNativeTests`."
)
} catch {
case _: ClassNotFoundException => // if we can't find the classes, we certainly are not in a ScalaNativeModule
}

override def scalaOrganization: Target[String] = outer.scalaOrganization()
override def scalaVersion: Target[String] = outer.scalaVersion()
override def scalacPluginIvyDeps: Target[Agg[Dep]] = outer.scalacPluginIvyDeps()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package mill.scalanativelib

import mill._
import mill.define.Discover
import mill.scalalib.TestModule
import mill.util.TestUtil
import utest._

object ScalaTestsErrorTests extends TestSuite {
object ScalaTestsError extends TestUtil.BaseModule {
object scalaTestsError extends ScalaNativeModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_3_3_VERSION", ???)
def scalaNativeVersion = sys.props.getOrElse("TEST_SCALANATIVE_VERSION", ???)
object test extends ScalaTests with TestModule.Utest
}

override lazy val millDiscover = Discover[this.type]
}

def tests: Tests = Tests {
test("extends-ScalaTests") {
val error = intercept[ExceptionInInitializerError] {
ScalaTestsError.scalaTestsError.test
}
val message = error.getCause.getMessage
assert(
message == s"scalaTestsError is a `ScalaNativeModule`. scalaTestsError.test needs to extend `ScalaNativeTests`."
)
}
}
}

0 comments on commit e93f6bd

Please # to comment.