Skip to content

Commit c0fa032

Browse files
committed
feat: add support for the Mill build tool
This PR adds in support for the Mill build tool by utilizing https://github.com/ckipp01/mill-scip. It's a pretty thin wrapper. You can find more details about mill-scip in the repo but the general workflow is: - It's an external Mill plugin that gathers everything needed to do a compile via Mill, but then adds some extra plugins/scalacOptions to ensure semanticDB gets produced - Once produced it uses `scip-java` as a library to actually produce the scip file. The plugin isn't actually a dependency here which ensures we don't have any cyclical dependency on anything, but rather just utilizes the `--import` functionality of Mill and external plugins. I'll leave a couple more comments on various parts of the PR. _NOTE_ This only currently supports Scala and Scala 3 projects. There are some issues with Java projects which will need some upstream work. You can track that in com-lihaoyi/mill#1983. Refs #306
1 parent 9a98c50 commit c0fa032

File tree

5 files changed

+154
-4
lines changed

5 files changed

+154
-4
lines changed

build.sbt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ lazy val V =
2222
def semanticdbKotlinc = "0.2.0"
2323
def testcontainers = "0.39.3"
2424
def requests = "0.6.5"
25+
def minimalMillVersion = "0.10.3"
26+
def millScipVersion = "0.2.2"
2527
}
2628

2729
inThisBuild(
@@ -166,7 +168,9 @@ lazy val cli = project
166168
"scala213" -> V.scala213,
167169
"scala3" -> V.scala3,
168170
"bloopVersion" -> V.bloop,
169-
"bspVersion" -> V.bsp
171+
"bspVersion" -> V.bsp,
172+
"minimalMillVersion" -> V.minimalMillVersion,
173+
"millScipVersion" -> V.millScipVersion
170174
),
171175
buildInfoPackage := "com.sourcegraph.scip_java",
172176
libraryDependencies ++=

docs/getting-started.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ free to subscribe to the tracking issues to receive updates on your build tool.
243243
| Ant |||| [sourcegraph/scip-java#305](https://github.com/sourcegraph/scip-java/issues/305) |
244244
| Bazel |||| |
245245
| Buck |||| [sourcegraph/scip-java#99](https://github.com/sourcegraph/scip-java/issues/99) |
246-
| Mill || || [sourcegraph/scip-java#306](https://github.com/sourcegraph/scip-java/issues/306) |
246+
| Mill || ||
247247

248248
****: automatic indexing is fully supported. Please report a bug if the
249249
`scip-java index` command does not work on your codebase.
@@ -292,13 +292,23 @@ The following Maven integrations are not yet supported:
292292

293293
### sbt
294294

295-
The `scip-java index` build should be able to automatically index most Maven
295+
The `scip-java index` build should be able to automatically index most sbt
296296
projects, with the following caveats:
297297

298298
| Integration | Supported | Recommendation |
299299
| ------------- | --------- | ----------------------- |
300300
| sbt <v0.13.17 || Upgrade to sbt v0.13.17 |
301301

302+
### Mill
303+
304+
The `scip-java index` build should be able to automatically index most Mill
305+
projects, with the following caveats:
306+
307+
| Integration | Supported | Recommendation |
308+
| ------------- | --------- | -------------------------- |
309+
| Mill <v0.10.3 || Upgrade to Mill >= v0.10.3 |
310+
311+
302312
### Bazel
303313

304314
Bazel is supported by scip-java but it requires custom configuration to work

scip-java/src/main/scala/com/sourcegraph/scip_java/buildtools/BuildTool.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ object BuildTool {
2424
new GradleBuildTool(index),
2525
new MavenBuildTool(index),
2626
new ScipBuildTool(index),
27-
new SbtBuildTool(index)
27+
new SbtBuildTool(index),
28+
new MillBuildTool(index)
2829
)
2930
def allNames: String =
3031
all(IndexCommand()).filterNot(_.isHidden).map(_.name).mkString(", ")
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.sourcegraph.scip_java.buildtools
2+
3+
import java.nio.file.Files
4+
import java.nio.file.StandardCopyOption
5+
6+
import scala.jdk.CollectionConverters._
7+
8+
import com.sourcegraph.scip_java.commands.IndexCommand
9+
import com.sourcegraph.scip_java.BuildInfo
10+
11+
class MillBuildTool(index: IndexCommand) extends BuildTool("mill", index) {
12+
13+
override def usedInCurrentDirectory(): Boolean =
14+
Files.isRegularFile(index.workingDirectory.resolve("build.sc"))
15+
16+
override def generateScip(): Int =
17+
millVersion() match {
18+
case Some(version) if isSupportedMillVersion(version) =>
19+
unconditionallyGenerateScip()
20+
case Some(version) =>
21+
failFast(
22+
s"Unsupported Mill version '${version}'. " +
23+
s"To fix this problem, upgrade Mill to at least ${minimalMillVersion} and try again."
24+
)
25+
case None =>
26+
failFast(
27+
s"No Mill version detected. " +
28+
s"To fix this problem, run the following command and try again: " +
29+
s"echo '${minimalMillVersion}' >> .mill-version"
30+
)
31+
}
32+
33+
private def failFast(message: String): Int = {
34+
index.app.error(message)
35+
1
36+
}
37+
38+
private def unconditionallyGenerateScip(): Int = {
39+
val localMill = Files.isRegularFile(millFile)
40+
val command =
41+
if (localMill) {
42+
"./mill"
43+
} else {
44+
"mill"
45+
}
46+
val millProcess = index.process(
47+
List(
48+
command,
49+
"--import",
50+
s"ivy:io.chris-kipp::mill-scip::${BuildInfo.millScipVersion}",
51+
"io.kipp.mill.scip.Scip/generate"
52+
)
53+
)
54+
val scipFile = index
55+
.workingDirectory
56+
.resolve("out")
57+
.resolve("io")
58+
.resolve("kipp")
59+
.resolve("mill")
60+
.resolve("scip")
61+
.resolve("Scip")
62+
.resolve("generate.dest")
63+
.resolve("index.scip")
64+
65+
if (millProcess.exitCode == 0 && Files.isRegularFile(scipFile)) {
66+
val output = index.workingDirectory.resolve("index.scip")
67+
Files.copy(scipFile, output, StandardCopyOption.REPLACE_EXISTING)
68+
index.app.info(output.toString)
69+
}
70+
millProcess.exitCode
71+
}
72+
73+
private lazy val minimalMillVersion = BuildInfo.minimalMillVersion
74+
75+
private lazy val millFile = index.workingDirectory.resolve("mill")
76+
77+
private def isSupportedMillVersion(version: String): Boolean =
78+
if (version.startsWith("0.1"))
79+
true
80+
else
81+
false
82+
83+
/**
84+
* Try to grab the Mill version from the .mill-version file. If not found we
85+
* fall back to the mill file which could be the official mill launcher or the
86+
* millw launcher renamed as mill, both which will have a DEFAULT_MILL_VERSION
87+
* line.
88+
*/
89+
private def millVersion(): Option[String] = {
90+
val millVersionFile = index.workingDirectory.resolve(".mill-version")
91+
if (Files.isRegularFile(millVersionFile)) {
92+
Files.readAllLines(millVersionFile).asScala.headOption
93+
} else if (Files.isRegularFile(millFile)) {
94+
Files
95+
.readAllLines(millFile)
96+
.asScala
97+
.find(_.startsWith("DEFAULT_MILL_VERSION"))
98+
.map(line => line.dropWhile(!_.isDigit))
99+
} else {
100+
None
101+
}
102+
}
103+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package tests
2+
3+
class MillBuildToolSuite extends BaseBuildToolSuite {
4+
checkBuild(
5+
s"minimal",
6+
s"""|/.mill-version
7+
|0.10.5
8+
|/build.sc
9+
|import mill._, scalalib._
10+
|object minimal extends ScalaModule {
11+
| def scalaVersion = "2.13.8"
12+
| object test extends Tests with TestModule.Munit {
13+
| def ivyDeps = Agg(ivy"org.scalameta::munit:1.0.0-M6")
14+
| }
15+
|}
16+
|/minimal/src/Main.scala
17+
|package minimal
18+
|object Main extends App
19+
|/minimal/test/src/MainSuite.scala
20+
|package minimal
21+
|class MainSpec extends munit.FunSuite {
22+
| test("numbers") {
23+
| assertEquals(1, 1)
24+
| }
25+
|}
26+
|""".stripMargin,
27+
expectedSemanticdbFiles = 2,
28+
expectedPackages =
29+
"""|maven:munit:munit:1.0.0-M6
30+
|""".stripMargin
31+
)
32+
}

0 commit comments

Comments
 (0)