From e51f88f65e9e14b3a1f6bca37e02507b76484822 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Thu, 8 Aug 2024 22:08:09 +0200 Subject: [PATCH 1/4] GenIdea: unroll module dependencies Since IDEA 2024.2, module dependencies in the `.iml` files are no longer interpreted transitively. Therefore, we need to unroll all transitive module dependencies when generating the project files. Fix https://github.com/com-lihaoyi/mill/issues/3354 --- idea/src/mill/idea/GenIdeaImpl.scala | 22 ++++++++++++------- .../ide/gen-idea/repo/hello-idea/build.sc | 17 ++++++++++++-- .../hello-idea/idea/mill_modules/modulea.iml | 12 ++++++++++ .../hello-idea/idea/mill_modules/moduleb.iml | 13 +++++++++++ .../hello-idea/idea/mill_modules/modulec.iml | 15 +++++++++++++ .../hello-idea/idea/mill_modules/moduled.iml | 15 +++++++++++++ .../hello-idea/idea/mill_modules/modulee.iml | 12 ++++++++++ .../gen-idea/repo/hello-idea/idea/modules.xml | 5 +++++ 8 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulea.iml create mode 100644 integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduleb.iml create mode 100644 integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulec.iml create mode 100644 integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduled.iml create mode 100644 integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulee.iml diff --git a/idea/src/mill/idea/GenIdeaImpl.scala b/idea/src/mill/idea/GenIdeaImpl.scala index f82e776aef7..3a53387d442 100755 --- a/idea/src/mill/idea/GenIdeaImpl.scala +++ b/idea/src/mill/idea/GenIdeaImpl.scala @@ -543,14 +543,20 @@ case class GenIdeaImpl( val libNames = Strict.Agg.from(sanizedDeps).iterator.toSeq - val depNames = Strict.Agg - .from(mod.moduleDeps.map((_, None)) ++ - mod.compileModuleDeps.map((_, Some("PROVIDED")))) - .filter(!_._1.skipIdea) - .map { case (v, s) => ScopedOrd(moduleName(moduleLabels(v)), s) } - .iterator - .toSeq - .distinct + val depNames = { + val allTransitive = mod.transitiveModuleCompileModuleDeps + val recursive = mod.recursiveModuleDeps + val provided = allTransitive.filterNot(recursive.contains) + + Strict.Agg + .from(recursive.map((_, None)) ++ + provided.map((_, Some("PROVIDED")))) + .filter(!_._1.skipIdea) + .map { case (v, s) => ScopedOrd(moduleName(moduleLabels(v)), s) } + .iterator + .toSeq + .distinct + } val isTest = mod.isInstanceOf[TestModule] diff --git a/integration/ide/gen-idea/repo/hello-idea/build.sc b/integration/ide/gen-idea/repo/hello-idea/build.sc index 7002dfc5a8f..df6d0d3b8dd 100644 --- a/integration/ide/gen-idea/repo/hello-idea/build.sc +++ b/integration/ide/gen-idea/repo/hello-idea/build.sc @@ -2,7 +2,7 @@ import mill.api.Loose.Agg import mill.define.Target import mill._ import mill.scalajslib.ScalaJSModule -import mill.scalalib.{Dep, DepSyntax, TestModule} +import mill.scalalib.{Dep, DepSyntax, JavaModule, TestModule} trait HelloIdeaModule extends scalalib.ScalaModule { def scalaVersion = "2.12.5" @@ -39,4 +39,17 @@ object HelloIdeaJs extends ScalaJSModule { ivy"com.lihaoyi::utest::0.8.4" ) } -} \ No newline at end of file +} + +object moduleA extends JavaModule +object moduleB extends JavaModule { + override def moduleDeps = Seq(moduleA) +} +object moduleC extends JavaModule { + override def moduleDeps = Seq(moduleB) + override def compileModuleDeps = Seq(moduleE) +} +object moduleD extends JavaModule { + override def compileModuleDeps = Seq(moduleC) +} +object moduleE extends JavaModule diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulea.iml b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulea.iml new file mode 100644 index 00000000000..7ed61b811eb --- /dev/null +++ b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulea.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduleb.iml b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduleb.iml new file mode 100644 index 00000000000..0b3311ac04b --- /dev/null +++ b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduleb.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulec.iml b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulec.iml new file mode 100644 index 00000000000..0ebb17da544 --- /dev/null +++ b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulec.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduled.iml b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduled.iml new file mode 100644 index 00000000000..da9278c171b --- /dev/null +++ b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/moduled.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulee.iml b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulee.iml new file mode 100644 index 00000000000..e8fb6ec88df --- /dev/null +++ b/integration/ide/gen-idea/repo/hello-idea/idea/mill_modules/modulee.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml b/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml index dbb4e87d0ab..3953d7d59f6 100644 --- a/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml +++ b/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml @@ -8,6 +8,11 @@ + + + + + From ed681b31eb8b33b21f2635af01d0ee42b5baa41e Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Fri, 9 Aug 2024 07:46:10 +0200 Subject: [PATCH 2/4] Add test case to catch duplicated items, and fixed the impl --- integration/ide/gen-idea/repo/hello-idea/build.sc | 4 ++++ integration/ide/gen-idea/repo/hello-idea/idea/modules.xml | 1 + scalalib/src/mill/scalalib/internal/ModuleUtils.scala | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/integration/ide/gen-idea/repo/hello-idea/build.sc b/integration/ide/gen-idea/repo/hello-idea/build.sc index df6d0d3b8dd..626a2280c27 100644 --- a/integration/ide/gen-idea/repo/hello-idea/build.sc +++ b/integration/ide/gen-idea/repo/hello-idea/build.sc @@ -53,3 +53,7 @@ object moduleD extends JavaModule { override def compileModuleDeps = Seq(moduleC) } object moduleE extends JavaModule +object moduleF extends JavaModule { + override def compileModuleDeps = Seq(moduleC) + override def moduleDeps = Seq(moduleB, moduleA) +} \ No newline at end of file diff --git a/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml b/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml index 3953d7d59f6..03f2710184e 100644 --- a/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml +++ b/integration/ide/gen-idea/repo/hello-idea/idea/modules.xml @@ -13,6 +13,7 @@ + diff --git a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala index dc991285ea6..6b3c67120d7 100644 --- a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala +++ b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala @@ -36,7 +36,8 @@ object ModuleUtils { throw new BuildScriptException(msg) } rec( - seenModules ++ Seq(cand), + if (seenModules.contains(cand)) seenModules + else { seenModules ++ Seq(cand) }, toAnalyze = ((cand :: trace, deps(cand).toList)) :: (trace, remaining) :: rest ) } From 88dcf68eec844fbde7cea44d0a01f7e5131f41d0 Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Fri, 9 Aug 2024 07:53:17 +0200 Subject: [PATCH 3/4] Added fixme comments and ported fix to copy-and-paste location --- scalalib/src/mill/scalalib/internal/ModuleUtils.scala | 3 +++ scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala index 6b3c67120d7..9213b03b6d9 100644 --- a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala +++ b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala @@ -15,6 +15,9 @@ object ModuleUtils { (module.millModuleShared.value.getOrElse(Segments()) ++ module.millModuleSegments).render } + // FIXME: Remove the Type restriction T <: Module + // although it makes sense in this context, the function is useful in other contexts as well + // FIMXE: Remove or consolidate with copy in ZincModuleImpl def recursive[T <: Module](name: String, start: T, deps: T => Seq[T]): Seq[T] = { @tailrec def rec( diff --git a/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala b/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala index e255335fe79..9a8d730bab8 100644 --- a/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala +++ b/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala @@ -669,7 +669,8 @@ object ZincWorkerImpl { throw sys.error(msg) } rec( - seenModules ++ Seq(cand), + if (seenModules.contains(cand)) seenModules + else { seenModules ++ Seq(cand) }, toAnalyze = ((cand :: trace, deps(cand).toList)) :: (trace, remaining) :: rest ) } From 064f193da9f900d89c4eb373a22c2cacf29fb72c Mon Sep 17 00:00:00 2001 From: Tobias Roeser Date: Fri, 9 Aug 2024 08:07:04 +0200 Subject: [PATCH 4/4] . --- .../api/src/mill/scalalib/api/ZincWorkerUtil.scala | 1 - .../src/mill/scalalib/internal/ModuleUtils.scala | 14 +++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/scalalib/api/src/mill/scalalib/api/ZincWorkerUtil.scala b/scalalib/api/src/mill/scalalib/api/ZincWorkerUtil.scala index 21848502cc0..699506c1a39 100644 --- a/scalalib/api/src/mill/scalalib/api/ZincWorkerUtil.scala +++ b/scalalib/api/src/mill/scalalib/api/ZincWorkerUtil.scala @@ -2,7 +2,6 @@ package mill.scalalib.api import mill.api.Loose.Agg import mill.api.PathRef -import mill.scalalib.api.Versions import scala.util.matching.Regex trait ZincWorkerUtil { diff --git a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala index 9213b03b6d9..54d9f82ae1c 100644 --- a/scalalib/src/mill/scalalib/internal/ModuleUtils.scala +++ b/scalalib/src/mill/scalalib/internal/ModuleUtils.scala @@ -15,10 +15,18 @@ object ModuleUtils { (module.millModuleShared.value.getOrElse(Segments()) ++ module.millModuleSegments).render } - // FIXME: Remove the Type restriction T <: Module - // although it makes sense in this context, the function is useful in other contexts as well + /** + * Find all dependencies. + * The result contains `start` and all its transitive dependencies provided by `deps`, + * but does not contain duplicates. + * If it detects a cycle, it throws an exception with a meaningful message containing the cycle trace. + * @param name The nane is used in the exception message only + * @param start the start element + * @param deps A function provided the direct dependencies + * @throws BuildScriptException if there were cycles in the dependencies + */ // FIMXE: Remove or consolidate with copy in ZincModuleImpl - def recursive[T <: Module](name: String, start: T, deps: T => Seq[T]): Seq[T] = { + def recursive[T](name: String, start: T, deps: T => Seq[T]): Seq[T] = { @tailrec def rec( seenModules: List[T],