Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pure JavaModules #155

Merged
merged 12 commits into from
May 30, 2024
7 changes: 6 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,12 @@ trait itestCross extends MillIntegrationTestModule with Cross.Module[String] {
TestInvocation.Targets(Seq("prepare")),
TestInvocation.Targets(Seq("verify")),
TestInvocation.Targets(Seq("verifyFail"), expectedExitCode = 1)
)
),
PathRef(testBase / "java") -> Seq(
TestInvocation.Targets(Seq("prepare")),
TestInvocation.Targets(Seq("verify"), expectedExitCode = 1)
),

)
}
}
26 changes: 26 additions & 0 deletions itest/src/java/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import mill._

import mill.scalalib._
import mill.scalalib.publish._
import $file.plugins
import com.github.lolgab.mill.mima._

trait Common extends JavaModule with PublishModule {
def publishVersion = "0.0.1"
def pomSettings =
PomSettings("", organization = "org", "", Seq(), VersionControl(), Seq())
}
object prev extends Common
object curr extends Common with Mima {
override def mimaPreviousArtifacts = T(Agg(ivy"org:prev:0.0.1"))
override def mimaCheckDirection = CheckDirection.Backward
}

def prepare() = T.command {
prev.publishLocal(sys.props("ivy.home") + "/local")()
}

def verify() = T.command {
curr.mimaReportBinaryIssues()()
()
}
2 changes: 2 additions & 0 deletions itest/src/java/curr/src/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
public class Main {
}
5 changes: 5 additions & 0 deletions itest/src/java/prev/src/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class Main {
public static String hello() {
return "Hello world!";
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.github.lolgab.mill.mima.worker.api;

public interface MimaWorkerApi {
java.util.Optional<String> reportBinaryIssues(
String scalaBinaryVersion,
String reportBinaryIssues(
String scalaBinaryVersionOrNull,
java.util.function.Consumer<String> logDebug,
java.util.function.Consumer<String> logError,
java.util.function.Consumer<String> logPrintln,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import scala.jdk.CollectionConverters._
class MimaWorkerImpl extends MimaWorkerApi {

def reportBinaryIssues(
scalaBinaryVersion: String,
scalaBinaryVersionOrNull: String,
logDebug: java.util.function.Consumer[String],
logError: java.util.function.Consumer[String],
logPrintln: java.util.function.Consumer[String],
Expand All @@ -25,8 +25,8 @@ class MimaWorkerImpl extends MimaWorkerApi {
forwardFilters: java.util.Map[String, Array[ProblemFilter]],
excludeAnnos: Array[String],
publishVersion: String
): java.util.Optional[String] = {
sanityCheckScalaBinaryVersion(scalaBinaryVersion)
): String = {
sanityCheckScalaBinaryVersion(scalaBinaryVersionOrNull)

val mimaLib = new MiMaLib(runClasspath.toSeq)

Expand Down Expand Up @@ -74,12 +74,10 @@ class MimaWorkerImpl extends MimaWorkerApi {
if (problemsCount > 0) {
val filteredNote =
if (filteredCount > 0) s" (filtered $filteredCount)" else ""
java.util.Optional.of(
s"Failed binary compatibility check! Found $problemsCount potential problems$filteredNote"
)
s"Failed binary compatibility check! Found $problemsCount potential problems$filteredNote"
} else {
logPrintln.accept("Binary compatibility check passed")
java.util.Optional.empty()
null
}
}

Expand All @@ -91,12 +89,14 @@ class MimaWorkerImpl extends MimaWorkerApi {
s" * $desc$howToFilter"
}

private def sanityCheckScalaBinaryVersion(scalaBinaryVersion: String) = {
scalaBinaryVersion match {
case "2.11" | "2.12" | "2.13" | "3" => // ok
case _ =>
private def sanityCheckScalaBinaryVersion(
scalaBinaryVersionOrNull: String
) = {
scalaBinaryVersionOrNull match {
case "3" | "2.13" | "2.12" | "2.11" | null => // ok
case other =>
throw new IllegalArgumentException(
s"MiMa supports Scala 2.11, 2.12, 2.13 and 3, not $scalaBinaryVersion"
s"MiMa supports Scala 2.11, 2.12, 2.13 and 3, not $other"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import mill.api.Result
import mill.define.Task
import mill.scalalib._

import scala.util.chaining._

private[mima] trait ExtraCoursierSupport
extends CoursierModule
with ScalaModule {
private[mima] trait ExtraCoursierSupport extends CoursierModule {

/** Resolves each dependency independently.
*
Expand All @@ -27,18 +23,14 @@ private[mima] trait ExtraCoursierSupport
deps: Task[Agg[Dep]]
): Task[Agg[(Dep, Agg[PathRef])]] = T.task {
val pRepositories = repositoriesTask()
val bind = bindDependency()
val pDeps = deps()
val scalaV = scalaVersion()
pDeps.map { dep =>
val Result.Success(resolved) = Lib.resolveDependencies(
repositories = pRepositories,
deps = Agg(dep).map(dep =>
Lib
.depToBoundDep(dep, scalaV)
.tap(dependency =>
dependency.copy(dep = dependency.dep.withTransitive(false))
)
),
deps = Agg(dep)
.map(bind)
.map(dep => dep.copy(dep = dep.dep.withTransitive(false))),
ctx = Some(implicitly[mill.api.Ctx.Log])
)
(dep, resolved)
Expand Down
138 changes: 73 additions & 65 deletions mill-mima/src/com/github/lolgab/mill/mima/MimaBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import scala.jdk.CollectionConverters._
import scala.util.chaining._

private[mima] trait MimaBase
extends ScalaModule
extends JavaModule
with PublishModule
with ExtraCoursierSupport
with VersionSpecific {
Expand Down Expand Up @@ -113,72 +113,80 @@ private[mima] trait MimaBase
*/
def mimaCurrentArtifact: T[PathRef] = T { jar() }

def mimaReportBinaryIssues(): Command[Unit] = T.command {
def prettyDep(dep: Dep): String = {
s"${dep.dep.module.orgName}:${dep.dep.version}"
def mimaReportBinaryIssues(): Command[Unit] = {
val scalaBinVersionOrNullTask: Task[Option[String]] = this match {
case m: ScalaModule =>
T.task { Some(scalaBinaryVersion(m.scalaVersion())) }
case _ => T.task { None }
}
val log = T.ctx().log
val logDebug: java.util.function.Consumer[String] = log.debug(_)
val logError: java.util.function.Consumer[String] = log.error(_)
val logPrintln: java.util.function.Consumer[String] =
log.outputStream.println(_)
val runClasspathIO =
runClasspath().view.map(_.path).filter(os.exists).map(_.toIO).toArray
val current = mimaCurrentArtifact().path.pipe {
case p if os.exists(p) => p
case _ => (T.dest / "emptyClasses").tap(os.makeDir)
}.toIO

val previous = resolvedMimaPreviousArtifacts().iterator.map {
case (dep, artifact) =>
new worker.api.Artifact(prettyDep(dep), artifact.path.toIO)
}.toArray

val checkDirection = mimaCheckDirection() match {
case CheckDirection.Forward => worker.api.CheckDirection.Forward
case CheckDirection.Backward => worker.api.CheckDirection.Backward
case CheckDirection.Both => worker.api.CheckDirection.Both
}

def toWorkerApi(p: ProblemFilter) =
new worker.api.ProblemFilter(p.name, p.problem)

val incompatibleSignatureProblemFilters =
if (mimaReportSignatureProblems()) Seq.empty
else Seq(ProblemFilter.exclude[IncompatibleSignatureProblem]("*"))
val binaryFilters =
(mimaBinaryIssueFilters() ++ incompatibleSignatureProblemFilters)
.map(toWorkerApi)
.toArray
val backwardFilters =
mimaBackwardIssueFilters().view
.mapValues(_.map(toWorkerApi).toArray)
.toMap
.asJava
val forwardFilters =
mimaForwardIssueFilters().view
.mapValues(_.map(toWorkerApi).toArray)
.toMap
.asJava

val errorOpt: java.util.Optional[String] = mimaWorker().reportBinaryIssues(
scalaBinaryVersion(scalaVersion()),
logDebug,
logError,
logPrintln,
checkDirection,
runClasspathIO,
previous,
current,
binaryFilters,
backwardFilters,
forwardFilters,
mimaExcludeAnnotations().toArray,
publishVersion()
)
T.command {
def prettyDep(dep: Dep): String = {
s"${dep.dep.module.orgName}:${dep.dep.version}"
}
val log = T.ctx().log
val logDebug: java.util.function.Consumer[String] = log.debug(_)
val logError: java.util.function.Consumer[String] = log.error(_)
val logPrintln: java.util.function.Consumer[String] =
log.outputStream.println(_)
val runClasspathIO =
runClasspath().view.map(_.path).filter(os.exists).map(_.toIO).toArray
val current = mimaCurrentArtifact().path.pipe {
case p if os.exists(p) => p
case _ => (T.dest / "emptyClasses").tap(os.makeDir)
}.toIO

val previous = resolvedMimaPreviousArtifacts().iterator.map {
case (dep, artifact) =>
new worker.api.Artifact(prettyDep(dep), artifact.path.toIO)
}.toArray

val checkDirection = mimaCheckDirection() match {
case CheckDirection.Forward => worker.api.CheckDirection.Forward
case CheckDirection.Backward => worker.api.CheckDirection.Backward
case CheckDirection.Both => worker.api.CheckDirection.Both
}

def toWorkerApi(p: ProblemFilter) =
new worker.api.ProblemFilter(p.name, p.problem)

val incompatibleSignatureProblemFilters =
if (mimaReportSignatureProblems()) Seq.empty
else Seq(ProblemFilter.exclude[IncompatibleSignatureProblem]("*"))
val binaryFilters =
(mimaBinaryIssueFilters() ++ incompatibleSignatureProblemFilters)
.map(toWorkerApi)
.toArray
val backwardFilters =
mimaBackwardIssueFilters().view
.mapValues(_.map(toWorkerApi).toArray)
.toMap
.asJava
val forwardFilters =
mimaForwardIssueFilters().view
.mapValues(_.map(toWorkerApi).toArray)
.toMap
.asJava

val errorOrNull: String =
mimaWorker().reportBinaryIssues(
scalaBinVersionOrNullTask().orNull,
logDebug,
logError,
logPrintln,
checkDirection,
runClasspathIO,
previous,
current,
binaryFilters,
backwardFilters,
forwardFilters,
mimaExcludeAnnotations().toArray,
publishVersion()
)

if (errorOpt.isPresent()) Result.Failure(errorOpt.get())
else Result.Success(())
if (errorOrNull == null) Result.Success(())
else Result.Failure(errorOrNull)
}
}

}
Loading