Skip to content

Commit e494aac

Browse files
committed
Support doc task with dottydoc
1 parent 61cba97 commit e494aac

File tree

5 files changed

+69
-53
lines changed

5 files changed

+69
-53
lines changed

project/Build.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,12 @@ object Build {
281281
}
282282

283283
// All compiler dependencies except the library
284-
val otherDependencies = dependencyClasspath.in(`dotty-compiler`, Compile).value
285-
.filterNot(_.get(artifact.key).exists(_.name == "dotty-library"))
286-
.map(_.data)
284+
val otherDependencies = {
285+
val excluded = Set("dotty-library", "dotty-compiler")
286+
fullClasspath.in(`dotty-doc`, Compile).value
287+
.filterNot(_.get(artifact.key).exists(a => excluded.contains(a.name)))
288+
.map(_.data)
289+
}
287290

288291
val allJars = libraryJar :: compilerJar :: otherDependencies.toList
289292
val classLoader = state.value.classLoaderCache(allJars)
@@ -769,7 +772,7 @@ object Build {
769772
description := "sbt compiler bridge for Dotty",
770773
resolvers += Resolver.typesafeIvyRepo("releases"), // For org.scala-sbt:api
771774
libraryDependencies ++= Seq(
772-
Dependencies.compilerInterface(sbtVersion.value),
775+
Dependencies.compilerInterface(sbtVersion.value) % Provided,
773776
(Dependencies.zincApiinfo(sbtVersion.value) % Test).withDottyCompat(scalaVersion.value)
774777
),
775778
// The sources should be published with crossPaths := false since they
@@ -1253,6 +1256,7 @@ object Build {
12531256
def asDottySbtBridge(implicit mode: Mode): Project = project.withCommonSettings.
12541257
disablePlugins(ScriptedPlugin).
12551258
dependsOn(dottyCompiler % Provided).
1259+
dependsOn(dottyDoc % Provided).
12561260
settings(dottySbtBridgeSettings)
12571261

12581262
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: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package dotty.tools.sbtplugin
22

33
import sbt._
44
import sbt.Keys._
5+
import sbt.librarymanagement.DependencyResolution
6+
import sbt.internal.inc.ScalaInstance
57
// import sbt.inc.{ ClassfileManager, IncOptions }
68
import xsbti.compile._
9+
import java.net.URLClassLoader
710
import java.util.Optional
811

912
object DottyPlugin extends AutoPlugin {
@@ -151,6 +154,8 @@ object DottyPlugin extends AutoPlugin {
151154
scalaOrganization.value
152155
},
153156

157+
scalacOptions in (Compile, doc) ++= Seq("-project", name.value),
158+
154159
incOptions in Compile := {
155160
val inc = (incOptions in Compile).value
156161
if (isDotty.value)
@@ -174,7 +179,42 @@ object DottyPlugin extends AutoPlugin {
174179
scalaVersion.value.split("\\.").take(2).mkString(".")
175180
else
176181
scalaBinaryVersion.value
177-
}
182+
},
183+
184+
scalaInstance := Def.taskDyn {
185+
val si = scalaInstance.value
186+
if (isDotty.value) {
187+
Def.task {
188+
val dottydocArtifacts = fetchArtifactsOf("dotty-doc").value
189+
val includeArtifact = (f: File) => f.getName.endsWith(".jar")
190+
val dottydocJars = dottydocArtifacts.filter(includeArtifact).toArray
191+
val allJars = (si.allJars ++ dottydocJars).distinct
192+
val loader = new URLClassLoader(Path.toURLs(dottydocJars), si.loader)
193+
new ScalaInstance(si.version, loader, si.loaderLibraryOnly, si.libraryJar, si.compilerJar, allJars, si.explicitActual)
194+
}
195+
} else {
196+
Def.task { si }
197+
}
198+
}.value
178199
)
179200
}
201+
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 Left(uw) =>
214+
throw new MessageOnlyException(
215+
s"Couldn't retrieve `${scalaOrganization.value} %% $moduleName %% {scalaVersion.value}`.")
216+
case Right(report) =>
217+
report.allFiles
218+
}
219+
}
180220
}

0 commit comments

Comments
 (0)