21

我正在尝试将 JDK 中的类链接到 scaladoc 生成的文档中。我使用了-doc-external-docscaladoc 2.10.1 的选项,但没有成功。

我正在使用-doc-external-doc:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar#http://docs.oracle.com/javase/7/docs/api/,但我得到了链接,例如index.html#java.io.File而不是index.html?java/io/File.html. 似乎此选项仅适用于 scaladoc 生成的文档。

我错过了 scaladoc 中的选项还是应该填写功能请求?

我已将 sbt 配置如下:

 scalacOptions in (Compile,doc) += "-doc-external-doc:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar#http://docs.oracle.com/javase/7/docs/api"

注意:我已经Opts.doc.externalAPI在即将发布的 sbt 0.13 中看到了该 util。我认为一个很好的补充(不确定是否可能)是通过 aModuleID而不是 a File。该 util 将找出哪个文件对应于ModuleID.

4

2 回答 2

7

我使用 sbt 0.13.5。

没有开箱即用的方法来具有在 scaladoc 中具有 Javadoc 链接的功能。根据我的理解,这不是 sbt 的错,而是 scaladoc 的工作方式。正如Josh在他的评论中指出的那样,您应该向 scaladoc 报告。

然而,我想出了一个解决方法——对生成的docscaladoc 进行后处理,以便替换 Java URL 以形成正确的 Javadoc 链接。

文件scaladoc.sbt应该放在 sbt 项目中,每当doc任务执行时,通过fixJavaLinksTask任务的后处理就会启动。

注意有很多硬编码的路径,所以请谨慎使用(也就是你认为合适的抛光)。

import scala.util.matching.Regex.Match

autoAPIMappings := true

// builds -doc-external-doc
apiMappings += (
    file("/Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/rt.jar") -> 
    url("http://docs.oracle.com/javase/8/docs/api")
)

lazy val fixJavaLinksTask = taskKey[Unit](
    "Fix Java links - replace #java.io.File with ?java/io/File.html"
)

fixJavaLinksTask := {
  println("Fixing Java links")
  val t = (target in (Compile, doc)).value
  (t ** "*.html").get.filter(hasJavadocApiLink).foreach { f => 
    println("fixing " + f)
    val newContent = javadocApiLink.replaceAllIn(IO.read(f), fixJavaLinks)
    IO.write(f, newContent)
  }
}

val fixJavaLinks: Match => String = m =>
    m.group(1) + "?" + m.group(2).replace(".", "/") + ".html"

val javadocApiLink = """\"(http://docs\.oracle\.com/javase/8/docs/api/index\.html)#([^"]*)\"""".r

def hasJavadocApiLink(f: File): Boolean = (javadocApiLink findFirstIn IO.read(f)).nonEmpty

fixJavaLinksTask <<= fixJavaLinksTask triggeredBy (doc in Compile)
于 2014-08-01T00:10:08.347 回答
6

我接受了@jacek-laskowski 的答案并对其进行了修改,以避免硬编码字符串,并且可以用于任意数量的 Java 库,而不仅仅是标准库。

编辑:现在的位置rt.jar是从运行时使用确定的,sun.boot.class.path并且不必进行硬编码。

您唯一需要修改的是地图,我externalJavadocMap在下面调用了它:

import scala.util.matching.Regex
import scala.util.matching.Regex.Match

val externalJavadocMap = Map(
  "owlapi" -> "http://owlcs.github.io/owlapi/apidocs_4_0_2/index.html"
)

/*
 * The rt.jar file is located in the path stored in the sun.boot.class.path system property.
 * See the Oracle documentation at http://docs.oracle.com/javase/6/docs/technotes/tools/findingclasses.html.
 */
val rtJar: String = System.getProperty("sun.boot.class.path").split(java.io.File.pathSeparator).collectFirst {
  case str: String if str.endsWith(java.io.File.separator + "rt.jar") => str
}.get // fail hard if not found

val javaApiUrl: String = "http://docs.oracle.com/javase/8/docs/api/index.html"

val allExternalJavadocLinks: Seq[String] = javaApiUrl +: externalJavadocMap.values.toSeq

def javadocLinkRegex(javadocURL: String): Regex = ("""\"(\Q""" + javadocURL + """\E)#([^"]*)\"""").r

def hasJavadocLink(f: File): Boolean = allExternalJavadocLinks exists {
  javadocURL: String => 
    (javadocLinkRegex(javadocURL) findFirstIn IO.read(f)).nonEmpty
}

val fixJavaLinks: Match => String = m =>
  m.group(1) + "?" + m.group(2).replace(".", "/") + ".html"

/* You can print the classpath with `show compile:fullClasspath` in the SBT REPL.
 * From that list you can find the name of the jar for the managed dependency.
 */
lazy val documentationSettings = Seq(
  apiMappings ++= {
    // Lookup the path to jar from the classpath
    val classpath = (fullClasspath in Compile).value
    def findJar(nameBeginsWith: String): File = {
      classpath.find { attributed: Attributed[File] => (attributed.data ** s"$nameBeginsWith*.jar").get.nonEmpty }.get.data // fail hard if not found
    }
    // Define external documentation paths
    (externalJavadocMap map {
      case (name, javadocURL) => findJar(name) -> url(javadocURL)
    }) + (file(rtJar) -> url(javaApiUrl))
  },
  // Override the task to fix the links to JavaDoc
  doc in Compile <<= (doc in Compile) map {
    target: File =>
      (target ** "*.html").get.filter(hasJavadocLink).foreach { f => 
        //println(s"Fixing $f.")
        val newContent: String = allExternalJavadocLinks.foldLeft(IO.read(f)) {
          case (oldContent: String, javadocURL: String) =>
            javadocLinkRegex(javadocURL).replaceAllIn(oldContent, fixJavaLinks)
        }
        IO.write(f, newContent)
      }
      target
  }
)

我正在使用 SBT 0.13.8。

于 2015-07-09T16:17:32.877 回答