diff options
Diffstat (limited to 'src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala')
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala | 109 |
1 files changed, 97 insertions, 12 deletions
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala index e3c94505ab..6b24c0f568 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/IndexScript.scala @@ -1,16 +1,22 @@ /* NSC -- new Scala compiler - * Copyright 2007-2013 LAMP/EPFL - * @author David Bernard, Manohar Jonnalagedda + * Copyright 2007-2016 LAMP/EPFL + * @author David Bernard, Manohar Jonnalagedda, Felix Mulder */ -package scala.tools.nsc.doc.html.page +package scala.tools.nsc.doc +package html +package page import scala.tools.nsc.doc import scala.tools.nsc.doc.model.{Package, DocTemplateEntity} import scala.tools.nsc.doc.html.{Page, HtmlFactory} -import scala.util.parsing.json.{JSONObject, JSONArray} +import scala.util.parsing.json.{JSONObject, JSONArray, JSONType} + +class IndexScript(universe: doc.Universe) extends Page { + import model._ + import scala.tools.nsc.doc.base.comment.Text + import scala.collection.immutable.Map -class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { def path = List("index.js") override def writeFor(site: HtmlFactory) { @@ -24,19 +30,32 @@ class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { case (pack, templates) => { val merged = mergeByQualifiedName(templates) - val ary = merged.keys.toList.sortBy(_.toLowerCase).map(key => { - val pairs = merged(key).map( - t => kindToString(t) -> relativeLinkTo(t) - ) :+ ("name" -> key) + val ary = merged.keys.toList.sortBy(_.toLowerCase).map { key => + /** One pair is generated for the class/trait and one for the + * companion object, both will have the same {"name": key} + * + * As such, we need to distinguish between the members that are + * generated by the object, and the members generated by the + * class/trait instance. Otherwise one of the member objects will be + * overwritten. + */ + val pairs = merged(key).flatMap { t: DocTemplateEntity => + val kind = kindToString(t) + Seq( + kind -> relativeLinkTo(t), + "kind" -> kind, + s"members_$kind" -> membersToJSON(t.members.filter(!_.isShadowedOrAmbiguousImplicit), t), + "shortDescription" -> shortDesc(t)) + } - JSONObject(scala.collection.immutable.Map(pairs : _*)) - }) + JSONObject(Map(pairs : _*) + ("name" -> key)) + } pack.qualifiedName -> JSONArray(ary) } }).toSeq - JSONObject(scala.collection.immutable.Map(pairs : _*)) + JSONObject(Map(pairs : _*)) } def mergeByQualifiedName(source: List[DocTemplateEntity]) = { @@ -66,4 +85,70 @@ class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { } }) : _*) } + + /** Gets the short description i.e. the first sentence of the docstring */ + def shortDesc(mbr: MemberEntity): String = mbr.comment.fold("") { c => + inlineToStr(c.short).replaceAll("\n", "") + } + + /** Returns the json representation of the supplied members */ + def membersToJSON(entities: List[MemberEntity], parent: DocTemplateEntity): JSONType = + JSONArray(entities map (memberToJSON(_, parent))) + + private def memberToJSON(mbr: MemberEntity, parent: DocTemplateEntity): JSONObject = { + /** This function takes a member and gets eventual parameters and the + * return type. For example, the definition: + * {{{ def get(key: A): Option[B] }}} + * Gets turned into: "(key: A): Option[B]" + */ + def memberTail: MemberEntity => String = { + case d: Def => d + .valueParams //List[List[ValueParam]] + .map { params => + params.map(p => p.name + ": " + p.resultType.name).mkString(", ") + } + .mkString("(", ")(", "): " + d.resultType.name) + case v: Val => ": " + v.resultType.name + case _ => "" + } + + /** This function takes a member entity and return all modifiers in a + * string, example: + * {{{ lazy val scalaProps: java.util.Properties }}} + * Gets turned into: "lazy val" + */ + def memberKindToString(mbr: MemberEntity): String = { + val kind = mbr.flags.map(_.text.asInstanceOf[Text].text).mkString(" ") + val space = if (kind == "") "" else " " + + kind + space + kindToString(mbr) + } + + /** This function turns a member entity into a JSON object that the index.js + * script can use to render search results + */ + def jsonObject(m: MemberEntity): JSONObject = + JSONObject(Map( + "label" -> "[^\\.]*\\.([^#]+#)?".r.replaceAllIn(m.definitionName, ""), // member name + "member" -> m.definitionName.replaceFirst("#", "."), // full member name + "tail" -> memberTail(m), + "kind" -> memberKindToString(m), // modifiers i.e. "abstract def" + "link" -> memberToUrl(m))) // permalink to the member + + mbr match { + case x @ (_: Def | _: Val | _: Object | _: AliasType) => jsonObject(x) + case e @ (_: Class | _: Trait) if parent.isRootPackage || !parent.isPackage => jsonObject(e) + case m: MemberEntity => + JSONObject(Map("member" -> m.definitionName, "error" -> "unsupported entity")) + } + } + + def memberToUrl(mbr: MemberEntity): String = { + val path = templateToPath(mbr.inTemplate).reverse.mkString("/") + s"$path#${mbr.signature}" + } +} + +object IndexScript { + def apply(universe: doc.Universe) = new IndexScript(universe) } |