diff --git a/doc-tool/resources/_includes/sidebar.html b/doc-tool/resources/_includes/sidebar.html
index aa1a6fe0440b..24f0292538e5 100644
--- a/doc-tool/resources/_includes/sidebar.html
+++ b/doc-tool/resources/_includes/sidebar.html
@@ -6,6 +6,25 @@
{% endfor %}
+
+
{% if docs.size > 0 %}
-
diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html
index 484f7ae58b8b..ecd57f81b8cf 100644
--- a/doc-tool/resources/_layouts/api-page.html
+++ b/doc-tool/resources/_layouts/api-page.html
@@ -175,22 +175,21 @@
{{ member.comment.body }}
-
{% endfor %}
+
diff --git a/doc-tool/resources/_layouts/search.html b/doc-tool/resources/_layouts/search.html
index e8603cbdfc2a..a9001dde4f3f 100644
--- a/doc-tool/resources/_layouts/search.html
+++ b/doc-tool/resources/_layouts/search.html
@@ -33,7 +33,7 @@ Member Results
// Parse parameters from URL:
var parameters = [];
var apiSearch = undefined;
- var docs = {{ docs | json }};
+ var docs = {{ searchableDocs | json }};
(function() {
var pairs = location.search.substring(1).split('&');
for (var i = 0; i < pairs.length; i++) {
@@ -61,7 +61,7 @@ Member Results
"docs": docs,
});
- var insertEntity = function(entityResultsNode, entityResults) {
+ var insertEntity = function(entityResultsNode, entityResults, suffix) {
return function(entity, parent) {
var shouldInsert =
parent.kind == "package" &&
@@ -92,41 +92,71 @@ Member Results
// Insert into list of results in package, no need to sort -
// already sorted:
var entityUl = entityResults[parent.name];
- var entityLi = document.createElement("li");
- if (entity.hasCompanion)
- entityLi.classList.add("entity-result-li", "with-companion");
- else
- entityLi.classList.add("entity-result-li");
-
- var companion = !entity.hasCompanion ? "" : (
- 'O'
- );
-
- var letter =
- '' +
- entity.kind.charAt(0).toUpperCase() +
- ''
-
- entityLi.innerHTML = (
- '
' +
- companion +
- letter +
- '
' +
- "" +
- entity.name +
- ""
- );
- entityUl.appendChild(entityLi);
+ var selector = entity.path.slice(0, entity.path.length - 1).join('-') + '-' + entity.name + '-' + suffix;
+ var entityLi = document.querySelector('#' + selector);
+ if (!entityLi) {
+ entityLi = document.createElement("li");
+ if (entity.hasCompanion)
+ entityLi.classList.add("entity-result-li", "with-companion");
+ else
+ entityLi.classList.add("entity-result-li");
+
+ entityLi.id = selector;
+
+ var companion = !entity.hasCompanion ? "" : (
+ 'O'
+ );
+
+ var letter =
+ '' +
+ entity.kind.charAt(0).toUpperCase() +
+ ''
+
+ entityLi.innerHTML = (
+ '' +
+ companion +
+ letter +
+ '
' +
+ "" +
+ entity.name +
+ ""
+ );
+ entityUl.appendChild(entityLi);
+ }
return entityLi;
}
else {
- return undefined;
+ var path = entity.path.slice(0, entity.path.length - 1)
+ return document.querySelector('#' + path + '-' + entity.name + '-' + suffix);
}
};
};
var insertMember = function(member, li) {
- li.appendChild(document.createTextNode(", " + member.name));
+ var div = document.createElement("div");
+ div.classList.add("member-result");
+
+ var renderParamList = function(plist) {
+ var start = plist.isImplicit ? "(implicit " : "(";
+ var args = plist.list.join(', ');
+ return start + args + ")";
+ };
+
+ var concatenateStrings = function(acc, str) { return acc + str; };
+
+ var paramLists = !member.paramLists ? "" : (
+ member.paramLists
+ .map(renderParamList)
+ .reduce(concatenateStrings, "")
+ );
+
+ div.innerHTML =
+ ''+ member.kind +'
' +
+ ''+ member.name +'
' +
+ '' + paramLists + ':
' +
+ ''+ member.returnValue +'
'
+
+ li.appendChild(div);
};
var entityResultsNode = document.getElementById("entity-results");
@@ -135,20 +165,19 @@ Member Results
var memberResults = [];
apiSearch.onmessage = function(res) {
+ var package = res.data.package;
switch(res.data.type) {
case "entityResult": {
var entity = res.data.entity;
- var package = res.data.package;
//console.log("got entity: " + entity.name + ", in package: " + package.name);
- insertEntity(entityResultsNode, entityResults)(entity, package);
+ insertEntity(entityResultsNode, entityResults, "entity")(entity, package);
break;
}
case "memberResult": {
var member = res.data.member;
var parent = res.data.parent;
- var package = res.data.package;
//console.log("got member: " + member.name + ", in entity: " + parent.name);
- var li = insertEntity(memberResultsNode, memberResults)(parent, package);
+ var li = insertEntity(memberResultsNode, memberResults, "member")(parent, package);
if (li) insertMember(member, li);
break;
}
diff --git a/doc-tool/resources/css/search.css b/doc-tool/resources/css/search.css
index 7169bb19668b..1432144acd29 100644
--- a/doc-tool/resources/css/search.css
+++ b/doc-tool/resources/css/search.css
@@ -47,15 +47,7 @@ div#result-container > div.results {
float: left;
width: 50%;
padding-right: 20px;
- min-height: 40px; /** debug */
-}
-
-div#entity-results {
- background-color: green; /** debug */
-}
-
-div#member-results {
- background-color: red; /** debug */
+ overflow: hidden;
}
div.results > h1 {
@@ -134,6 +126,39 @@ div.results li.entity-result-li:hover {
margin-left: 0;
}
+div.results li.entity-result-li > div.member-result {
+ padding-top: 3px;
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ transition: all 0.2s ease;
+ margin-left: 105px;
+}
+
+div.results li.entity-result-li:hover > div.member-result {
+ margin-left: 23px;
+}
+
+div.results li.entity-result-li > div.member-result > div.member-kind {
+ margin-right: 5px;
+ font-weight: 400;
+}
+
+div.results li.entity-result-li > div.member-result > div.member-return {
+ margin-left: 5px;
+ font-weight: 400;
+ white-space: nowrap;
+}
+
+div.results li.entity-result-li > div.member-result > div.member-kind,
+div.results li.entity-result-li > div.member-result > div.member-name,
+div.results li.entity-result-li > div.member-result > div.member-param-lists,
+div.results li.entity-result-li > div.member-result > div.member-return {
+ float: left;
+ line-height: 16px;
+ display: inline;
+}
+
div.results li.entity-result-li > div.entity-kinds {
float: left;
}
diff --git a/doc-tool/resources/css/sidebar.css b/doc-tool/resources/css/sidebar.css
index 09c12352a8ab..79322a329e28 100644
--- a/doc-tool/resources/css/sidebar.css
+++ b/doc-tool/resources/css/sidebar.css
@@ -39,6 +39,15 @@ ul.toc {
padding-left: 0;
}
+ul.toc ul {
+ padding-left: 0;
+}
+
+ul.toc > li,
+ul.toc ul > li {
+ padding-left: 24px;
+}
+
ul.toc > li:hover {
background-color: transparent;
}
@@ -72,10 +81,11 @@ ul.toc > li.logo-li > a {
float: none;
}
-ul.toc > li > a {
+ul.toc > li > a,
+ul.toc li > a.toggle-children {
font-size: 13px;
display: block;
- padding: 0 0 0 24px;
+ padding: 0;
width: 100%;
color: rgba(0, 0, 0, 0.87);
background: transparent;
@@ -84,13 +94,9 @@ ul.toc > li > a {
text-transform: uppercase;
}
-ul.toc > li > ul.show {
- display: block;
+ul.toc > li ul {
list-style-type: none;
font-size: 13px;
-}
-
-ul.toc > li > ul.hide {
display: none;
}
diff --git a/doc-tool/resources/js/api-search.js b/doc-tool/resources/js/api-search.js
index c64d56484466..4950d2067ffe 100644
--- a/doc-tool/resources/js/api-search.js
+++ b/doc-tool/resources/js/api-search.js
@@ -47,7 +47,15 @@ onmessage = function(e) {
var searchRegex = regexForTerm(searchTerm);
var filterPackages = function(entity) {
- return entity.kind != "package";
+ switch(entity.kind) {
+ case "val":
+ case "def":
+ case "type":
+ case "package":
+ return false;
+ default:
+ return true;
+ }
};
// look at this higher order function, such syntax:
@@ -78,7 +86,7 @@ onmessage = function(e) {
};
docs.forEach(function(pack) {
- pack.children
+ pack.members
.filter(filterPackages)
.forEach(messageParentIfMatches(pack));
});
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
index c5d20d30b9ab..282f9e81c035 100644
--- a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
@@ -33,6 +33,7 @@ class DocCompiler extends Compiler {
new LinkCompanions,
new AlternateConstructors,
new SortMembers)),
+ List(DocMiniTransformations(new RemoveEmptyPackages)),
List(new StatisticsPhase)
)
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/RemoveEmptyPackagesPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/RemoveEmptyPackagesPhase.scala
new file mode 100644
index 000000000000..c7917b9d0e1c
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/RemoveEmptyPackagesPhase.scala
@@ -0,0 +1,15 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotc.core.Contexts.Context
+
+import transform.DocMiniPhase
+import model._
+
+class RemoveEmptyPackages extends DocMiniPhase {
+ override def transformPackage(implicit ctx: Context) = { case p: Package =>
+ if (p.members.exists(_.kind != "package")) p
+ else NonEntity
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
index 5174c09225bc..cdf57bd02c5d 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
@@ -53,6 +53,11 @@ object transform {
pack <- rootPackages(ctx.docbase.packages)
transformed = performPackageTransform(pack)
} yield ctx.docbase.packagesMutable(pack.name) = transformed
+
+ ctx.docbase.packagesMutable.foreach { case (key, value) =>
+ if (value eq NonEntity) ctx.docbase.packagesMutable -= key
+ }
+
units
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
index dfb6e35df7b1..39a088c97ed3 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
@@ -241,13 +241,58 @@ object JavaConverters {
}
implicit class JavaMap(val map: collection.Map[String, Package]) extends AnyVal {
- def toJavaList: LinkedList[AnyRef] = {
- map.toList
- .sortBy(_._1)
- .foldLeft(new LinkedList[AnyRef]()) { case (list, (_, pkg)) =>
- list.add(pkg.asJava())
- list
- }
- }
+ def toJavaList: LinkedList[AnyRef] =
+ convertToList(map.mapValues(_.asJava))
+
+ def flattened: LinkedList[AnyRef] =
+ convertToList(map.mapValues(flattenEntity))
+
+ private[this] def convertToList(ms: collection.Map[String, AnyRef]): LinkedList[AnyRef] =
+ ms.toList.sortBy(_._1)
+ .foldLeft(new LinkedList[AnyRef]()) { case (list, (_, value)) =>
+ list.add(value); list
+ }
+
+ private[this] def flattenEntity(e: Entity): JMap[String, _] = {
+ def entity(e: Entity) =
+ Map("name" -> e.name, "path" -> e.path.asJava, "kind" -> e.kind)
+
+ def members(e: Entity with Members) =
+ Map("members" -> e.members.map(flattenEntity).asJava)
+
+ def companion(e: Companion) = Map(
+ "hasCompanion" -> e.hasCompanion,
+ "companionPath" -> e.companionPath.asJava
+ )
+
+ def typeParams(e: TypeParams) =
+ Map("typeParams" -> e.typeParams.asJava)
+
+ def paramLists(e: Def) = Map(
+ "paramLists" -> {
+ e.paramLists.map { paramList =>
+ Map(
+ "isImplicit" -> paramList.isImplicit,
+ "list" -> paramList.list.map(_.showReference).asJava
+ ).asJava
+ }
+ .asJava
+ }
+ )
+
+ def returnValue(e: ReturnValue) =
+ Map("returnValue" -> e.returnValue.showReference)
+
+ entity(e) ++ (e match {
+ case e: Package => members(e)
+ case e: Class => members(e) ++ companion(e)
+ case e: CaseClass => members(e) ++ companion(e)
+ case e: Trait => members(e) ++ companion(e)
+ case e: Object => members(e) ++ companion(e)
+ case e: Def => typeParams(e) ++ paramLists(e) ++ returnValue(e)
+ case e: TypeAlias => Map.empty
+ case e: Val => Map.empty
+ })
+ }.asJava
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/references.scala b/doc-tool/src/dotty/tools/dottydoc/model/references.scala
index a103347c1efc..f111842641c9 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/references.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/references.scala
@@ -35,4 +35,38 @@ object references {
case _ => None
}
}
+
+ implicit class ReferenceShower(val ref: Reference) extends AnyVal {
+ def showReference: String = ref match {
+ case TypeReference(title, _, tparams) =>
+ title + {
+ if (tparams.nonEmpty) tparams.map(_.showReference).mkString("[", ",", "]")
+ else ""
+ }
+
+ case AndOrTypeReference(left, part, right) =>
+ left.showReference + s" $part " + right.showReference
+
+ case FunctionReference(args, ret) =>
+ if (args.isEmpty)
+ "() => " + ret.showReference
+ else if (args.tail.isEmpty)
+ args.head + " => " + ret.showReference
+ else
+ args.mkString("(", ",", s") => ${ret.showReference}")
+
+ case TupleReference(xs) =>
+ xs.mkString("(", ",", ")")
+
+ case BoundsReference(lo, hi) =>
+ lo.showReference + "<: " + hi.showReference
+
+ case NamedReference(title, ref, isByName, isRepeated) =>
+ val byName = if (isByName) "=> " else ""
+ val repeated = if (isRepeated) "*" else ""
+ s"$title: $byName${ref.showReference}$repeated"
+
+ case ConstantReference(title) => title
+ }
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala
index 300e1b90a724..5307416cd811 100644
--- a/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala
@@ -11,6 +11,7 @@ import scala.collection.JavaConverters._
case class DefaultParams(
docs: JList[_],
+ docsFlattened: JList[_],
originalDocs: Map[String, Package],
page: PageInfo,
site: SiteInfo,
@@ -23,6 +24,8 @@ case class DefaultParams(
val base = Map(
"docs" -> docs,
+ "searchableDocs" -> docsFlattened,
+
"originalDocs" -> originalDocs,
"page" -> Map(
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala
index 4a18b2e12255..2f1756783c54 100644
--- a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala
@@ -41,6 +41,11 @@ case class Site(
documentation.toJavaList
}
+ private val docsFlattened: JList[_] = {
+ import model.JavaConverters._
+ documentation.flattened
+ }
+
/** All files that are considered static in this context, this can be
* anything from CSS, JS to images and other files.
*
@@ -166,7 +171,7 @@ case class Site(
}
DefaultParams(
- docs, documentation, PageInfo(pathFromRoot),
+ docs, docsFlattened, documentation, PageInfo(pathFromRoot),
SiteInfo(baseUrl, projectTitle, projectVersion, projectUrl, Array()),
sidebar
)
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
index 8e82041f386a..0a8427c32012 100644
--- a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
@@ -9,7 +9,7 @@ import liqp.tags.Tag
import liqp.TemplateContext
import liqp.nodes.LNode
-import java.util.{ Map => JMap }
+import java.util.{ Map => JMap, List => JList }
import model._
import util.syntax._
@@ -163,22 +163,23 @@ object tags {
case class RenderTitle(params: Map[String, AnyRef])(implicit ctx: Context)
extends Tag("renderTitle") with ParamConverter {
private def renderTitle(t: Title, parent: String): String = {
- if (!t.url.isDefined && t.subsection.nonEmpty) {
- val onclickFunction =
- s"""(function(){var child=document.getElementById("${t.title}");child.classList.toggle("show");child.classList.toggle("hide");})();"""
- s"""|${t.title}
- |
- | ${t.subsection.map(renderTitle(_, parent)).mkString("- ", "
- ", "
")}
- |
""".stripMargin
- }
- else if (t.url.isDefined) {
- val url = t.url.get
- s"""${t.title}"""
- }
- else /*if (t.subsection.nonEmpty)*/ {
- ctx.docbase.error(s"url was defined for subsection with title: ${t.title}, remove url to get toggleable entries")
- t.title
- }
+ if (!t.url.isDefined && t.subsection.nonEmpty) {
+ s"""|${t.title}
+ |
+ | ${ t.subsection.map(renderTitle(_, parent)).mkString("- ","\n
\n- ", "
") }
+ |
+ |""".stripMargin
+ }
+ else if (t.url.isDefined) {
+ val url = t.url.get
+ s"""${t.title}"""
+ }
+ else {
+ ctx.docbase.error(
+ s"url was defined for subsection with title: ${t.title}, remove url to get toggleable entries"
+ )
+ t.title
+ }
}
override def render(ctx: TemplateContext, nodes: LNode*): AnyRef =
diff --git a/doc-tool/test/PackageStructure.scala b/doc-tool/test/PackageStructure.scala
index 569bfbc1c338..e53de5de71e6 100644
--- a/doc-tool/test/PackageStructure.scala
+++ b/doc-tool/test/PackageStructure.scala
@@ -60,14 +60,8 @@ class PackageStructure extends DottyDocTest {
""".stripMargin)
checkSources(source1 :: source2 :: Nil) { packages =>
- packages("scala") match {
- case PackageImpl(
- _,
- _,
- "scala",
- List(PackageImpl(_, _, "scala.collection", List(tA, tB), _, _, _, _)),
- _, _, _, _
- ) =>
+ packages("scala.collection") match {
+ case PackageImpl(_, _, "scala.collection", List(tA, tB), _, _, _, _) =>
assert(
tA.name == "A" && tB.name == "B",
s"trait A had name '${tA.name}' and trait B had name '${tB.name}'"