-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add unidoc directive for markdowns #24563
Changes from all commits
b7e7509
4161175
662e2bc
ad9843d
28824b6
7d41a33
d8d1214
ad4ec77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright (C) 2016-2018 Lightbend Inc. <https://www.lightbend.com> | ||
*/ | ||
|
||
package akka | ||
|
||
import _root_.io.github.lukehutch.fastclasspathscanner.FastClasspathScanner | ||
import com.lightbend.paradox.markdown._ | ||
import com.lightbend.paradox.sbt.ParadoxPlugin.autoImport._ | ||
import org.pegdown.Printer | ||
import org.pegdown.ast._ | ||
import sbt.Keys._ | ||
import sbt._ | ||
|
||
import scala.collection.JavaConverters._ | ||
|
||
object ParadoxSupport { | ||
val paradoxWithCustomDirectives = Seq( | ||
paradoxDirectives ++= Def.taskDyn { | ||
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( | ||
{ _: Writer.Context ⇒ new UnidocDirective(allClasses) } | ||
)} | ||
}.value | ||
) | ||
|
||
class UnidocDirective(allClasses: IndexedSeq[String]) extends InlineDirective("unidoc") { | ||
def render(node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = { | ||
if (node.label.split('[')(0).contains('.')) { | ||
val fqcn = node.label | ||
if (allClasses.contains(fqcn)) { | ||
val label = fqcn.split('.').last | ||
syntheticNode("java", javaLabel(label), fqcn, node).accept(visitor) | ||
syntheticNode("scala", label, fqcn, node).accept(visitor) | ||
} else { | ||
throw new java.lang.IllegalStateException(s"fqcn not found by @unidoc[$fqcn]") | ||
} | ||
} | ||
else { | ||
renderByClassName(node.label, node, visitor, printer) | ||
} | ||
} | ||
|
||
def javaLabel(label: String): String = | ||
label.replaceAll("\\[", "<").replaceAll("\\]", ">").replace('_', '?') | ||
|
||
def syntheticNode(group: String, label: String, fqcn: String, node: DirectiveNode): DirectiveNode = { | ||
val syntheticSource = new DirectiveNode.Source.Direct(fqcn) | ||
val attributes = new org.pegdown.ast.DirectiveAttributes.AttributeMap() | ||
new DirectiveNode(DirectiveNode.Format.Inline, group, null, null, attributes, null, | ||
new DirectiveNode(DirectiveNode.Format.Inline, group + "doc", label, syntheticSource, node.attributes, fqcn, | ||
new TextNode(label) | ||
)) | ||
} | ||
|
||
def renderByClassName(label: String, node: DirectiveNode, visitor: Visitor, printer: Printer): Unit = { | ||
val label = node.label.replaceAll("\\\\_", "_") | ||
val labelWithoutGenericParameters = label.split("\\[")(0) | ||
val labelWithJavaGenerics = javaLabel(label) | ||
val matches = allClasses.filter(_.endsWith('.' + labelWithoutGenericParameters)) | ||
matches.size match { | ||
case 0 => | ||
throw new java.lang.IllegalStateException(s"No matches found for $label") | ||
case 1 if matches(0).contains("adsl") => | ||
throw new java.lang.IllegalStateException(s"Match for $label only found in one language: ${matches(0)}") | ||
case 1 => | ||
syntheticNode("scala", label, matches(0), node).accept(visitor) | ||
syntheticNode("java", labelWithJavaGenerics, matches(0), node).accept(visitor) | ||
case 2 if matches.forall(_.contains("adsl")) => | ||
matches.foreach(m => { | ||
if (!m.contains("javadsl")) | ||
syntheticNode("scala", label, m, node).accept(visitor) | ||
if (!m.contains("scaladsl")) | ||
syntheticNode("java", labelWithJavaGenerics, m, node).accept(visitor) | ||
}) | ||
case n => | ||
throw new java.lang.IllegalStateException( | ||
s"$n matches found for @unidoc[$label], but not javadsl/scaladsl: ${matches.mkString(", ")}. " + | ||
s"You may want to use the fully qualified class name as @unidoc[fqcn] instead of @unidoc[${label}]." | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error message is like:
|
||
) | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is copied from akka/akka-http#1579 removing unnecessary stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What unnecessary stuff could be removed? can we also remove it over there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary stuff was removed in 4161175 - unused parameters, and
case 2
in the pattern match could be handled bycase n
.As we are making the new sbt plugin anyway, we don't need to do the same in akka-http? However, if the plugin takes too much time, yes I'll do that in akka-http.