Skip to content

Commit 288d9b4

Browse files
committed
Support doc task with dottydoc
1 parent 86c4e72 commit 288d9b4

File tree

5 files changed

+72
-55
lines changed

5 files changed

+72
-55
lines changed

project/Build.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,14 @@ object Build {
289289
compilerJar = jars.find(_.getName.startsWith("dotty-compiler_2.12")).get
290290
}
291291

292-
// All compiler dependencies except the library
293-
val otherDependencies = dependencyClasspath.in(`dotty-compiler`, Compile).value
294-
.filterNot(_.get(artifact.key).exists(_.name == "dotty-library"))
295-
.map(_.data)
292+
// All dotty-doc's and compiler's dependencies except the library.
293+
// (we get the compiler's dependencies because dottydoc depends on the compiler)
294+
val otherDependencies = {
295+
val excluded = Set("dotty-library", "dotty-compiler")
296+
fullClasspath.in(`dotty-doc`, Compile).value
297+
.filterNot(_.get(artifact.key).exists(a => excluded.contains(a.name)))
298+
.map(_.data)
299+
}
296300

297301
val allJars = libraryJar :: compilerJar :: otherDependencies.toList
298302
val classLoader = state.value.classLoaderCache(allJars)
@@ -785,7 +789,7 @@ object Build {
785789
description := "sbt compiler bridge for Dotty",
786790
resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api
787791
libraryDependencies ++= Seq(
788-
Dependencies.compilerInterface(sbtVersion.value),
792+
Dependencies.compilerInterface(sbtVersion.value) % Provided,
789793
(Dependencies.zincApiinfo(sbtVersion.value) % Test).withDottyCompat(scalaVersion.value)
790794
),
791795
// The sources should be published with crossPaths := false since they
@@ -1269,6 +1273,7 @@ object Build {
12691273
def asDottySbtBridge(implicit mode: Mode): Project = project.withCommonSettings.
12701274
disablePlugins(ScriptedPlugin).
12711275
dependsOn(dottyCompiler % Provided).
1276+
dependsOn(dottyDoc % Provided).
12721277
settings(dottySbtBridgeSettings)
12731278

12741279
def asDottyBench(implicit mode: Mode): Project = project.withCommonSettings.

sbt-bridge/src/xsbt/ScaladocInterface.scala

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,57 +7,27 @@ import xsbti.{ Logger, Severity }
77
import java.net.URL
88
import java.util.Optional
99

10+
import dotty.tools.dotc.core.Contexts.{ Context, ContextBase }
11+
import dotty.tools.dotc.reporting.Reporter
12+
1013
class ScaladocInterface {
11-
def run(args: Array[String], log: Logger, delegate: xsbti.Reporter) =
12-
(new DottydocRunner(args, log, delegate)).run()
14+
def run(args: Array[String], log: Logger, delegate: xsbti.Reporter) = {
15+
new DottydocRunner(args, log, delegate).run()
16+
}
1317
}
1418

1519
class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) {
16-
def run(): Unit = delegate.log(Problem(
17-
NoPosition,
18-
"""|The dotty sbt-bridge currently does not support doc generation directly
19-
|via sbt. Please see the dotty documentation at dotty.epfl.ch""".stripMargin,
20-
Severity.Error
21-
))
22-
23-
private[this] val NoPosition = new xsbti.Position {
24-
val line = Optional.empty[Integer]
25-
val lineContent = ""
26-
val offset = Optional.empty[Integer]
27-
val sourcePath = Optional.empty[String]
28-
val sourceFile = Optional.empty[java.io.File]
29-
val pointer = Optional.empty[Integer]
30-
val pointerSpace = Optional.empty[String]
31-
}
32-
33-
private def getStringSetting(name: String): Option[String] =
34-
args find (_.startsWith(name)) map (_.drop(name.length))
35-
36-
private def getOutputFolder(args: Array[String]): Option[String] =
37-
args sliding(2) find { case Array(x, _) => x == "-d" } map (_.tail.head.trim)
38-
39-
private def getTemplate(resources: List[URL]): Option[URL] =
40-
resources.find(_.getFile.endsWith("template.html"))
41-
42-
private def getResources(args: Array[String]): List[URL] = {
43-
val cp = args sliding (2) find { case Array(x, _) => x == "-classpath" } map (_.tail.head.trim) getOrElse ""
44-
45-
cp.split(":").find(_.endsWith("dottydoc-client.jar")).map { resourceJar =>
46-
import java.util.jar.JarFile
47-
val jarEntries = (new JarFile(resourceJar)).entries
48-
var entries: List[URL] = Nil
49-
50-
while (jarEntries.hasMoreElements) {
51-
val entry = jarEntries.nextElement()
52-
53-
if (!entry.isDirectory()) {
54-
val path = s"jar:file:$resourceJar!/${entry.getName}"
55-
val url = new URL(path)
56-
entries = url :: entries
57-
}
58-
}
59-
60-
entries
61-
} getOrElse (Nil)
20+
def run(): Unit = {
21+
log.debug(() => args.mkString("Calling Dottydoc with arguments (ScaladocInterface):\n\t", "\n\t", ""))
22+
23+
val ctx = (new ContextBase).initialCtx.fresh
24+
.setReporter(new DelegatingReporter(delegate))
25+
26+
val dottydocMainClass = Class.forName("dotty.tools.dottydoc.Main")
27+
val processMethod = dottydocMainClass.getMethod("process", classOf[Array[String]], classOf[Context])
28+
val reporter = processMethod.invoke(null, args, ctx).asInstanceOf[Reporter]
29+
if (reporter.hasErrors) {
30+
throw new InterfaceCompileFailed(args, Array())
31+
}
6232
}
6333
}

sbt-dotty/sbt-test/sbt-dotty/example-project/src/main/scala/hello/Hello.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
package hello
2+
/** Hello, world! */
23
object Hello {
34
def main(args: Array[String]): Unit = {
45
val dotty: Int | String = "dotty"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
> run
2+
> doc
23
> 'set initialCommands := "1 + 1" '
34
# FIXME: does not work on the CI
45
#> console

sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package dotty.tools.sbtplugin
22

33
import sbt._
44
import sbt.Keys._
5-
// import sbt.inc.{ ClassfileManager, IncOptions }
5+
import sbt.librarymanagement.DependencyResolution
6+
import sbt.internal.inc.ScalaInstance
67
import xsbti.compile._
8+
import java.net.URLClassLoader
79
import java.util.Optional
810

911
object DottyPlugin extends AutoPlugin {
@@ -151,6 +153,8 @@ object DottyPlugin extends AutoPlugin {
151153
scalaOrganization.value
152154
},
153155

156+
scalacOptions in (Compile, doc) ++= Seq("-project", name.value),
157+
154158
incOptions in Compile := {
155159
val inc = (incOptions in Compile).value
156160
if (isDotty.value)
@@ -174,7 +178,43 @@ object DottyPlugin extends AutoPlugin {
174178
scalaVersion.value.split("\\.").take(2).mkString(".")
175179
else
176180
scalaBinaryVersion.value
177-
}
181+
},
182+
183+
scalaInstance := Def.taskDyn {
184+
val si = scalaInstance.value
185+
if (isDotty.value) {
186+
Def.task {
187+
val dottydocArtifacts = fetchArtifactsOf("dotty-doc").value
188+
val includeArtifact = (f: File) => f.getName.endsWith(".jar")
189+
val dottydocJars = dottydocArtifacts.filter(includeArtifact).toArray
190+
val allJars = (si.allJars ++ dottydocJars).distinct
191+
val loader = new URLClassLoader(Path.toURLs(dottydocJars), si.loader)
192+
new ScalaInstance(si.version, loader, si.loaderLibraryOnly, si.libraryJar, si.compilerJar, allJars, si.explicitActual)
193+
}
194+
} else {
195+
Def.task { si }
196+
}
197+
}.value
178198
)
179199
}
200+
201+
/** Fetch artefacts for scalaOrganization.value %% moduleName % scalaVersion.value */
202+
private def fetchArtifactsOf(moduleName: String) = Def.task {
203+
val dependencyResolution = Keys.dependencyResolution.value
204+
val log = streams.value.log
205+
val scalaInfo = scalaModuleInfo.value
206+
val updateConfiguration = Keys.updateConfiguration.value
207+
val warningConfiguration = (unresolvedWarningConfiguration in update).value
208+
209+
val moduleID = (scalaOrganization.value %% moduleName % scalaVersion.value).cross(CrossVersion.binary)
210+
val descriptor = dependencyResolution.wrapDependencyInModule(moduleID, scalaInfo)
211+
212+
dependencyResolution.update(descriptor, updateConfiguration, warningConfiguration, log) match {
213+
case Right(report) =>
214+
report.allFiles
215+
case _ =>
216+
throw new MessageOnlyException(
217+
s"Couldn't retrieve `${scalaOrganization.value} %% $moduleName %% ${scalaVersion.value}`.")
218+
}
219+
}
180220
}

0 commit comments

Comments
 (0)