2013-06-05 15 views
18

Sto provando a collegare le classi dal JDK al documento generato con lo scaladoc. Ho usato l'opzione -doc-external-doc di scaladoc 2.10.1 ma senza successo.Come collegare classi da JDK a documenti generati in scaladoc?

Sto usando -doc-external-doc:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar#http://docs.oracle.com/javase/7/docs/api/, ma ottengo collegamenti come index.html#java.io.File anziché index.html?java/io/File.html. Sembra che questa opzione funzioni solo per i documenti generati con lo scaladoc.

Ho perso un'opzione in scaladoc o devo compilare una richiesta di funzionalità?

Ho configurato SBT come segue:

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" 

Nota: Ho visto il Opts.doc.externalAPI util nel prossimo sbt 0,13. Penso che una bella aggiunta (non è sicuro se è possibile) sarebbe passare un ModuleID invece di un File. L'util capirebbe quale file corrisponde allo ModuleID.

+1

È necessario segnalare a scaladoc. – jsuereth

+0

Esiste una riga di comando per questo esterno sbt? Seguendo la risposta di @jsuereth, sbt passa semplicemente le opzioni a scaladoc e se non supporta la funzione, neanche SBT. –

risposta

7

Io uso sbt 0.13.5.

Non esiste un modo semplice per avere la funzionalità di avere collegamenti Javadoc all'interno di scaladoc. E come capisco, non è colpa di sbt, ma del modo in cui lo scaladoc funziona. Come Josh ha sottolineato nel suo commento You should report to scaladoc.

C'è però una soluzione mi è venuta - postprocess il doc scaladoc -Generata così gli URL Java vengono sostituiti per formare legami Javadoc adeguate.

Il file scaladoc.sbt deve essere collocato all'interno di un progetto di SBT e ogni volta che viene eseguito doc compito, la post-elaborazione tramite fixJavaLinksTask calci compito in.

NOTA Ci sono un sacco di percorsi hardcoded in modo da utilizzare con attenzione (alias esegui la lucidatura come ritieni opportuno).

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) 
6

ho preso la risposta @ Jacek-Laskowski e modificato in modo che esso evitare stringhe hard-coded e può essere utilizzato per qualsiasi numero di librerie Java, non solo quello standard.

Edit: la posizione del rt.jar è ora determinato dal runtime utilizzando sun.boot.class.path e non deve essere codificato duro.

L'unica cosa che è necessario modificare è la mappa, che ho chiamato externalJavadocMap nella seguente:

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 
    } 
) 

Sto usando SBT 0.13.8.

+0

Ho provato ad aggiungere il codice al mio file di build SBT, ma ancora sembra che ScaleDoc non trovi le classi JDK. Probabilmente ho fatto qualcosa di stupido - questo dovrebbe essere aggiunto a build.sbt, giusto? –

+1

Sì, dovrebbe essere aggiunto a 'build.sbt'. Qual è il valore di 'System.getProperty (" sun.boot.class.path ")'?È possibile controllare digitando 'console' da SBT REPL per accedere a Scala REPL. Funzionano su Windows o Linux o Mac? Ricevi avvisi quando esegui il task 'doc'? –

+1

@Hawk Forse, cosa più importante, hai aggiunto 'documentationSettings' alle impostazioni del tuo progetto? Ad esempio, qualcosa come 'lazy val myProject = (project in file (" myProject ")). Settings (documentationSettings: _ *)' in 'build.sbt'. –