Adds support for the signature directive to the paradox configuration

(copied from the akka-http configuration)
This commit is contained in:
Luc Bourlier 2018-04-18 09:03:58 +00:00 committed by Arnout Engelen
parent d86730e001
commit 7b29b08d46
24 changed files with 165 additions and 112 deletions

View file

@ -4,6 +4,8 @@
package akka
import java.io.{File, FileNotFoundException}
import _root_.io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
import com.lightbend.paradox.markdown._
import com.lightbend.paradox.sbt.ParadoxPlugin.autoImport._
@ -12,16 +14,22 @@ import org.pegdown.ast._
import sbt.Keys._
import sbt._
import scala.io.{Codec, Source}
import scala.collection.JavaConverters._
object ParadoxSupport {
val paradoxWithCustomDirectives = Seq(
paradoxDirectives ++= Def.taskDyn {
val log = streams.value.log
val classpath = (fullClasspath in Compile).value.files.map(_.toURI.toURL).toArray
val classloader = new java.net.URLClassLoader(classpath, this.getClass().getClassLoader())
lazy val scanner = new FastClasspathScanner("akka").addClassLoader(classloader).scan()
val allClasses = scanner.getNamesOfAllClasses.asScala.toVector
Def.task { Seq(
{ context: Writer.Context
new SignatureDirective(context.location.tree.label, context.properties, msg log.warn(msg))
},
{ _: Writer.Context new UnidocDirective(allClasses) }
)}
}.value
@ -84,4 +92,47 @@ object ParadoxSupport {
}
}
}
class SignatureDirective(page: Page, variables: Map[String, String], logWarn: String => Unit) extends LeafBlockDirective("signature") {
def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit =
try {
val labels = node.attributes.values("identifier").asScala.map(_.toLowerCase())
val source = node.source match {
case direct: DirectiveNode.Source.Direct => direct.value
case _ => sys.error("Source references are not supported")
}
val file =
if (source startsWith "$") {
val baseKey = source.drop(1).takeWhile(_ != '$')
val base = new File(PropertyUrl(s"signature.$baseKey.base_dir", variables.get).base.trim)
val effectiveBase = if (base.isAbsolute) base else new File(page.file.getParentFile, base.toString)
new File(effectiveBase, source.drop(baseKey.length + 2))
} else new File(page.file.getParentFile, source)
val Signature = """\s*((def|val|type) (\w+)(?=[:(\[]).*)(\s+\=.*)""".r // stupid approximation to match a signature
//println(s"Looking for signature regex '$Signature'")
val text =
Source.fromFile(file)(Codec.UTF8).getLines.collect {
case line@Signature(signature, kind, l, definition) if labels contains l.toLowerCase() =>
//println(s"Found label '$l' with sig '$full' in line $line")
if (kind == "type") signature + definition
else signature
}.mkString("\n")
if (text.trim.isEmpty) {
logWarn(
s"Did not find any signatures with one of those names [${labels.mkString(", ")}] in ${node.source} " +
s"(was referenced from [${page.path}])")
new HtmlBlockNode(s"""<div style="color: red;">[Broken signature inclusion [${labels.mkString(", ")}] to [${node.source}]</div>""").accept(visitor)
} else {
val lang = Option(node.attributes.value("type")).getOrElse(Snippet.language(file))
new VerbatimNode(text, lang).accept(visitor)
}
} catch {
case e: FileNotFoundException =>
throw new SnipDirective.LinkException(s"Unknown snippet [${e.getMessage}] referenced from [${page.path}]")
}
}
}