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

GenIdea improvements #3153

Merged
merged 6 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion idea/src/mill/idea/GenIdea.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object GenIdea extends ExternalModule {
def idea(allBootstrapEvaluators: Evaluator.AllBootstrapEvaluators): Command[Unit] = T.command {
try {
Result.Success(GenIdeaImpl(
evaluators = Evaluator.allBootstrapEvaluators.value.value
evaluators = allBootstrapEvaluators.value
).run())
} catch {
case GenIdeaImpl.GenIdeaException(m) => Result.Failure(m)
Expand Down
85 changes: 51 additions & 34 deletions idea/src/mill/idea/GenIdeaImpl.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mill.idea

import scala.collection.immutable
import scala.util.Try
import scala.util.{Success, Try}
import scala.xml.{Elem, MetaData, Node, NodeSeq, Null, UnprefixedAttribute}
import coursier.core.compatibility.xmlParseDom
import coursier.maven.Pom
Expand All @@ -15,16 +15,15 @@ import mill.scalalib.GenIdeaModule.{IdeaConfigFile, JavaFacet}
import mill.scalalib.internal.JavaModuleUtils
import mill.util.Classpath
import mill.{T, scalalib}
import os.{Path, SubPath}
import mill.scalalib.{GenIdeaImpl => _, _}

case class GenIdeaImpl(
private val evaluators: Seq[Evaluator]
)(implicit ctx: Ctx) {
import GenIdeaImpl._

val workDir: Path = evaluators.head.rootModule.millSourcePath
val ideaDir: Path = workDir / ".idea"
val workDir: os.Path = evaluators.head.rootModule.millSourcePath
val ideaDir: os.Path = workDir / ".idea"

val ideaConfigVersion = 4

Expand All @@ -34,7 +33,7 @@ case class GenIdeaImpl(
.getOrElse(("JDK_1_8", "1.8 (1)"))

ctx.log.info("Analyzing modules ...")
val layout: Seq[(SubPath, Node)] =
val layout: Seq[(os.SubPath, Node)] =
xmlFileLayout(evaluators, jdkInfo)

ctx.log.debug("Cleaning obsolete IDEA project files ...")
Expand Down Expand Up @@ -102,7 +101,7 @@ case class GenIdeaImpl(
// .toSeq
// .distinct

val buildLibraryPaths: immutable.Seq[Path] = {
val buildLibraryPaths: immutable.Seq[os.Path] = {
if (!fetchMillModules) Nil
else {
val moduleRepos = modulesByEvaluator.toSeq.flatMap { case (ev, modules) =>
Expand Down Expand Up @@ -197,7 +196,7 @@ case class GenIdeaImpl(
}

T.task {
val resolvedCp: Agg[Scoped[Path]] =
val resolvedCp: Agg[Scoped[os.Path]] =
externalDependencies().map(_.path).map(Scoped(_, None)) ++
extCompileIvyDeps()
.map(_.path)
Expand Down Expand Up @@ -251,14 +250,14 @@ case class GenIdeaImpl(

val moduleLabels = modules.map { case (s, m, e) => (m, s) }.toMap

val allResolved: Seq[Path] =
val allResolved: Seq[os.Path] =
(resolvedModules.flatMap(_.classpath).map(_.value) ++ buildLibraryPaths ++ buildDepsPaths)
.distinct
.sorted

val librariesProperties: Map[Path, Agg[Path]] =
val librariesProperties: Map[os.Path, Agg[os.Path]] =
resolvedModules
.flatMap(x => x.libraryClasspath.map(_ -> x.compilerClasspath))
.flatMap(rm => rm.libraryClasspath.map(_ -> rm.compilerClasspath))
.toMap

val (wholeFileConfigs, configFileContributions) =
Expand All @@ -267,20 +266,20 @@ case class GenIdeaImpl(
.partition(_.asWholeFile.isDefined)

// whole file
val ideaWholeConfigFiles: Seq[(SubPath, Elem)] =
val ideaWholeConfigFiles: Seq[(os.SubPath, Elem)] =
wholeFileConfigs.flatMap(_.asWholeFile).map { wf =>
os.sub / wf._1 -> ideaConfigElementTemplate(wf._2)
}

type FileComponent = (SubPath, Option[String])
type FileComponent = (os.SubPath, Option[String])

/** Ensure, the additional configs don't collide. */
def collisionFreeExtraConfigs(
confs: Seq[IdeaConfigFile]
): Map[SubPath, Seq[IdeaConfigFile]] = {
): Map[os.SubPath, Seq[IdeaConfigFile]] = {

var seen: Map[FileComponent, Seq[GenIdeaModule.Element]] = Map()
var result: Map[SubPath, Seq[IdeaConfigFile]] = Map()
var result: Map[os.SubPath, Seq[IdeaConfigFile]] = Map()
confs.foreach { conf =>
val key = conf.subPath -> conf.component
seen.get(key) match {
Expand All @@ -307,7 +306,7 @@ case class GenIdeaImpl(
result
}

val fileComponentContributions: Seq[(SubPath, Elem)] =
val fileComponentContributions: Seq[(os.SubPath, Elem)] =
collisionFreeExtraConfigs(configFileContributions).toSeq.map {
case (file, configs) =>
val map: Map[Option[String], Seq[GenIdeaModule.Element]] =
Expand Down Expand Up @@ -340,7 +339,7 @@ case class GenIdeaImpl(
type ArtifactAndVersion = (String, String)

def guessJarArtifactNameAndVersionFromPath(
path: Path
path: os.Path
): Option[ArtifactAndVersion] =
Try {
// in a local maven repo or a local Coursier repo,
Expand Down Expand Up @@ -444,7 +443,7 @@ case class GenIdeaImpl(
r + (key -> (r.getOrElse(key, Vector()) :+ q.module))
}

val fixedFiles: Seq[(SubPath, Elem)] = Seq(
val fixedFiles: Seq[(os.SubPath, Elem)] = Seq(
Tuple2(os.sub / "misc.xml", miscXmlTemplate(jdkInfo)),
Tuple2(os.sub / "scala_settings.xml", scalaSettingsTemplate()),
Tuple2(
Expand All @@ -471,7 +470,7 @@ case class GenIdeaImpl(
name.replaceAll("""[-.:]""", "_")
}

val libraries: Seq[(SubPath, Elem)] =
val libraries: Seq[(os.SubPath, Elem)] =
resolvedLibraries(allResolved).flatMap { resolved =>
val names = libraryNames(resolved)
val sources = resolved match {
Expand All @@ -481,7 +480,7 @@ case class GenIdeaImpl(
}
for (name <- names)
yield {
val compilerCp: Agg[Path] = librariesProperties.getOrElse(resolved.path, Agg.empty)
val compilerCp: Agg[os.Path] = librariesProperties.getOrElse(resolved.path, Agg.empty)
val languageLevel = name match {
case _ if compilerCp.iterator.isEmpty => None
case _ if name.startsWith("scala3-library_3-3.3.") => Some("Scala_3_3")
Expand Down Expand Up @@ -509,7 +508,7 @@ case class GenIdeaImpl(
}
}

val moduleFiles: Seq[(SubPath, Elem)] = resolvedModules.map {
val moduleFiles: Seq[(os.SubPath, Elem)] = resolvedModules.map {
case ResolvedModule(
path,
resolvedDeps,
Expand Down Expand Up @@ -557,7 +556,7 @@ case class GenIdeaImpl(

val sanizedDeps: Seq[ScopedOrd[String]] = {
resolvedDeps
.map((s: Scoped[Path]) => pathToLibName(s.value) -> s.scope)
.map((s: Scoped[os.Path]) => pathToLibName(s.value) -> s.scope)
.iterator
.toSeq
.groupBy(_._1)
Expand Down Expand Up @@ -727,31 +726,49 @@ case class GenIdeaImpl(
</module>
}

/** Try to make the file path a relative JAR URL (to PROJECT_DIR). */
/** Try to make the file path a relative JAR URL (to PROJECT_DIR or HOME_DIR). */
def relativeJarUrl(path: os.Path): String = {
// When coursier cache dir is on different logical drive than project dir
// we can not use a relative path. See issue: https://github.com/lihaoyi/mill/issues/905
val relPath = relForwardPath(path, "$PROJECT_DIR$/")
val relPath = relForwardPath(path)
if (path.ext == "jar") "jar://" + relPath + "!/" else "file://" + relPath
}

/** Try to make the file path a relative URL (to PROJECT_DIR). */
def relativeFileUrl(path: Path): String = {
/** Try to make the file path a relative URL (to PROJECT_DIR or HOME_DIR). */
def relativeFileUrl(path: os.Path): String = {
// When coursier cache dir is on different logical drive than project dir
// we can not use a relative path. See issue: https://github.com/lihaoyi/mill/issues/905
"file://" + relForwardPath(path, "$PROJECT_DIR$/")
"file://" + relForwardPath(path)
}

private def relForwardPath(path: os.Path, prefix: String): String = {
private val projectDir = (workDir, "$PROJECT_DIR$/")
private val homeDir = (os.home, "$USER_HOME$/")

private def relForwardPath(path: os.Path): String = {

def forward(p: os.FilePath): String = p.toString().replace("""\""", "/")
Try(prefix + forward(path.relativeTo(workDir))).getOrElse(forward(path))

val relToProjectDir = Try(projectDir._2 + forward(path.relativeTo(projectDir._1)))
val relToHomeDir = Try(homeDir._2 + forward(path.relativeTo(homeDir._1)))

(relToProjectDir, relToHomeDir) match {
// We seem to be outside of project-dir but inside home dir, so use releative path to home dir
case (Success(p1), Success(p2)) if p1.contains("..") && !p2.contains("..") => p2
// default to project-dir-relative
case (Success(p), _) => p
// if that fails, use home-dir-relative, which might fix cases on Windows
// where the home-dir is not on the same drive as the project-dir
case (_, Success(p)) => p
// Use the absolute path
case _ => forward(path)
}
}

def libraryXmlTemplate(
name: String,
path: os.Path,
sources: Option[os.Path],
scalaCompilerClassPath: Agg[Path],
scalaCompilerClassPath: Agg[os.Path],
languageLevel: Option[String]
): Elem = {
val isScalaLibrary = scalaCompilerClassPath.iterator.nonEmpty
Expand Down Expand Up @@ -990,15 +1007,15 @@ object GenIdeaImpl {

final case class ResolvedModule(
path: Segments,
classpath: Agg[Scoped[Path]],
classpath: Agg[Scoped[os.Path]],
module: JavaModule,
pluginClasspath: Agg[Path],
pluginClasspath: Agg[os.Path],
scalaOptions: Seq[String],
compilerClasspath: Agg[Path],
libraryClasspath: Agg[Path],
compilerClasspath: Agg[os.Path],
libraryClasspath: Agg[os.Path],
facets: Seq[JavaFacet],
configFileContributions: Seq[IdeaConfigFile],
compilerOutput: Path,
compilerOutput: os.Path,
evaluator: Evaluator
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<component name="libraryTable">
<library name="SBT: junit:junit_2.13:4.13.2:jar">
<CLASSES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2.jar!/"/>
</CLASSES>
<SOURCES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2-sources.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2-sources.jar!/"/>
</SOURCES>
</library>
</component>
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<component name="libraryTable">
<library name="SBT: org.scalameta:munit_2.13:0.7.29:jar">
<CLASSES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/org/scalameta/munit_2.13/0.7.29/munit_2.13-0.7.29.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scalameta/munit_2.13/0.7.29/munit_2.13-0.7.29.jar!/"/>
</CLASSES>
<SOURCES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/org/scalameta/munit_2.13/0.7.29/munit_2.13-0.7.29-sources.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scalameta/munit_2.13/0.7.29/munit_2.13-0.7.29-sources.jar!/"/>
</SOURCES>
</library>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<properties>
<language-level>Scala_2_13</language-level>
<compiler-classpath>
<root url="file://COURSIER_HOME/https/repo1.maven.org/maven2/net/java/dev/jna/jna/5.3.1/jna-5.3.1.jar"/>
<root url="file://COURSIER_HOME/https/repo1.maven.org/maven2/org/jline/jline/3.19.0/jline-3.19.0.jar"/>
<root url="file://COURSIER_HOME/https/repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.6/scala-compiler-2.13.6.jar"/>
<root url="file://COURSIER_HOME/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar"/>
<root url="file://COURSIER_HOME/https/repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.6/scala-reflect-2.13.6.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/net/java/dev/jna/jna/5.3.1/jna-5.3.1.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/jline/jline/3.19.0/jline-3.19.0.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.13.6/scala-compiler-2.13.6.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.13.6/scala-reflect-2.13.6.jar"/>
</compiler-classpath>
</properties>
<CLASSES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6.jar!/"/>
</CLASSES>
<SOURCES>
<root url="jar://COURSIER_HOME/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6-sources.jar!/"/>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.6/scala-library-2.13.6-sources.jar!/"/>
</SOURCES>
</library>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import mill.define.Target
import mill._
import mill.scalalib.{Dep, DepSyntax, TestModule}

trait HelloWorldModule extends scalalib.ScalaModule {
trait HelloIdeaModule extends scalalib.ScalaModule {
def scalaVersion = "2.12.5"
object test extends ScalaTests with TestModule.Utest {
override def compileIvyDeps: Target[Agg[Dep]] = Agg(
Expand All @@ -20,8 +20,8 @@ trait HelloWorldModule extends scalalib.ScalaModule {
}
}

object HelloWorld extends HelloWorldModule
object HelloIdea extends HelloIdeaModule

object HiddenWorld extends HelloWorldModule {
object HiddenIdea extends HelloIdeaModule {
override def skipIdea = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<component name="libraryTable">
<library name="scala-library-2.12.5.jar" type="Scala">
<properties>
<language-level>Scala_2_12</language-level>
<compiler-classpath>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/modules/scala-xml_2.12/1.0.6/scala-xml_2.12-1.0.6.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-compiler/2.12.5/scala-compiler-2.12.5.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.5/scala-library-2.12.5.jar"/>
<root url="file://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-reflect/2.12.5/scala-reflect-2.12.5.jar"/>
</compiler-classpath>
</properties>
<CLASSES>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.5/scala-library-2.12.5.jar!/"/>
</CLASSES>
<SOURCES>
<root url="jar://$USER_HOME$/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.5/scala-library-2.12.5-sources.jar!/"/>
</SOURCES>
</library>
</component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/../../out/HelloIdea/ideaCompileOutput.dest/classes"/>
<exclude-output/>
<content url="file://$MODULE_DIR$/../../HelloIdea">
<sourceFolder url="file://$MODULE_DIR$/../../HelloIdea/src" isTestSource="false"/>
<sourceFolder url="file://$MODULE_DIR$/../../HelloIdea/resources" type="java-resource"/>
</content>
<orderEntry type="inheritedJdk"/>
<orderEntry type="sourceFolder" forTests="false"/>
<orderEntry type="library" name="scala-library-2.12.5.jar" level="project"/>
</component>
</module>
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output-test url="file://$MODULE_DIR$/../../out/HelloWorld/test/ideaCompileOutput.dest/classes"/>
<output-test url="file://$MODULE_DIR$/../../out/HelloIdea/test/ideaCompileOutput.dest/classes"/>
<exclude-output/>
<content url="file://$MODULE_DIR$/../../HelloWorld/test">
<sourceFolder url="file://$MODULE_DIR$/../../HelloWorld/test/src" isTestSource="true"/>
<sourceFolder url="file://$MODULE_DIR$/../../HelloWorld/test/resources" type="java-test-resource"/>
<content url="file://$MODULE_DIR$/../../HelloIdea/test">
<sourceFolder url="file://$MODULE_DIR$/../../HelloIdea/test/src" isTestSource="true"/>
<sourceFolder url="file://$MODULE_DIR$/../../HelloIdea/test/resources" type="java-test-resource"/>
</content>
<orderEntry type="inheritedJdk"/>
<orderEntry type="sourceFolder" forTests="false"/>
Expand All @@ -13,6 +13,6 @@
<orderEntry type="library" name="logback-core-1.2.3.jar" level="project"/>
<orderEntry type="library" name="scala-library-2.12.5.jar" level="project"/>
<orderEntry type="library" name="slf4j-api-1.7.25.jar" level="project"/>
<orderEntry type="module" module-name="helloworld" exported=""/>
<orderEntry type="module" module-name="helloidea" exported=""/>
</component>
</module>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/mill_modules/helloworld.iml" filepath="$PROJECT_DIR$/.idea/mill_modules/helloworld.iml"/>
<module fileurl="file://$PROJECT_DIR$/.idea/mill_modules/helloworld.test.iml" filepath="$PROJECT_DIR$/.idea/mill_modules/helloworld.test.iml"/>
<module fileurl="file://$PROJECT_DIR$/.idea/mill_modules/helloidea.iml" filepath="$PROJECT_DIR$/.idea/mill_modules/helloidea.iml"/>
<module fileurl="file://$PROJECT_DIR$/.idea/mill_modules/helloidea.test.iml" filepath="$PROJECT_DIR$/.idea/mill_modules/helloidea.test.iml"/>
<module fileurl="file://$PROJECT_DIR$/.idea/mill_modules/mill-build.iml" filepath="$PROJECT_DIR$/.idea/mill_modules/mill-build.iml"/>
</modules>
</component>
Expand Down
Loading